From 0be623aea6bb26c71a0af9a28c9e1c4722653422 Mon Sep 17 00:00:00 2001 From: Xavier Roblot Date: Fri, 21 Jun 2024 12:03:49 +0000 Subject: [PATCH 01/19] feat: Define the regulator of a number field (#12504) This PR defines the regulator of a number field `K` as the covolume of its `unitLattice K`. Basic results about the regulator are proved including the fact that it is equal to the absolute value of the matrix with entries `mult w * Real.log w (fundSystem K i)` where `fundSystem K` is the fundamental system of units and `w` runs through all the infinite places of `K` but one. --- Mathlib.lean | 1 + Mathlib/Algebra/Ring/NegOnePow.lean | 4 + Mathlib/GroupTheory/Perm/Sign.lean | 5 + .../NumberTheory/NumberField/Units/Basic.lean | 5 + .../NumberField/Units/DirichletTheorem.lean | 77 +++++++----- .../NumberField/Units/Regulator.lean | 110 ++++++++++++++++++ 6 files changed, 173 insertions(+), 29 deletions(-) create mode 100644 Mathlib/NumberTheory/NumberField/Units/Regulator.lean diff --git a/Mathlib.lean b/Mathlib.lean index bb7471b605b785..15709eedd0f120 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3213,6 +3213,7 @@ import Mathlib.NumberTheory.NumberField.FractionalIdeal import Mathlib.NumberTheory.NumberField.Norm import Mathlib.NumberTheory.NumberField.Units.Basic import Mathlib.NumberTheory.NumberField.Units.DirichletTheorem +import Mathlib.NumberTheory.NumberField.Units.Regulator import Mathlib.NumberTheory.Ostrowski import Mathlib.NumberTheory.Padics.Hensel import Mathlib.NumberTheory.Padics.PadicIntegers diff --git a/Mathlib/Algebra/Ring/NegOnePow.lean b/Mathlib/Algebra/Ring/NegOnePow.lean index ee14c60754e0fa..0ad5c85f388994 100644 --- a/Mathlib/Algebra/Ring/NegOnePow.lean +++ b/Mathlib/Algebra/Ring/NegOnePow.lean @@ -70,6 +70,10 @@ lemma negOnePow_eq_neg_one_iff (n : ℤ) : n.negOnePow = -1 ↔ Odd n := by contradiction · exact negOnePow_odd n +@[simp] +theorem abs_negOnePow (n : ℤ) : |(n.negOnePow : ℤ)| = 1 := by + rw [abs_eq_natAbs, Int.units_natAbs, Nat.cast_one] + @[simp] lemma negOnePow_neg (n : ℤ) : (-n).negOnePow = n.negOnePow := by dsimp [negOnePow] diff --git a/Mathlib/GroupTheory/Perm/Sign.lean b/Mathlib/GroupTheory/Perm/Sign.lean index 42f07b9419e1ec..f2730ab6a71b7e 100644 --- a/Mathlib/GroupTheory/Perm/Sign.lean +++ b/Mathlib/GroupTheory/Perm/Sign.lean @@ -462,6 +462,11 @@ theorem sign_prod_list_swap {l : List (Perm α)} (hl : ∀ g ∈ l, IsSwap g) : rw [← List.prod_replicate, ← h₁, List.prod_hom _ (@sign α _ _)] #align equiv.perm.sign_prod_list_swap Equiv.Perm.sign_prod_list_swap +@[simp] +theorem sign_abs (f : Perm α) : + |(Equiv.Perm.sign f : ℤ)| = 1 := by + rw [Int.abs_eq_natAbs, Int.units_natAbs, Nat.cast_one] + variable (α) theorem sign_surjective [Nontrivial α] : Function.Surjective (sign : Perm α → ℤˣ) := fun a => diff --git a/Mathlib/NumberTheory/NumberField/Units/Basic.lean b/Mathlib/NumberTheory/NumberField/Units/Basic.lean index 147c1f2b7512b8..d6fc4de5ec09c7 100644 --- a/Mathlib/NumberTheory/NumberField/Units/Basic.lean +++ b/Mathlib/NumberTheory/NumberField/Units/Basic.lean @@ -93,6 +93,11 @@ end coe open NumberField.InfinitePlace +@[simp] +protected theorem norm [NumberField K] (x : (𝓞 K)ˣ) : + |Algebra.norm ℚ (x : K)| = 1 := by + rw [← RingOfIntegers.coe_norm, isUnit_iff_norm.mp x.isUnit] + section torsion /-- The torsion subgroup of the group of units. -/ diff --git a/Mathlib/NumberTheory/NumberField/Units/DirichletTheorem.lean b/Mathlib/NumberTheory/NumberField/Units/DirichletTheorem.lean index b6c8cbf113ef63..95405a155f07f1 100644 --- a/Mathlib/NumberTheory/NumberField/Units/DirichletTheorem.lean +++ b/Mathlib/NumberTheory/NumberField/Units/DirichletTheorem.lean @@ -72,7 +72,8 @@ def w₀ : InfinitePlace K := (inferInstance : Nonempty (InfinitePlace K)).some variable (K) /-- The logarithmic embedding of the units (seen as an `Additive` group). -/ -def logEmbedding : Additive ((𝓞 K)ˣ) →+ ({w : InfinitePlace K // w ≠ w₀} → ℝ) := +def _root_.NumberField.Units.logEmbedding : + Additive ((𝓞 K)ˣ) →+ ({w : InfinitePlace K // w ≠ w₀} → ℝ) := { toFun := fun x w => mult w.val * Real.log (w.val ↑(Additive.toMul x)) map_zero' := by simp; rfl map_add' := fun _ _ => by simp [Real.log_mul, mul_add]; rfl } @@ -86,8 +87,7 @@ theorem logEmbedding_component (x : (𝓞 K)ˣ) (w : {w : InfinitePlace K // w theorem sum_logEmbedding_component (x : (𝓞 K)ˣ) : ∑ w, logEmbedding K x w = - mult (w₀ : InfinitePlace K) * Real.log (w₀ (x : K)) := by have h := congr_arg Real.log (prod_eq_abs_norm (x : K)) - rw [show |(Algebra.norm ℚ) (x : K)| = 1 from isUnit_iff_norm.mp x.isUnit, Rat.cast_one, - Real.log_one, Real.log_prod] at h + rw [Units.norm, Rat.cast_one, Real.log_one, Real.log_prod] at h · simp_rw [Real.log_pow] at h rw [← insert_erase (mem_univ w₀), sum_insert (not_mem_erase w₀ univ), add_comm, add_eq_zero_iff_eq_neg] at h @@ -374,6 +374,29 @@ theorem unitLattice_rank : finrank ℤ (unitLattice K) = Units.rank K := by rw [← Units.finrank_eq_rank, Zlattice.rank ℝ] +/-- The map obtained by quotienting by the kernel of `logEmbedding`. -/ +def logEmbeddingQuot : + Additive ((𝓞 K)ˣ ⧸ (torsion K)) →+ ({w : InfinitePlace K // w ≠ w₀} → ℝ) := + MonoidHom.toAdditive' <| + (QuotientGroup.kerLift (AddMonoidHom.toMultiplicative' (logEmbedding K))).comp + (QuotientGroup.quotientMulEquivOfEq (by + ext + rw [MonoidHom.mem_ker, AddMonoidHom.toMultiplicative'_apply_apply, ofAdd_eq_one, + ← logEmbedding_eq_zero_iff] + rfl)).toMonoidHom + +@[simp] +theorem logEmbeddingQuot_apply (x : (𝓞 K)ˣ) : + logEmbeddingQuot K ⟦x⟧ = logEmbedding K x := rfl + +theorem logEmbeddingQuot_injective : + Function.Injective (logEmbeddingQuot K) := by + unfold logEmbeddingQuot + intro _ _ h + simp_rw [MonoidHom.toAdditive'_apply_apply, MonoidHom.coe_comp, MulEquiv.coe_toMonoidHom, + 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 @@ -386,36 +409,25 @@ local instance : CommGroup (𝓞 K)ˣ := inferInstance -/ set_option maxSynthPendingDepth 2 -- Note this is active for the remainder of the file. -private theorem unitLatticeEquiv_aux1 : - (logEmbedding K).ker = (MonoidHom.toAdditive (QuotientGroup.mk' (torsion K))).ker := by - ext - rw [MonoidHom.coe_toAdditive_ker, QuotientGroup.ker_mk', AddMonoidHom.mem_ker, - logEmbedding_eq_zero_iff] - rfl +/-- The linear equivalence between `(𝓞 K)ˣ ⧸ (torsion K)` as an additive `ℤ`-module and +`unitLattice` . -/ +def logEmbeddingEquiv : + Additive ((𝓞 K)ˣ ⧸ (torsion K)) ≃ₗ[ℤ] (unitLattice K) := + (AddEquiv.ofBijective (AddMonoidHom.codRestrict (logEmbeddingQuot K) _ + (Quotient.ind fun x ↦ logEmbeddingQuot_apply K _ ▸ AddSubgroup.mem_map_of_mem _ trivial)) + ⟨fun _ _ ↦ by + rw [AddMonoidHom.codRestrict_apply, AddMonoidHom.codRestrict_apply, Subtype.mk.injEq] + apply logEmbeddingQuot_injective K, fun ⟨a, ⟨b, _, ha⟩⟩ ↦ ⟨⟦b⟧, by simp [ha]⟩⟩).toIntLinearEquiv -private theorem unitLatticeEquiv_aux2 : - Function.Surjective (MonoidHom.toAdditive (QuotientGroup.mk' (torsion K))) := by - intro x - refine ⟨Additive.ofMul x.out', ?_⟩ - simp only [MonoidHom.toAdditive_apply_apply, toMul_ofMul, QuotientGroup.mk'_apply, - QuotientGroup.out_eq'] - rfl - -/-- The linear equivalence between `unitLattice` and `(𝓞 K)ˣ ⧸ (torsion K)` as an additive -`ℤ`-module. -/ -def unitLatticeEquiv : (unitLattice K) ≃ₗ[ℤ] Additive ((𝓞 K)ˣ ⧸ (torsion K)) := - AddEquiv.toIntLinearEquiv <| - (AddEquiv.addSubgroupCongr (AddMonoidHom.range_eq_map (logEmbedding K)).symm).trans <| - (QuotientAddGroup.quotientKerEquivRange (logEmbedding K)).symm.trans <| - (QuotientAddGroup.quotientAddEquivOfEq (unitLatticeEquiv_aux1 K)).trans <| - QuotientAddGroup.quotientKerEquivOfSurjective - (MonoidHom.toAdditive (QuotientGroup.mk' (torsion K))) (unitLatticeEquiv_aux2 K) +@[simp] +theorem logEmbeddingEquiv_apply (x : (𝓞 K)ˣ) : + logEmbeddingEquiv K ⟦x⟧ = logEmbedding K x := rfl instance : Module.Free ℤ (Additive ((𝓞 K)ˣ ⧸ (torsion K))) := - Module.Free.of_equiv (unitLatticeEquiv K) + Module.Free.of_equiv (logEmbeddingEquiv K).symm instance : Module.Finite ℤ (Additive ((𝓞 K)ˣ ⧸ (torsion K))) := - Module.Finite.equiv (unitLatticeEquiv K) + Module.Finite.equiv (logEmbeddingEquiv K).symm -- Note that we prove this instance first and then deduce from it the instance -- `Monoid.FG (𝓞 K)ˣ`, and not the other way around, due to no `Subgroup` version @@ -439,7 +451,7 @@ instance : Monoid.FG (𝓞 K)ˣ := by theorem rank_modTorsion : FiniteDimensional.finrank ℤ (Additive ((𝓞 K)ˣ ⧸ (torsion K))) = rank K := by - rw [← LinearEquiv.finrank_eq (unitLatticeEquiv K), unitLattice_rank] + rw [← LinearEquiv.finrank_eq (logEmbeddingEquiv K).symm, unitLattice_rank] /-- A basis of the quotient `(𝓞 K)ˣ ⧸ (torsion K)` seen as an additive ℤ-module. -/ def basisModTorsion : Basis (Fin (rank K)) ℤ (Additive ((𝓞 K)ˣ ⧸ (torsion K))) := @@ -452,6 +464,12 @@ def fundSystem : Fin (rank K) → (𝓞 K)ˣ := -- `:)` prevents the `⧸` decaying to a quotient by `leftRel` when we unfold this later fun i => Quotient.out' (Additive.toMul (basisModTorsion K i) :) +theorem fundSystem_mk (i : Fin (rank K)) : + Additive.ofMul ⟦fundSystem K i⟧ = (basisModTorsion K i) := by + rw [fundSystem, Equiv.apply_eq_iff_eq_symm_apply, @Quotient.mk_eq_iff_out, + Quotient.out', Quotient.out_equiv_out] + rfl + /-- The exponents that appear in the unique decomposition of a unit as the product of a root of unity and powers of the units of the fundamental system `fundSystem` (see `exist_unique_eq_mul_prod`) are given by the representation of the unit on `basisModTorsion`. -/ @@ -488,4 +506,5 @@ theorem exist_unique_eq_mul_prod (x : (𝓞 K)ˣ) : ∃! ζe : torsion K × (Fin end statements + end NumberField.Units diff --git a/Mathlib/NumberTheory/NumberField/Units/Regulator.lean b/Mathlib/NumberTheory/NumberField/Units/Regulator.lean new file mode 100644 index 00000000000000..cf2f64578bd94e --- /dev/null +++ b/Mathlib/NumberTheory/NumberField/Units/Regulator.lean @@ -0,0 +1,110 @@ +/- +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.Algebra.Module.Zlattice.Covolume +import Mathlib.LinearAlgebra.Matrix.Determinant.Misc +import Mathlib.NumberTheory.NumberField.Units.DirichletTheorem + +/-! +# Regulator of a number field + +We define and prove basic results about the regulator of a number field `K`. + +## Main definitions and results + +* `NumberField.Units.regulator`: the regulator of the number field `K`. + +* `Number.Field.Units.regulator_eq_det`: 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` +where `w` runs through the infinite places distinct from `w'`. + +## Tags +number field, units, regulator + -/ + +open scoped NumberField + +noncomputable section + +namespace NumberField.Units + +variable (K : Type*) [Field K] + +open MeasureTheory Classical BigOperators NumberField.InfinitePlace + NumberField NumberField.Units.dirichletUnitTheorem + +variable [NumberField K] + +/-- The regulator of a number fied `K`. -/ +def regulator : ℝ := Zlattice.covolume (unitLattice K) + +theorem regulator_ne_zero : regulator K ≠ 0 := Zlattice.covolume_ne_zero (unitLattice K) volume + +theorem regulator_pos : 0 < regulator K := Zlattice.covolume_pos (unitLattice K) volume + +#adaptation_note +/-- +After 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: +``` +local instance : CommGroup (𝓞 K)ˣ := inferInstance +``` +-/ +set_option maxSynthPendingDepth 2 -- Note this is active for the remainder of the file. + +theorem regulator_eq_det' (e : {w : InfinitePlace K // w ≠ w₀} ≃ Fin (rank K)) : + regulator K = |(Matrix.of fun i ↦ (logEmbedding K) (fundSystem K (e i))).det| := by + simp_rw [regulator, Zlattice.covolume_eq_det _ + (((basisModTorsion K).map (logEmbeddingEquiv K)).reindex e.symm), Basis.coe_reindex, + Function.comp, Basis.map_apply, ← fundSystem_mk, Equiv.symm_symm] + rfl + +/-- 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. -/ +theorem abs_det_eq_abs_det (u : Fin (rank K) → (𝓞 K)ˣ) + {w₁ w₂ : InfinitePlace K} (e₁ : {w // w ≠ w₁} ≃ Fin (rank K)) + (e₂ : {w // w ≠ w₂} ≃ Fin (rank K)) : + |(Matrix.of fun i w : {w // w ≠ w₁} ↦ (mult w.val : ℝ) * (w.val (u (e₁ i) : K)).log).det| = + |(Matrix.of fun i w : {w // w ≠ w₂} ↦ (mult w.val : ℝ) * (w.val (u (e₂ i) : K)).log).det| := by + -- We construct an equiv `Fin (rank K + 1) ≃ InfinitePlace K` from `e₂.symm` + let f : Fin (rank K + 1) ≃ InfinitePlace K := + (finSuccEquiv _).trans ((Equiv.optionSubtype _).symm e₁.symm).val + -- And `g` corresponds to the restriction of `f⁻¹` to `{w // w ≠ w₂}` + let g : {w // w ≠ w₂} ≃ Fin (rank K) := + (Equiv.subtypeEquiv f.symm (fun _ ↦ by simp [f])).trans + (finSuccAboveEquiv (f.symm w₂)).toEquiv.symm + have h_col := congr_arg abs <| Matrix.det_permute (g.trans e₂.symm) + (Matrix.of fun i w : {w // w ≠ w₂} ↦ (mult w.val : ℝ) * (w.val (u (e₂ i) : K)).log) + rw [abs_mul, ← Int.cast_abs, Equiv.Perm.sign_abs, Int.cast_one, one_mul] at h_col + rw [← h_col] + have h := congr_arg abs <| Matrix.submatrix_succAbove_det_eq_negOnePow_submatrix_succAbove_det' + (Matrix.of fun i w ↦ (mult (f w) : ℝ) * ((f w) (u i)).log) ?_ 0 (f.symm w₂) + rw [← Matrix.det_reindex_self e₁, ← Matrix.det_reindex_self g] + · rw [Units.smul_def, abs_zsmul, Int.abs_negOnePow, one_smul] at h + convert h + · ext; simp only [ne_eq, Matrix.reindex_apply, Matrix.submatrix_apply, Matrix.of_apply, + Equiv.apply_symm_apply, Equiv.trans_apply, Fin.succAbove_zero, id_eq, finSuccEquiv_succ, + Equiv.optionSubtype_symm_apply_apply_coe, f] + · ext; simp only [ne_eq, Equiv.coe_trans, Matrix.reindex_apply, Matrix.submatrix_apply, + Function.comp_apply, Equiv.apply_symm_apply, id_eq, Matrix.of_apply]; rfl + · intro _ + simp_rw [Matrix.of_apply, ← Real.log_pow] + rw [← Real.log_prod, Equiv.prod_comp f (fun w ↦ (w (u _) ^ (mult w))), prod_eq_abs_norm, + Units.norm, Rat.cast_one, Real.log_one] + exact fun _ _ ↦ pow_ne_zero _ <| (map_ne_zero _).mpr (coe_ne_zero _) + +/-- 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)) : + regulator K = + |(Matrix.of fun i w : {w // w ≠ w'} ↦ (mult w.val : ℝ) * + Real.log (w.val (fundSystem K (e i) : K))).det| := by + let e' : {w : InfinitePlace K // w ≠ w₀} ≃ Fin (rank K) := Fintype.equivOfCardEq (by + rw [Fintype.card_subtype_compl, Fintype.card_ofSubsingleton, Fintype.card_fin, rank]) + simp_rw [regulator_eq_det' K e', logEmbedding, AddMonoidHom.coe_mk, ZeroHom.coe_mk] + exact abs_det_eq_abs_det K (fun i ↦ fundSystem K i) e' e From 2176d73b65eb67441c3b37e5df6eeab0f75b105b Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Fri, 21 Jun 2024 17:41:59 +0000 Subject: [PATCH 02/19] chore: add `IsRegular.mul` (#14010) This matches `IsLeftRegular.mul` and `IsRightRegular.mul`, and was already inside another proof. --- Mathlib/Algebra/Regular/Basic.lean | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Mathlib/Algebra/Regular/Basic.lean b/Mathlib/Algebra/Regular/Basic.lean index 73c3280641f75d..ffa41f7776bade 100644 --- a/Mathlib/Algebra/Regular/Basic.lean +++ b/Mathlib/Algebra/Regular/Basic.lean @@ -127,6 +127,12 @@ theorem IsRightRegular.mul (rra : IsRightRegular a) (rrb : IsRightRegular b) : #align is_right_regular.mul IsRightRegular.mul #align is_add_right_regular.add IsAddRightRegular.add +/-- In a semigroup, the product of regular elements is regular. -/ +@[to_additive "In an additive semigroup, the sum of add-regular elements is add-regular."] +theorem IsRegular.mul (rra : IsRegular a) (rrb : IsRegular b) : + IsRegular (a * b) := + ⟨rra.left.mul rrb.left, rra.right.mul rrb.right⟩ + /-- If an element `b` becomes left-regular after multiplying it on the left by a left-regular element, then `b` is left-regular. -/ @[to_additive "If an element `b` becomes add-left-regular after adding to it on the left @@ -180,11 +186,7 @@ theorem isRegular_mul_and_mul_iff : ⟨⟨IsLeftRegular.of_mul ba.left, IsRightRegular.of_mul ab.right⟩, ⟨IsLeftRegular.of_mul ab.left, IsRightRegular.of_mul ba.right⟩⟩ · rintro ⟨ha, hb⟩ - exact - ⟨⟨(mul_isLeftRegular_iff _ ha.left).mpr hb.left, - (mul_isRightRegular_iff _ hb.right).mpr ha.right⟩, - ⟨(mul_isLeftRegular_iff _ hb.left).mpr ha.left, - (mul_isRightRegular_iff _ ha.right).mpr hb.right⟩⟩ + exact ⟨ha.mul hb, hb.mul ha⟩ #align is_regular_mul_and_mul_iff isRegular_mul_and_mul_iff #align is_add_regular_add_and_add_iff isAddRegular_add_and_add_iff From b732d172c8df80627afffffc71306d0db599d617 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Fri, 21 Jun 2024 18:31:03 +0000 Subject: [PATCH 03/19] feat: more matrix lemmas about `37 : Matrix n n R` etc (#13976) This extends the lemmas about `zero` and `one` in this file to lemmas about `ofNat`, `natCast`, and `intCast`. --- Mathlib/Data/Matrix/Basic.lean | 114 ++++++++++++++++++++++++++++++--- 1 file changed, 104 insertions(+), 10 deletions(-) diff --git a/Mathlib/Data/Matrix/Basic.lean b/Mathlib/Data/Matrix/Basic.lean index 3c1cedf875c96c..0cd517d6556fe3 100644 --- a/Mathlib/Data/Matrix/Basic.lean +++ b/Mathlib/Data/Matrix/Basic.lean @@ -512,6 +512,22 @@ theorem diagonal_map [Zero α] [Zero β] {f : α → β} (h : f 0 = 0) {d : n split_ifs <;> simp [h] #align matrix.diagonal_map Matrix.diagonal_map +protected theorem map_natCast [DecidableEq n] [AddMonoidWithOne α] [AddMonoidWithOne β] + {f : α → β} (h : f 0 = 0) (d : ℕ) : + (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)) := + diagonal_map h + +protected theorem map_intCast [DecidableEq n] [AddGroupWithOne α] [AddGroupWithOne β] + {f : α → β} (h : f 0 = 0) (d : ℤ) : + (d : Matrix n n α).map f = diagonal (fun _ => f d) := + diagonal_map h + @[simp] theorem diagonal_conjTranspose [AddMonoid α] [StarAddMonoid α] (v : n → α) : (diagonal v)ᴴ = diagonal (star v) := by @@ -2046,26 +2062,60 @@ theorem transpose_injective : Function.Injective (transpose : Matrix m n α → @[simp] theorem transpose_inj {A B : Matrix m n α} : Aᵀ = Bᵀ ↔ A = B := transpose_injective.eq_iff @[simp] -theorem transpose_zero [Zero α] : (0 : Matrix m n α)ᵀ = 0 := by - ext - rfl +theorem transpose_eq_diagonal [DecidableEq n] [Zero α] {M : Matrix n n α} {v : n → α} : + Mᵀ = diagonal v ↔ M = diagonal v := + (Function.Involutive.eq_iff transpose_transpose).trans <| + by rw [diagonal_transpose] + +@[simp] +theorem transpose_zero [Zero α] : (0 : Matrix m n α)ᵀ = 0 := rfl #align matrix.transpose_zero Matrix.transpose_zero @[simp] theorem transpose_eq_zero [Zero α] {M : Matrix m n α} : Mᵀ = 0 ↔ M = 0 := transpose_inj @[simp] -theorem transpose_one [DecidableEq n] [Zero α] [One α] : (1 : Matrix n n α)ᵀ = 1 := by - ext i j - rw [transpose_apply, ← diagonal_one] - by_cases h : i = j - · simp only [h, diagonal_apply_eq] - · simp only [diagonal_apply_ne _ h, diagonal_apply_ne' _ h] +theorem transpose_one [DecidableEq n] [Zero α] [One α] : (1 : Matrix n n α)ᵀ = 1 := + diagonal_transpose _ #align matrix.transpose_one Matrix.transpose_one @[simp] theorem transpose_eq_one [DecidableEq n] [Zero α] [One α] {M : Matrix n n α} : Mᵀ = 1 ↔ M = 1 := - (Function.Involutive.eq_iff transpose_transpose).trans <| by rw [transpose_one] + transpose_eq_diagonal + +@[simp] +theorem transpose_natCast [DecidableEq n] [AddMonoidWithOne α] (d : ℕ) : + (d : Matrix n n α)ᵀ = d := + diagonal_transpose _ + +@[simp] +theorem transpose_eq_natCast [DecidableEq n] [AddMonoidWithOne α] {M : Matrix n n α} {d : ℕ} : + 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 := + 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 := + transpose_eq_diagonal + +@[simp] +theorem transpose_intCast [DecidableEq n] [AddGroupWithOne α] (d : ℤ) : + (d : Matrix n n α)ᵀ = d := + diagonal_transpose _ + +@[simp] +theorem transpose_eq_intCast [DecidableEq n] [AddGroupWithOne α] + {M : Matrix n n α} {d : ℤ} : + Mᵀ = d ↔ M = d := + transpose_eq_diagonal @[simp] theorem transpose_add [Add α] (M : Matrix m n α) (N : Matrix m n α) : (M + N)ᵀ = Mᵀ + Nᵀ := by @@ -2224,6 +2274,13 @@ theorem conjTranspose_injective [InvolutiveStar α] : @[simp] theorem conjTranspose_inj [InvolutiveStar α] {A B : Matrix m n α} : Aᴴ = Bᴴ ↔ A = B := conjTranspose_injective.eq_iff +@[simp] +theorem conjTranspose_eq_diagonal [DecidableEq n] [AddMonoid α] [StarAddMonoid α] + {M : Matrix n n α} {v : n → α} : + Mᴴ = diagonal v ↔ M = diagonal (star v) := + (Function.Involutive.eq_iff conjTranspose_conjTranspose).trans <| + by rw [diagonal_conjTranspose] + @[simp] theorem conjTranspose_zero [AddMonoid α] [StarAddMonoid α] : (0 : Matrix m n α)ᴴ = 0 := Matrix.ext <| by simp @@ -2245,6 +2302,43 @@ theorem conjTranspose_eq_one [DecidableEq n] [Semiring α] [StarRing α] {M : Ma (Function.Involutive.eq_iff conjTranspose_conjTranspose).trans <| by rw [conjTranspose_one] +@[simp] +theorem conjTranspose_natCast [DecidableEq n] [Semiring α] [StarRing α] (d : ℕ) : + (d : Matrix n n α)ᴴ = d := by + simp [conjTranspose, Matrix.map_natCast, diagonal_natCast] + +@[simp] +theorem conjTranspose_eq_natCast [DecidableEq n] [Semiring α] [StarRing α] + {M : Matrix n n α} {d : ℕ} : + Mᴴ = d ↔ M = d := + (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 := + 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 := + conjTranspose_eq_natCast + +@[simp] +theorem conjTranspose_intCast [DecidableEq n] [Ring α] [StarRing α] (d : ℤ) : + (d : Matrix n n α)ᴴ = d := by + simp [conjTranspose, Matrix.map_intCast, diagonal_intCast] + +@[simp] +theorem conjTranspose_eq_intCast [DecidableEq n] [Ring α] [StarRing α] + {M : Matrix n n α} {d : ℤ} : + Mᴴ = d ↔ M = d := + (Function.Involutive.eq_iff conjTranspose_conjTranspose).trans <| + by rw [conjTranspose_intCast] + @[simp] theorem conjTranspose_add [AddMonoid α] [StarAddMonoid α] (M N : Matrix m n α) : (M + N)ᴴ = Mᴴ + Nᴴ := From 23725d3c75b6d2eca0ec17d66cdc65ea9b924b47 Mon Sep 17 00:00:00 2001 From: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> Date: Fri, 21 Jun 2024 21:56:38 +0000 Subject: [PATCH 04/19] chore: deprecate AlgEquiv.map_* lemmas (#14005) These are redundant. --- Mathlib/Algebra/Algebra/Equiv.lean | 57 +++++++++++-------- Mathlib/Algebra/Algebra/Operations.lean | 4 +- Mathlib/Algebra/MvPolynomial/Equiv.lean | 4 +- Mathlib/Algebra/MvPolynomial/Funext.lean | 2 +- Mathlib/FieldTheory/AbelRuffini.lean | 6 +- Mathlib/FieldTheory/Adjoin.lean | 2 +- Mathlib/FieldTheory/KummerExtension.lean | 4 +- .../LinearAlgebra/CliffordAlgebra/Equivs.lean | 2 +- .../LinearAlgebra/Matrix/Charpoly/Basic.lean | 2 +- .../LinearAlgebra/Matrix/Charpoly/Coeff.lean | 4 +- .../Matrix/Charpoly/FiniteField.lean | 2 +- Mathlib/LinearAlgebra/Matrix/Reindex.lean | 2 +- Mathlib/NumberTheory/FunctionField.lean | 3 +- Mathlib/RingTheory/Localization/Basic.lean | 2 +- Mathlib/RingTheory/PowerBasis.lean | 4 +- Mathlib/RingTheory/RootsOfUnity/Basic.lean | 2 +- 16 files changed, 56 insertions(+), 46 deletions(-) diff --git a/Mathlib/Algebra/Algebra/Equiv.lean b/Mathlib/Algebra/Algebra/Equiv.lean index b39e2e44001ecd..b6502e35b2b2ec 100644 --- a/Mathlib/Algebra/Algebra/Equiv.lean +++ b/Mathlib/Algebra/Algebra/Equiv.lean @@ -196,18 +196,22 @@ theorem coe_ringEquiv_injective : Function.Injective ((↑) : (A₁ ≃ₐ[R] A fun _ _ h => ext <| RingEquiv.congr_fun h #align alg_equiv.coe_ring_equiv_injective AlgEquiv.coe_ringEquiv_injective +@[deprecated map_add (since := "2024-06-20")] protected theorem map_add : ∀ x y, e (x + y) = e x + e y := map_add e #align alg_equiv.map_add AlgEquiv.map_add +@[deprecated map_zero (since := "2024-06-20")] protected theorem map_zero : e 0 = 0 := map_zero e #align alg_equiv.map_zero AlgEquiv.map_zero +@[deprecated map_mul (since := "2024-06-20")] protected theorem map_mul : ∀ x y, e (x * y) = e x * e y := map_mul e #align alg_equiv.map_mul AlgEquiv.map_mul +@[deprecated map_one (since := "2024-06-20")] protected theorem map_one : e 1 = 1 := map_one e #align alg_equiv.map_one AlgEquiv.map_one @@ -218,19 +222,21 @@ theorem commutes : ∀ r : R, e (algebraMap R A₁ r) = algebraMap R A₂ r := #align alg_equiv.commutes AlgEquiv.commutes -- @[simp] -- Porting note (#10618): simp can prove this -theorem map_smul (r : R) (x : A₁) : e (r • x) = r • e x := by - simp only [Algebra.smul_def, map_mul, commutes] +@[deprecated map_smul (since := "2024-06-20")] +protected theorem map_smul (r : R) (x : A₁) : e (r • x) = r • e x := + map_smul _ _ _ #align alg_equiv.map_smul AlgEquiv.map_smul -@[deprecated _root_.map_sum (since := "2023-12-26")] -nonrec theorem map_sum {ι : Type*} (f : ι → A₁) (s : Finset ι) : +@[deprecated map_sum (since := "2023-12-26")] +protected theorem map_sum {ι : Type*} (f : ι → A₁) (s : Finset ι) : e (∑ x ∈ s, f x) = ∑ x ∈ s, e (f x) := map_sum e f s #align alg_equiv.map_sum AlgEquiv.map_sum -theorem map_finsupp_sum {α : Type*} [Zero α] {ι : Type*} (f : ι →₀ α) (g : ι → α → A₁) : +@[deprecated map_finsupp_sum (since := "2024-06-20")] +protected theorem map_finsupp_sum {α : Type*} [Zero α] {ι : Type*} (f : ι →₀ α) (g : ι → α → A₁) : e (f.sum g) = f.sum fun i b => e (g i b) := - _root_.map_sum e _ _ + map_finsupp_sum _ _ _ #align alg_equiv.map_finsupp_sum AlgEquiv.map_finsupp_sum -- Porting note: Added [coe] attribute @@ -241,8 +247,8 @@ The `simp` normal form is to use the coercion of the `AlgHomClass.coeTC` instanc @[coe] def toAlgHom : A₁ →ₐ[R] A₂ := { e with - map_one' := e.map_one - map_zero' := e.map_zero } + map_one' := map_one e + map_zero' := map_zero e } #align alg_equiv.to_alg_hom AlgEquiv.toAlgHom @[simp] @@ -268,6 +274,7 @@ theorem coe_ringHom_commutes : ((e : A₁ →ₐ[R] A₂) : A₁ →+* A₂) = ( rfl #align alg_equiv.coe_ring_hom_commutes AlgEquiv.coe_ringHom_commutes +@[deprecated map_pow (since := "2024-06-20")] protected theorem map_pow : ∀ (x : A₁) (n : ℕ), e (x ^ n) = e x ^ n := map_pow _ #align alg_equiv.map_pow AlgEquiv.map_pow @@ -565,7 +572,7 @@ theorem ofBijective_apply {f : A₁ →ₐ[R] A₂} {hf : Function.Bijective f} def toLinearEquiv (e : A₁ ≃ₐ[R] A₂) : A₁ ≃ₗ[R] A₂ := { e with toFun := e - map_smul' := e.map_smul + map_smul' := map_smul e invFun := e.symm } #align alg_equiv.to_linear_equiv AlgEquiv.toLinearEquiv #align alg_equiv.to_linear_equiv_apply AlgEquiv.toLinearEquiv_apply @@ -648,8 +655,8 @@ protected def ofLinearEquiv_symm.aux := (ofLinearEquiv l map_one map_mul).symm theorem ofLinearEquiv_symm : (ofLinearEquiv l map_one map_mul).symm = ofLinearEquiv l.symm - (ofLinearEquiv_symm.aux l map_one map_mul).map_one - (ofLinearEquiv_symm.aux l map_one map_mul).map_mul := + (_root_.map_one <| ofLinearEquiv_symm.aux l map_one map_mul) + (_root_.map_mul <| ofLinearEquiv_symm.aux l map_one map_mul) := rfl #align alg_equiv.of_linear_equiv_symm AlgEquiv.ofLinearEquiv_symm @@ -745,10 +752,10 @@ theorem autCongr_trans (ϕ : A₁ ≃ₐ[R] A₂) (ψ : A₂ ≃ₐ[R] A₃) : This generalizes `Function.End.applyMulAction`. -/ instance applyMulSemiringAction : MulSemiringAction (A₁ ≃ₐ[R] A₁) A₁ where smul := (· <| ·) - smul_zero := AlgEquiv.map_zero - smul_add := AlgEquiv.map_add - smul_one := AlgEquiv.map_one - smul_mul := AlgEquiv.map_mul + smul_zero := map_zero + smul_add := map_add + smul_one := map_one + smul_mul := map_mul one_smul _ := rfl mul_smul _ _ _ := rfl #align alg_equiv.apply_mul_semiring_action AlgEquiv.applyMulSemiringAction @@ -763,19 +770,19 @@ instance apply_faithfulSMul : FaithfulSMul (A₁ ≃ₐ[R] A₁) A₁ := #align alg_equiv.apply_has_faithful_smul AlgEquiv.apply_faithfulSMul instance apply_smulCommClass : SMulCommClass R (A₁ ≃ₐ[R] A₁) A₁ where - smul_comm r e a := (e.map_smul r a).symm + smul_comm r e a := (map_smul e r a).symm #align alg_equiv.apply_smul_comm_class AlgEquiv.apply_smulCommClass instance apply_smulCommClass' : SMulCommClass (A₁ ≃ₐ[R] A₁) R A₁ where - smul_comm e r a := e.map_smul r a + smul_comm e r a := map_smul e r a #align alg_equiv.apply_smul_comm_class' AlgEquiv.apply_smulCommClass' instance : MulDistribMulAction (A₁ ≃ₐ[R] A₁) A₁ˣ where smul := fun f => Units.map f one_smul := fun x => by ext; rfl mul_smul := fun x y z => by ext; rfl - smul_mul := fun x y z => by ext; exact x.map_mul _ _ - smul_one := fun x => by ext; exact x.map_one + smul_mul := fun x y z => by ext; exact map_mul x _ _ + smul_one := fun x => by ext; exact map_one x @[simp] theorem smul_units_def (f : A₁ ≃ₐ[R] A₁) (x : A₁ˣ) : @@ -826,14 +833,16 @@ section CommSemiring variable [CommSemiring R] [CommSemiring A₁] [CommSemiring A₂] variable [Algebra R A₁] [Algebra R A₂] (e : A₁ ≃ₐ[R] A₂) -theorem map_prod {ι : Type*} (f : ι → A₁) (s : Finset ι) : +@[deprecated map_prod (since := "2024-06-20")] +protected theorem map_prod {ι : Type*} (f : ι → A₁) (s : Finset ι) : e (∏ x ∈ s, f x) = ∏ x ∈ s, e (f x) := - _root_.map_prod _ f s + map_prod _ f s #align alg_equiv.map_prod AlgEquiv.map_prod -theorem map_finsupp_prod {α : Type*} [Zero α] {ι : Type*} (f : ι →₀ α) (g : ι → α → A₁) : +@[deprecated map_finsupp_prod (since := "2024-06-20")] +protected theorem map_finsupp_prod {α : Type*} [Zero α] {ι : Type*} (f : ι →₀ α) (g : ι → α → A₁) : e (f.prod g) = f.prod fun i a => e (g i a) := - _root_.map_finsupp_prod _ f g + map_finsupp_prod _ f g #align alg_equiv.map_finsupp_prod AlgEquiv.map_finsupp_prod end CommSemiring @@ -843,10 +852,12 @@ section Ring variable [CommSemiring R] [Ring A₁] [Ring A₂] variable [Algebra R A₁] [Algebra R A₂] (e : A₁ ≃ₐ[R] A₂) +@[deprecated map_neg (since := "2024-06-20")] protected theorem map_neg (x) : e (-x) = -e x := map_neg e x #align alg_equiv.map_neg AlgEquiv.map_neg +@[deprecated map_sub (since := "2024-06-20")] protected theorem map_sub (x y) : e (x - y) = e x - e y := map_sub e x y #align alg_equiv.map_sub AlgEquiv.map_sub diff --git a/Mathlib/Algebra/Algebra/Operations.lean b/Mathlib/Algebra/Algebra/Operations.lean index 84a4bfd2c21d95..6d858fdca2e4ee 100644 --- a/Mathlib/Algebra/Algebra/Operations.lean +++ b/Mathlib/Algebra/Algebra/Operations.lean @@ -762,13 +762,13 @@ protected theorem map_div {B : Type*} [CommSemiring B] [Algebra R B] (I J : Subm simp only [mem_map, mem_div_iff_forall_mul_mem] constructor · rintro ⟨x, hx, rfl⟩ _ ⟨y, hy, rfl⟩ - exact ⟨x * y, hx _ hy, h.map_mul x y⟩ + exact ⟨x * y, hx _ hy, map_mul h x y⟩ · rintro hx refine ⟨h.symm x, fun z hz => ?_, h.apply_symm_apply x⟩ obtain ⟨xz, xz_mem, hxz⟩ := hx (h z) ⟨z, hz, rfl⟩ convert xz_mem apply h.injective - erw [h.map_mul, h.apply_symm_apply, hxz] + erw [map_mul, h.apply_symm_apply, hxz] #align submodule.map_div Submodule.map_div end Quotient diff --git a/Mathlib/Algebra/MvPolynomial/Equiv.lean b/Mathlib/Algebra/MvPolynomial/Equiv.lean index 670bf5cf613101..33f359176823d7 100644 --- a/Mathlib/Algebra/MvPolynomial/Equiv.lean +++ b/Mathlib/Algebra/MvPolynomial/Equiv.lean @@ -385,7 +385,7 @@ theorem finSuccEquiv_coeff_coeff (m : Fin n →₀ ℕ) (f : MvPolynomial (Fin ( coeff m (Polynomial.coeff (finSuccEquiv R n f) i) = coeff (m.cons i) f := by induction' f using MvPolynomial.induction_on' with j r p q hp hq generalizing i m swap - · simp only [(finSuccEquiv R n).map_add, Polynomial.coeff_add, coeff_add, hp, hq] + · 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, 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] @@ -518,7 +518,7 @@ theorem degree_finSuccEquiv {f : MvPolynomial (Fin (n + 1)) R} (h : f ≠ 0) : theorem natDegree_finSuccEquiv (f : MvPolynomial (Fin (n + 1)) R) : (finSuccEquiv R n f).natDegree = degreeOf 0 f := by by_cases c : f = 0 - · rw [c, (finSuccEquiv R n).map_zero, Polynomial.natDegree_zero, degreeOf_zero] + · rw [c, map_zero, Polynomial.natDegree_zero, degreeOf_zero] · rw [Polynomial.natDegree, degree_finSuccEquiv (by simpa only [Ne] )] erw [WithBot.unbot'_coe] simp diff --git a/Mathlib/Algebra/MvPolynomial/Funext.lean b/Mathlib/Algebra/MvPolynomial/Funext.lean index 030a3dab8c6a45..23e6d4cd64daaf 100644 --- a/Mathlib/Algebra/MvPolynomial/Funext.lean +++ b/Mathlib/Algebra/MvPolynomial/Funext.lean @@ -34,7 +34,7 @@ private theorem funext_fin {n : ℕ} {p : MvPolynomial (Fin n) R} rw [RingEquiv.map_zero] convert h finZeroElim · apply (finSuccEquiv R n).injective - simp only [AlgEquiv.map_zero] + simp only [map_zero] refine Polynomial.funext fun q => ?_ rw [Polynomial.eval_zero] apply ih fun x => ?_ diff --git a/Mathlib/FieldTheory/AbelRuffini.lean b/Mathlib/FieldTheory/AbelRuffini.lean index 8f0aabf987c64d..2a550013f82e07 100644 --- a/Mathlib/FieldTheory/AbelRuffini.lean +++ b/Mathlib/FieldTheory/AbelRuffini.lean @@ -111,7 +111,7 @@ theorem gal_X_pow_sub_one_isSolvable (n : ℕ) : IsSolvable (X ^ n - 1 : F[X]).G exact map_rootsOfUnity_eq_pow_self σ.toAlgHom (rootsOfUnity.mkOfPowEq a ha) obtain ⟨c, hc⟩ := key σ obtain ⟨d, hd⟩ := key τ - rw [σ.mul_apply, τ.mul_apply, hc, τ.map_pow, hd, σ.map_pow, hc, ← pow_mul, pow_mul'] + rw [σ.mul_apply, τ.mul_apply, hc, map_pow, hd, map_pow, hc, ← pow_mul, pow_mul'] set_option linter.uppercaseLean3 false in #align gal_X_pow_sub_one_is_solvable gal_X_pow_sub_one_isSolvable @@ -143,13 +143,13 @@ theorem gal_X_pow_sub_C_isSolvable_aux (n : ℕ) (a : F) exact ha' hb.symm have key : ∀ σ : (X ^ n - C a).Gal, ∃ c, σ b = b * algebraMap F _ c := by intro σ - have key : (σ b / b) ^ n = 1 := by rw [div_pow, ← σ.map_pow, hb, σ.commutes, div_self ha'] + have key : (σ b / b) ^ n = 1 := by rw [div_pow, ← map_pow, hb, σ.commutes, div_self ha'] obtain ⟨c, hc⟩ := mem_range key use c rw [hc, mul_div_cancel₀ (σ b) hb'] obtain ⟨c, hc⟩ := key σ obtain ⟨d, hd⟩ := key τ - rw [σ.mul_apply, τ.mul_apply, hc, τ.map_mul, τ.commutes, hd, σ.map_mul, σ.commutes, hc, + rw [σ.mul_apply, τ.mul_apply, hc, map_mul, τ.commutes, hd, map_mul, σ.commutes, hc, mul_assoc, mul_assoc, mul_right_inj' hb', mul_comm] set_option linter.uppercaseLean3 false in #align gal_X_pow_sub_C_is_solvable_aux gal_X_pow_sub_C_isSolvable_aux diff --git a/Mathlib/FieldTheory/Adjoin.lean b/Mathlib/FieldTheory/Adjoin.lean index e2be0276e4ceb1..702f816ad34264 100644 --- a/Mathlib/FieldTheory/Adjoin.lean +++ b/Mathlib/FieldTheory/Adjoin.lean @@ -1136,7 +1136,7 @@ noncomputable def adjoin.powerBasis {x : L} (hx : IsIntegral K x) : PowerBasis K basis_eq_pow i := by -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 erw [powerBasisAux, Basis.map_apply, PowerBasis.basis_eq_pow, AlgEquiv.toLinearEquiv_apply, - AlgEquiv.map_pow, AdjoinRoot.powerBasis_gen, adjoinRootEquivAdjoin_apply_root] + map_pow, AdjoinRoot.powerBasis_gen, adjoinRootEquivAdjoin_apply_root] #align intermediate_field.adjoin.power_basis IntermediateField.adjoin.powerBasis theorem adjoin.finiteDimensional {x : L} (hx : IsIntegral K x) : FiniteDimensional K K⟮x⟯ := diff --git a/Mathlib/FieldTheory/KummerExtension.lean b/Mathlib/FieldTheory/KummerExtension.lean index 48be18386d035b..e0f19aa3a1de89 100644 --- a/Mathlib/FieldTheory/KummerExtension.lean +++ b/Mathlib/FieldTheory/KummerExtension.lean @@ -476,7 +476,7 @@ lemma autEquivRootsOfUnity_apply_rootOfSplit (σ : L ≃ₐ[K] L) : rw [MulEquiv.apply_symm_apply, autEquivRootsOfUnity] simp only [MulEquiv.symm_trans_apply, AlgEquiv.autCongr_symm, AlgEquiv.symm_symm, MulEquiv.symm_symm, AlgEquiv.autCongr_apply, AlgEquiv.trans_apply, - adjoinRootXPowSubCEquiv_symm_eq_root, autAdjoinRootXPowSubCEquiv_root, AlgEquiv.map_smul, + adjoinRootXPowSubCEquiv_symm_eq_root, autAdjoinRootXPowSubCEquiv_root, map_smul, adjoinRootXPowSubCEquiv_root] rfl @@ -488,7 +488,7 @@ lemma autEquivRootsOfUnity_smul (σ : L ≃ₐ[K] L) : (rootOfSplitsXPowSubC_pow hn a L)] at hα simp only [Finset.range_val, Multiset.mem_map, Multiset.mem_range] at hα obtain ⟨i, _, rfl⟩ := hα - simp only [map_mul, ← map_pow, ← Algebra.smul_def, AlgEquiv.map_smul, + simp only [map_mul, ← map_pow, ← Algebra.smul_def, map_smul, autEquivRootsOfUnity_apply_rootOfSplit hζ hn H L] exact smul_comm _ _ _ diff --git a/Mathlib/LinearAlgebra/CliffordAlgebra/Equivs.lean b/Mathlib/LinearAlgebra/CliffordAlgebra/Equivs.lean index b2c812719b0ef0..ae94a45e64efa4 100644 --- a/Mathlib/LinearAlgebra/CliffordAlgebra/Equivs.lean +++ b/Mathlib/LinearAlgebra/CliffordAlgebra/Equivs.lean @@ -216,7 +216,7 @@ instance : CommRing (CliffordAlgebra Q) := { CliffordAlgebra.instRing _ with mul_comm := fun x y => CliffordAlgebraComplex.equiv.injective <| by - rw [AlgEquiv.map_mul, mul_comm, AlgEquiv.map_mul] } + rw [map_mul, mul_comm, map_mul] } -- Porting note: Changed `x.reverse` to `reverse (R := ℝ) x` /-- `reverse` is a no-op over `CliffordAlgebraComplex.Q`. -/ diff --git a/Mathlib/LinearAlgebra/Matrix/Charpoly/Basic.lean b/Mathlib/LinearAlgebra/Matrix/Charpoly/Basic.lean index 1859ac7e9ba273..eb6442e3848c3b 100644 --- a/Mathlib/LinearAlgebra/Matrix/Charpoly/Basic.lean +++ b/Mathlib/LinearAlgebra/Matrix/Charpoly/Basic.lean @@ -139,7 +139,7 @@ theorem aeval_self_charpoly (M : Matrix n n R) : aeval M M.charpoly = 0 := by -- Using the algebra isomorphism `Matrix n n R[X] ≃ₐ[R] Polynomial (Matrix n n R)`, -- we have the same identity in `Polynomial (Matrix n n R)`. apply_fun matPolyEquiv at h - simp only [matPolyEquiv.map_mul, matPolyEquiv_charmatrix] at h + simp only [_root_.map_mul, matPolyEquiv_charmatrix] at h -- Because the coefficient ring `Matrix n n R` is non-commutative, -- evaluation at `M` is not multiplicative. -- However, any polynomial which is a product of the form $N * (t I - M)$ diff --git a/Mathlib/LinearAlgebra/Matrix/Charpoly/Coeff.lean b/Mathlib/LinearAlgebra/Matrix/Charpoly/Coeff.lean index 2c04cc514d8a0b..0c6f31e4b6e974 100644 --- a/Mathlib/LinearAlgebra/Matrix/Charpoly/Coeff.lean +++ b/Mathlib/LinearAlgebra/Matrix/Charpoly/Coeff.lean @@ -343,8 +343,8 @@ lemma reverse_charpoly (M : Matrix n n R) : suffices t_inv ^ Fintype.card n * p = invert q by apply toLaurent_injective rwa [toLaurent_reverse, ← coe_toLaurentAlg, hp, hq, ← involutive_invert.injective.eq_iff, - invert.map_mul, involutive_invert p, charpoly_natDegree_eq_dim, - ← mul_one (Fintype.card n : ℤ), ← T_pow, invert.map_pow, invert_T, mul_comm] + _root_.map_mul, involutive_invert p, charpoly_natDegree_eq_dim, + ← mul_one (Fintype.card n : ℤ), ← T_pow, map_pow, invert_T, mul_comm] rw [← det_smul, smul_sub, scalar_apply, ← diagonal_smul, Pi.smul_def, smul_eq_mul, ht, diagonal_one, invert.map_det] simp [t, map_smul', smul_eq_diagonal_mul] diff --git a/Mathlib/LinearAlgebra/Matrix/Charpoly/FiniteField.lean b/Mathlib/LinearAlgebra/Matrix/Charpoly/FiniteField.lean index 85f21e0e5c8388..56952314e59e34 100644 --- a/Mathlib/LinearAlgebra/Matrix/Charpoly/FiniteField.lean +++ b/Mathlib/LinearAlgebra/Matrix/Charpoly/FiniteField.lean @@ -37,7 +37,7 @@ theorem FiniteField.Matrix.charpoly_pow_card {K : Type*} [Field K] [Fintype K] ( rw [AlgHom.map_det, ← coe_detMonoidHom, ← (detMonoidHom : Matrix n n K[X] →* K[X]).map_pow] apply congr_arg det refine matPolyEquiv.injective ?_ - rw [AlgEquiv.map_pow, matPolyEquiv_charmatrix, hk, sub_pow_char_pow_of_commute, ← C_pow] + 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 (C M).commute_X · exact congr_arg _ (Subsingleton.elim _ _) diff --git a/Mathlib/LinearAlgebra/Matrix/Reindex.lean b/Mathlib/LinearAlgebra/Matrix/Reindex.lean index 6b538c02ae19bc..dd375f7d3a46ba 100644 --- a/Mathlib/LinearAlgebra/Matrix/Reindex.lean +++ b/Mathlib/LinearAlgebra/Matrix/Reindex.lean @@ -145,7 +145,7 @@ theorem reindexAlgEquiv_refl : reindexAlgEquiv R (Equiv.refl m) = AlgEquiv.refl theorem reindexAlgEquiv_mul (e : m ≃ n) (M : Matrix m m R) (N : Matrix m m R) : reindexAlgEquiv R e (M * N) = reindexAlgEquiv R e M * reindexAlgEquiv R e N := - (reindexAlgEquiv R e).map_mul M N + _root_.map_mul .. #align matrix.reindex_alg_equiv_mul Matrix.reindexAlgEquiv_mul end Algebra diff --git a/Mathlib/NumberTheory/FunctionField.lean b/Mathlib/NumberTheory/FunctionField.lean index 53267c695233b9..7179ff7f08f6cf 100644 --- a/Mathlib/NumberTheory/FunctionField.lean +++ b/Mathlib/NumberTheory/FunctionField.lean @@ -70,8 +70,7 @@ theorem functionField_iff (Fqt : Type*) [Field Fqt] [Algebra Fq[X] Fqt] congr refine congr_fun (f := fun c => algebraMap Fqt F (e c)) ?_ c -- Porting note: Added `(f := _)` refine IsLocalization.ext (nonZeroDivisors Fq[X]) _ _ ?_ ?_ ?_ ?_ ?_ <;> intros <;> - simp only [AlgEquiv.map_one, RingHom.map_one, AlgEquiv.map_mul, RingHom.map_mul, - AlgEquiv.commutes, ← IsScalarTower.algebraMap_apply] + simp only [map_one, map_mul, AlgEquiv.commutes, ← IsScalarTower.algebraMap_apply] constructor <;> intro h · let b := FiniteDimensional.finBasis (RatFunc Fq) F exact FiniteDimensional.of_fintype_basis (b.mapCoeffs e this) diff --git a/Mathlib/RingTheory/Localization/Basic.lean b/Mathlib/RingTheory/Localization/Basic.lean index 1a23c981c8f94f..0bd39b6a52d4b7 100644 --- a/Mathlib/RingTheory/Localization/Basic.lean +++ b/Mathlib/RingTheory/Localization/Basic.lean @@ -812,7 +812,7 @@ theorem isLocalization_of_algEquiv [Algebra R P] [IsLocalization M S] (h : S ≃ · intro y obtain ⟨⟨x, s⟩, e⟩ := IsLocalization.surj M (h.symm y) apply_fun (show S → P from h) at e - simp only [h.map_mul, h.apply_symm_apply, h.commutes] at e + simp only [map_mul, h.apply_symm_apply, h.commutes] at e exact ⟨⟨x, s⟩, e⟩ · intro x y rw [← h.symm.toEquiv.injective.eq_iff, ← IsLocalization.eq_iff_exists M S, ← h.symm.commutes, ← diff --git a/Mathlib/RingTheory/PowerBasis.lean b/Mathlib/RingTheory/PowerBasis.lean index 75ac0435335e2c..7f724c64b8666e 100644 --- a/Mathlib/RingTheory/PowerBasis.lean +++ b/Mathlib/RingTheory/PowerBasis.lean @@ -462,7 +462,7 @@ noncomputable def map (pb : PowerBasis R S) (e : S ≃ₐ[R] S') : PowerBasis R dim := pb.dim basis := pb.basis.map e.toLinearEquiv gen := e pb.gen - basis_eq_pow i := by rw [Basis.map_apply, pb.basis_eq_pow, e.toLinearEquiv_apply, e.map_pow] + basis_eq_pow i := by rw [Basis.map_apply, pb.basis_eq_pow, e.toLinearEquiv_apply, map_pow] #align power_basis.map PowerBasis.map variable [Algebra A S] [Algebra A S'] @@ -473,7 +473,7 @@ theorem minpolyGen_map (pb : PowerBasis A S) (e : S ≃ₐ[A] S') : dsimp only [minpolyGen, map_dim] -- Turn `Fin (pb.map e).dim` into `Fin pb.dim` simp only [LinearEquiv.trans_apply, map_basis, Basis.map_repr, map_gen, - AlgEquiv.toLinearEquiv_apply, e.toLinearEquiv_symm, AlgEquiv.map_pow, + AlgEquiv.toLinearEquiv_apply, e.toLinearEquiv_symm, map_pow, AlgEquiv.symm_apply_apply, sub_right_inj] #align power_basis.minpoly_gen_map PowerBasis.minpolyGen_map diff --git a/Mathlib/RingTheory/RootsOfUnity/Basic.lean b/Mathlib/RingTheory/RootsOfUnity/Basic.lean index a74fcb46da0b13..6374f1a371ec3d 100644 --- a/Mathlib/RingTheory/RootsOfUnity/Basic.lean +++ b/Mathlib/RingTheory/RootsOfUnity/Basic.lean @@ -1056,7 +1056,7 @@ noncomputable def autToPow : (S ≃ₐ[R] S) →* (ZMod n)ˣ := dsimp only [μ', AlgEquiv.toRingEquiv_eq_coe, RingEquiv.toRingHom_eq_coe, RingEquiv.coe_toRingHom, AlgEquiv.coe_ringEquiv, AlgEquiv.mul_apply] at * replace hxy : x (((μ' : Sˣ) : S) ^ hy'.choose) = ((μ' : Sˣ) : S) ^ hxy'.choose := hy ▸ hxy - rw [x.map_pow] at hxy + rw [map_pow] at hxy replace hxy : (((μ' : Sˣ) : S) ^ hx'.choose) ^ hy'.choose = ((μ' : Sˣ) : S) ^ hxy'.choose := hx ▸ hxy rw [← pow_mul] at hxy From ab0de47a15970636867ab3bea74476a1264ffbb2 Mon Sep 17 00:00:00 2001 From: Fabrizio Barroero Date: Sat, 22 Jun 2024 09:09:18 +0000 Subject: [PATCH 05/19] feat(NumberTheory/SiegelsLemma): Siegel's lemma for small integral non-trivial solutions of linear systems (#13487) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the proof of [Siegel's Lemma](https://en.wikipedia.org/wiki/Siegel%27s_lemma). This is a fundamental tool in diophantine approximation and transcendency and says that there exists a "small" integral non-zero solution of a non-trivial underdetermined system of linear equations with integer coefficients. theorem `exists_ne_zero_int_vec_norm_le`: Given a non-singular `m × n` matrix `A` with `m < n` the linear system it determines has a non-zero integer solution `t` with `‖t‖ ≤ ((n * ‖A‖) ^ ((m : ℝ) / (n - m)))` [Zulip thread](https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Siegel's.20Lemma) Co-authored-by: Laura Capuano and Amos Turchet @amosturchet --- Mathlib.lean | 1 + Mathlib/NumberTheory/SiegelsLemma.lean | 205 +++++++++++++++++++++++++ docs/references.bib | 11 ++ 3 files changed, 217 insertions(+) create mode 100644 Mathlib/NumberTheory/SiegelsLemma.lean diff --git a/Mathlib.lean b/Mathlib.lean index 15709eedd0f120..5009a8d559f4ef 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3229,6 +3229,7 @@ import Mathlib.NumberTheory.Primorial import Mathlib.NumberTheory.PythagoreanTriples import Mathlib.NumberTheory.RamificationInertia import Mathlib.NumberTheory.Rayleigh +import Mathlib.NumberTheory.SiegelsLemma import Mathlib.NumberTheory.SmoothNumbers import Mathlib.NumberTheory.SumFourSquares import Mathlib.NumberTheory.SumPrimeReciprocals diff --git a/Mathlib/NumberTheory/SiegelsLemma.lean b/Mathlib/NumberTheory/SiegelsLemma.lean new file mode 100644 index 00000000000000..a578dc7dbc450a --- /dev/null +++ b/Mathlib/NumberTheory/SiegelsLemma.lean @@ -0,0 +1,205 @@ +/- +Copyright (c) 2024 Fabrizio Barroero. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Fabrizio Barroero, Laura Capuano, Amos Turchet +-/ +import Mathlib.Analysis.Matrix +import Mathlib.Data.Pi.Interval +import Mathlib.Tactic.Rify + +/-! +# Siegel's Lemma + +In this file we introduce and prove Siegel's Lemma in its most basic version. This is a fundamental +tool in diophantine approximation and transcendency and says that there exists a "small" integral +non-zero solution of a non-trivial underdetermined system of linear equations with integer +coefficients. + +## Main results + +- `exists_ne_zero_int_vec_norm_le`: Given a non-zero `m × n` matrix `A` with `m < n` the linear +system it determines has a non-zero integer solution `t` with +`‖t‖ ≤ ((n * ‖A‖) ^ ((m : ℝ) / (n - m)))` + +## Notation + + - `‖_‖ ` : Matrix.seminormedAddCommGroup is the sup norm, the maximum of the absolute values of + the entries of the matrix + +## References + +See [M. Hindry and J. Silverman, Diophantine Geometry: an Introduction][hindrysilverman00]. +-/ + +/-We set ‖⬝‖ to be Matrix.seminormedAddCommGroup -/ +attribute [local instance] Matrix.seminormedAddCommGroup + +open Matrix Finset + +namespace Int.Matrix + +variable (m n : ℕ) (A : Matrix (Fin m) (Fin n) ℤ) (v : Fin n → ℤ) (hn : m < n) +(hm : 0 < m) + +--Some definitions and relative properties + +local notation3 "e" => m / ((n : ℝ) - m) --exponent +local notation3 "B" => Nat.floor (((n : ℝ) * ‖A‖) ^ e) +--B' is the vector with all components = B +local notation3 "B'" => fun _ : Fin n => (B : ℤ) +--T is the box [0 B]^n +local notation3 "T" => Finset.Icc 0 B' +local notation3 "P" => fun i : Fin m => ∑ j : Fin n, B * posPart (A i j) +local notation3 "N" => fun i : Fin m => ∑ j : Fin n, B * (- negPart (A i j)) +--S is the box where the image of T goes +local notation3 "S" => Finset.Icc N P + +section preparation + +/- In order to apply Pigeohole we need: +# Step 1: ∀ v ∈ T, A *ᵥ v ∈ S +and +# Step 2: S.card < T.card +Pigeohole will give different x and y in T with A.mulVec x = A.mulVec y in S +Their difference is the solution we are looking for +-/ + +--# Step 1: ∀ v ∈ T, A *ᵥ v ∈ S + +private lemma image_T_subset_S : ∀ v ∈ T, A *ᵥ v ∈ S := by + intro v hv + rw [mem_Icc] at hv + rw [mem_Icc] + have mulVec_def : A.mulVec v = + fun i ↦ Finset.sum univ fun j : Fin n ↦ A i j * v j := by rfl + rw [mulVec_def] --unfold def of MulVec + refine ⟨fun i ↦ ?_, fun i ↦ ?_⟩ --2 goals + all_goals + simp only [mul_neg] + gcongr ∑ _ : Fin n, ?_ with j _ --get rid of sums + rw [← mul_comm (v j)] --move A i j to the right of the products + rcases le_total 0 (A i j) with hsign | hsign--we have to distinguish cases: we have now 4 goals + · rw [negPart_eq_zero.2 hsign] + exact mul_nonneg (hv.1 j) hsign + · rw [negPart_eq_neg.2 hsign] + simp only [mul_neg, neg_neg] + exact mul_le_mul_of_nonpos_right (hv.2 j) hsign + · rw [posPart_eq_self.2 hsign] + exact mul_le_mul_of_nonneg_right (hv.2 j) hsign + · rw [posPart_eq_zero.2 hsign] + exact mul_nonpos_of_nonneg_of_nonpos (hv.1 j) hsign + +--# Preparation for Step 2 + +private lemma card_T_eq : (T).card = (B + 1) ^ n := by + rw [Pi.card_Icc 0 B'] + simp only [Pi.zero_apply, Int.card_Icc, sub_zero, Int.toNat_ofNat_add_one, prod_const, card_fin] + +--This lemma is necessary to be able to apply the formula (Icc a b).card = b + 1 - a +private lemma N_le_P_add_one (i : Fin m) : N i ≤ P i + 1 := by + calc N i + _ ≤ 0 := by + apply Finset.sum_nonpos + intro j _ + simp only [mul_neg, Left.neg_nonpos_iff] + exact mul_nonneg (Nat.cast_nonneg B) (negPart_nonneg (A i j)) + _ ≤ P i + 1 := by + apply le_trans (Finset.sum_nonneg _) (Int.le_add_one (le_refl P i)) + intro j _ + exact mul_nonneg (Nat.cast_nonneg B) (posPart_nonneg (A i j)) + +private lemma card_S_eq : (Finset.Icc N P).card = ∏ i : Fin m, (P i - N i + 1) := by + rw [Pi.card_Icc N P, Nat.cast_prod] + congr + ext i + rw [Int.card_Icc_of_le (N i) (P i) (N_le_P_add_one m n A i)] + exact add_sub_right_comm (P i) 1 (N i) + +variable (hA : A ≠ 0) + +/--The sup norm of a non-zero integer matrix is at lest one -/ +lemma one_le_norm_A_of_ne_zero : 1 ≤ ‖A‖ := by + by_contra! h + apply hA + ext i j + simp only [zero_apply] + rw [norm_lt_iff Real.zero_lt_one] at h + specialize h i j + rw [Int.norm_eq_abs] at h + norm_cast at h + exact Int.abs_lt_one_iff.1 h + +--# Step 2: S.card < T.card + +open Real Nat + +private lemma card_S_lt_card_T : (S).card < (T).card := by + zify --this is necessary to use card_S_eq + rw [card_T_eq, card_S_eq] + rify --this is necessary because ‖A‖ is a real number + calc + ∏ x : Fin m, (∑ x_1 : Fin n, ↑B * ↑(A x x_1)⁺ - ∑ x_1 : Fin n, ↑B * -↑(A x x_1)⁻ + 1) + ≤ (n * ‖A‖ * B + 1) ^ m := by + rw [← Fin.prod_const m (n * ‖A‖ * B + 1)] --transform ^m into a product + refine Finset.prod_le_prod (fun i _ ↦ ?_) (fun i _ ↦ ?_) + · have h := N_le_P_add_one m n A i + rify at h + linarith only [h] + · simp only [mul_neg, sum_neg_distrib, sub_neg_eq_add, add_le_add_iff_right] + have h1 : n * ‖A‖ * B = ∑ _ : Fin n, ‖A‖ * B := by + simp only [sum_const, card_univ, Fintype.card_fin, nsmul_eq_mul, mul_assoc ↑n ‖A‖ ↑B] + simp_rw [h1, ← Finset.sum_add_distrib, ← mul_add, mul_comm ‖A‖, ← Int.cast_add] + gcongr with j _ + rw [posPart_add_negPart (A i j), Int.cast_abs] + exact norm_entry_le_entrywise_sup_norm A + _ ≤ (n * ‖A‖) ^ m * (B + 1) ^ m := by + rw [← mul_pow, mul_add, mul_one] + gcongr + have H : 1 ≤ (n : ℝ) := mod_cast (hm.trans hn) + exact one_le_mul_of_one_le_of_one_le H <| one_le_norm_A_of_ne_zero m n A hA + _ = ((n * ‖A‖) ^ (m / ((n : ℝ) - m))) ^ ((n : ℝ) - m) * (B + 1) ^ m := by + congr 1 + rw [← rpow_mul (mul_nonneg n.cast_nonneg (norm_nonneg A)), ← Real.rpow_natCast, + div_mul_cancel₀] + exact sub_ne_zero_of_ne (mod_cast hn.ne') + _ < (B + 1) ^ ((n : ℝ) - m) * (B + 1) ^ m := by + gcongr + · exact sub_pos.mpr (mod_cast hn) + · exact Nat.lt_floor_add_one ((n * ‖A‖) ^ e) + _ = (B + 1) ^ n := by + rw [← rpow_natCast, ← rpow_add (Nat.cast_add_one_pos B), ← rpow_natCast, sub_add_cancel] + +end preparation + +theorem exists_ne_zero_int_vec_norm_le (hA_nezero : A ≠ 0) : ∃ t : Fin n → ℤ, t ≠ 0 ∧ + A *ᵥ t = 0 ∧ ‖t‖ ≤ (n * ‖A‖) ^ ((m : ℝ) / (n - m)) := by + --Pigeonhole + rcases Finset.exists_ne_map_eq_of_card_lt_of_maps_to + (card_S_lt_card_T m n A hn hm hA_nezero) (image_T_subset_S m n A) + with ⟨x, hxT, y, hyT, hneq, hfeq⟩ + --proofs that x - y ≠ 0 and x - y is a solution + refine ⟨x - y, sub_ne_zero.mpr hneq, by simp only [mulVec_sub, sub_eq_zero, hfeq], ?_⟩ + --Inequality + have n_mul_norm_A_pow_e_nonneg : 0 ≤ (n * ‖A‖) ^ e := by positivity + rw [← norm_col (ι := Unit), norm_le_iff n_mul_norm_A_pow_e_nonneg] + intro i j + simp only [col_apply, Pi.sub_apply] + rw [Int.norm_eq_abs, ← Int.cast_abs] + refine le_trans ?_ (Nat.floor_le n_mul_norm_A_pow_e_nonneg) + norm_cast + rw [abs_le] + rw [Finset.mem_Icc] at hyT + rw [Finset.mem_Icc] at hxT + constructor --two goals + · simp only [neg_le_sub_iff_le_add] + apply le_trans (hyT.2 i) + norm_cast + simp only [le_add_iff_nonneg_left] + exact hxT.1 i + · simp only [tsub_le_iff_right] + apply le_trans (hxT.2 i) + norm_cast + simp only [le_add_iff_nonneg_right] + exact hyT.1 i + +end Int.Matrix diff --git a/docs/references.bib b/docs/references.bib index 76282dabfa43f1..e0e2b43497b1c3 100644 --- a/docs/references.bib +++ b/docs/references.bib @@ -1745,6 +1745,17 @@ @Article{ Higman52 year = {1952} } +@Book{ hindrysilverman00, + author = {Hindry, Marc and Silverman, Joseph H.}, + title = {Diophantine geometry}, + series = {Graduate Texts in Mathematics}, + volume = {201}, + note = {An introduction}, + publisher = {Springer-Verlag, New York}, + year = {2000}, + pages = {xiv+558} +} + @Unpublished{ hochsterunpublished, title = {Local cohomology}, author = {Hochster, Mel}, From ca53aab4db182b0f3b5b23989903e2e212129474 Mon Sep 17 00:00:00 2001 From: Christian Merten Date: Sat, 22 Jun 2024 09:37:04 +0000 Subject: [PATCH 06/19] feat: unramified, smooth, etale are stable under base change (#14020) --- Mathlib/RingTheory/Etale/Basic.lean | 12 +++++------- Mathlib/RingTheory/Smooth/Basic.lean | 13 ++++++------- Mathlib/RingTheory/Unramified/Basic.lean | 12 ++++++------ 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/Mathlib/RingTheory/Etale/Basic.lean b/Mathlib/RingTheory/Etale/Basic.lean index 19c29826e3e24c..a28628cc562b4b 100644 --- a/Mathlib/RingTheory/Etale/Basic.lean +++ b/Mathlib/RingTheory/Etale/Basic.lean @@ -24,10 +24,6 @@ under `R`-algebra homomorphisms and compositions. We show that étale is stable under algebra isomorphisms, composition and localization at an element. -## TODO: - -- Show that étale is stable under base change. - -/ @@ -182,13 +178,15 @@ theorem of_equiv [Etale R A] (e : A ≃ₐ[R] B) : Etale R B where section Comp variable (R A B) -variable [Algebra A B] [IsScalarTower R A B] -/-- Étale is stable under composition. -/ -theorem comp [Etale R A] [Etale A B] : Etale R B where +/-- Etale is stable under composition. -/ +theorem comp [Algebra A B] [IsScalarTower R A B] [Etale R A] [Etale A B] : Etale R B where formallyEtale := FormallyEtale.comp R A B finitePresentation := FinitePresentation.trans R A B +/-- Etale is stable under base change. -/ +instance baseChange [Etale R A] : Etale B (B ⊗[R] A) where + end Comp /-- Localization at an element is étale. -/ diff --git a/Mathlib/RingTheory/Smooth/Basic.lean b/Mathlib/RingTheory/Smooth/Basic.lean index 6a2915ed4c6a39..ccd27008af34c3 100644 --- a/Mathlib/RingTheory/Smooth/Basic.lean +++ b/Mathlib/RingTheory/Smooth/Basic.lean @@ -7,8 +7,10 @@ import Mathlib.RingTheory.Ideal.Cotangent import Mathlib.RingTheory.QuotientNilpotent import Mathlib.RingTheory.TensorProduct.Basic import Mathlib.RingTheory.FinitePresentation +import Mathlib.RingTheory.FiniteStability import Mathlib.RingTheory.Localization.Away.Basic import Mathlib.RingTheory.Localization.Away.AdjoinRoot + #align_import ring_theory.etale from "leanprover-community/mathlib"@"73f96237417835f148a1f7bc1ff55f67119b7166" /-! @@ -26,11 +28,6 @@ and that it is stable under `R`-algebra homomorphisms and compositions. We show that smooth is stable under algebra isomorphisms, composition and localization at an element. - -# TODO - -- Show that smooth is stable under base change. - -/ -- Porting note: added to make the syntax work below. @@ -384,13 +381,15 @@ theorem of_isLocalization_Away (r : R) [IsLocalization.Away r A] : Smooth R A wh section Comp variable (R A B) -variable [Algebra A B] [IsScalarTower R A B] /-- Smooth is stable under composition. -/ -theorem comp [Smooth R A] [Smooth A B] : Smooth R B where +theorem comp [Algebra A B] [IsScalarTower R A B] [Smooth R A] [Smooth A B] : Smooth R B where formallySmooth := FormallySmooth.comp R A B finitePresentation := FinitePresentation.trans R A B +/-- Smooth is stable under base change. -/ +instance baseChange [Smooth R A] : Smooth B (B ⊗[R] A) where + end Comp end Smooth diff --git a/Mathlib/RingTheory/Unramified/Basic.lean b/Mathlib/RingTheory/Unramified/Basic.lean index 11a8b636bde53c..ffbb840132e10a 100644 --- a/Mathlib/RingTheory/Unramified/Basic.lean +++ b/Mathlib/RingTheory/Unramified/Basic.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ import Mathlib.RingTheory.FinitePresentation +import Mathlib.RingTheory.FiniteStability import Mathlib.RingTheory.Localization.Away.Basic import Mathlib.RingTheory.Localization.Away.AdjoinRoot import Mathlib.RingTheory.QuotientNilpotent @@ -28,10 +29,6 @@ under `R`-algebra homomorphisms and compositions. We show that unramified is stable under algebra isomorphisms, composition and localization at an element. -# TODO - -- Show that unramified is stable under base change. - -/ -- Porting note: added to make the syntax work below. @@ -266,14 +263,17 @@ theorem of_isLocalization_Away (r : R) [IsLocalization.Away r A] : Unramified R section Comp variable (R A B) -variable [Algebra A B] [IsScalarTower R A B] /-- Unramified is stable under composition. -/ -theorem comp [Unramified R A] [Unramified A B] : Unramified R B where +theorem comp [Algebra A B] [IsScalarTower R A B] [Unramified R A] [Unramified A B] : + Unramified R B where formallyUnramified := FormallyUnramified.comp R A B finiteType := FiniteType.trans (S := A) Unramified.finiteType Unramified.finiteType +/-- Unramified is stable under base change. -/ +instance baseChange [Unramified R A] : Unramified B (B ⊗[R] A) where + end Comp end Unramified From eb89176fcdea78ebc70f2033cae58d4a510461f3 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Sat, 22 Jun 2024 09:56:28 +0000 Subject: [PATCH 07/19] =?UTF-8?q?feat(*):=20add=20lemmas=20about=20`(=5F?= =?UTF-8?q?=20:=20UniformSpace=20=5F)=20=3D=20=E2=8A=A5`=20(#13481)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Mathlib/Analysis/Normed/Group/Basic.lean | 7 +++++++ Mathlib/Topology/MetricSpace/PseudoMetric.lean | 13 +++++++++++++ Mathlib/Topology/UniformSpace/Basic.lean | 8 ++++++++ 3 files changed, 28 insertions(+) diff --git a/Mathlib/Analysis/Normed/Group/Basic.lean b/Mathlib/Analysis/Normed/Group/Basic.lean index 8e9ed66b510e22..f3ec5453a417d4 100644 --- a/Mathlib/Analysis/Normed/Group/Basic.lean +++ b/Mathlib/Analysis/Normed/Group/Basic.lean @@ -402,6 +402,13 @@ alias dist_eq_norm := dist_eq_norm_sub alias dist_eq_norm' := dist_eq_norm_sub' #align dist_eq_norm' dist_eq_norm' +@[to_additive of_forall_le_norm] +lemma DiscreteTopology.of_forall_le_norm' (hpos : 0 < r) (hr : ∀ x : E, x ≠ 1 → r ≤ ‖x‖) : + DiscreteTopology E := + .of_forall_le_dist hpos fun x y hne ↦ by + simp only [dist_eq_norm_div] + exact hr _ (div_ne_one.2 hne) + @[to_additive (attr := simp)] theorem dist_one_right (a : E) : dist a 1 = ‖a‖ := by rw [dist_eq_norm_div, div_one] #align dist_one_right dist_one_right diff --git a/Mathlib/Topology/MetricSpace/PseudoMetric.lean b/Mathlib/Topology/MetricSpace/PseudoMetric.lean index b23e6dcb772f40..d34a2343676380 100644 --- a/Mathlib/Topology/MetricSpace/PseudoMetric.lean +++ b/Mathlib/Topology/MetricSpace/PseudoMetric.lean @@ -1147,10 +1147,23 @@ nonrec theorem _root_.DenseRange.exists_dist_lt {β : Type*} {f : β → α} (hf exists_range_iff.1 (hf.exists_dist_lt x hε) #align dense_range.exists_dist_lt DenseRange.exists_dist_lt +/-- (Pseudo) metric space has discrete `UniformSpace` structure +iff the distances between distinct points are uniformly bounded away from zero. -/ +protected lemma uniformSpace_eq_bot : + ‹PseudoMetricSpace α›.toUniformSpace = ⊥ ↔ + ∃ r : ℝ, 0 < r ∧ Pairwise (r ≤ dist · · : α → α → Prop) := by + simp only [uniformity_basis_dist.uniformSpace_eq_bot, mem_setOf_eq, not_lt] + end Metric open Metric +/-- If the distances between distinct points in a (pseudo) metric space +are uniformly bounded away from zero, then the space has discrete topology. -/ +lemma DiscreteTopology.of_forall_le_dist {α} [PseudoMetricSpace α] {r : ℝ} (hpos : 0 < r) + (hr : Pairwise (r ≤ dist · · : α → α → Prop)) : DiscreteTopology α := + ⟨by rw [Metric.uniformSpace_eq_bot.2 ⟨r, hpos, hr⟩, UniformSpace.toTopologicalSpace_bot]⟩ + /- Instantiate a pseudometric space as a pseudoemetric space. Before we can state the instance, we need to show that the uniform structure coming from the edistance and the distance coincide. -/ diff --git a/Mathlib/Topology/UniformSpace/Basic.lean b/Mathlib/Topology/UniformSpace/Basic.lean index 28b569d8f98170..1e14413fa5818a 100644 --- a/Mathlib/Topology/UniformSpace/Basic.lean +++ b/Mathlib/Topology/UniformSpace/Basic.lean @@ -1322,6 +1322,14 @@ theorem toTopologicalSpace_comap {f : α → β} {u : UniformSpace β} : rfl #align to_topological_space_comap UniformSpace.toTopologicalSpace_comap +lemma uniformSpace_eq_bot {u : UniformSpace α} : u = ⊥ ↔ idRel ∈ 𝓤[u] := + le_bot_iff.symm.trans le_principal_iff + +protected lemma _root_.Filter.HasBasis.uniformSpace_eq_bot {ι p} {s : ι → Set (α × α)} + {u : UniformSpace α} (h : 𝓤[u].HasBasis p s) : + u = ⊥ ↔ ∃ i, p i ∧ Pairwise fun x y : α ↦ (x, y) ∉ s i := by + simp [uniformSpace_eq_bot, h.mem_iff, subset_def, Pairwise, not_imp_not] + theorem toTopologicalSpace_bot : @UniformSpace.toTopologicalSpace α ⊥ = ⊥ := rfl #align to_topological_space_bot UniformSpace.toTopologicalSpace_bot From e19c07e6753d1d2844a1849a0077a6c9ad2d8676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Serr=C3=A9?= Date: Sat, 22 Jun 2024 12:48:31 +0000 Subject: [PATCH 08/19] feat(MeasureTheory/Function/ConditionalExpectation): relax `integral_condexp` assumption and add `integral_condexp_indicator` (#13932) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the `Integrable` assumption of `integral_condexp` and add the total probability law using `condexp` as conditional probability. Co-authored-by: Gaëtan Serré <56162277+gaetanserre@users.noreply.github.com> --- .../ConditionalExpectation/Basic.lean | 20 ++++++++++++------- .../Function/ConditionalExpectation/Real.lean | 2 +- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean index af712704ff225f..42e8d24fee3e3a 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean @@ -226,13 +226,21 @@ 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)] (hf : Integrable f μ) : +theorem integral_condexp (hm : m ≤ m0) [hμm : SigmaFinite (μ.trim hm)] : ∫ x, (μ[f|m]) x ∂μ = ∫ x, f x ∂μ := by - suffices ∫ x in Set.univ, (μ[f|m]) x ∂μ = ∫ x in Set.univ, f x ∂μ by - simp_rw [integral_univ] at this; exact this - exact setIntegral_condexp hm hf (@MeasurableSet.univ _ m) + by_cases hf : Integrable f μ + · suffices ∫ x in Set.univ, (μ[f|m]) x ∂μ = ∫ x in Set.univ, f x ∂μ by + simp_rw [integral_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] #align measure_theory.integral_condexp MeasureTheory.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] + /-- **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]`. -/ @@ -259,12 +267,10 @@ theorem condexp_bot' [hμ : NeZero μ] (f : α → F') : rw [condexp_of_not_sigmaFinite bot_le h] simp only [hμ_finite, ENNReal.top_toReal, inv_zero, zero_smul] rfl - by_cases hf : Integrable f μ - swap; · rw [integral_undef hf, smul_zero, condexp_undef hf]; rfl 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 hf + 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] diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean index f9964a4a78ec72..7651a83a90793e 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean @@ -79,7 +79,7 @@ theorem snorm_one_condexp_le_snorm (f : α → ℝ) : snorm (μ[f|m]) 1 μ ≤ s (stronglyMeasurable_condexp.mono hm).aestronglyMeasurable, ← integral_norm_eq_lintegral_nnnorm hf.1] simp_rw [Real.norm_eq_abs] - rw [← integral_condexp hm hf.abs] + rw (config := {occs := .pos [2]}) [← integral_condexp hm] refine integral_congr_ae ?_ have : 0 ≤ᵐ[μ] μ[(|f|)|m] := by rw [← condexp_zero] From 5c1bf5e7e26c6b1e9ea246331b58d23e4d0a991c Mon Sep 17 00:00:00 2001 From: Andrew Yang Date: Sat, 22 Jun 2024 13:56:49 +0000 Subject: [PATCH 09/19] chore(AlgebraicGeometry): Fix wrong names (#14021) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `PrimeSpectrum.IsPrime` -> `PrimeSpectrum.isPrime` `PrimeSpectrum.vanishingIdeal_univ` -> `PrimeSpectrum.vanishingIdeal_empty` `isAffineAffineScheme` -> `isAffine_affineScheme` `SpecIsAffine` -> `isAffine_Spec` `isAffineOfIso` -> `isAffine_of_isIso` `rangeIsAffineOpenOfOpenImmersion` -> `isAffineOpen_opensRange` `topIsAffineOpen` -> `isAffineOpen_top` `Scheme.affineCoverIsAffine` -> `Scheme.isAffine_affineCover` `Scheme.affineBasisCoverIsAffine` -> `Scheme.isAffine_affineBasisCover` `IsAffineOpen.fromSpec_range` -> `IsAffineOpen.range_fromSpec` `IsAffineOpen.imageIsOpenImmersion` -> `IsAffineOpen.image_of_isOpenImmersion` `Scheme.quasi_compact_of_affine` -> `Scheme.compactSpace_of_isAffine` `IsAffineOpen.fromSpec_base_preimage` -> `IsAffineOpen.fromSpec_preimage_self` `IsAffineOpen.fromSpec_map_basicOpen'` -> `IsAffineOpen.fromSpec_preimage_basicOpen'` `IsAffineOpen.fromSpec_map_basicOpen` -> `IsAffineOpen.fromSpec_preimage_basicOpen` `IsAffineOpen.opensFunctor_map_basicOpen` -> `IsAffineOpen.fromSpec_image_basicOpen` `IsAffineOpen.basicOpenIsAffine` -> `IsAffineOpen.basicOpen` `IsAffineOpen.mapRestrictBasicOpen` -> `IsAffineOpen.ιOpens_preimage` `AffineTargetMorphismProperty.IsLocal.targetAffineLocallyIsLocal` -> `AffineTargetMorphismProperty.IsLocal.targetAffineLocally_isLocal` `AffineTargetMorphismProperty.IsLocal.targetAffineLocallyPullbackFstOfRightOfStableUnderBaseChange` -> `AffineTargetMorphismProperty.IsLocal.targetAffineLocally_pullback_fst_of_right_of_stableUnderBaseChange` `diagonalTargetAffineLocallyOfOpenCover` -> `diagonal_targetAffineLocally_of_openCover` `AffineTargetMorphismProperty.diagonalOfTargetAffineLocally` -> `AffineTargetMorphismProperty.diagonal_of_targetAffineLocally` `universallyIsLocalAtTarget` -> `universally_isLocalAtTarget` `universallyIsLocalAtTargetOfMorphismRestrict` -> `universally_isLocalAtTarget_of_morphismRestrict` `bot_isAffineOpen` -> `isAffineOpen_bot` `isOpenImmersion_is_local_at_target` -> `isOpenImmersion_isLocalAtTarget` `QuasiCompact.is_local_at_target` -> `QuasiCompact.isLocalAtTarget` `QuasiSeparated.is_local_at_target` -> `QuasiSeparated.isLocalAtTarget` `universallyClosed_is_local_at_target` -> `universallyClosed_isLocalAtTarget` `isReducedOfStalkIsReduced` -> `isReduced_of_isReduced_stalk` `stalk_isReduced_of_reduced` -> `isReduced_stalk_of_isReduced` `isReducedOfOpenImmersion` -> `isReduced_of_isOpenImmersion` `isReducedOfIsAffineIsReduced` -> `isReduced_of_isAffine_isReduced` `isReducedOfIsIntegral` -> `isReduced_of_isIntegral` `is_irreducible_of_isIntegral` -> `irreducibleSpace_of_isIntegral` `isIntegralOfIsIrreducibleIsReduced` -> `isIntegral_of_irreducibleSpace_of_isReduced` `isIntegral_iff_is_irreducible_and_isReduced` -> `isIntegral_iff_irreducibleSpace_and_isReduced` `isIntegralOfOpenImmersion` -> `isIntegral_of_isOpenImmersion` `isIntegralOfIsAffineIsDomain` -> `isIntegral_of_isAffine_of_isDomain` --- Mathlib/AlgebraicGeometry/AffineScheme.lean | 160 +++++++++++------- Mathlib/AlgebraicGeometry/FunctionField.lean | 8 +- Mathlib/AlgebraicGeometry/Limits.lean | 10 +- .../AlgebraicGeometry/Morphisms/Basic.lean | 93 ++++++---- .../Morphisms/OpenImmersion.lean | 8 +- .../Morphisms/QuasiCompact.lean | 16 +- .../Morphisms/QuasiSeparated.lean | 16 +- .../Morphisms/RingHomProperties.lean | 16 +- .../Morphisms/UniversallyClosed.lean | 8 +- .../PrimeSpectrum/Basic.lean | 18 +- .../PrimeSpectrum/IsOpenComapC.lean | 2 +- .../ProjectiveSpectrum/Scheme.lean | 2 +- Mathlib/AlgebraicGeometry/Properties.lean | 53 +++--- Mathlib/AlgebraicGeometry/Pullbacks.lean | 2 +- Mathlib/AlgebraicGeometry/StructureSheaf.lean | 8 +- Mathlib/RingTheory/DedekindDomain/Ideal.lean | 2 +- 16 files changed, 243 insertions(+), 179 deletions(-) diff --git a/Mathlib/AlgebraicGeometry/AffineScheme.lean b/Mathlib/AlgebraicGeometry/AffineScheme.lean index 117b0d2f979bae..3775c8aec7f600 100644 --- a/Mathlib/AlgebraicGeometry/AffineScheme.lean +++ b/Mathlib/AlgebraicGeometry/AffineScheme.lean @@ -37,6 +37,9 @@ We also define predicates about affine schemes and affine open sets. set_option linter.uppercaseLean3 false +set_option allowUnsafeReducibility true in +attribute [local reducible] Quiver.Hom + noncomputable section open CategoryTheory CategoryTheory.Limits Opposite TopologicalSpace @@ -91,17 +94,17 @@ theorem mem_Spec_essImage (X : Scheme) : X ∈ Scheme.Spec.essImage ↔ IsAffine fun _ => ΓSpec.adjunction.mem_essImage_of_unit_isIso _⟩ #align algebraic_geometry.mem_Spec_ess_image AlgebraicGeometry.mem_Spec_essImage -instance isAffineAffineScheme (X : AffineScheme.{u}) : IsAffine X.obj := +instance isAffine_affineScheme (X : AffineScheme.{u}) : IsAffine X.obj := ⟨Functor.essImage.unit_isIso X.property⟩ -#align algebraic_geometry.is_affine_AffineScheme AlgebraicGeometry.isAffineAffineScheme +#align algebraic_geometry.is_affine_AffineScheme AlgebraicGeometry.isAffine_affineScheme -instance SpecIsAffine (R : CommRingCatᵒᵖ) : IsAffine (Scheme.Spec.obj R) := - AlgebraicGeometry.isAffineAffineScheme ⟨_, Scheme.Spec.obj_mem_essImage R⟩ -#align algebraic_geometry.Spec_is_affine AlgebraicGeometry.SpecIsAffine +instance isAffine_Spec (R : CommRingCatᵒᵖ) : IsAffine (Scheme.Spec.obj R) := + AlgebraicGeometry.isAffine_affineScheme ⟨_, Scheme.Spec.obj_mem_essImage R⟩ +#align algebraic_geometry.Spec_is_affine AlgebraicGeometry.isAffine_Spec -theorem isAffineOfIso {X Y : Scheme} (f : X ⟶ Y) [IsIso f] [h : IsAffine Y] : IsAffine X := by +theorem isAffine_of_isIso {X Y : Scheme} (f : X ⟶ Y) [IsIso f] [h : IsAffine Y] : IsAffine X := by rw [← mem_Spec_essImage] at h ⊢; exact Functor.essImage.ofIso (asIso f).symm h -#align algebraic_geometry.is_affine_of_iso AlgebraicGeometry.isAffineOfIso +#align algebraic_geometry.is_affine_of_iso AlgebraicGeometry.isAffine_of_isIso namespace AffineScheme @@ -185,27 +188,27 @@ instance {Y : Scheme.{u}} (U : Y.affineOpens) : IsAffine (Scheme.restrict Y <| Opens.openEmbedding U.val) := U.property -theorem rangeIsAffineOpenOfOpenImmersion {X Y : Scheme} [IsAffine X] (f : X ⟶ Y) +theorem isAffineOpen_opensRange {X Y : Scheme} [IsAffine X] (f : X ⟶ Y) [H : IsOpenImmersion f] : IsAffineOpen (Scheme.Hom.opensRange f) := by - refine isAffineOfIso (IsOpenImmersion.isoOfRangeEq f (Y.ofRestrict _) ?_).inv + refine isAffine_of_isIso (IsOpenImmersion.isoOfRangeEq f (Y.ofRestrict _) ?_).inv exact Subtype.range_val.symm -#align algebraic_geometry.range_is_affine_open_of_open_immersion AlgebraicGeometry.rangeIsAffineOpenOfOpenImmersion +#align algebraic_geometry.range_is_affine_open_of_open_immersion AlgebraicGeometry.isAffineOpen_opensRange -theorem topIsAffineOpen (X : Scheme) [IsAffine X] : IsAffineOpen (⊤ : Opens X) := by - convert rangeIsAffineOpenOfOpenImmersion (𝟙 X) +theorem isAffineOpen_top (X : Scheme) [IsAffine X] : IsAffineOpen (⊤ : Opens X) := by + convert isAffineOpen_opensRange (𝟙 X) ext1 exact Set.range_id.symm -#align algebraic_geometry.top_is_affine_open AlgebraicGeometry.topIsAffineOpen +#align algebraic_geometry.top_is_affine_open AlgebraicGeometry.isAffineOpen_top -instance Scheme.affineCoverIsAffine (X : Scheme) (i : X.affineCover.J) : +instance Scheme.isAffine_affineCover (X : Scheme) (i : X.affineCover.J) : IsAffine (X.affineCover.obj i) := - AlgebraicGeometry.SpecIsAffine _ -#align algebraic_geometry.Scheme.affine_cover_is_affine AlgebraicGeometry.Scheme.affineCoverIsAffine + isAffine_Spec _ +#align algebraic_geometry.Scheme.affine_cover_is_affine AlgebraicGeometry.Scheme.isAffine_affineCover -instance Scheme.affineBasisCoverIsAffine (X : Scheme) (i : X.affineBasisCover.J) : +instance Scheme.isAffine_affineBasisCover (X : Scheme) (i : X.affineBasisCover.J) : IsAffine (X.affineBasisCover.obj i) := - AlgebraicGeometry.SpecIsAffine _ -#align algebraic_geometry.Scheme.affine_basis_cover_is_affine AlgebraicGeometry.Scheme.affineBasisCoverIsAffine + isAffine_Spec _ +#align algebraic_geometry.Scheme.affine_basis_cover_is_affine AlgebraicGeometry.Scheme.isAffine_affineBasisCover theorem isBasis_affine_open (X : Scheme) : Opens.IsBasis X.affineOpens := by rw [Opens.isBasis_iff_nbhd] @@ -213,7 +216,7 @@ theorem isBasis_affine_open (X : Scheme) : Opens.IsBasis X.affineOpens := by obtain ⟨S, hS, hxS, hSU⟩ := X.affineBasisCover_is_basis.exists_subset_of_mem_open hU U.isOpen refine ⟨⟨S, X.affineBasisCover_is_basis.isOpen hS⟩, ?_, hxS, hSU⟩ rcases hS with ⟨i, rfl⟩ - exact rangeIsAffineOpenOfOpenImmersion _ + exact isAffineOpen_opensRange _ #align algebraic_geometry.is_basis_affine_open AlgebraicGeometry.isBasis_affine_open theorem Scheme.map_PrimeSpectrum_basicOpen_of_affine @@ -271,42 +274,42 @@ instance isOpenImmersion_fromSpec : infer_instance #align algebraic_geometry.is_affine_open.is_open_immersion_from_Spec AlgebraicGeometry.IsAffineOpen.isOpenImmersion_fromSpec -theorem fromSpec_range : +theorem range_fromSpec : Set.range hU.fromSpec.1.base = (U : Set X) := by delta IsAffineOpen.fromSpec; dsimp rw [Function.comp.assoc, Set.range_comp, Set.range_iff_surjective.mpr, Set.image_univ] · exact Subtype.range_coe erw [← coe_comp, ← TopCat.epi_iff_surjective] -- now `erw` after #13170 infer_instance -#align algebraic_geometry.is_affine_open.from_Spec_range AlgebraicGeometry.IsAffineOpen.fromSpec_range +#align algebraic_geometry.is_affine_open.from_Spec_range AlgebraicGeometry.IsAffineOpen.range_fromSpec theorem fromSpec_image_top : hU.fromSpec.opensFunctor.obj ⊤ = U := by - ext1; exact Set.image_univ.trans hU.fromSpec_range + ext1; exact Set.image_univ.trans hU.range_fromSpec #align algebraic_geometry.is_affine_open.from_Spec_image_top AlgebraicGeometry.IsAffineOpen.fromSpec_image_top protected theorem isCompact : IsCompact (U : Set X) := by convert @IsCompact.image _ _ _ _ Set.univ hU.fromSpec.1.base PrimeSpectrum.compactSpace.1 (by fun_prop) - convert hU.fromSpec_range.symm + convert hU.range_fromSpec.symm exact Set.image_univ #align algebraic_geometry.is_affine_open.is_compact AlgebraicGeometry.IsAffineOpen.isCompact -theorem imageIsOpenImmersion (f : X ⟶ Y) [H : IsOpenImmersion f] : +theorem image_of_isOpenImmersion (f : X ⟶ Y) [H : IsOpenImmersion f] : IsAffineOpen (f.opensFunctor.obj U) := by have : IsAffine _ := hU - convert rangeIsAffineOpenOfOpenImmersion (X.ofRestrict U.openEmbedding ≫ f) + convert isAffineOpen_opensRange (X.ofRestrict U.openEmbedding ≫ f) ext1 exact Set.image_eq_range _ _ -#align algebraic_geometry.is_affine_open.image_is_open_immersion AlgebraicGeometry.IsAffineOpen.imageIsOpenImmersion +#align algebraic_geometry.is_affine_open.image_is_open_immersion AlgebraicGeometry.IsAffineOpen.image_of_isOpenImmersion theorem _root_.AlgebraicGeometry.Scheme.Hom.isAffineOpen_iff_of_isOpenImmersion (f : AlgebraicGeometry.Scheme.Hom X Y) [H : IsOpenImmersion f] {U : Opens X} : IsAffineOpen (f.opensFunctor.obj U) ↔ IsAffineOpen U := by - refine ⟨fun hU => @isAffineOfIso _ _ + refine ⟨fun hU => @isAffine_of_isIso _ _ (IsOpenImmersion.isoOfRangeEq (X.ofRestrict U.openEmbedding ≫ f) (Y.ofRestrict _) ?_).hom ?_ hU, - fun hU => hU.imageIsOpenImmersion f⟩ + fun hU => hU.image_of_isOpenImmersion f⟩ · erw [Scheme.comp_val_base, coe_comp, Set.range_comp] -- now `erw` after #13170 dsimp [Opens.coe_inclusion, Scheme.restrict] erw [Subtype.range_coe, Subtype.range_coe] -- now `erw` after #13170 @@ -314,17 +317,17 @@ theorem _root_.AlgebraicGeometry.Scheme.Hom.isAffineOpen_iff_of_isOpenImmersion · infer_instance #align algebraic_geometry.is_affine_open_iff_of_is_open_immersion AlgebraicGeometry.Scheme.Hom.isAffineOpen_iff_of_isOpenImmersion -instance _root_.AlgebraicGeometry.Scheme.quasi_compact_of_affine (X : Scheme) [IsAffine X] : +instance _root_.AlgebraicGeometry.Scheme.compactSpace_of_isAffine (X : Scheme) [IsAffine X] : CompactSpace X := - ⟨(topIsAffineOpen X).isCompact⟩ -#align algebraic_geometry.Scheme.quasi_compact_of_affine AlgebraicGeometry.Scheme.quasi_compact_of_affine + ⟨(isAffineOpen_top X).isCompact⟩ +#align algebraic_geometry.Scheme.quasi_compact_of_affine AlgebraicGeometry.Scheme.compactSpace_of_isAffine -theorem fromSpec_base_preimage : +theorem fromSpec_preimage_self : hU.fromSpec ⁻¹ᵁ U = ⊤ := by ext1 - rw [Opens.map_coe, Opens.coe_top, ← hU.fromSpec_range, ← Set.image_univ] + rw [Opens.map_coe, Opens.coe_top, ← hU.range_fromSpec, ← Set.image_univ] exact Set.preimage_image_eq _ PresheafedSpace.IsOpenImmersion.base_open.inj -#align algebraic_geometry.is_affine_open.from_Spec_base_preimage AlgebraicGeometry.IsAffineOpen.fromSpec_base_preimage +#align algebraic_geometry.is_affine_open.from_Spec_base_preimage AlgebraicGeometry.IsAffineOpen.fromSpec_preimage_self #adaptation_note /-- 2024-04-23 The backwards compatibility flags don't help here. -/ @@ -333,7 +336,7 @@ set_option maxHeartbeats 400000 in @[nolint unusedHavesSuffices] theorem SpecΓIdentity_hom_app_fromSpec : SpecΓIdentity.hom.app (X.presheaf.obj <| op U) ≫ hU.fromSpec.1.c.app (op U) = - (𝖲𝗉𝖾𝖼 𝓞ₓ(U)).presheaf.map (eqToHom hU.fromSpec_base_preimage).op := by + (𝖲𝗉𝖾𝖼 𝓞ₓ(U)).presheaf.map (eqToHom hU.fromSpec_preimage_self).op := by have : IsAffine _ := hU delta IsAffineOpen.fromSpec Scheme.isoSpec rw [Scheme.comp_val_c_app, Scheme.comp_val_c_app, SpecΓIdentity_hom_app_presheaf_obj, @@ -348,29 +351,29 @@ theorem SpecΓIdentity_hom_app_fromSpec : @[elementwise] theorem fromSpec_app_self : hU.fromSpec.1.c.app (op U) = SpecΓIdentity.inv.app (X.presheaf.obj <| op U) ≫ - (𝖲𝗉𝖾𝖼 𝓞ₓ(U)).presheaf.map (eqToHom hU.fromSpec_base_preimage).op := by + (𝖲𝗉𝖾𝖼 𝓞ₓ(U)).presheaf.map (eqToHom hU.fromSpec_preimage_self).op := by rw [← hU.SpecΓIdentity_hom_app_fromSpec, ← NatTrans.comp_app_assoc, Iso.inv_hom_id, NatTrans.id_app, Category.id_comp] #align algebraic_geometry.is_affine_open.from_Spec_app_eq AlgebraicGeometry.IsAffineOpen.fromSpec_app_self -theorem fromSpec_map_basicOpen' : +theorem fromSpec_preimage_basicOpen' : hU.fromSpec ⁻¹ᵁ X.basicOpen f = (𝖲𝗉𝖾𝖼 𝓞ₓ(U)).basicOpen (SpecΓIdentity.inv.app (X.presheaf.obj (op U)) f) := by rw [Scheme.preimage_basicOpen, hU.fromSpec_app_self] - exact Scheme.basicOpen_res_eq _ _ (eqToHom hU.fromSpec_base_preimage).op -#align algebraic_geometry.is_affine_open.opens_map_from_Spec_basic_open AlgebraicGeometry.IsAffineOpen.fromSpec_map_basicOpen' + exact Scheme.basicOpen_res_eq _ _ (eqToHom hU.fromSpec_preimage_self).op +#align algebraic_geometry.is_affine_open.opens_map_from_Spec_basic_open AlgebraicGeometry.IsAffineOpen.fromSpec_preimage_basicOpen' -theorem fromSpec_map_basicOpen : +theorem fromSpec_preimage_basicOpen : hU.fromSpec ⁻¹ᵁ X.basicOpen f = PrimeSpectrum.basicOpen f := by - rw [fromSpec_map_basicOpen', ← basicOpen_eq_of_affine, NatIso.app_inv] -#align algebraic_geometry.is_affine_open.from_Spec_map_basic_open AlgebraicGeometry.IsAffineOpen.fromSpec_map_basicOpen + rw [fromSpec_preimage_basicOpen', ← basicOpen_eq_of_affine, NatIso.app_inv] +#align algebraic_geometry.is_affine_open.from_Spec_map_basic_open AlgebraicGeometry.IsAffineOpen.fromSpec_preimage_basicOpen -theorem opensFunctor_map_basicOpen : +theorem fromSpec_image_basicOpen : hU.fromSpec.opensFunctor.obj (PrimeSpectrum.basicOpen f) = X.basicOpen f := by - rw [← hU.fromSpec_map_basicOpen] + rw [← hU.fromSpec_preimage_basicOpen] ext1 change hU.fromSpec.val.base '' (hU.fromSpec.val.base ⁻¹' (X.basicOpen f : Set X)) = _ - rw [Set.image_preimage_eq_inter_range, Set.inter_eq_left, hU.fromSpec_range] + rw [Set.image_preimage_eq_inter_range, Set.inter_eq_left, hU.range_fromSpec] exact Scheme.basicOpen_le _ _ -- Porting note: linter complains that LHS is not in simp-normal-form. However, the error provided @@ -381,25 +384,25 @@ theorem opensFunctor_map_basicOpen : theorem basicOpen_fromSpec_app : (𝖲𝗉𝖾𝖼 𝓞ₓ(U)).basicOpen (hU.fromSpec.1.c.app (op U) f) = PrimeSpectrum.basicOpen f := by - rw [← hU.fromSpec_map_basicOpen, Scheme.preimage_basicOpen] + rw [← hU.fromSpec_preimage_basicOpen, Scheme.preimage_basicOpen] #align algebraic_geometry.is_affine_open.basic_open_from_Spec_app AlgebraicGeometry.IsAffineOpen.basicOpen_fromSpec_app -theorem basicOpenIsAffine : +theorem basicOpen : IsAffineOpen (X.basicOpen f) := by - rw [← hU.opensFunctor_map_basicOpen, Scheme.Hom.isAffineOpen_iff_of_isOpenImmersion] - convert rangeIsAffineOpenOfOpenImmersion (Scheme.Spec.map + rw [← hU.fromSpec_image_basicOpen, Scheme.Hom.isAffineOpen_iff_of_isOpenImmersion] + convert isAffineOpen_opensRange (Scheme.Spec.map (CommRingCat.ofHom <| algebraMap (X.presheaf.obj (op U)) (Localization.Away f)).op) exact Opens.ext (PrimeSpectrum.localization_away_comap_range (Localization.Away f) f).symm -#align algebraic_geometry.is_affine_open.basic_open_is_affine AlgebraicGeometry.IsAffineOpen.basicOpenIsAffine +#align algebraic_geometry.is_affine_open.basic_open_is_affine AlgebraicGeometry.IsAffineOpen.basicOpen -theorem mapRestrictBasicOpen (r : X.presheaf.obj (op ⊤)) : +theorem ιOpens_preimage (r : X.presheaf.obj (op ⊤)) : IsAffineOpen (Scheme.ιOpens (X.basicOpen r) ⁻¹ᵁ U) := by apply (Scheme.ιOpens (X.basicOpen r)).isAffineOpen_iff_of_isOpenImmersion.mp dsimp [Scheme.Hom.opensFunctor, PresheafedSpace.IsOpenImmersion.openFunctor] rw [Opens.functor_obj_map_obj, Opens.openEmbedding_obj_top, inf_comm, ← Scheme.basicOpen_res _ _ (homOfLE le_top).op] - exact hU.basicOpenIsAffine _ -#align algebraic_geometry.is_affine_open.map_restrict_basic_open AlgebraicGeometry.IsAffineOpen.mapRestrictBasicOpen + exact hU.basicOpen _ +#align algebraic_geometry.is_affine_open.map_restrict_basic_open AlgebraicGeometry.IsAffineOpen.ιOpens_preimage theorem exists_basicOpen_le {V : Opens X} (x : V) (h : ↑x ∈ U) : ∃ f : X.presheaf.obj (op U), X.basicOpen f ≤ V ∧ ↑x ∈ X.basicOpen f := by @@ -428,7 +431,7 @@ def basicOpenSectionsToAffine : X.presheaf.obj (op <| X.basicOpen f) ⟶ (𝖲𝗉𝖾𝖼 𝓞ₓ(U)).presheaf.obj (op <| PrimeSpectrum.basicOpen f) := hU.fromSpec.1.c.app (op <| X.basicOpen f) ≫ - (𝖲𝗉𝖾𝖼 𝓞ₓ(U)).presheaf.map (eqToHom <| (hU.fromSpec_map_basicOpen f).symm).op + (𝖲𝗉𝖾𝖼 𝓞ₓ(U)).presheaf.map (eqToHom <| (hU.fromSpec_preimage_basicOpen f).symm).op #align algebraic_geometry.basic_open_sections_to_affine AlgebraicGeometry.IsAffineOpen.basicOpenSectionsToAffine instance basicOpenSectionsToAffine_isIso : @@ -436,7 +439,7 @@ instance basicOpenSectionsToAffine_isIso : delta basicOpenSectionsToAffine apply (config := { allowSynthFailures := true }) IsIso.comp_isIso apply PresheafedSpace.IsOpenImmersion.isIso_of_subset - rw [hU.fromSpec_range] + rw [hU.range_fromSpec] exact RingedSpace.basicOpen_le _ _ theorem isLocalization_basicOpen : @@ -461,7 +464,7 @@ theorem isLocalization_basicOpen : instance _root_.AlgebraicGeometry.isLocalization_away_of_isAffine [IsAffine X] (r : X.presheaf.obj (op ⊤)) : IsLocalization.Away r (X.presheaf.obj (op <| X.basicOpen r)) := - isLocalization_basicOpen (topIsAffineOpen X) r + isLocalization_basicOpen (isAffineOpen_top X) r theorem isLocalization_of_eq_basicOpen {V : Opens X} (i : V ⟶ U) (e : V = X.basicOpen f) : @IsLocalization.Away _ _ f (X.presheaf.obj (op V)) _ (X.presheaf.map i.op).toAlgebra := by @@ -471,7 +474,7 @@ theorem isLocalization_of_eq_basicOpen {V : Opens X} (i : V ⟶ U) (e : V = X.ba instance _root_.AlgebraicGeometry.Γ_restrict_isLocalization (X : Scheme.{u}) [IsAffine X] (r : Scheme.Γ.obj (op X)) : IsLocalization.Away r (Scheme.Γ.obj (op (X ∣_ᵤ X.basicOpen r))) := - (topIsAffineOpen X).isLocalization_of_eq_basicOpen r _ (Opens.openEmbedding_obj_top _) + (isAffineOpen_top X).isLocalization_of_eq_basicOpen r _ (Opens.openEmbedding_obj_top _) #align algebraic_geometry.Γ_restrict_is_localization AlgebraicGeometry.Γ_restrict_isLocalization theorem basicOpen_basicOpen_is_basicOpen (g : X.presheaf.obj (op <| X.basicOpen f)) : @@ -562,7 +565,7 @@ theorem isLocalization_stalk (x : U) : @[simps] def _root_.AlgebraicGeometry.Scheme.affineBasicOpen (X : Scheme) {U : X.affineOpens} (f : X.presheaf.obj <| op U) : X.affineOpens := - ⟨X.basicOpen f, U.prop.basicOpenIsAffine f⟩ + ⟨X.basicOpen f, U.prop.basicOpen f⟩ #align algebraic_geometry.Scheme.affine_basic_open AlgebraicGeometry.Scheme.affineBasicOpen theorem basicOpen_union_eq_self_iff (s : Set (X.presheaf.obj <| op U)) : @@ -574,7 +577,7 @@ theorem basicOpen_union_eq_self_iff (s : Set (X.presheaf.obj <| op U)) : · refine ⟨fun h => by rw [h], ?_⟩ intro h apply_fun Set.image hU.fromSpec.1.base at h - rw [Set.image_preimage_eq_inter_range, Set.image_preimage_eq_inter_range, hU.fromSpec_range] + rw [Set.image_preimage_eq_inter_range, Set.image_preimage_eq_inter_range, hU.range_fromSpec] at h simp only [Set.inter_self, Opens.carrier_eq_coe, Set.inter_eq_right] at h ext1 @@ -586,8 +589,8 @@ theorem basicOpen_union_eq_self_iff (s : Set (X.presheaf.obj <| op U)) : congr! 1 · refine congr_arg (Set.iUnion ·) ?_ ext1 x - exact congr_arg Opens.carrier (hU.fromSpec_map_basicOpen _) - · exact congr_arg Opens.carrier hU.fromSpec_base_preimage + exact congr_arg Opens.carrier (hU.fromSpec_preimage_basicOpen _) + · exact congr_arg Opens.carrier hU.fromSpec_preimage_self · simp only [Opens.carrier_eq_coe, PrimeSpectrum.basicOpen_eq_zeroLocus_compl] rw [← Set.compl_iInter, Set.compl_univ_iff, ← PrimeSpectrum.zeroLocus_iUnion, ← PrimeSpectrum.zeroLocus_empty_iff_eq_top, PrimeSpectrum.zeroLocus_span] @@ -645,4 +648,37 @@ theorem of_affine_open_cover {X : Scheme} (V : X.affineOpens) (S : Set X.affineO exact ⟨_, hf₁ ⟨x, hx⟩⟩ #align algebraic_geometry.of_affine_open_cover AlgebraicGeometry.of_affine_open_cover +@[deprecated (since := "2024-06-21"), nolint defLemma] +alias isAffineAffineScheme := isAffine_affineScheme +@[deprecated (since := "2024-06-21"), nolint defLemma] +alias SpecIsAffine := isAffine_Spec +@[deprecated (since := "2024-06-21")] +alias isAffineOfIso := isAffine_of_isIso +@[deprecated (since := "2024-06-21")] +alias rangeIsAffineOpenOfOpenImmersion := isAffineOpen_opensRange +@[deprecated (since := "2024-06-21")] +alias topIsAffineOpen := isAffineOpen_top +@[deprecated (since := "2024-06-21"), nolint defLemma] +alias Scheme.affineCoverIsAffine := Scheme.isAffine_affineCover +@[deprecated (since := "2024-06-21"), nolint defLemma] +alias Scheme.affineBasisCoverIsAffine := Scheme.isAffine_affineBasisCover +@[deprecated (since := "2024-06-21")] +alias IsAffineOpen.fromSpec_range := IsAffineOpen.range_fromSpec +@[deprecated (since := "2024-06-21")] +alias IsAffineOpen.imageIsOpenImmersion := IsAffineOpen.image_of_isOpenImmersion +@[deprecated (since := "2024-06-21"), nolint defLemma] +alias Scheme.quasi_compact_of_affine := Scheme.compactSpace_of_isAffine +@[deprecated (since := "2024-06-21")] +alias IsAffineOpen.fromSpec_base_preimage := IsAffineOpen.fromSpec_preimage_self +@[deprecated (since := "2024-06-21")] +alias IsAffineOpen.fromSpec_map_basicOpen' := IsAffineOpen.fromSpec_preimage_basicOpen' +@[deprecated (since := "2024-06-21")] +alias IsAffineOpen.fromSpec_map_basicOpen := IsAffineOpen.fromSpec_preimage_basicOpen +@[deprecated (since := "2024-06-21")] +alias IsAffineOpen.opensFunctor_map_basicOpen := IsAffineOpen.fromSpec_image_basicOpen +@[deprecated (since := "2024-06-21")] +alias IsAffineOpen.basicOpenIsAffine := IsAffineOpen.basicOpen +@[deprecated (since := "2024-06-21")] +alias IsAffineOpen.mapRestrictBasicOpen := IsAffineOpen.ιOpens_preimage + end AlgebraicGeometry diff --git a/Mathlib/AlgebraicGeometry/FunctionField.lean b/Mathlib/AlgebraicGeometry/FunctionField.lean index d0bc6cab1a8820..b0d23fa48c6bd6 100644 --- a/Mathlib/AlgebraicGeometry/FunctionField.lean +++ b/Mathlib/AlgebraicGeometry/FunctionField.lean @@ -136,7 +136,7 @@ instance functionField_isFractionRing_of_affine (R : CommRingCat.{u}) [IsDomain instance {X : Scheme} [IsIntegral X] {U : Opens X.carrier} [hU : Nonempty U] : IsIntegral (X.restrict U.openEmbedding) := haveI : Nonempty (X.restrict U.openEmbedding).carrier := hU - isIntegralOfOpenImmersion (X.ofRestrict U.openEmbedding) + isIntegral_of_isOpenImmersion (X.ofRestrict U.openEmbedding) theorem IsAffineOpen.primeIdealOf_genericPoint {X : Scheme} [IsIntegral X] {U : Opens X.carrier} (hU : IsAffineOpen U) [h : Nonempty U] : @@ -161,7 +161,7 @@ theorem functionField_isFractionRing_of_isAffineOpen [IsIntegral X] (U : Opens X haveI : IsAffine _ := hU haveI : Nonempty (X.restrict U.openEmbedding).carrier := hU' haveI : IsIntegral (X.restrict U.openEmbedding) := - @isIntegralOfIsAffineIsDomain _ _ _ + @isIntegral_of_isAffine_of_isDomain _ _ _ (by dsimp; rw [Opens.openEmbedding_obj_top]; infer_instance) delta IsFractionRing Scheme.functionField convert hU.isLocalization_stalk ⟨genericPoint X.carrier, _⟩ using 1 @@ -170,14 +170,14 @@ theorem functionField_isFractionRing_of_isAffineOpen [IsIntegral X] (U : Opens X #align algebraic_geometry.function_field_is_fraction_ring_of_is_affine_open AlgebraicGeometry.functionField_isFractionRing_of_isAffineOpen instance (x : X.carrier) : IsAffine (X.affineCover.obj x) := - AlgebraicGeometry.SpecIsAffine _ + AlgebraicGeometry.isAffine_Spec _ instance [IsIntegral X] (x : X.carrier) : IsFractionRing (X.presheaf.stalk x) X.functionField := let U : Opens X.carrier := ⟨Set.range (X.affineCover.map x).1.base, PresheafedSpace.IsOpenImmersion.base_open.isOpen_range⟩ - have hU : IsAffineOpen U := rangeIsAffineOpenOfOpenImmersion (X.affineCover.map x) + have hU : IsAffineOpen U := isAffineOpen_opensRange (X.affineCover.map x) let x : U := ⟨x, X.affineCover.Covers x⟩ have : Nonempty U := ⟨x⟩ let M := (hU.primeIdealOf x).asIdeal.primeCompl diff --git a/Mathlib/AlgebraicGeometry/Limits.lean b/Mathlib/AlgebraicGeometry/Limits.lean index 993ae08ddad01b..67c61edafaf901 100644 --- a/Mathlib/AlgebraicGeometry/Limits.lean +++ b/Mathlib/AlgebraicGeometry/Limits.lean @@ -44,7 +44,7 @@ instance : HasTerminal Scheme := hasTerminal_of_hasTerminal_of_preservesLimit Scheme.Spec instance : IsAffine (⊤_ Scheme.{u}) := - isAffineOfIso (PreservesTerminal.iso Scheme.Spec).inv + isAffine_of_isIso (PreservesTerminal.iso Scheme.Spec).inv instance : HasFiniteLimits Scheme := hasFiniteLimits_of_hasTerminal_and_pullbacks @@ -117,7 +117,7 @@ noncomputable def specPunitIsInitial : IsInitial (Scheme.Spec.obj (op <| CommRin #align algebraic_geometry.Spec_punit_is_initial AlgebraicGeometry.specPunitIsInitial instance (priority := 100) isAffine_of_isEmpty {X : Scheme} [IsEmpty X.carrier] : IsAffine X := - isAffineOfIso + isAffine_of_isIso (inv (emptyIsInitial.to X) ≫ emptyIsInitial.to (Scheme.Spec.obj (op <| CommRingCat.of PUnit))) #align algebraic_geometry.is_affine_of_is_empty AlgebraicGeometry.isAffine_of_isEmpty @@ -130,14 +130,14 @@ instance initial_isEmpty : IsEmpty (⊥_ Scheme).carrier := ⟨fun x => ((initial.to Scheme.empty : _).1.base x).elim⟩ #align algebraic_geometry.initial_is_empty AlgebraicGeometry.initial_isEmpty -theorem bot_isAffineOpen (X : Scheme) : IsAffineOpen (⊥ : Opens X.carrier) := by - convert rangeIsAffineOpenOfOpenImmersion (initial.to X) +theorem isAffineOpen_bot (X : Scheme) : IsAffineOpen (⊥ : Opens X.carrier) := by + convert isAffineOpen_opensRange (initial.to X) ext -- Porting note: added this `erw` to turn LHS to `False` erw [Set.mem_empty_iff_false] rw [false_iff_iff] exact fun x => isEmptyElim (show (⊥_ Scheme).carrier from x.choose) -#align algebraic_geometry.bot_is_affine_open AlgebraicGeometry.bot_isAffineOpen +#align algebraic_geometry.bot_is_affine_open AlgebraicGeometry.isAffineOpen_bot instance : HasStrictInitialObjects Scheme := hasStrictInitialObjects_of_initial_is_strict fun A f => by infer_instance diff --git a/Mathlib/AlgebraicGeometry/Morphisms/Basic.lean b/Mathlib/AlgebraicGeometry/Morphisms/Basic.lean index 68fd93fdaa464b..43e1ad8d8f26ee 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/Basic.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/Basic.lean @@ -48,7 +48,7 @@ satisfies the assumptions of the affine communication lemma `targetAffineLocally P f`, then `P.IsLocal`. - `AlgebraicGeometry.AffineTargetMorphismProperty.IsLocal.affine_target_iff`: If `Y` is affine and `f : X ⟶ Y`, then `targetAffineLocally P f ↔ P f` provided `P.IsLocal`. -- `AlgebraicGeometry.AffineTargetMorphismProperty.IsLocal.targetAffineLocallyIsLocal` : +- `AlgebraicGeometry.AffineTargetMorphismProperty.IsLocal.targetAffineLocally_isLocal` : If `P.IsLocal`, then `PropertyIsLocalAtTarget (targetAffineLocally P)`. - `AlgebraicGeometry.PropertyIsLocalAtTarget.openCover_TFAE`: If `PropertyIsLocalAtTarget P`, then `P f` iff there exists an open cover `{ Uᵢ }` of `Y` @@ -109,11 +109,11 @@ theorem affine_cancel_right_isIso {P : AffineTargetMorphismProperty} (hP : P.toP theorem AffineTargetMorphismProperty.respectsIso_mk {P : AffineTargetMorphismProperty} (h₁ : ∀ {X Y Z} (e : X ≅ Y) (f : Y ⟶ Z) [IsAffine Z], P f → P (e.hom ≫ f)) (h₂ : ∀ {X Y Z} (e : Y ≅ Z) (f : X ⟶ Y) [h : IsAffine Y], - P f → @P _ _ (f ≫ e.hom) (isAffineOfIso e.inv)) : + P f → @P _ _ (f ≫ e.hom) (isAffine_of_isIso e.inv)) : P.toProperty.RespectsIso := by constructor · rintro X Y Z e f ⟨a, h⟩; exact ⟨a, h₁ e f h⟩ - · rintro X Y Z e f ⟨a, h⟩; exact ⟨isAffineOfIso e.inv, h₂ e f h⟩ + · rintro X Y Z e f ⟨a, h⟩; exact ⟨isAffine_of_isIso e.inv, h₂ e f h⟩ #align algebraic_geometry.affine_target_morphism_property.respects_iso_mk AlgebraicGeometry.AffineTargetMorphismProperty.respectsIso_mk /-- For a `P : AffineTargetMorphismProperty`, `targetAffineLocally P` holds for @@ -125,7 +125,7 @@ def targetAffineLocally (P : AffineTargetMorphismProperty) : MorphismProperty Sc theorem IsAffineOpen.map_isIso {X Y : Scheme} {U : Opens Y.carrier} (hU : IsAffineOpen U) (f : X ⟶ Y) [IsIso f] : IsAffineOpen ((Opens.map f.1.base).obj U) := haveI : IsAffine _ := hU - isAffineOfIso (f ∣_ U) + isAffine_of_isIso (f ∣_ U) #align algebraic_geometry.is_affine_open.map_is_iso AlgebraicGeometry.IsAffineOpen.map_isIso theorem targetAffineLocally_respectsIso {P : AffineTargetMorphismProperty} @@ -154,13 +154,13 @@ structure AffineTargetMorphismProperty.IsLocal (P : AffineTargetMorphismProperty /-- `P` is stable under restriction to basic open set of global sections. -/ toBasicOpen : ∀ {X Y : Scheme} [IsAffine Y] (f : X ⟶ Y) (r : Y.presheaf.obj <| op ⊤), - P f → @P _ _ (f ∣_ Y.basicOpen r) ((topIsAffineOpen Y).basicOpenIsAffine _) + P f → @P _ _ (f ∣_ Y.basicOpen r) ((isAffineOpen_top Y).basicOpen _) /-- `P` for `f` if `P` holds for `f` restricted to basic sets of a spanning set of the global sections -/ ofBasicOpenCover : ∀ {X Y : Scheme} [IsAffine Y] (f : X ⟶ Y) (s : Finset (Y.presheaf.obj <| op ⊤)) (_ : Ideal.span (s : Set (Y.presheaf.obj <| op ⊤)) = ⊤), - (∀ r : s, @P _ _ (f ∣_ Y.basicOpen r.1) ((topIsAffineOpen Y).basicOpenIsAffine _)) → P f + (∀ r : s, @P _ _ (f ∣_ Y.basicOpen r.1) ((isAffineOpen_top Y).basicOpen _)) → P f #align algebraic_geometry.affine_target_morphism_property.is_local AlgebraicGeometry.AffineTargetMorphismProperty.IsLocal /-- Specialization of `ConcreteCategory.id_apply` because `simp` can't see through the defeq. -/ @@ -171,8 +171,7 @@ theorem targetAffineLocallyOfOpenCover {P : AffineTargetMorphismProperty} (hP : (h𝒰 : ∀ i, P (pullback.snd : (𝒰.pullbackCover f).obj i ⟶ 𝒰.obj i)) : targetAffineLocally P f := by classical - let S i := (⟨⟨Set.range (𝒰.map i).1.base, (𝒰.IsOpen i).base_open.isOpen_range⟩, - rangeIsAffineOpenOfOpenImmersion (𝒰.map i)⟩ : Y.affineOpens) + let S i := (⟨_, isAffineOpen_opensRange (𝒰.map i)⟩ : Y.affineOpens) intro U apply of_affine_open_cover (P := _) U (Set.range S) · intro U r h @@ -226,7 +225,7 @@ theorem AffineTargetMorphismProperty.IsLocal.affine_openCover_TFAE ∀ i, @P _ _ (f ∣_ U i) (hU' i)] := by tfae_have 1 → 4 · intro H U g h₁ h₂ - replace H := H ⟨⟨_, h₂.base_open.isOpen_range⟩, rangeIsAffineOpenOfOpenImmersion g⟩ + replace H := H ⟨_, isAffineOpen_opensRange g⟩ rw [← P.toProperty_apply] at H ⊢ rwa [← hP.1.arrow_mk_iso_iff (morphismRestrictOpensRange f _)] tfae_have 4 → 3 @@ -248,9 +247,9 @@ theorem AffineTargetMorphismProperty.IsLocal.affine_openCover_TFAE tfae_have 1 → 5 · intro H refine ⟨Y.carrier, fun x => (Scheme.Hom.opensRange <| Y.affineCover.map x), - ?_, fun i => rangeIsAffineOpenOfOpenImmersion _, ?_⟩ + ?_, fun i => isAffineOpen_opensRange _, ?_⟩ · rw [eq_top_iff]; intro x _; erw [Opens.mem_iSup]; exact ⟨x, Y.affineCover.Covers x⟩ - · intro i; exact H ⟨_, rangeIsAffineOpenOfOpenImmersion _⟩ + · intro i; exact H ⟨_, isAffineOpen_opensRange _⟩ tfae_finish #align algebraic_geometry.affine_target_morphism_property.is_local.affine_open_cover_tfae AlgebraicGeometry.AffineTargetMorphismProperty.IsLocal.affine_openCover_TFAE @@ -264,7 +263,7 @@ theorem AffineTargetMorphismProperty.isLocalOfOpenCoverImply (P : AffineTargetMo P.IsLocal := by refine ⟨hP, ?_, ?_⟩ · introv h - haveI : IsAffine _ := (topIsAffineOpen Y).basicOpenIsAffine r + haveI : IsAffine _ := (isAffineOpen_top Y).basicOpen r delta morphismRestrict rw [affine_cancel_left_isIso hP] refine @H _ _ f ⟨Scheme.openCoverOfIsIso (𝟙 Y), ?_, ?_⟩ _ (Y.ofRestrict _) _ _ @@ -272,14 +271,14 @@ theorem AffineTargetMorphismProperty.isLocalOfOpenCoverImply (P : AffineTargetMo · intro i; dsimp rwa [← Category.comp_id pullback.snd, ← pullback.condition, affine_cancel_left_isIso hP] · introv hs hs' - replace hs := ((topIsAffineOpen Y).basicOpen_union_eq_self_iff _).mpr hs + replace hs := ((isAffineOpen_top Y).basicOpen_union_eq_self_iff _).mpr hs have := H f ⟨Y.openCoverOfSuprEqTop _ hs, ?_, ?_⟩ (𝟙 _) · rwa [← Category.comp_id pullback.snd, ← pullback.condition, affine_cancel_left_isIso hP] at this - · intro i; exact (topIsAffineOpen Y).basicOpenIsAffine _ + · intro i; exact (isAffineOpen_top Y).basicOpen _ · rintro (i : s) specialize hs' i - haveI : IsAffine _ := (topIsAffineOpen Y).basicOpenIsAffine i.1 + haveI : IsAffine _ := (isAffineOpen_top Y).basicOpen i.1 delta morphismRestrict at hs' rwa [affine_cancel_left_isIso hP] at hs' #align algebraic_geometry.affine_target_morphism_property.is_local_of_open_cover_imply AlgebraicGeometry.AffineTargetMorphismProperty.isLocalOfOpenCoverImply @@ -334,14 +333,14 @@ lemma propertyIsLocalAtTarget_of_morphismRestrict (P : MorphismProperty Scheme) simp_rw [hP₁.arrow_mk_iso_iff (morphismRestrictOpensRange f _)] exact h𝒰 -theorem AffineTargetMorphismProperty.IsLocal.targetAffineLocallyIsLocal +theorem AffineTargetMorphismProperty.IsLocal.targetAffineLocally_isLocal {P : AffineTargetMorphismProperty} (hP : P.IsLocal) : PropertyIsLocalAtTarget (targetAffineLocally P) := by constructor · exact targetAffineLocally_respectsIso hP.1 · intro X Y f U H V rw [← P.toProperty_apply (i := V.2), hP.1.arrow_mk_iso_iff (morphismRestrictRestrict f _ _)] - convert H ⟨_, IsAffineOpen.imageIsOpenImmersion V.2 (Y.ofRestrict _)⟩ + convert H ⟨_, V.2.image_of_isOpenImmersion (Y.ofRestrict _)⟩ rw [← P.toProperty_apply] · rintro X Y f 𝒰 h𝒰 -- Porting note: rewrite `[(hP.affine_openCover_TFAE f).out 0 1` directly complains about @@ -368,7 +367,7 @@ theorem AffineTargetMorphismProperty.IsLocal.targetAffineLocallyIsLocal rw [← affine_cancel_left_isIso hP.1 e] at h𝒰 convert h𝒰 using 1 simp [e] -#align algebraic_geometry.affine_target_morphism_property.is_local.target_affine_locally_is_local AlgebraicGeometry.AffineTargetMorphismProperty.IsLocal.targetAffineLocallyIsLocal +#align algebraic_geometry.affine_target_morphism_property.is_local.target_affine_locally_is_local AlgebraicGeometry.AffineTargetMorphismProperty.IsLocal.targetAffineLocally_isLocal open List in theorem PropertyIsLocalAtTarget.openCover_TFAE {P : MorphismProperty Scheme} @@ -431,7 +430,7 @@ def StableUnderBaseChange (P : AffineTargetMorphismProperty) : Prop := P g → P (pullback.fst : pullback f g ⟶ X) #align algebraic_geometry.affine_target_morphism_property.stable_under_base_change AlgebraicGeometry.AffineTargetMorphismProperty.StableUnderBaseChange -theorem IsLocal.targetAffineLocallyPullbackFstOfRightOfStableUnderBaseChange +theorem IsLocal.targetAffineLocally_pullback_fst_of_right_of_stableUnderBaseChange {P : AffineTargetMorphismProperty} (hP : P.IsLocal) (hP' : P.StableUnderBaseChange) {X Y S : Scheme} (f : X ⟶ S) (g : Y ⟶ S) [IsAffine S] (H : P g) : targetAffineLocally P (pullback.fst : pullback f g ⟶ X) := by @@ -444,7 +443,7 @@ theorem IsLocal.targetAffineLocallyPullbackFstOfRightOfStableUnderBaseChange have : e.hom ≫ pullback.fst = pullback.snd := by simp [e] rw [← this, affine_cancel_left_isIso hP.1] apply hP'; assumption -#align algebraic_geometry.affine_target_morphism_property.is_local.target_affine_locally_pullback_fst_of_right_of_stable_under_base_change AlgebraicGeometry.AffineTargetMorphismProperty.IsLocal.targetAffineLocallyPullbackFstOfRightOfStableUnderBaseChange +#align algebraic_geometry.affine_target_morphism_property.is_local.target_affine_locally_pullback_fst_of_right_of_stable_under_base_change AlgebraicGeometry.AffineTargetMorphismProperty.IsLocal.targetAffineLocally_pullback_fst_of_right_of_stableUnderBaseChange theorem IsLocal.stableUnderBaseChange {P : AffineTargetMorphismProperty} (hP : P.IsLocal) (hP' : P.StableUnderBaseChange) : (targetAffineLocally P).StableUnderBaseChange := @@ -452,7 +451,7 @@ theorem IsLocal.stableUnderBaseChange {P : AffineTargetMorphismProperty} (hP : P (fun X Y S f g H => by -- Porting note: rewrite `(...openCover_TFAE).out 0 1` directly doesn't work, complains about -- metavariable - have h01 := (hP.targetAffineLocallyIsLocal.openCover_TFAE + have h01 := (hP.targetAffineLocally_isLocal.openCover_TFAE (pullback.fst : pullback f g ⟶ X)).out 0 1 rw [h01] use S.affineCover.pullbackCover f @@ -470,7 +469,7 @@ theorem IsLocal.stableUnderBaseChange {P : AffineTargetMorphismProperty} (hP : P (pullback.map _ _ _ _ (𝟙 _) (𝟙 _) (𝟙 _) (by simpa using pullback.condition) (by simp)) have : e.hom ≫ pullback.fst = pullback.snd := by simp [e] rw [← this, (targetAffineLocally_respectsIso hP.1).cancel_left_isIso] - apply hP.targetAffineLocallyPullbackFstOfRightOfStableUnderBaseChange hP' + apply hP.targetAffineLocally_pullback_fst_of_right_of_stableUnderBaseChange hP' rw [← pullbackSymmetry_hom_comp_snd, affine_cancel_left_isIso hP.1] apply H) #align algebraic_geometry.affine_target_morphism_property.is_local.stable_under_base_change AlgebraicGeometry.AffineTargetMorphismProperty.IsLocal.stableUnderBaseChange @@ -499,12 +498,13 @@ theorem AffineTargetMorphismProperty.diagonal_respectsIso (P : AffineTargetMorph apply H · introv H _ _ -- Porting note: add the following two instances - have _ : IsAffine Z := isAffineOfIso e.inv + have _ : IsAffine Z := isAffine_of_isIso e.inv rw [pullback.mapDesc_comp, affine_cancel_right_isIso hP] apply H #align algebraic_geometry.affine_target_morphism_property.diagonal_respects_iso AlgebraicGeometry.AffineTargetMorphismProperty.diagonal_respectsIso -theorem diagonalTargetAffineLocallyOfOpenCover (P : AffineTargetMorphismProperty) (hP : P.IsLocal) +theorem diagonal_targetAffineLocally_of_openCover + (P : AffineTargetMorphismProperty) (hP : P.IsLocal) {X Y : Scheme.{u}} (f : X ⟶ Y) (𝒰 : Scheme.OpenCover.{u} Y) [∀ i, IsAffine (𝒰.obj i)] (𝒰' : ∀ i, Scheme.OpenCover.{u} (pullback f (𝒰.map i))) [∀ i j, IsAffine ((𝒰' i).obj j)] (h𝒰' : ∀ i j k, P (pullback.mapDesc ((𝒰' i).map j) ((𝒰' i).map k) pullback.snd)) : @@ -522,9 +522,9 @@ theorem diagonalTargetAffineLocallyOfOpenCover (P : AffineTargetMorphismProperty all_goals apply pullback.hom_ext <;> simp only [Category.assoc, pullback.lift_fst, pullback.lift_snd, pullback.lift_fst_assoc, pullback.lift_snd_assoc] -#align algebraic_geometry.diagonal_target_affine_locally_of_open_cover AlgebraicGeometry.diagonalTargetAffineLocallyOfOpenCover +#align algebraic_geometry.diagonal_target_affine_locally_of_open_cover AlgebraicGeometry.diagonal_targetAffineLocally_of_openCover -theorem AffineTargetMorphismProperty.diagonalOfTargetAffineLocally +theorem AffineTargetMorphismProperty.diagonal_of_targetAffineLocally (P : AffineTargetMorphismProperty) (hP : P.IsLocal) {X Y U : Scheme.{u}} (f : X ⟶ Y) (g : U ⟶ Y) [IsAffine U] [IsOpenImmersion g] (H : (targetAffineLocally P).diagonal f) : P.diagonal (pullback.snd : pullback f g ⟶ _) := by @@ -541,7 +541,7 @@ theorem AffineTargetMorphismProperty.diagonalOfTargetAffineLocally simp only [Category.assoc, pullback.lift_fst, pullback.lift_snd, pullback.lift_fst_assoc, pullback.lift_snd_assoc, Category.comp_id, pullbackDiagonalMapIso_hom_fst, pullbackDiagonalMapIso_hom_snd] -#align algebraic_geometry.affine_target_morphism_property.diagonal_of_target_affine_locally AlgebraicGeometry.AffineTargetMorphismProperty.diagonalOfTargetAffineLocally +#align algebraic_geometry.affine_target_morphism_property.diagonal_of_target_affine_locally AlgebraicGeometry.AffineTargetMorphismProperty.diagonal_of_targetAffineLocally open List in theorem AffineTargetMorphismProperty.IsLocal.diagonal_affine_openCover_TFAE @@ -558,7 +558,7 @@ theorem AffineTargetMorphismProperty.IsLocal.diagonal_affine_openCover_TFAE ∀ i, Scheme.OpenCover.{u} (pullback f (𝒰.map i))) (_ : ∀ i j, IsAffine ((𝒰' i).obj j)), ∀ i j k, P (pullback.mapDesc ((𝒰' i).map j) ((𝒰' i).map k) pullback.snd)] := by tfae_have 1 → 4 - · introv H hU hg _ _; apply P.diagonalOfTargetAffineLocally <;> assumption + · introv H hU hg _ _; apply P.diagonal_of_targetAffineLocally <;> assumption tfae_have 4 → 3 · introv H h𝒰; apply H tfae_have 3 → 2 @@ -570,7 +570,7 @@ theorem AffineTargetMorphismProperty.IsLocal.diagonal_affine_openCover_TFAE apply H tfae_have 5 → 1 · rintro ⟨𝒰, _, 𝒰', _, H⟩ - exact diagonalTargetAffineLocallyOfOpenCover P hP f 𝒰 𝒰' H + exact diagonal_targetAffineLocally_of_openCover P hP f 𝒰 𝒰' H tfae_finish #align algebraic_geometry.affine_target_morphism_property.is_local.diagonal_affine_open_cover_tfae AlgebraicGeometry.AffineTargetMorphismProperty.IsLocal.diagonal_affine_openCover_TFAE @@ -587,7 +587,7 @@ theorem diagonal_targetAffineLocally_eq_targetAffineLocally (P : AffineTargetMor ((hP.diagonal.affine_openCover_TFAE f).out 1 0) #align algebraic_geometry.diagonal_target_affine_locally_eq_target_affine_locally AlgebraicGeometry.diagonal_targetAffineLocally_eq_targetAffineLocally -theorem universallyIsLocalAtTarget (P : MorphismProperty Scheme) +theorem universally_isLocalAtTarget (P : MorphismProperty Scheme) (hP : ∀ {X Y : Scheme.{u}} (f : X ⟶ Y) (𝒰 : Scheme.OpenCover.{u} Y), (∀ i : 𝒰.J, P (pullback.snd : (𝒰.pullbackCover f).obj i ⟶ 𝒰.obj i)) → P f) : PropertyIsLocalAtTarget P.universally := by @@ -603,17 +603,17 @@ theorem universallyIsLocalAtTarget (P : MorphismProperty Scheme) refine (IsPullback.of_right ?_ (pullback.lift_snd _ _ _) (IsPullback.of_hasPullback _ _)).flip rw [pullback.lift_fst, ← pullback.condition] exact (IsPullback.of_hasPullback _ _).paste_horiz H.flip -#align algebraic_geometry.universally_is_local_at_target AlgebraicGeometry.universallyIsLocalAtTarget +#align algebraic_geometry.universally_is_local_at_target AlgebraicGeometry.universally_isLocalAtTarget -theorem universallyIsLocalAtTargetOfMorphismRestrict (P : MorphismProperty Scheme) +theorem universally_isLocalAtTarget_of_morphismRestrict (P : MorphismProperty Scheme) (hP₁ : P.RespectsIso) (hP₂ : ∀ {X Y : Scheme.{u}} (f : X ⟶ Y) {ι : Type u} (U : ι → Opens Y.carrier) (_ : iSup U = ⊤), (∀ i, P (f ∣_ U i)) → P f) : PropertyIsLocalAtTarget P.universally := - universallyIsLocalAtTarget P (fun f 𝒰 h𝒰 => by + universally_isLocalAtTarget P (fun f 𝒰 h𝒰 => by apply hP₂ f (fun i : 𝒰.J => Scheme.Hom.opensRange (𝒰.map i)) 𝒰.iSup_opensRange simp_rw [hP₁.arrow_mk_iso_iff (morphismRestrictOpensRange f _)] exact h𝒰) -#align algebraic_geometry.universally_is_local_at_target_of_morphism_restrict AlgebraicGeometry.universallyIsLocalAtTargetOfMorphismRestrict +#align algebraic_geometry.universally_is_local_at_target_of_morphism_restrict AlgebraicGeometry.universally_isLocalAtTarget_of_morphismRestrict theorem morphismRestrict_base {X Y : Scheme} (f : X ⟶ Y) (U : Opens Y.carrier) : ⇑(f ∣_ U).1.base = U.1.restrictPreimage f.1.1 := @@ -680,4 +680,29 @@ lemma MorphismProperty.topologically_propertyIsLocalAtTarget rw [← morphismRestrict_base] exact hf i +namespace AffineTargetMorphismProperty.IsLocal + +@[deprecated (since := "2024-06-22")] +alias targetAffineLocallyIsLocal := targetAffineLocally_isLocal + +@[deprecated (since := "2024-06-22")] +alias targetAffineLocallyPullbackFstOfRightOfStableUnderBaseChange := + targetAffineLocally_pullback_fst_of_right_of_stableUnderBaseChange + +end AffineTargetMorphismProperty.IsLocal + +@[deprecated (since := "2024-06-22")] +alias diagonalTargetAffineLocallyOfOpenCover := diagonal_targetAffineLocally_of_openCover + +@[deprecated (since := "2024-06-22")] +alias AffineTargetMorphismProperty.diagonalOfTargetAffineLocally := + AffineTargetMorphismProperty.diagonal_of_targetAffineLocally + +@[deprecated (since := "2024-06-22")] +alias universallyIsLocalAtTarget := universally_isLocalAtTarget + +@[deprecated (since := "2024-06-22")] +alias universallyIsLocalAtTargetOfMorphismRestrict := + universally_isLocalAtTarget_of_morphismRestrict + end AlgebraicGeometry diff --git a/Mathlib/AlgebraicGeometry/Morphisms/OpenImmersion.lean b/Mathlib/AlgebraicGeometry/Morphisms/OpenImmersion.lean index 8cfb3b103b42d1..3ae267323d5660 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/OpenImmersion.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/OpenImmersion.lean @@ -50,7 +50,7 @@ theorem isOpenImmersion_respectsIso : MorphismProperty.RespectsIso @IsOpenImmers infer_instance #align algebraic_geometry.is_open_immersion_respects_iso AlgebraicGeometry.isOpenImmersion_respectsIso -theorem isOpenImmersion_is_local_at_target : PropertyIsLocalAtTarget @IsOpenImmersion := by +theorem isOpenImmersion_isLocalAtTarget : PropertyIsLocalAtTarget @IsOpenImmersion := by constructor · exact isOpenImmersion_respectsIso · intros; infer_instance @@ -72,7 +72,7 @@ theorem isOpenImmersion_is_local_at_target : PropertyIsLocalAtTarget @IsOpenImme (isOpenImmersion_respectsIso.arrow_iso_iff (morphismRestrictOpensRange f (𝒰.map _))).mpr (H _) infer_instance -#align algebraic_geometry.is_open_immersion_is_local_at_target AlgebraicGeometry.isOpenImmersion_is_local_at_target +#align algebraic_geometry.is_open_immersion_is_local_at_target AlgebraicGeometry.isOpenImmersion_isLocalAtTarget theorem IsOpenImmersion.openCover_TFAE {X Y : Scheme.{u}} (f : X ⟶ Y) : List.TFAE [IsOpenImmersion f, @@ -85,13 +85,13 @@ theorem IsOpenImmersion.openCover_TFAE {X Y : Scheme.{u}} (f : X ⟶ Y) : List.T IsOpenImmersion (pullback.snd : pullback f g ⟶ _), ∃ (ι : Type u) (U : ι → Opens Y.carrier) (_ : iSup U = ⊤), ∀ i, IsOpenImmersion (f ∣_ U i)] := - isOpenImmersion_is_local_at_target.openCover_TFAE f + isOpenImmersion_isLocalAtTarget.openCover_TFAE f #align algebraic_geometry.is_open_immersion.open_cover_tfae AlgebraicGeometry.IsOpenImmersion.openCover_TFAE theorem IsOpenImmersion.openCover_iff {X Y : Scheme.{u}} (𝒰 : Scheme.OpenCover.{u} Y) (f : X ⟶ Y) : IsOpenImmersion f ↔ ∀ i, IsOpenImmersion (pullback.snd : pullback f (𝒰.map i) ⟶ _) := - isOpenImmersion_is_local_at_target.openCover_iff f 𝒰 + isOpenImmersion_isLocalAtTarget.openCover_iff f 𝒰 #align algebraic_geometry.is_open_immersion.open_cover_iff AlgebraicGeometry.IsOpenImmersion.openCover_iff theorem isOpenImmersion_stableUnderBaseChange : diff --git a/Mathlib/AlgebraicGeometry/Morphisms/QuasiCompact.lean b/Mathlib/AlgebraicGeometry/Morphisms/QuasiCompact.lean index c91734ce4ca238..018e1cbf82fab4 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/QuasiCompact.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/QuasiCompact.lean @@ -88,7 +88,7 @@ theorem isCompact_open_iff_eq_basicOpen_union {X : Scheme} [IsAffine X] (U : Set ∃ s : Set (X.presheaf.obj (op ⊤)), s.Finite ∧ U = ⋃ (i : X.presheaf.obj (op ⊤)) (_ : i ∈ s), X.basicOpen i := (isBasis_basicOpen X).isCompact_open_iff_eq_finite_iUnion _ - (fun _ => ((topIsAffineOpen _).basicOpenIsAffine _).isCompact) _ + (fun _ => ((isAffineOpen_top _).basicOpen _).isCompact) _ #align algebraic_geometry.is_compact_open_iff_eq_basic_open_union AlgebraicGeometry.isCompact_open_iff_eq_basicOpen_union theorem quasiCompact_iff_forall_affine : @@ -136,7 +136,7 @@ theorem isCompact_basicOpen (X : Scheme) {U : Opens X.carrier} (hU : IsCompact ( convert Set.subset_iUnion₂ (s := fun (U : X.affineOpens) (_ : U ∈ s) => (U : Set X.carrier)) V V.prop using 1 erw [← X.toLocallyRingedSpace.toRingedSpace.basicOpen_res this.op] - exact IsAffineOpen.basicOpenIsAffine V.1.prop _ + exact IsAffineOpen.basicOpen V.1.prop _ haveI : Finite s := hs.to_subtype refine ⟨Set.range g, Set.finite_range g, ?_⟩ refine (Set.inter_eq_right.mpr @@ -176,7 +176,7 @@ theorem QuasiCompact.affineProperty_isLocal : (QuasiCompact.affineProperty : _). dsimp [Opens.map] simp only [Opens.iSup_mk, Opens.carrier_eq_coe, Opens.coe_mk, Set.preimage_iUnion] exact isCompact_iUnion fun i => isCompact_iff_compactSpace.mpr (hS' i) - · exact topIsAffineOpen _ + · exact isAffineOpen_top _ #align algebraic_geometry.quasi_compact.affine_property_is_local AlgebraicGeometry.QuasiCompact.affineProperty_isLocal theorem QuasiCompact.affine_openCover_tfae {X Y : Scheme.{u}} (f : X ⟶ Y) : @@ -193,10 +193,10 @@ theorem QuasiCompact.affine_openCover_tfae {X Y : Scheme.{u}} (f : X ⟶ Y) : quasiCompact_eq_affineProperty.symm ▸ QuasiCompact.affineProperty_isLocal.affine_openCover_TFAE f #align algebraic_geometry.quasi_compact.affine_open_cover_tfae AlgebraicGeometry.QuasiCompact.affine_openCover_tfae -theorem QuasiCompact.is_local_at_target : PropertyIsLocalAtTarget @QuasiCompact := +theorem QuasiCompact.isLocalAtTarget : PropertyIsLocalAtTarget @QuasiCompact := quasiCompact_eq_affineProperty.symm ▸ - QuasiCompact.affineProperty_isLocal.targetAffineLocallyIsLocal -#align algebraic_geometry.quasi_compact.is_local_at_target AlgebraicGeometry.QuasiCompact.is_local_at_target + QuasiCompact.affineProperty_isLocal.targetAffineLocally_isLocal +#align algebraic_geometry.quasi_compact.is_local_at_target AlgebraicGeometry.QuasiCompact.isLocalAtTarget theorem QuasiCompact.openCover_tfae {X Y : Scheme.{u}} (f : X ⟶ Y) : List.TFAE @@ -210,7 +210,7 @@ theorem QuasiCompact.openCover_tfae {X Y : Scheme.{u}} (f : X ⟶ Y) : QuasiCompact (pullback.snd : pullback f g ⟶ _), ∃ (ι : Type u) (U : ι → Opens Y.carrier) (_ : iSup U = ⊤), ∀ i, QuasiCompact (f ∣_ U i)] := quasiCompact_eq_affineProperty.symm ▸ - QuasiCompact.affineProperty_isLocal.targetAffineLocallyIsLocal.openCover_TFAE f + QuasiCompact.affineProperty_isLocal.targetAffineLocally_isLocal.openCover_TFAE f #align algebraic_geometry.quasi_compact.open_cover_tfae AlgebraicGeometry.QuasiCompact.openCover_tfae theorem quasiCompact_over_affine_iff {X Y : Scheme} (f : X ⟶ Y) [IsAffine Y] : @@ -232,7 +232,7 @@ theorem QuasiCompact.affine_openCover_iff {X Y : Scheme.{u}} (𝒰 : Scheme.Open theorem QuasiCompact.openCover_iff {X Y : Scheme.{u}} (𝒰 : Scheme.OpenCover.{u} Y) (f : X ⟶ Y) : QuasiCompact f ↔ ∀ i, QuasiCompact (pullback.snd : pullback f (𝒰.map i) ⟶ _) := quasiCompact_eq_affineProperty.symm ▸ - QuasiCompact.affineProperty_isLocal.targetAffineLocallyIsLocal.openCover_iff f 𝒰 + QuasiCompact.affineProperty_isLocal.targetAffineLocally_isLocal.openCover_iff f 𝒰 #align algebraic_geometry.quasi_compact.open_cover_iff AlgebraicGeometry.QuasiCompact.openCover_iff theorem quasiCompact_respectsIso : MorphismProperty.RespectsIso @QuasiCompact := diff --git a/Mathlib/AlgebraicGeometry/Morphisms/QuasiSeparated.lean b/Mathlib/AlgebraicGeometry/Morphisms/QuasiSeparated.lean index 4b9d72fce8cc9f..5d8257f22257ca 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/QuasiSeparated.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/QuasiSeparated.lean @@ -109,8 +109,8 @@ theorem quasi_compact_affineProperty_iff_quasiSeparatedSpace {X Y : Scheme} [IsA simp_rw [isCompact_iff_compactSpace] at H exact @Homeomorph.compactSpace _ _ _ _ - (H ⟨⟨_, h₁.base_open.isOpen_range⟩, rangeIsAffineOpenOfOpenImmersion _⟩ - ⟨⟨_, h₂.base_open.isOpen_range⟩, rangeIsAffineOpenOfOpenImmersion _⟩) + (H ⟨⟨_, h₁.base_open.isOpen_range⟩, isAffineOpen_opensRange _⟩ + ⟨⟨_, h₂.base_open.isOpen_range⟩, isAffineOpen_opensRange _⟩) e.symm #align algebraic_geometry.quasi_compact_affine_property_iff_quasi_separated_space AlgebraicGeometry.quasi_compact_affineProperty_iff_quasiSeparatedSpace @@ -186,10 +186,10 @@ theorem QuasiSeparated.affine_openCover_TFAE {X Y : Scheme.{u}} (f : X ⟶ Y) : exact this #align algebraic_geometry.quasi_separated.affine_open_cover_tfae AlgebraicGeometry.QuasiSeparated.affine_openCover_TFAE -theorem QuasiSeparated.is_local_at_target : PropertyIsLocalAtTarget @QuasiSeparated := +theorem QuasiSeparated.isLocalAtTarget : PropertyIsLocalAtTarget @QuasiSeparated := quasiSeparated_eq_affineProperty_diagonal.symm ▸ - QuasiCompact.affineProperty_isLocal.diagonal.targetAffineLocallyIsLocal -#align algebraic_geometry.quasi_separated.is_local_at_target AlgebraicGeometry.QuasiSeparated.is_local_at_target + QuasiCompact.affineProperty_isLocal.diagonal.targetAffineLocally_isLocal +#align algebraic_geometry.quasi_separated.is_local_at_target AlgebraicGeometry.QuasiSeparated.isLocalAtTarget open List in theorem QuasiSeparated.openCover_TFAE {X Y : Scheme.{u}} (f : X ⟶ Y) : @@ -204,7 +204,7 @@ theorem QuasiSeparated.openCover_TFAE {X Y : Scheme.{u}} (f : X ⟶ Y) : QuasiSeparated (pullback.snd : pullback f g ⟶ _), ∃ (ι : Type u) (U : ι → Opens Y.carrier) (_ : iSup U = ⊤), ∀ i, QuasiSeparated (f ∣_ U i)] := - QuasiSeparated.is_local_at_target.openCover_TFAE f + QuasiSeparated.isLocalAtTarget.openCover_TFAE f #align algebraic_geometry.quasi_separated.open_cover_tfae AlgebraicGeometry.QuasiSeparated.openCover_TFAE theorem quasiSeparated_over_affine_iff {X Y : Scheme} (f : X ⟶ Y) [IsAffine Y] : @@ -228,7 +228,7 @@ theorem QuasiSeparated.affine_openCover_iff {X Y : Scheme.{u}} (𝒰 : Scheme.Op theorem QuasiSeparated.openCover_iff {X Y : Scheme.{u}} (𝒰 : Scheme.OpenCover.{u} Y) (f : X ⟶ Y) : QuasiSeparated f ↔ ∀ i, QuasiSeparated (pullback.snd : pullback f (𝒰.map i) ⟶ _) := - QuasiSeparated.is_local_at_target.openCover_iff f 𝒰 + QuasiSeparated.isLocalAtTarget.openCover_iff f 𝒰 #align algebraic_geometry.quasi_separated.open_cover_iff AlgebraicGeometry.QuasiSeparated.openCover_iff instance {X Y S : Scheme} (f : X ⟶ S) (g : Y ⟶ S) [QuasiSeparated g] : @@ -265,7 +265,7 @@ instance quasiSeparatedSpace_of_isAffine (X : Scheme) [IsAffine X] : intro i' _ change IsCompact (X.basicOpen i ⊓ X.basicOpen i').1 rw [← Scheme.basicOpen_mul] - exact ((topIsAffineOpen _).basicOpenIsAffine _).isCompact + exact ((isAffineOpen_top _).basicOpen _).isCompact #align algebraic_geometry.quasi_separated_space_of_is_affine AlgebraicGeometry.quasiSeparatedSpace_of_isAffine theorem IsAffineOpen.isQuasiSeparated {X : Scheme} {U : Opens X.carrier} (hU : IsAffineOpen U) : diff --git a/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean b/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean index 3c2c81dd0e8bef..efd135495125fb 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean @@ -197,7 +197,7 @@ theorem affineLocally_iff_affineOpens_le · simp only [Scheme.ofRestrict_val_c_app, Scheme.restrict_presheaf_map, ← X.presheaf.map_comp] congr 1 · intro H V - specialize H ⟨_, V.2.imageIsOpenImmersion (X.ofRestrict _)⟩ (Subtype.coe_image_subset _ _) + specialize H ⟨_, V.2.image_of_isOpenImmersion (X.ofRestrict _)⟩ (Subtype.coe_image_subset _ _) rw [← hP.cancel_right_isIso _ (X.presheaf.map (eqToHom _)), Category.assoc] · convert H simp only [Scheme.ofRestrict_val_c_app, Scheme.restrict_presheaf_map, ← X.presheaf.map_comp] @@ -211,12 +211,12 @@ theorem scheme_restrict_basicOpen_of_localizationPreserves (h₁ : RingHom.Respe (U : (X.restrict ((Opens.map f.1.base).obj <| Y.basicOpen r).openEmbedding).affineOpens) : P (Scheme.Γ.map ((X.restrict ((Opens.map f.1.base).obj <| Y.basicOpen r).openEmbedding).ofRestrict U.1.openEmbedding ≫ f ∣_ Y.basicOpen r).op) := by - specialize H ⟨_, U.2.imageIsOpenImmersion (X.ofRestrict _)⟩ + specialize H ⟨_, U.2.image_of_isOpenImmersion (X.ofRestrict _)⟩ letI i1 : Algebra (Y.presheaf.obj <| Opposite.op ⊤) (Localization.Away r) := Localization.algebra exact (h₁.ofRestrict_morphismRestrict_iff f r ((Scheme.Hom.opensFunctor (X.ofRestrict ((Opens.map f.1.base).obj <| Y.basicOpen r).openEmbedding)).obj U.1) - (IsAffineOpen.imageIsOpenImmersion U.2 + (IsAffineOpen.image_of_isOpenImmersion U.2 (X.ofRestrict ((Opens.map f.1.base).obj <| Y.basicOpen r).openEmbedding)) (Opens.ext (Set.preimage_image_eq _ Subtype.coe_injective).symm)).mpr (h₂.away r H) set_option linter.uppercaseLean3 false in @@ -242,7 +242,7 @@ theorem sourceAffineLocally_isLocal (h₁ : RingHom.RespectsIso @P) intro V hV rw [Scheme.preimage_basicOpen] at hV subst hV - exact U.2.mapRestrictBasicOpen (Scheme.Γ.map f.op r.1) + exact U.2.ιOpens_preimage (Scheme.Γ.map f.op r.1) #align algebraic_geometry.source_affine_locally_is_local AlgebraicGeometry.sourceAffineLocally_isLocal variable (hP : RingHom.PropertyIsLocal @P) @@ -274,7 +274,7 @@ theorem isOpenImmersionCat_comp_of_sourceAffineLocally (h₁ : RingHom.RespectsI rw [← h₁.cancel_right_isIso _ (Scheme.Γ.map (IsOpenImmersion.isoOfRangeEq (Y.ofRestrict _) f _).hom.op), ← Functor.map_comp, ← op_comp] - · convert h₂ ⟨_, rangeIsAffineOpenOfOpenImmersion f⟩ using 3 + · convert h₂ ⟨_, isAffineOpen_opensRange f⟩ using 3 · rw [IsOpenImmersion.isoOfRangeEq_hom_fac_assoc] exact Subtype.range_coe #align algebraic_geometry.is_open_immersion_comp_of_source_affine_locally AlgebraicGeometry.isOpenImmersionCat_comp_of_sourceAffineLocally @@ -291,7 +291,7 @@ theorem sourceAffineLocally_of_source_openCover {X Y : Scheme.{u}} (f : X ⟶ Y) (𝒰 : X.OpenCover) [∀ i, IsAffine (𝒰.obj i)] (H : ∀ i, P (Scheme.Γ.map (𝒰.map i ≫ f).op)) : sourceAffineLocally (@P) f := by let S i := (⟨⟨Set.range (𝒰.map i).1.base, (𝒰.IsOpen i).base_open.isOpen_range⟩, - rangeIsAffineOpenOfOpenImmersion (𝒰.map i)⟩ : X.affineOpens) + isAffineOpen_opensRange (𝒰.map i)⟩ : X.affineOpens) intro U -- Porting note: here is what we are eliminating into Lean apply of_affine_open_cover @@ -360,7 +360,7 @@ theorem affine_openCover_TFAE {X Y : Scheme.{u}} [IsAffine Y] (f : X ⟶ Y) : P (Scheme.Γ.map (g ≫ f).op)] := by tfae_have 1 → 4 · intro H U g _ hg - specialize H ⟨⟨_, hg.base_open.isOpen_range⟩, rangeIsAffineOpenOfOpenImmersion g⟩ + specialize H ⟨⟨_, hg.base_open.isOpen_range⟩, isAffineOpen_opensRange g⟩ rw [← hP.respectsIso.cancel_right_isIso _ (Scheme.Γ.map (IsOpenImmersion.isoOfRangeEq g (X.ofRestrict (Opens.openEmbedding ⟨_, hg.base_open.isOpen_range⟩)) Subtype.range_coe.symm).hom.op), @@ -446,7 +446,7 @@ theorem isLocal_sourceAffineLocally : (sourceAffineLocally @P).IsLocal := #align ring_hom.property_is_local.is_local_source_affine_locally RingHom.PropertyIsLocal.isLocal_sourceAffineLocally theorem is_local_affineLocally : PropertyIsLocalAtTarget (affineLocally @P) := - hP.isLocal_sourceAffineLocally.targetAffineLocallyIsLocal + hP.isLocal_sourceAffineLocally.targetAffineLocally_isLocal #align ring_hom.property_is_local.is_local_affine_locally RingHom.PropertyIsLocal.is_local_affineLocally theorem affine_openCover_iff {X Y : Scheme.{u}} (f : X ⟶ Y) (𝒰 : Scheme.OpenCover.{u} Y) diff --git a/Mathlib/AlgebraicGeometry/Morphisms/UniversallyClosed.lean b/Mathlib/AlgebraicGeometry/Morphisms/UniversallyClosed.lean index 9ca5c620887d1e..fe0ba532688755 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/UniversallyClosed.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/UniversallyClosed.lean @@ -85,19 +85,19 @@ instance universallyClosedSnd {X Y Z : Scheme} (f : X ⟶ Z) (g : Y ⟶ Z) [hf : universallyClosed_stableUnderBaseChange.snd f g hf #align algebraic_geometry.universally_closed_snd AlgebraicGeometry.universallyClosedSnd -theorem universallyClosed_is_local_at_target : PropertyIsLocalAtTarget @UniversallyClosed := by +theorem universallyClosed_isLocalAtTarget : PropertyIsLocalAtTarget @UniversallyClosed := by rw [universallyClosed_eq] - apply universallyIsLocalAtTargetOfMorphismRestrict + apply universally_isLocalAtTarget_of_morphismRestrict · exact topologically_isClosedMap_respectsIso · intro X Y f ι U hU H simp_rw [topologically, morphismRestrict_base] at H exact (isClosedMap_iff_isClosedMap_of_iSup_eq_top hU).mpr H -#align algebraic_geometry.universally_closed_is_local_at_target AlgebraicGeometry.universallyClosed_is_local_at_target +#align algebraic_geometry.universally_closed_is_local_at_target AlgebraicGeometry.universallyClosed_isLocalAtTarget theorem UniversallyClosed.openCover_iff {X Y : Scheme.{u}} (f : X ⟶ Y) (𝒰 : Scheme.OpenCover.{u} Y) : UniversallyClosed f ↔ ∀ i, UniversallyClosed (pullback.snd : pullback f (𝒰.map i) ⟶ _) := - universallyClosed_is_local_at_target.openCover_iff f 𝒰 + universallyClosed_isLocalAtTarget.openCover_iff f 𝒰 #align algebraic_geometry.universally_closed.open_cover_iff AlgebraicGeometry.UniversallyClosed.openCover_iff end AlgebraicGeometry diff --git a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean b/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean index 51289b51d3cd88..c5d14489605354 100644 --- a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean +++ b/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean @@ -61,10 +61,12 @@ It is a fundamental building block in algebraic geometry. -/ @[ext] structure PrimeSpectrum [CommSemiring R] where asIdeal : Ideal R - IsPrime : asIdeal.IsPrime + isPrime : asIdeal.IsPrime #align prime_spectrum PrimeSpectrum -attribute [instance] PrimeSpectrum.IsPrime +@[deprecated (since := "2024-06-22")] alias PrimeSpectrum.IsPrime := PrimeSpectrum.isPrime + +attribute [instance] PrimeSpectrum.isPrime namespace PrimeSpectrum @@ -79,7 +81,7 @@ instance [Nontrivial R] : Nonempty <| PrimeSpectrum R := /-- The prime spectrum of the zero ring is empty. -/ instance [Subsingleton R] : IsEmpty (PrimeSpectrum R) := - ⟨fun x ↦ x.IsPrime.ne_top <| SetLike.ext' <| Subsingleton.eq_univ_of_nonempty x.asIdeal.nonempty⟩ + ⟨fun x ↦ x.isPrime.ne_top <| SetLike.ext' <| Subsingleton.eq_univ_of_nonempty x.asIdeal.nonempty⟩ #noalign prime_spectrum.punit variable (R S) @@ -158,11 +160,11 @@ At a point `x` (a prime ideal) the function (i.e., element) `f` takes values in consisting of all "functions" that vanish on all of `t`. -/ def vanishingIdeal (t : Set (PrimeSpectrum R)) : Ideal R := - ⨅ (x : PrimeSpectrum R) (_ : x ∈ t), x.asIdeal + ⨅ x ∈ t, x.asIdeal #align prime_spectrum.vanishing_ideal PrimeSpectrum.vanishingIdeal theorem coe_vanishingIdeal (t : Set (PrimeSpectrum R)) : - (vanishingIdeal t : Set R) = { f : R | ∀ x : PrimeSpectrum R, x ∈ t → f ∈ x.asIdeal } := by + (vanishingIdeal t : Set R) = { f : R | ∀ x ∈ t, f ∈ x.asIdeal } := by ext f rw [vanishingIdeal, SetLike.mem_coe, Submodule.mem_iInf] apply forall_congr'; intro x @@ -170,7 +172,7 @@ theorem coe_vanishingIdeal (t : Set (PrimeSpectrum R)) : #align prime_spectrum.coe_vanishing_ideal PrimeSpectrum.coe_vanishingIdeal theorem mem_vanishingIdeal (t : Set (PrimeSpectrum R)) (f : R) : - f ∈ vanishingIdeal t ↔ ∀ x : PrimeSpectrum R, x ∈ t → f ∈ x.asIdeal := by + f ∈ vanishingIdeal t ↔ ∀ x ∈ t, f ∈ x.asIdeal := by rw [← SetLike.mem_coe, coe_vanishingIdeal, Set.mem_setOf_eq] #align prime_spectrum.mem_vanishing_ideal PrimeSpectrum.mem_vanishingIdeal @@ -277,9 +279,9 @@ theorem zeroLocus_empty : zeroLocus (∅ : Set R) = Set.univ := #align prime_spectrum.zero_locus_empty PrimeSpectrum.zeroLocus_empty @[simp] -theorem vanishingIdeal_univ : vanishingIdeal (∅ : Set (PrimeSpectrum R)) = ⊤ := by +theorem vanishingIdeal_empty : vanishingIdeal (∅ : Set (PrimeSpectrum R)) = ⊤ := by simpa using (gc R).u_top -#align prime_spectrum.vanishing_ideal_univ PrimeSpectrum.vanishingIdeal_univ +#align prime_spectrum.vanishing_ideal_univ PrimeSpectrum.vanishingIdeal_empty theorem zeroLocus_empty_of_one_mem {s : Set R} (h : (1 : R) ∈ s) : zeroLocus s = ∅ := by rw [Set.eq_empty_iff_forall_not_mem] diff --git a/Mathlib/AlgebraicGeometry/PrimeSpectrum/IsOpenComapC.lean b/Mathlib/AlgebraicGeometry/PrimeSpectrum/IsOpenComapC.lean index 4d8a7218b37e0c..92687e313cbadd 100644 --- a/Mathlib/AlgebraicGeometry/PrimeSpectrum/IsOpenComapC.lean +++ b/Mathlib/AlgebraicGeometry/PrimeSpectrum/IsOpenComapC.lean @@ -54,7 +54,7 @@ morphism `C⁺ : Spec R[x] → Spec R`. -/ theorem imageOfDf_eq_comap_C_compl_zeroLocus : imageOfDf f = PrimeSpectrum.comap (C : R →+* R[X]) '' (zeroLocus {f})ᶜ := by ext x - refine ⟨fun hx => ⟨⟨map C x.asIdeal, isPrime_map_C_of_isPrime x.IsPrime⟩, ⟨?_, ?_⟩⟩, ?_⟩ + refine ⟨fun hx => ⟨⟨map C x.asIdeal, isPrime_map_C_of_isPrime x.isPrime⟩, ⟨?_, ?_⟩⟩, ?_⟩ · rw [mem_compl_iff, mem_zeroLocus, singleton_subset_iff] cases' hx with i hi exact fun a => hi (mem_map_C_iff.mp a i) diff --git a/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Scheme.lean b/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Scheme.lean index a7aa99dbe5efc5..1f8df1f5721ce9 100644 --- a/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Scheme.lean +++ b/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Scheme.lean @@ -444,7 +444,7 @@ def carrier.asHomogeneousIdeal : HomogeneousIdeal 𝒜 := #align algebraic_geometry.Proj_iso_Spec_Top_component.from_Spec.carrier.as_homogeneous_ideal AlgebraicGeometry.ProjIsoSpecTopComponent.FromSpec.carrier.asHomogeneousIdeal theorem carrier.denom_not_mem : f ∉ carrier.asIdeal f_deg hm q := fun rid => - q.IsPrime.ne_top <| + q.isPrime.ne_top <| (Ideal.eq_top_iff_one _).mpr (by convert rid m diff --git a/Mathlib/AlgebraicGeometry/Properties.lean b/Mathlib/AlgebraicGeometry/Properties.lean index da907957b19f8d..4a67fe7afd31b9 100644 --- a/Mathlib/AlgebraicGeometry/Properties.lean +++ b/Mathlib/AlgebraicGeometry/Properties.lean @@ -58,7 +58,7 @@ class IsReduced : Prop where attribute [instance] IsReduced.component_reduced -theorem isReducedOfStalkIsReduced [∀ x : X.carrier, _root_.IsReduced (X.presheaf.stalk x)] : +theorem isReduced_of_isReduced_stalk [∀ x : X.carrier, _root_.IsReduced (X.presheaf.stalk x)] : IsReduced X := by refine ⟨fun U => ⟨fun s hs => ?_⟩⟩ apply Presheaf.section_ext X.sheaf U s 0 @@ -66,9 +66,9 @@ theorem isReducedOfStalkIsReduced [∀ x : X.carrier, _root_.IsReduced (X.preshe rw [RingHom.map_zero] change X.presheaf.germ x s = 0 exact (hs.map _).eq_zero -#align algebraic_geometry.is_reduced_of_stalk_is_reduced AlgebraicGeometry.isReducedOfStalkIsReduced +#align algebraic_geometry.is_reduced_of_stalk_is_reduced AlgebraicGeometry.isReduced_of_isReduced_stalk -instance stalk_isReduced_of_reduced [IsReduced X] (x : X.carrier) : +instance isReduced_stalk_of_isReduced [IsReduced X] (x : X.carrier) : _root_.IsReduced (X.presheaf.stalk x) := by constructor rintro g ⟨n, e⟩ @@ -79,9 +79,9 @@ instance stalk_isReduced_of_reduced [IsReduced X] (x : X.carrier) : replace e' := (IsNilpotent.mk _ _ e').eq_zero (R := X.presheaf.obj <| op V) erw [← ConcreteCategory.congr_hom (X.presheaf.germ_res iU ⟨x, hxV⟩) s] rw [comp_apply, e', map_zero] -#align algebraic_geometry.stalk_is_reduced_of_reduced AlgebraicGeometry.stalk_isReduced_of_reduced +#align algebraic_geometry.stalk_is_reduced_of_reduced AlgebraicGeometry.isReduced_stalk_of_isReduced -theorem isReducedOfOpenImmersion {X Y : Scheme} (f : X ⟶ Y) [H : IsOpenImmersion f] +theorem isReduced_of_isOpenImmersion {X Y : Scheme} (f : X ⟶ Y) [H : IsOpenImmersion f] [IsReduced Y] : IsReduced X := by constructor intro U @@ -91,10 +91,10 @@ theorem isReducedOfOpenImmersion {X Y : Scheme} (f : X ⟶ Y) [H : IsOpenImmersi exact isReduced_of_injective (inv <| f.1.c.app (op <| H.base_open.isOpenMap.functor.obj U)) (asIso <| f.1.c.app (op <| H.base_open.isOpenMap.functor.obj U) : Y.presheaf.obj _ ≅ _).symm.commRingCatIsoToRingEquiv.injective -#align algebraic_geometry.is_reduced_of_open_immersion AlgebraicGeometry.isReducedOfOpenImmersion +#align algebraic_geometry.is_reduced_of_open_immersion AlgebraicGeometry.isReduced_of_isOpenImmersion instance {R : CommRingCat.{u}} [H : _root_.IsReduced R] : IsReduced (Scheme.Spec.obj <| op R) := by - apply (config := { allowSynthFailures := true }) isReducedOfStalkIsReduced + apply (config := { allowSynthFailures := true }) isReduced_of_isReduced_stalk intro x; dsimp have : _root_.IsReduced (CommRingCat.of <| Localization.AtPrime (PrimeSpectrum.asIdeal x)) := by dsimp; infer_instance @@ -112,12 +112,13 @@ theorem affine_isReduced_iff (R : CommRingCat) : exact isReduced_of_injective (toSpecΓ R) (asIso <| toSpecΓ R).commRingCatIsoToRingEquiv.injective #align algebraic_geometry.affine_is_reduced_iff AlgebraicGeometry.affine_isReduced_iff -theorem isReducedOfIsAffineIsReduced [IsAffine X] [h : _root_.IsReduced (X.presheaf.obj (op ⊤))] : +theorem isReduced_of_isAffine_isReduced [IsAffine X] + [h : _root_.IsReduced (X.presheaf.obj (op ⊤))] : IsReduced X := haveI : IsReduced (Scheme.Spec.obj (op (Scheme.Γ.obj (op X)))) := by rw [affine_isReduced_iff]; exact h - isReducedOfOpenImmersion X.isoSpec.hom -#align algebraic_geometry.is_reduced_of_is_affine_is_reduced AlgebraicGeometry.isReducedOfIsAffineIsReduced + isReduced_of_isOpenImmersion X.isoSpec.hom +#align algebraic_geometry.is_reduced_of_is_affine_is_reduced AlgebraicGeometry.isReduced_of_isAffine_isReduced /-- To show that a statement `P` holds for all open subsets of all schemes, it suffices to show that 1. In any scheme `X`, if `P` holds for an open cover of `U`, then `P` holds for `U`. @@ -177,7 +178,7 @@ theorem eq_zero_of_basicOpen_eq_bot {X : Scheme} [hX : IsReduced X] {U : Opens X rw [← Set.image_univ, Set.preimage_image_eq _ hf.base_open.inj] refine ⟨_, _, e, rfl, ?_⟩ rintro H hX s hs ⟨_, x, rfl⟩ - haveI := isReducedOfOpenImmersion f + haveI := isReduced_of_isOpenImmersion f specialize H (f.1.c.app _ s) _ ⟨x, by rw [Opens.mem_mk, e]; trivial⟩ · rw [← Scheme.preimage_basicOpen, hs]; ext1; simp [Opens.map] · erw [← PresheafedSpace.stalkMap_germ_apply f.1 ⟨_, _⟩ ⟨x, _⟩] at H @@ -216,7 +217,7 @@ instance [h : IsIntegral X] : IsDomain (X.presheaf.obj (op ⊤)) := @IsIntegral.component_integral _ _ _ (by simp only [Set.univ_nonempty, Opens.nonempty_coeSort, Opens.coe_top]) -instance (priority := 900) isReducedOfIsIntegral [IsIntegral X] : IsReduced X := by +instance (priority := 900) isReduced_of_isIntegral [IsIntegral X] : IsReduced X := by constructor intro U rcases U.1.eq_empty_or_nonempty with h | h @@ -226,9 +227,9 @@ instance (priority := 900) isReducedOfIsIntegral [IsIntegral X] : IsReduced X := infer_instance · haveI : Nonempty U := by simpa infer_instance -#align algebraic_geometry.is_reduced_of_is_integral AlgebraicGeometry.isReducedOfIsIntegral +#align algebraic_geometry.is_reduced_of_is_integral AlgebraicGeometry.isReduced_of_isIntegral -instance is_irreducible_of_isIntegral [IsIntegral X] : IrreducibleSpace X.carrier := by +instance irreducibleSpace_of_isIntegral [IsIntegral X] : IrreducibleSpace X.carrier := by by_contra H replace H : ¬IsPreirreducible (⊤ : Set X.carrier) := fun h => H { toPreirreducibleSpace := ⟨h⟩ @@ -255,9 +256,9 @@ instance is_irreducible_of_isIntegral [IsIntegral X] : IrreducibleSpace X.carrie exacts [hS h, hT h] · intro x exact x.rec (by contradiction) -#align algebraic_geometry.is_irreducible_of_is_integral AlgebraicGeometry.is_irreducible_of_isIntegral +#align algebraic_geometry.is_irreducible_of_is_integral AlgebraicGeometry.irreducibleSpace_of_isIntegral -theorem isIntegralOfIsIrreducibleIsReduced [IsReduced X] [H : IrreducibleSpace X.carrier] : +theorem isIntegral_of_irreducibleSpace_of_isReduced [IsReduced X] [H : IrreducibleSpace X.carrier] : IsIntegral X := by constructor; · infer_instance intro U hU @@ -277,15 +278,15 @@ theorem isIntegralOfIsIrreducibleIsReduced [IsReduced X] [H : IrreducibleSpace X convert hx₁.mul hx₂ exact e.symm exact NoZeroDivisors.to_isDomain _ -#align algebraic_geometry.is_integral_of_is_irreducible_is_reduced AlgebraicGeometry.isIntegralOfIsIrreducibleIsReduced +#align algebraic_geometry.is_integral_of_is_irreducible_is_reduced AlgebraicGeometry.isIntegral_of_irreducibleSpace_of_isReduced -theorem isIntegral_iff_is_irreducible_and_isReduced : +theorem isIntegral_iff_irreducibleSpace_and_isReduced : IsIntegral X ↔ IrreducibleSpace X.carrier ∧ IsReduced X := ⟨fun _ => ⟨inferInstance, inferInstance⟩, fun ⟨_, _⟩ => - isIntegralOfIsIrreducibleIsReduced X⟩ -#align algebraic_geometry.is_integral_iff_is_irreducible_and_is_reduced AlgebraicGeometry.isIntegral_iff_is_irreducible_and_isReduced + isIntegral_of_irreducibleSpace_of_isReduced X⟩ +#align algebraic_geometry.is_integral_iff_is_irreducible_and_is_reduced AlgebraicGeometry.isIntegral_iff_irreducibleSpace_and_isReduced -theorem isIntegralOfOpenImmersion {X Y : Scheme} (f : X ⟶ Y) [H : IsOpenImmersion f] +theorem isIntegral_of_isOpenImmersion {X Y : Scheme} (f : X ⟶ Y) [H : IsOpenImmersion f] [IsIntegral Y] [Nonempty X.carrier] : IsIntegral X := by constructor; · infer_instance intro U hU @@ -297,14 +298,14 @@ theorem isIntegralOfOpenImmersion {X Y : Scheme} (f : X ⟶ Y) [H : IsOpenImmers exact ⟨⟨_, _, hU.some.prop, rfl⟩⟩ exact (asIso <| f.1.c.app (op <| H.base_open.isOpenMap.functor.obj U) : Y.presheaf.obj _ ≅ _).symm.commRingCatIsoToRingEquiv.toMulEquiv.isDomain _ -#align algebraic_geometry.is_integral_of_open_immersion AlgebraicGeometry.isIntegralOfOpenImmersion +#align algebraic_geometry.is_integral_of_open_immersion AlgebraicGeometry.isIntegral_of_isOpenImmersion instance {R : CommRingCat} [H : IsDomain R] : IrreducibleSpace (Scheme.Spec.obj <| op R).carrier := by convert PrimeSpectrum.irreducibleSpace (R := R) instance {R : CommRingCat} [IsDomain R] : IsIntegral (Scheme.Spec.obj <| op R) := - isIntegralOfIsIrreducibleIsReduced _ + isIntegral_of_irreducibleSpace_of_isReduced _ theorem affine_isIntegral_iff (R : CommRingCat) : IsIntegral (Scheme.Spec.obj <| op R) ↔ IsDomain R := @@ -312,12 +313,12 @@ theorem affine_isIntegral_iff (R : CommRingCat) : (asIso <| toSpecΓ R).commRingCatIsoToRingEquiv.toMulEquiv, fun _ => inferInstance⟩ #align algebraic_geometry.affine_is_integral_iff AlgebraicGeometry.affine_isIntegral_iff -theorem isIntegralOfIsAffineIsDomain [IsAffine X] [Nonempty X.carrier] +theorem isIntegral_of_isAffine_of_isDomain [IsAffine X] [Nonempty X.carrier] [h : IsDomain (X.presheaf.obj (op ⊤))] : IsIntegral X := haveI : IsIntegral (Scheme.Spec.obj (op (Scheme.Γ.obj (op X)))) := by rw [affine_isIntegral_iff]; exact h - isIntegralOfOpenImmersion X.isoSpec.hom -#align algebraic_geometry.is_integral_of_is_affine_is_domain AlgebraicGeometry.isIntegralOfIsAffineIsDomain + isIntegral_of_isOpenImmersion X.isoSpec.hom +#align algebraic_geometry.is_integral_of_is_affine_is_domain AlgebraicGeometry.isIntegral_of_isAffine_of_isDomain theorem map_injective_of_isIntegral [IsIntegral X] {U V : Opens X.carrier} (i : U ⟶ V) [H : Nonempty U] : Function.Injective (X.presheaf.map i.op) := by diff --git a/Mathlib/AlgebraicGeometry/Pullbacks.lean b/Mathlib/AlgebraicGeometry/Pullbacks.lean index 7eb5da00b53ec4..e1e8b6af724bf9 100644 --- a/Mathlib/AlgebraicGeometry/Pullbacks.lean +++ b/Mathlib/AlgebraicGeometry/Pullbacks.lean @@ -502,7 +502,7 @@ instance : HasPullbacks Scheme := instance isAffine_of_isAffine_isAffine_isAffine {X Y Z : Scheme} (f : X ⟶ Z) (g : Y ⟶ Z) [IsAffine X] [IsAffine Y] [IsAffine Z] : IsAffine (pullback f g) := - isAffineOfIso + isAffine_of_isIso (pullback.map f g (Spec.map (Γ.map f.op).op) (Spec.map (Γ.map g.op).op) (ΓSpec.adjunction.unit.app X) (ΓSpec.adjunction.unit.app Y) (ΓSpec.adjunction.unit.app Z) (ΓSpec.adjunction.unit.naturality f) (ΓSpec.adjunction.unit.naturality g) ≫ diff --git a/Mathlib/AlgebraicGeometry/StructureSheaf.lean b/Mathlib/AlgebraicGeometry/StructureSheaf.lean index 1d82cb89283cd9..0052d66fb75bac 100644 --- a/Mathlib/AlgebraicGeometry/StructureSheaf.lean +++ b/Mathlib/AlgebraicGeometry/StructureSheaf.lean @@ -167,11 +167,11 @@ def sectionsSubring (U : (Opens (PrimeSpectrum.Top R))ᵒᵖ) : carrier := { f | (isLocallyFraction R).pred f } zero_mem' := by refine fun x => ⟨unop U, x.2, 𝟙 _, 0, 1, fun y => ⟨?_, ?_⟩⟩ - · rw [← Ideal.ne_top_iff_one]; exact y.1.IsPrime.1 + · rw [← Ideal.ne_top_iff_one]; exact y.1.isPrime.1 · simp one_mem' := by refine fun x => ⟨unop U, x.2, 𝟙 _, 1, 1, fun y => ⟨?_, ?_⟩⟩ - · rw [← Ideal.ne_top_iff_one]; exact y.1.IsPrime.1 + · rw [← Ideal.ne_top_iff_one]; exact y.1.isPrime.1 · simp add_mem' := by intro a b ha hb x @@ -182,7 +182,7 @@ def sectionsSubring (U : (Opens (PrimeSpectrum.Top R))ᵒᵖ) : rcases wa (Opens.infLELeft _ _ y) with ⟨nma, wa⟩ rcases wb (Opens.infLERight _ _ y) with ⟨nmb, wb⟩ fconstructor - · intro H; cases y.1.IsPrime.mem_or_mem H <;> contradiction + · intro H; cases y.1.isPrime.mem_or_mem H <;> contradiction · simp only [add_mul, RingHom.map_add, Pi.add_apply, RingHom.map_mul] erw [← wa, ← wb] simp only [mul_assoc] @@ -208,7 +208,7 @@ def sectionsSubring (U : (Opens (PrimeSpectrum.Top R))ᵒᵖ) : rcases wa (Opens.infLELeft _ _ y) with ⟨nma, wa⟩ rcases wb (Opens.infLERight _ _ y) with ⟨nmb, wb⟩ fconstructor - · intro H; cases y.1.IsPrime.mem_or_mem H <;> contradiction + · intro H; cases y.1.isPrime.mem_or_mem H <;> contradiction · simp only [Pi.mul_apply, RingHom.map_mul] erw [← wa, ← wb] simp only [mul_left_comm, mul_assoc, mul_comm] diff --git a/Mathlib/RingTheory/DedekindDomain/Ideal.lean b/Mathlib/RingTheory/DedekindDomain/Ideal.lean index 5b086aed18de2a..4986ddedc43b8c 100644 --- a/Mathlib/RingTheory/DedekindDomain/Ideal.lean +++ b/Mathlib/RingTheory/DedekindDomain/Ideal.lean @@ -388,7 +388,7 @@ theorem exists_multiset_prod_cons_le_and_prod_not_le [IsDedekindDomain A] (hNF : rwa [Ne, ← Multiset.cons_erase hPZ', Multiset.prod_cons, Ideal.mul_eq_bot, not_or, ← this] at hprodZ -- By maximality of `P` and `M`, we have that `P ≤ M` implies `P = M`. - have hPM' := (P.IsPrime.isMaximal hP0).eq_of_le hM.ne_top hPM + have hPM' := (P.isPrime.isMaximal hP0).eq_of_le hM.ne_top hPM subst hPM' -- By minimality of `Z`, erasing `P` from `Z` is exactly what we need. refine ⟨Z.erase P, ?_, ?_⟩ From e4a15fb24957249959de6425ee315240575b158b Mon Sep 17 00:00:00 2001 From: Andrew Yang Date: Sat, 22 Jun 2024 15:35:57 +0000 Subject: [PATCH 10/19] =?UTF-8?q?refactor(AlgebraicGeometry)=20Add=20notat?= =?UTF-8?q?ion=20`=CE=93(X,=20U)`.=20(#14025)?= 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/AlgebraicGeometry/AffineScheme.lean | 125 ++++++++---------- .../GammaSpecAdjunction.lean | 80 +++++++---- Mathlib/AlgebraicGeometry/OpenImmersion.lean | 11 +- Mathlib/AlgebraicGeometry/Properties.lean | 119 ++++++++--------- Mathlib/AlgebraicGeometry/Restrict.lean | 49 +++---- Mathlib/AlgebraicGeometry/Scheme.lean | 102 +++++++++----- Mathlib/AlgebraicGeometry/Spec.lean | 4 +- 7 files changed, 266 insertions(+), 224 deletions(-) diff --git a/Mathlib/AlgebraicGeometry/AffineScheme.lean b/Mathlib/AlgebraicGeometry/AffineScheme.lean index 3775c8aec7f600..34123063f50503 100644 --- a/Mathlib/AlgebraicGeometry/AffineScheme.lean +++ b/Mathlib/AlgebraicGeometry/AffineScheme.lean @@ -66,6 +66,7 @@ class IsAffine (X : Scheme) : Prop where attribute [instance] IsAffine.affine /-- The canonical isomorphism `X ≅ Spec Γ(X)` for an affine scheme. -/ +@[simps! (config := .lemmasOnly) hom] def Scheme.isoSpec (X : Scheme) [IsAffine X] : X ≅ Scheme.Spec.obj (op <| Scheme.Γ.obj <| op X) := asIso (ΓSpec.adjunction.unit.app X) #align algebraic_geometry.Scheme.iso_Spec AlgebraicGeometry.Scheme.isoSpec @@ -221,25 +222,12 @@ theorem isBasis_affine_open (X : Scheme) : Opens.IsBasis X.affineOpens := by theorem Scheme.map_PrimeSpectrum_basicOpen_of_affine (X : Scheme) [IsAffine X] (f : Scheme.Γ.obj (op X)) : - X.isoSpec.hom ⁻¹ᵁ PrimeSpectrum.basicOpen f = X.basicOpen f := by - rw [← basicOpen_eq_of_affine] - trans - X.isoSpec.hom ⁻¹ᵁ (Scheme.Spec.obj (op (Scheme.Γ.obj (op X)))).basicOpen - ((inv (X.isoSpec.hom.1.c.app (op ((Opens.map (inv X.isoSpec.hom).val.base).obj ⊤)))) f) - · congr - rw [← IsIso.inv_eq_inv, IsIso.inv_inv, IsIso.Iso.inv_inv, NatIso.app_hom] - -- Porting note: added this `change` to prevent timeout - change SpecΓIdentity.hom.app (X.presheaf.obj <| op ⊤) = _ - rw [← ΓSpec.adjunction_unit_app_app_top X] - rfl - · dsimp - refine (Scheme.preimage_basicOpen _ _).trans ?_ - congr 1 - exact IsIso.inv_hom_id_apply _ _ + X.isoSpec.hom ⁻¹ᵁ PrimeSpectrum.basicOpen f = X.basicOpen f := + ΓSpec.adjunction_unit_map_basicOpen _ _ #align algebraic_geometry.Scheme.map_prime_spectrum_basic_open_of_affine AlgebraicGeometry.Scheme.map_PrimeSpectrum_basicOpen_of_affine theorem isBasis_basicOpen (X : Scheme) [IsAffine X] : - Opens.IsBasis (Set.range (X.basicOpen : X.presheaf.obj (op ⊤) → Opens X)) := by + Opens.IsBasis (Set.range (X.basicOpen : Γ(X, ⊤) → Opens X)) := by delta Opens.IsBasis convert PrimeSpectrum.isBasis_basic_opens.inducing (TopCat.homeoOfIso (Scheme.forgetToTop.mapIso X.isoSpec)).inducing using 1 @@ -248,21 +236,19 @@ theorem isBasis_basicOpen (X : Scheme) [IsAffine X] : constructor · rintro ⟨_, ⟨x, rfl⟩, rfl⟩ refine ⟨_, ⟨_, ⟨x, rfl⟩, rfl⟩, ?_⟩ - exact congr_arg Opens.carrier (X.map_PrimeSpectrum_basicOpen_of_affine x) + exact congr_arg Opens.carrier (ΓSpec.adjunction_unit_map_basicOpen _ _) · rintro ⟨_, ⟨_, ⟨x, rfl⟩, rfl⟩, rfl⟩ refine ⟨_, ⟨x, rfl⟩, ?_⟩ - exact congr_arg Opens.carrier (X.map_PrimeSpectrum_basicOpen_of_affine x).symm + exact congr_arg Opens.carrier (ΓSpec.adjunction_unit_map_basicOpen _ _).symm #align algebraic_geometry.is_basis_basic_open AlgebraicGeometry.isBasis_basicOpen namespace IsAffineOpen -variable {X Y : Scheme.{u}} {U : Opens X} (hU : IsAffineOpen U) (f : X.presheaf.obj (op U)) - -local notation "𝖲𝗉𝖾𝖼 𝓞ₓ(U)" => Scheme.Spec.obj (op <| X.presheaf.obj <| op U) +variable {X Y : Scheme.{u}} {U : Opens X} (hU : IsAffineOpen U) (f : Γ(X, U)) -/-- The open immersion `Spec 𝒪ₓ(U) ⟶ X` for an affine `U`. -/ +/-- The open immersion `Spec Γ(X, U) ⟶ X` for an affine `U`. -/ def fromSpec : - 𝖲𝗉𝖾𝖼 𝓞ₓ(U) ⟶ X := + (𝖲𝗉𝖾𝖼 Γ(X, U)) ⟶ X := haveI : IsAffine (X ∣_ᵤ U) := hU Scheme.Spec.map (X.presheaf.map (eqToHom U.openEmbedding_obj_top.symm).op).op ≫ (X ∣_ᵤ U).isoSpec.inv ≫ Scheme.ιOpens U @@ -274,6 +260,7 @@ instance isOpenImmersion_fromSpec : infer_instance #align algebraic_geometry.is_affine_open.is_open_immersion_from_Spec AlgebraicGeometry.IsAffineOpen.isOpenImmersion_fromSpec +@[simp] theorem range_fromSpec : Set.range hU.fromSpec.1.base = (U : Set X) := by delta IsAffineOpen.fromSpec; dsimp @@ -283,11 +270,14 @@ theorem range_fromSpec : infer_instance #align algebraic_geometry.is_affine_open.from_Spec_range AlgebraicGeometry.IsAffineOpen.range_fromSpec -theorem fromSpec_image_top : - hU.fromSpec.opensFunctor.obj ⊤ = U := by - ext1; exact Set.image_univ.trans hU.range_fromSpec +@[simp] +theorem fromSpec_image_top : hU.fromSpec ''ᵁ ⊤ = U := + Opens.ext (Set.image_univ.trans (range_fromSpec hU)) #align algebraic_geometry.is_affine_open.from_Spec_image_top AlgebraicGeometry.IsAffineOpen.fromSpec_image_top +@[simp] +theorem opensRange_fromSpec : Scheme.Hom.opensRange hU.fromSpec = U := Opens.ext (range_fromSpec hU) + protected theorem isCompact : IsCompact (U : Set X) := by convert @IsCompact.image _ _ _ _ Set.univ hU.fromSpec.1.base PrimeSpectrum.compactSpace.1 @@ -297,7 +287,7 @@ protected theorem isCompact : #align algebraic_geometry.is_affine_open.is_compact AlgebraicGeometry.IsAffineOpen.isCompact theorem image_of_isOpenImmersion (f : X ⟶ Y) [H : IsOpenImmersion f] : - IsAffineOpen (f.opensFunctor.obj U) := by + IsAffineOpen (f ''ᵁ U) := by have : IsAffine _ := hU convert isAffineOpen_opensRange (X.ofRestrict U.openEmbedding ≫ f) ext1 @@ -306,7 +296,7 @@ theorem image_of_isOpenImmersion (f : X ⟶ Y) [H : IsOpenImmersion f] : theorem _root_.AlgebraicGeometry.Scheme.Hom.isAffineOpen_iff_of_isOpenImmersion (f : AlgebraicGeometry.Scheme.Hom X Y) [H : IsOpenImmersion f] {U : Opens X} : - IsAffineOpen (f.opensFunctor.obj U) ↔ IsAffineOpen U := by + IsAffineOpen (f ''ᵁ U) ↔ IsAffineOpen U := by refine ⟨fun hU => @isAffine_of_isIso _ _ (IsOpenImmersion.isoOfRangeEq (X.ofRestrict U.openEmbedding ≫ f) (Y.ofRestrict _) ?_).hom ?_ hU, fun hU => hU.image_of_isOpenImmersion f⟩ @@ -317,11 +307,13 @@ theorem _root_.AlgebraicGeometry.Scheme.Hom.isAffineOpen_iff_of_isOpenImmersion · infer_instance #align algebraic_geometry.is_affine_open_iff_of_is_open_immersion AlgebraicGeometry.Scheme.Hom.isAffineOpen_iff_of_isOpenImmersion -instance _root_.AlgebraicGeometry.Scheme.compactSpace_of_isAffine (X : Scheme) [IsAffine X] : +instance (priority := 100) _root_.AlgebraicGeometry.Scheme.compactSpace_of_isAffine + (X : Scheme) [IsAffine X] : CompactSpace X := ⟨(isAffineOpen_top X).isCompact⟩ #align algebraic_geometry.Scheme.quasi_compact_of_affine AlgebraicGeometry.Scheme.compactSpace_of_isAffine +@[simp] theorem fromSpec_preimage_self : hU.fromSpec ⁻¹ᵁ U = ⊤ := by ext1 @@ -335,8 +327,8 @@ set_option maxHeartbeats 400000 in -- Doesn't build without the `IsAffine` instance but the linter complains @[nolint unusedHavesSuffices] theorem SpecΓIdentity_hom_app_fromSpec : - SpecΓIdentity.hom.app (X.presheaf.obj <| op U) ≫ hU.fromSpec.1.c.app (op U) = - (𝖲𝗉𝖾𝖼 𝓞ₓ(U)).presheaf.map (eqToHom hU.fromSpec_preimage_self).op := by + Scheme.SpecΓIdentity.hom.app Γ(X, U) ≫ hU.fromSpec.1.c.app (op U) = + (𝖲𝗉𝖾𝖼 Γ(X, U)).presheaf.map (eqToHom hU.fromSpec_preimage_self).op := by have : IsAffine _ := hU delta IsAffineOpen.fromSpec Scheme.isoSpec rw [Scheme.comp_val_c_app, Scheme.comp_val_c_app, SpecΓIdentity_hom_app_presheaf_obj, @@ -350,15 +342,15 @@ theorem SpecΓIdentity_hom_app_fromSpec : @[elementwise] theorem fromSpec_app_self : - hU.fromSpec.1.c.app (op U) = SpecΓIdentity.inv.app (X.presheaf.obj <| op U) ≫ - (𝖲𝗉𝖾𝖼 𝓞ₓ(U)).presheaf.map (eqToHom hU.fromSpec_preimage_self).op := by + hU.fromSpec.1.c.app (op U) = Scheme.SpecΓIdentity.inv.app Γ(X, U) ≫ + (𝖲𝗉𝖾𝖼 Γ(X, U)).presheaf.map (eqToHom hU.fromSpec_preimage_self).op := by rw [← hU.SpecΓIdentity_hom_app_fromSpec, ← NatTrans.comp_app_assoc, Iso.inv_hom_id, NatTrans.id_app, Category.id_comp] #align algebraic_geometry.is_affine_open.from_Spec_app_eq AlgebraicGeometry.IsAffineOpen.fromSpec_app_self theorem fromSpec_preimage_basicOpen' : hU.fromSpec ⁻¹ᵁ X.basicOpen f = - (𝖲𝗉𝖾𝖼 𝓞ₓ(U)).basicOpen (SpecΓIdentity.inv.app (X.presheaf.obj (op U)) f) := by + (𝖲𝗉𝖾𝖼 Γ(X, U)).basicOpen (Scheme.SpecΓIdentity.inv.app Γ(X, U) f) := by rw [Scheme.preimage_basicOpen, hU.fromSpec_app_self] exact Scheme.basicOpen_res_eq _ _ (eqToHom hU.fromSpec_preimage_self).op #align algebraic_geometry.is_affine_open.opens_map_from_Spec_basic_open AlgebraicGeometry.IsAffineOpen.fromSpec_preimage_basicOpen' @@ -369,7 +361,7 @@ theorem fromSpec_preimage_basicOpen : #align algebraic_geometry.is_affine_open.from_Spec_map_basic_open AlgebraicGeometry.IsAffineOpen.fromSpec_preimage_basicOpen theorem fromSpec_image_basicOpen : - hU.fromSpec.opensFunctor.obj (PrimeSpectrum.basicOpen f) = X.basicOpen f := by + hU.fromSpec ''ᵁ (PrimeSpectrum.basicOpen f) = X.basicOpen f := by rw [← hU.fromSpec_preimage_basicOpen] ext1 change hU.fromSpec.val.base '' (hU.fromSpec.val.base ⁻¹' (X.basicOpen f : Set X)) = _ @@ -382,8 +374,7 @@ theorem fromSpec_image_basicOpen : -- I am not sure if this is intentional or not. @[simp, nolint simpNF] theorem basicOpen_fromSpec_app : - (𝖲𝗉𝖾𝖼 𝓞ₓ(U)).basicOpen (hU.fromSpec.1.c.app (op U) f) = - PrimeSpectrum.basicOpen f := by + (𝖲𝗉𝖾𝖼 Γ(X, U)).basicOpen (hU.fromSpec.1.c.app (op U) f) = PrimeSpectrum.basicOpen f := by rw [← hU.fromSpec_preimage_basicOpen, Scheme.preimage_basicOpen] #align algebraic_geometry.is_affine_open.basic_open_from_Spec_app AlgebraicGeometry.IsAffineOpen.basicOpen_fromSpec_app @@ -391,11 +382,11 @@ theorem basicOpen : IsAffineOpen (X.basicOpen f) := by rw [← hU.fromSpec_image_basicOpen, Scheme.Hom.isAffineOpen_iff_of_isOpenImmersion] convert isAffineOpen_opensRange (Scheme.Spec.map - (CommRingCat.ofHom <| algebraMap (X.presheaf.obj (op U)) (Localization.Away f)).op) + (CommRingCat.ofHom <| algebraMap Γ(X, U) (Localization.Away f)).op) exact Opens.ext (PrimeSpectrum.localization_away_comap_range (Localization.Away f) f).symm #align algebraic_geometry.is_affine_open.basic_open_is_affine AlgebraicGeometry.IsAffineOpen.basicOpen -theorem ιOpens_preimage (r : X.presheaf.obj (op ⊤)) : +theorem ιOpens_preimage (r : Γ(X, ⊤)): IsAffineOpen (Scheme.ιOpens (X.basicOpen r) ⁻¹ᵁ U) := by apply (Scheme.ιOpens (X.basicOpen r)).isAffineOpen_iff_of_isOpenImmersion.mp dsimp [Scheme.Hom.opensFunctor, PresheafedSpace.IsOpenImmersion.openFunctor] @@ -405,7 +396,7 @@ theorem ιOpens_preimage (r : X.presheaf.obj (op ⊤)) : #align algebraic_geometry.is_affine_open.map_restrict_basic_open AlgebraicGeometry.IsAffineOpen.ιOpens_preimage theorem exists_basicOpen_le {V : Opens X} (x : V) (h : ↑x ∈ U) : - ∃ f : X.presheaf.obj (op U), X.basicOpen f ≤ V ∧ ↑x ∈ X.basicOpen f := by + ∃ f : Γ(X, U), X.basicOpen f ≤ V ∧ ↑x ∈ X.basicOpen f := by have : IsAffine _ := hU obtain ⟨_, ⟨_, ⟨r, rfl⟩, rfl⟩, h₁, h₂⟩ := (isBasis_basicOpen (X ∣_ᵤ U)).exists_subset_of_mem_open (x.2 : ⟨x, h⟩ ∈ _) @@ -428,10 +419,9 @@ theorem exists_basicOpen_le {V : Opens X} (x : V) (h : ↑x ∈ U) : this is the canonical map `Γ(𝒪ₓ, D(f)) ⟶ Γ(Spec 𝒪ₓ(U), D(f))` This is an isomorphism, as witnessed by an `IsIso` instance. -/ def basicOpenSectionsToAffine : - X.presheaf.obj (op <| X.basicOpen f) ⟶ - (𝖲𝗉𝖾𝖼 𝓞ₓ(U)).presheaf.obj (op <| PrimeSpectrum.basicOpen f) := + Γ(X, X.basicOpen f) ⟶ Γ(𝖲𝗉𝖾𝖼 Γ(X, U), PrimeSpectrum.basicOpen f) := hU.fromSpec.1.c.app (op <| X.basicOpen f) ≫ - (𝖲𝗉𝖾𝖼 𝓞ₓ(U)).presheaf.map (eqToHom <| (hU.fromSpec_preimage_basicOpen f).symm).op + (𝖲𝗉𝖾𝖼 Γ(X, U)).presheaf.map (eqToHom <| (hU.fromSpec_preimage_basicOpen f).symm).op #align algebraic_geometry.basic_open_sections_to_affine AlgebraicGeometry.IsAffineOpen.basicOpenSectionsToAffine instance basicOpenSectionsToAffine_isIso : @@ -443,7 +433,7 @@ instance basicOpenSectionsToAffine_isIso : exact RingedSpace.basicOpen_le _ _ theorem isLocalization_basicOpen : - IsLocalization.Away f (X.presheaf.obj (op <| X.basicOpen f)) := by + IsLocalization.Away f Γ(X, X.basicOpen f) := by apply (IsLocalization.isLocalization_iff_of_ringEquiv (Submonoid.powers f) (asIso <| basicOpenSectionsToAffine hU f).commRingCatIsoToRingEquiv).mpr @@ -462,12 +452,12 @@ theorem isLocalization_basicOpen : #align algebraic_geometry.is_localization_basic_open AlgebraicGeometry.IsAffineOpen.isLocalization_basicOpen instance _root_.AlgebraicGeometry.isLocalization_away_of_isAffine - [IsAffine X] (r : X.presheaf.obj (op ⊤)) : - IsLocalization.Away r (X.presheaf.obj (op <| X.basicOpen r)) := + [IsAffine X] (r : Γ(X, ⊤)) : + IsLocalization.Away r Γ(X, X.basicOpen r) := isLocalization_basicOpen (isAffineOpen_top X) r theorem isLocalization_of_eq_basicOpen {V : Opens X} (i : V ⟶ U) (e : V = X.basicOpen f) : - @IsLocalization.Away _ _ f (X.presheaf.obj (op V)) _ (X.presheaf.map i.op).toAlgebra := by + @IsLocalization.Away _ _ f Γ(X, V) _ (X.presheaf.map i.op).toAlgebra := by subst e; convert isLocalization_basicOpen hU f using 3 #align algebraic_geometry.is_localization_of_eq_basic_open AlgebraicGeometry.IsAffineOpen.isLocalization_of_eq_basicOpen @@ -477,8 +467,8 @@ instance _root_.AlgebraicGeometry.Γ_restrict_isLocalization (isAffineOpen_top X).isLocalization_of_eq_basicOpen r _ (Opens.openEmbedding_obj_top _) #align algebraic_geometry.Γ_restrict_is_localization AlgebraicGeometry.Γ_restrict_isLocalization -theorem basicOpen_basicOpen_is_basicOpen (g : X.presheaf.obj (op <| X.basicOpen f)) : - ∃ f' : X.presheaf.obj (op U), X.basicOpen f' = X.basicOpen g := by +theorem basicOpen_basicOpen_is_basicOpen (g : Γ(X, X.basicOpen f)) : + ∃ f' : Γ(X, U), X.basicOpen f' = X.basicOpen g := by have := isLocalization_basicOpen hU f obtain ⟨x, ⟨_, n, rfl⟩, rfl⟩ := IsLocalization.surj'' (Submonoid.powers f) g use f * x @@ -490,14 +480,13 @@ theorem basicOpen_basicOpen_is_basicOpen (g : X.presheaf.obj (op <| X.basicOpen apply Scheme.basicOpen_of_isUnit apply Submonoid.leftInv_le_isUnit _ - (IsLocalization.toInvSubmonoid (Submonoid.powers f) (X.presheaf.obj (op <| X.basicOpen f)) + (IsLocalization.toInvSubmonoid (Submonoid.powers f) (Γ(X, X.basicOpen f)) _).prop #align algebraic_geometry.basic_open_basic_open_is_basic_open AlgebraicGeometry.IsAffineOpen.basicOpen_basicOpen_is_basicOpen theorem _root_.AlgebraicGeometry.exists_basicOpen_le_affine_inter {V : Opens X} (hV : IsAffineOpen V) (x : X) (hx : x ∈ U ⊓ V) : - ∃ (f : X.presheaf.obj <| op U) (g : X.presheaf.obj <| op V), - X.basicOpen f = X.basicOpen g ∧ x ∈ X.basicOpen f := by + ∃ (f : Γ(X, U)) (g : Γ(X, V)), X.basicOpen f = X.basicOpen g ∧ x ∈ X.basicOpen f := by obtain ⟨f, hf₁, hf₂⟩ := hU.exists_basicOpen_le ⟨x, hx.2⟩ hx.1 obtain ⟨g, hg₁, hg₂⟩ := hV.exists_basicOpen_le ⟨x, hf₂⟩ hx.2 obtain ⟨f', hf'⟩ := @@ -508,7 +497,7 @@ theorem _root_.AlgebraicGeometry.exists_basicOpen_le_affine_inter /-- The prime ideal of `𝒪ₓ(U)` corresponding to a point `x : U`. -/ noncomputable def primeIdealOf (x : U) : - PrimeSpectrum (X.presheaf.obj <| op U) := + PrimeSpectrum Γ(X, U) := ((@Scheme.isoSpec (X ∣_ᵤ U) hU).hom ≫ Scheme.Spec.map (X.presheaf.map (eqToHom U.openEmbedding_obj_top).op).op).1.base x #align algebraic_geometry.is_affine_open.prime_ideal_of AlgebraicGeometry.IsAffineOpen.primeIdealOf @@ -528,20 +517,19 @@ theorem fromSpec_primeIdealOf (x : U) : #align algebraic_geometry.is_affine_open.from_Spec_prime_ideal_of AlgebraicGeometry.IsAffineOpen.fromSpec_primeIdealOf set_option backward.isDefEq.lazyWhnfCore false in -- See https://github.com/leanprover-community/mathlib4/issues/12534 -theorem isLocalization_stalk' - (y : PrimeSpectrum (X.presheaf.obj <| op U)) (hy : hU.fromSpec.1.base y ∈ U) : +theorem isLocalization_stalk' (y : PrimeSpectrum Γ(X, U)) (hy : hU.fromSpec.1.base y ∈ U) : @IsLocalization.AtPrime - (R := X.presheaf.obj <| op U) + (R := Γ(X, U)) (S := X.presheaf.stalk <| hU.fromSpec.1.base y) _ _ ((TopCat.Presheaf.algebra_section_stalk X.presheaf _)) y.asIdeal _ := by apply - (@IsLocalization.isLocalization_iff_of_ringEquiv (R := X.presheaf.obj <| op U) + (@IsLocalization.isLocalization_iff_of_ringEquiv (R := Γ(X, U)) (S := X.presheaf.stalk (hU.fromSpec.1.base y)) _ y.asIdeal.primeCompl _ (TopCat.Presheaf.algebra_section_stalk X.presheaf ⟨hU.fromSpec.1.base y, hy⟩) _ _ (asIso <| PresheafedSpace.stalkMap hU.fromSpec.1 y).commRingCatIsoToRingEquiv).mpr -- Porting note: need to know what the ring is and after convert, instead of equality -- we get an `iff`. - convert StructureSheaf.IsLocalization.to_stalk (X.presheaf.obj <| op U) y using 1 + convert StructureSheaf.IsLocalization.to_stalk Γ(X, U) y using 1 delta IsLocalization.AtPrime StructureSheaf.stalkAlgebra rw [iff_iff_eq] congr 2 @@ -564,15 +552,15 @@ theorem isLocalization_stalk (x : U) : /-- The basic open set of a section `f` on an affine open as an `X.affineOpens`. -/ @[simps] def _root_.AlgebraicGeometry.Scheme.affineBasicOpen - (X : Scheme) {U : X.affineOpens} (f : X.presheaf.obj <| op U) : X.affineOpens := + (X : Scheme) {U : X.affineOpens} (f : Γ(X, U)) : X.affineOpens := ⟨X.basicOpen f, U.prop.basicOpen f⟩ #align algebraic_geometry.Scheme.affine_basic_open AlgebraicGeometry.Scheme.affineBasicOpen -theorem basicOpen_union_eq_self_iff (s : Set (X.presheaf.obj <| op U)) : - ⨆ f : s, X.basicOpen (f : X.presheaf.obj <| op U) = U ↔ Ideal.span s = ⊤ := by +theorem basicOpen_union_eq_self_iff (s : Set Γ(X, U)) : + ⨆ f : s, X.basicOpen (f : Γ(X, U)) = U ↔ Ideal.span s = ⊤ := by trans ⋃ i : s, (PrimeSpectrum.basicOpen i.1).1 = Set.univ · trans - hU.fromSpec.1.base ⁻¹' (⨆ f : s, X.basicOpen (f : X.presheaf.obj <| op U)).1 = + hU.fromSpec.1.base ⁻¹' (⨆ f : s, X.basicOpen (f : Γ(X, U))).1 = hU.fromSpec.1.base ⁻¹' U.1 · refine ⟨fun h => by rw [h], ?_⟩ intro h @@ -597,8 +585,8 @@ theorem basicOpen_union_eq_self_iff (s : Set (X.presheaf.obj <| op U)) : simp only [Set.iUnion_singleton_eq_range, Subtype.range_val_subtype, Set.setOf_mem_eq] #align algebraic_geometry.is_affine_open.basic_open_union_eq_self_iff AlgebraicGeometry.IsAffineOpen.basicOpen_union_eq_self_iff -theorem self_le_basicOpen_union_iff (s : Set (X.presheaf.obj <| op U)) : - (U ≤ ⨆ f : s, X.basicOpen (f : X.presheaf.obj <| op U)) ↔ Ideal.span s = ⊤ := by +theorem self_le_basicOpen_union_iff (s : Set Γ(X, U)) : + (U ≤ ⨆ f : s, X.basicOpen f.1) ↔ Ideal.span s = ⊤ := by rw [← hU.basicOpen_union_eq_self_iff, @comm _ Eq] refine ⟨fun h => le_antisymm h ?_, le_of_eq⟩ simp only [iSup_le_iff, SetCoe.forall] @@ -619,15 +607,14 @@ This is also known as the **Affine communication lemma** in [*The rising sea*][R @[elab_as_elim] theorem of_affine_open_cover {X : Scheme} (V : X.affineOpens) (S : Set X.affineOpens) {P : X.affineOpens → Prop} - (hP₁ : ∀ (U : X.affineOpens) (f : X.presheaf.obj <| op U.1), P U → P (X.affineBasicOpen f)) + (hP₁ : ∀ (U : X.affineOpens) (f : Γ(X, U)), P U → P (X.affineBasicOpen f)) (hP₂ : - ∀ (U : X.affineOpens) (s : Finset (X.presheaf.obj <| op U)) - (_ : Ideal.span (s : Set (X.presheaf.obj <| op U)) = ⊤), + ∀ (U : X.affineOpens) (s : Finset (Γ(X, U))) + (_ : Ideal.span (s : Set (Γ(X, U))) = ⊤), (∀ f : s, P (X.affineBasicOpen f.1)) → P U) (hS : (⋃ i : S, i : Set X) = Set.univ) (hS' : ∀ U : S, P U) : P V := by classical - have : ∀ (x : V.1), ∃ f : X.presheaf.obj <| op V.1, - ↑x ∈ X.basicOpen f ∧ P (X.affineBasicOpen f) := by + have : ∀ (x : V.1), ∃ f : Γ(X, V), ↑x ∈ X.basicOpen f ∧ P (X.affineBasicOpen f) := by intro x obtain ⟨W, hW⟩ := Set.mem_iUnion.mp (by simpa only [← hS] using Set.mem_univ (x : X)) obtain ⟨f, g, e, hf⟩ := exists_basicOpen_le_affine_inter V.prop W.1.prop x ⟨x.prop, hW⟩ diff --git a/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean b/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean index 89e4ddcf3886e4..e88c994a3bad66 100644 --- a/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean +++ b/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean @@ -436,23 +436,25 @@ theorem adjunction_homEquiv_symm_apply {X : Scheme} {R : CommRingCatᵒᵖ} #align algebraic_geometry.Γ_Spec.adjunction_hom_equiv_symm_apply AlgebraicGeometry.ΓSpec.adjunction_homEquiv_symm_apply set_option backward.isDefEq.lazyWhnfCore false in -- See https://github.com/leanprover-community/mathlib4/issues/12534 -@[simp] -theorem adjunction_counit_app {R : CommRingCatᵒᵖ} : +theorem adjunction_counit_app' {R : CommRingCatᵒᵖ} : ΓSpec.adjunction.counit.app R = locallyRingedSpaceAdjunction.counit.app R := by rw [← Adjunction.homEquiv_symm_id, ← Adjunction.homEquiv_symm_id, adjunction_homEquiv_symm_apply] rfl -#align algebraic_geometry.Γ_Spec.adjunction_counit_app AlgebraicGeometry.ΓSpec.adjunction_counit_app +#align algebraic_geometry.Γ_Spec.adjunction_counit_app AlgebraicGeometry.ΓSpec.adjunction_counit_app' @[simp] +theorem adjunction_counit_app {R : CommRingCatᵒᵖ} : + ΓSpec.adjunction.counit.app R = (Scheme.SpecΓIdentity.inv.app (unop R)).op := by + rw [adjunction_counit_app'] + rfl + +-- This is not a simp lemma to respect the abstraction theorem adjunction_unit_app {X : Scheme} : ΓSpec.adjunction.unit.app X = locallyRingedSpaceAdjunction.unit.app X.1 := by rw [← Adjunction.homEquiv_id, ← Adjunction.homEquiv_id, adjunction_homEquiv_apply]; rfl #align algebraic_geometry.Γ_Spec.adjunction_unit_app AlgebraicGeometry.ΓSpec.adjunction_unit_app --- Porting Note: Commented --- attribute [local semireducible] locallyRingedSpaceAdjunction ΓSpec.adjunction - instance isIso_locallyRingedSpaceAdjunction_counit : IsIso.{u + 1, u + 1} locallyRingedSpaceAdjunction.counit := (NatIso.op SpecΓIdentity).isIso_inv @@ -465,39 +467,61 @@ instance isIso_adjunction_counit : IsIso ΓSpec.adjunction.counit := by infer_instance #align algebraic_geometry.Γ_Spec.is_iso_adjunction_counit AlgebraicGeometry.ΓSpec.isIso_adjunction_counit +@[simp] theorem adjunction_unit_app_app_top (X : Scheme.{u}) : - (ΓSpec.adjunction.unit.app X).1.c.app (op ⊤) = - SpecΓIdentity.hom.app (X.presheaf.obj (op ⊤)) := by - have := congr_app ΓSpec.adjunction.left_triangle X + (ΓSpec.adjunction.unit.app X).1.c.app (op ⊤) = Scheme.SpecΓIdentity.hom.app Γ(X, ⊤) := by + have := ΓSpec.adjunction.left_triangle_components X dsimp at this - -- Porting note: Slightly changed some rewrites. - -- Originally: - -- rw [← is_iso.eq_comp_inv] at this - -- simp only [Γ_Spec.LocallyRingedSpace_adjunction_counit, nat_trans.op_app, category.id_comp, - -- Γ_Spec.adjunction_counit_app] at this - -- rw [← op_inv, nat_iso.inv_inv_app, quiver.hom.op_inj.eq_iff] at this rw [← IsIso.eq_comp_inv] at this - simp only [adjunction_counit_app, locallyRingedSpaceAdjunction_counit, NatIso.op_inv, - NatTrans.op_app, unop_op, Functor.id_obj, Functor.comp_obj, Functor.rightOp_obj, - Spec.toLocallyRingedSpace_obj, Γ_obj, Spec.locallyRingedSpaceObj_toSheafedSpace, - Spec.sheafedSpaceObj_carrier, Spec.sheafedSpaceObj_presheaf, - SpecΓIdentity_inv_app, Category.id_comp] at this - rw [← op_inv, Quiver.Hom.op_inj.eq_iff] at this - -- Note: changed from `rw` to `simp_rw` to improve performance - simp_rw [SpecΓIdentity_hom_app] - exact this + simp only [adjunction_counit_app, Functor.id_obj, Functor.comp_obj, Functor.rightOp_obj, + Scheme.Γ_obj, Category.id_comp] at this + rw [← Quiver.Hom.op_inj.eq_iff, this, ← op_inv, NatIso.inv_inv_app] #align algebraic_geometry.Γ_Spec.adjunction_unit_app_app_top AlgebraicGeometry.ΓSpec.adjunction_unit_app_app_top +@[simp] +theorem adjunction_unit_app_Spec (R : CommRingCat.{u}) : + adjunction.unit.app (𝖲𝗉𝖾𝖼 R) = 𝖲𝗉𝖾𝖼(Scheme.SpecΓIdentity.hom.app R) := by + have := ΓSpec.adjunction.right_triangle_components (op R) + dsimp at this + rwa [adjunction_counit_app, ← IsIso.eq_comp_inv, Category.id_comp, + ← Functor.map_inv, ← op_inv, NatIso.inv_inv_app] at this + +lemma adjunction_unit_map_basicOpen (X : Scheme.{u}) (r : Γ(X, ⊤)) : + (ΓSpec.adjunction.unit.app X ⁻¹ᵁ (PrimeSpectrum.basicOpen r)) = X.basicOpen r := by + rw [← basicOpen_eq_of_affine] + erw [Scheme.preimage_basicOpen] + congr + rw [ΓSpec.adjunction_unit_app_app_top] + erw [← comp_apply] + simp + +theorem toOpen_unit_app_val_c_app {X : Scheme.{u}} (U) : + StructureSheaf.toOpen _ _ ≫ (ΓSpec.adjunction.unit.app X).val.c.app U = + X.presheaf.map (homOfLE (by exact le_top)).op := by + rw [← StructureSheaf.toOpen_res _ _ _ (homOfLE le_top), Category.assoc, + NatTrans.naturality _ (homOfLE (le_top (a := U.unop))).op] + show (ΓSpec.adjunction.counit.app (Scheme.Γ.rightOp.obj X)).unop ≫ + (Scheme.Γ.rightOp.map (ΓSpec.adjunction.unit.app X)).unop ≫ _ = _ + rw [← Category.assoc, ← unop_comp, ΓSpec.adjunction.left_triangle_components] + dsimp + exact Category.id_comp _ + +@[reassoc (attr := simp)] +theorem toOpen_unit_app_val_c_app' {X : Scheme.{u}} (U : Opens (PrimeSpectrum Γ(X, ⊤))) : + toOpen Γ(X, ⊤) U ≫ (adjunction.unit.app X).val.c.app (op U) = + X.presheaf.map (homOfLE (by exact le_top)).op := + ΓSpec.toOpen_unit_app_val_c_app (op U) + end ΓSpec @[reassoc] theorem SpecΓIdentity_naturality {R S : CommRingCat.{u}} (f : R ⟶ S) : - (Scheme.Spec.map f.op).1.c.app (op ⊤) ≫ SpecΓIdentity.hom.app _ = - SpecΓIdentity.hom.app _ ≫ f := SpecΓIdentity.hom.naturality f + (Scheme.Spec.map f.op).1.c.app (op ⊤) ≫ Scheme.SpecΓIdentity.hom.app _ = + Scheme.SpecΓIdentity.hom.app _ ≫ f := SpecΓIdentity.hom.naturality f theorem SpecΓIdentity_hom_app_presheaf_obj {X : Scheme.{u}} (U : Opens X) : - SpecΓIdentity.hom.app (X.presheaf.obj (op U)) = - Scheme.Γ.map (Scheme.Spec.map (X.presheaf.map (eqToHom U.openEmbedding_obj_top).op).op).op ≫ + Scheme.SpecΓIdentity.hom.app Γ(X, U) = + Scheme.Γ.map (𝖲𝗉𝖾𝖼(X.presheaf.map (eqToHom U.openEmbedding_obj_top).op)).op ≫ (ΓSpec.adjunction.unit.app (X ∣_ᵤ U)).val.c.app (op ⊤) ≫ X.presheaf.map (eqToHom U.openEmbedding_obj_top.symm).op := by rw [ΓSpec.adjunction_unit_app_app_top] diff --git a/Mathlib/AlgebraicGeometry/OpenImmersion.lean b/Mathlib/AlgebraicGeometry/OpenImmersion.lean index f18349de819031..a4b34ffe1f5a6d 100644 --- a/Mathlib/AlgebraicGeometry/OpenImmersion.lean +++ b/Mathlib/AlgebraicGeometry/OpenImmersion.lean @@ -440,16 +440,19 @@ abbrev _root_.AlgebraicGeometry.Scheme.Hom.opensFunctor {X Y : Scheme.{u}} (f : H.openFunctor #align algebraic_geometry.Scheme.hom.opens_functor AlgebraicGeometry.Scheme.Hom.opensFunctor +/-- `f ''ᵁ U` is notation for the image (as an open set) of `U` under an open immersion `f`. -/ +scoped[AlgebraicGeometry] notation3:90 f:91 " ''ᵁ " U:90 => (Scheme.Hom.opensFunctor f).obj U + /-- The isomorphism `Γ(X, U) ⟶ Γ(Y, f(U))` induced by an open immersion `f : X ⟶ Y`. -/ def _root_.AlgebraicGeometry.Scheme.Hom.invApp {X Y : Scheme.{u}} (f : X ⟶ Y) [H : IsOpenImmersion f] (U) : - X.presheaf.obj (op U) ⟶ Y.presheaf.obj (op (f.opensFunctor.obj U)) := + Γ(X, U) ⟶ Γ(Y, f ''ᵁ U) := H.invApp U #align algebraic_geometry.Scheme.hom.inv_app AlgebraicGeometry.Scheme.Hom.invApp theorem app_eq_inv_app_app_of_comp_eq_aux {X Y U : Scheme.{u}} (f : Y ⟶ U) (g : U ⟶ X) (fg : Y ⟶ X) (H : fg = f ≫ g) [h : IsOpenImmersion g] (V : Opens U) : - (Opens.map f.1.base).obj V = (Opens.map fg.1.base).obj (g.opensFunctor.obj V) := by + f ⁻¹ᵁ V = fg ⁻¹ᵁ (g ''ᵁ V) := by subst H rw [Scheme.comp_val_base, Opens.map_comp_obj] congr 1 @@ -490,8 +493,8 @@ end IsOpenImmersion namespace Scheme theorem image_basicOpen {X Y : Scheme.{u}} (f : X ⟶ Y) [H : IsOpenImmersion f] {U : Opens X} - (r : X.presheaf.obj (op U)) : - f.opensFunctor.obj (X.basicOpen r) = Y.basicOpen (Scheme.Hom.invApp f U r) := by + (r : Γ(X, U)) : + f ''ᵁ X.basicOpen r = Y.basicOpen (Scheme.Hom.invApp f U r) := by have e := Scheme.preimage_basicOpen f (Scheme.Hom.invApp f U r) rw [Scheme.Hom.invApp] at e -- Porting note (#10691): was `rw` diff --git a/Mathlib/AlgebraicGeometry/Properties.lean b/Mathlib/AlgebraicGeometry/Properties.lean index 4a67fe7afd31b9..8ee94f9349f151 100644 --- a/Mathlib/AlgebraicGeometry/Properties.lean +++ b/Mathlib/AlgebraicGeometry/Properties.lean @@ -34,14 +34,14 @@ namespace AlgebraicGeometry variable (X : Scheme) -instance : T0Space X.carrier := by +instance : T0Space X := by refine T0Space.of_open_cover fun x => ?_ obtain ⟨U, R, ⟨e⟩⟩ := X.local_affine x let e' : U.1 ≃ₜ PrimeSpectrum R := homeoOfIso ((LocallyRingedSpace.forgetToSheafedSpace ⋙ SheafedSpace.forget _).mapIso e) exact ⟨U.1.1, U.2, U.1.2, e'.embedding.t0Space⟩ -instance : QuasiSober X.carrier := by +instance : QuasiSober X := by apply (config := { allowSynthFailures := true }) quasiSober_of_open_cover (Set.range fun x => Set.range <| (X.affineCover.map x).1.base) · rintro ⟨_, i, rfl⟩; exact (X.affineCover.IsOpen i).base_open.isOpen_range @@ -53,12 +53,12 @@ instance : QuasiSober X.carrier := by /-- A scheme `X` is reduced if all `𝒪ₓ(U)` are reduced. -/ class IsReduced : Prop where - component_reduced : ∀ U, IsReduced (X.presheaf.obj (op U)) := by infer_instance + component_reduced : ∀ U, IsReduced Γ(X, U) := by infer_instance #align algebraic_geometry.is_reduced AlgebraicGeometry.IsReduced attribute [instance] IsReduced.component_reduced -theorem isReduced_of_isReduced_stalk [∀ x : X.carrier, _root_.IsReduced (X.presheaf.stalk x)] : +theorem isReduced_of_isReduced_stalk [∀ x : X, _root_.IsReduced (X.presheaf.stalk x)] : IsReduced X := by refine ⟨fun U => ⟨fun s hs => ?_⟩⟩ apply Presheaf.section_ext X.sheaf U s 0 @@ -68,7 +68,7 @@ theorem isReduced_of_isReduced_stalk [∀ x : X.carrier, _root_.IsReduced (X.pre exact (hs.map _).eq_zero #align algebraic_geometry.is_reduced_of_stalk_is_reduced AlgebraicGeometry.isReduced_of_isReduced_stalk -instance isReduced_stalk_of_isReduced [IsReduced X] (x : X.carrier) : +instance isReduced_stalk_of_isReduced [IsReduced X] (x : X) : _root_.IsReduced (X.presheaf.stalk x) := by constructor rintro g ⟨n, e⟩ @@ -76,7 +76,7 @@ instance isReduced_stalk_of_isReduced [IsReduced X] (x : X.carrier) : rw [← map_pow, ← map_zero (X.presheaf.germ ⟨x, hxU⟩)] at e obtain ⟨V, hxV, iU, iV, e'⟩ := X.presheaf.germ_eq x hxU hxU _ 0 e rw [map_pow, map_zero] at e' - replace e' := (IsNilpotent.mk _ _ e').eq_zero (R := X.presheaf.obj <| op V) + replace e' := (IsNilpotent.mk _ _ e').eq_zero (R := Γ(X, V)) erw [← ConcreteCategory.congr_hom (X.presheaf.germ_res iU ⟨x, hxV⟩) s] rw [comp_apply, e', map_zero] #align algebraic_geometry.stalk_is_reduced_of_reduced AlgebraicGeometry.isReduced_stalk_of_isReduced @@ -85,15 +85,15 @@ theorem isReduced_of_isOpenImmersion {X Y : Scheme} (f : X ⟶ Y) [H : IsOpenImm [IsReduced Y] : IsReduced X := by constructor intro U - have : U = (Opens.map f.1.base).obj (H.base_open.isOpenMap.functor.obj U) := by + have : U = f ⁻¹ᵁ f ''ᵁ U := by ext1; exact (Set.preimage_image_eq _ H.base_open.inj).symm rw [this] - exact isReduced_of_injective (inv <| f.1.c.app (op <| H.base_open.isOpenMap.functor.obj U)) - (asIso <| f.1.c.app (op <| H.base_open.isOpenMap.functor.obj U) : - Y.presheaf.obj _ ≅ _).symm.commRingCatIsoToRingEquiv.injective + exact isReduced_of_injective (inv <| f.1.c.app (op <| f ''ᵁ U)) + (asIso <| f.1.c.app (op <| f ''ᵁ U) : + Γ(Y, f ''ᵁ U) ≅ _).symm.commRingCatIsoToRingEquiv.injective #align algebraic_geometry.is_reduced_of_open_immersion AlgebraicGeometry.isReduced_of_isOpenImmersion -instance {R : CommRingCat.{u}} [H : _root_.IsReduced R] : IsReduced (Scheme.Spec.obj <| op R) := by +instance {R : CommRingCat.{u}} [H : _root_.IsReduced R] : IsReduced (𝖲𝗉𝖾𝖼 R) := by apply (config := { allowSynthFailures := true }) isReduced_of_isReduced_stalk intro x; dsimp have : _root_.IsReduced (CommRingCat.of <| Localization.AtPrime (PrimeSpectrum.asIdeal x)) := by @@ -103,7 +103,7 @@ instance {R : CommRingCat.{u}} [H : _root_.IsReduced R] : IsReduced (Scheme.Spec (StructureSheaf.stalkIso R x).commRingCatIsoToRingEquiv.injective theorem affine_isReduced_iff (R : CommRingCat) : - IsReduced (Scheme.Spec.obj <| op R) ↔ _root_.IsReduced R := by + IsReduced (𝖲𝗉𝖾𝖼 R) ↔ _root_.IsReduced R := by refine ⟨?_, fun h => inferInstance⟩ intro h have : _root_.IsReduced @@ -112,10 +112,9 @@ theorem affine_isReduced_iff (R : CommRingCat) : exact isReduced_of_injective (toSpecΓ R) (asIso <| toSpecΓ R).commRingCatIsoToRingEquiv.injective #align algebraic_geometry.affine_is_reduced_iff AlgebraicGeometry.affine_isReduced_iff -theorem isReduced_of_isAffine_isReduced [IsAffine X] - [h : _root_.IsReduced (X.presheaf.obj (op ⊤))] : +theorem isReduced_of_isAffine_isReduced [IsAffine X] [h : _root_.IsReduced Γ(X, ⊤)] : IsReduced X := - haveI : IsReduced (Scheme.Spec.obj (op (Scheme.Γ.obj (op X)))) := by + haveI : IsReduced (𝖲𝗉𝖾𝖼 (Scheme.Γ.obj (op X))) := by rw [affine_isReduced_iff]; exact h isReduced_of_isOpenImmersion X.isoSpec.hom #align algebraic_geometry.is_reduced_of_is_affine_is_reduced AlgebraicGeometry.isReduced_of_isAffine_isReduced @@ -126,15 +125,15 @@ theorem isReduced_of_isAffine_isReduced [IsAffine X] the image of `f`. 3. `P` holds for the entire space of an affine scheme. -/ -theorem reduce_to_affine_global (P : ∀ (X : Scheme) (_ : Opens X.carrier), Prop) - (h₁ : ∀ (X : Scheme) (U : Opens X.carrier), - (∀ x : U, ∃ (V : _) (_ : x.1 ∈ V) (_ : V ⟶ U), P X V) → P X U) - (h₂ : ∀ {X Y} (f : X ⟶ Y) [hf : IsOpenImmersion f], - ∃ (U : Set X.carrier) (V : Set Y.carrier) (hU : U = ⊤) (hV : V = Set.range f.1.base), - P X ⟨U, hU.symm ▸ isOpen_univ⟩ → P Y ⟨V, hV.symm ▸ hf.base_open.isOpen_range⟩) - (h₃ : ∀ R : CommRingCat, P (Scheme.Spec.obj <| op R) ⊤) : - ∀ (X : Scheme) (U : Opens X.carrier), P X U := by - intro X U +@[elab_as_elim] +theorem reduce_to_affine_global (P : ∀ {X : Scheme} (_ : Opens X), Prop) + {X : Scheme} (U : Opens X) + (h₁ : ∀ (X : Scheme) (U : Opens X), + (∀ x : U, ∃ (V : _) (_ : x.1 ∈ V) (_ : V ⟶ U), P V) → P U) + (h₂ : ∀ (X Y) (f : X ⟶ Y) [hf : IsOpenImmersion f], + ∃ (U : Set X) (V : Set Y) (hU : U = ⊤) (hV : V = Set.range f.1.base), + P ⟨U, hU.symm ▸ isOpen_univ⟩ → P ⟨V, hV.symm ▸ hf.base_open.isOpen_range⟩) + (h₃ : ∀ R : CommRingCat, P (X := 𝖲𝗉𝖾𝖼 R) ⊤) : P U := by apply h₁ intro x obtain ⟨_, ⟨j, rfl⟩, hx, i⟩ := @@ -142,7 +141,7 @@ theorem reduce_to_affine_global (P : ∀ (X : Scheme) (_ : Opens X.carrier), Pro let U' : Opens _ := ⟨_, (X.affineBasisCover.IsOpen j).base_open.isOpen_range⟩ let i' : U' ⟶ U := homOfLE i refine ⟨U', hx, i', ?_⟩ - obtain ⟨_, _, rfl, rfl, h₂'⟩ := h₂ (X.affineBasisCover.map j) + obtain ⟨_, _, rfl, rfl, h₂'⟩ := h₂ _ _ (X.affineBasisCover.map j) apply h₂' apply h₃ #align algebraic_geometry.reduce_to_affine_global AlgebraicGeometry.reduce_to_affine_global @@ -158,14 +157,13 @@ theorem reduce_to_affine_nbhd (P : ∀ (X : Scheme) (_ : X.carrier), Prop) apply h₁ #align algebraic_geometry.reduce_to_affine_nbhd AlgebraicGeometry.reduce_to_affine_nbhd -theorem eq_zero_of_basicOpen_eq_bot {X : Scheme} [hX : IsReduced X] {U : Opens X.carrier} - (s : X.presheaf.obj (op U)) (hs : X.basicOpen s = ⊥) : s = 0 := by +theorem eq_zero_of_basicOpen_eq_bot {X : Scheme} [hX : IsReduced X] {U : Opens X} + (s : Γ(X, U)) (hs : X.basicOpen s = ⊥) : s = 0 := by apply TopCat.Presheaf.section_ext X.sheaf U - conv => intro x; rw [RingHom.map_zero] - refine (@reduce_to_affine_global (fun X U => - ∀ [IsReduced X] (s : X.presheaf.obj (op U)), - X.basicOpen s = ⊥ → ∀ x, (X.sheaf.presheaf.germ x) s = 0) ?_ ?_ ?_) X U s hs - · intro X U hx hX s hs x + intro x + rw [RingHom.map_zero] + induction U using reduce_to_affine_global generalizing hX with + | h₁ X U hx => obtain ⟨V, hx, i, H⟩ := hx x specialize H (X.presheaf.map i.op s) erw [Scheme.basicOpen_res] at H @@ -173,9 +171,9 @@ theorem eq_zero_of_basicOpen_eq_bot {X : Scheme} [hX : IsReduced X] {U : Opens X specialize H (inf_bot_eq _) ⟨x, hx⟩ erw [TopCat.Presheaf.germ_res_apply] at H exact H - · rintro X Y f hf + | h₂ X Y f => have e : f.val.base ⁻¹' Set.range ↑f.val.base = Set.univ := by - rw [← Set.image_univ, Set.preimage_image_eq _ hf.base_open.inj] + rw [← Set.image_univ, Set.preimage_image_eq _ ‹IsOpenImmersion f›.base_open.inj] refine ⟨_, _, e, rfl, ?_⟩ rintro H hX s hs ⟨_, x, rfl⟩ haveI := isReduced_of_isOpenImmersion f @@ -185,9 +183,9 @@ theorem eq_zero_of_basicOpen_eq_bot {X : Scheme} [hX : IsReduced X] {U : Opens X apply_fun inv <| PresheafedSpace.stalkMap f.val x at H erw [CategoryTheory.IsIso.hom_inv_id_apply, map_zero] at H exact H - · intro R hX s hs x + | h₃ R => erw [basicOpen_eq_of_affine', PrimeSpectrum.basicOpen_eq_bot_iff] at hs - replace hs := hs.map (SpecΓIdentity.app R).inv + replace hs := hs.map (Scheme.SpecΓIdentity.app R).inv -- what the hell?! replace hs := @IsNilpotent.eq_zero _ _ _ _ (show _ from ?_) hs · rw [Iso.hom_inv_id_apply] at hs @@ -206,9 +204,8 @@ theorem basicOpen_eq_bot_iff {X : Scheme} [IsReduced X] {U : Opens X.carrier} /-- A scheme `X` is integral if its carrier is nonempty, and `𝒪ₓ(U)` is an integral domain for each `U ≠ ∅`. -/ class IsIntegral : Prop where - nonempty : Nonempty X.carrier := by infer_instance - component_integral : ∀ (U : Opens X.carrier) [Nonempty U], IsDomain (X.presheaf.obj (op U)) := by - infer_instance + nonempty : Nonempty X := by infer_instance + component_integral : ∀ (U : Opens X) [Nonempty U], IsDomain Γ(X, U) := by infer_instance #align algebraic_geometry.is_integral AlgebraicGeometry.IsIntegral attribute [instance] IsIntegral.component_integral IsIntegral.nonempty @@ -222,27 +219,27 @@ instance (priority := 900) isReduced_of_isIntegral [IsIntegral X] : IsReduced X intro U rcases U.1.eq_empty_or_nonempty with h | h · have : U = ⊥ := SetLike.ext' h - haveI := CommRingCat.subsingleton_of_isTerminal (X.sheaf.isTerminalOfEqEmpty this) - change _root_.IsReduced (X.sheaf.val.obj (op U)) + haveI : Subsingleton Γ(X, U) := + CommRingCat.subsingleton_of_isTerminal (X.sheaf.isTerminalOfEqEmpty this) infer_instance · haveI : Nonempty U := by simpa infer_instance #align algebraic_geometry.is_reduced_of_is_integral AlgebraicGeometry.isReduced_of_isIntegral -instance irreducibleSpace_of_isIntegral [IsIntegral X] : IrreducibleSpace X.carrier := by +instance irreducibleSpace_of_isIntegral [IsIntegral X] : IrreducibleSpace X := by by_contra H - replace H : ¬IsPreirreducible (⊤ : Set X.carrier) := fun h => + replace H : ¬IsPreirreducible (⊤ : Set X) := fun h => H { toPreirreducibleSpace := ⟨h⟩ toNonempty := inferInstance } simp_rw [isPreirreducible_iff_closed_union_closed, not_forall, not_or] at H rcases H with ⟨S, T, hS, hT, h₁, h₂, h₃⟩ erw [not_forall] at h₂ h₃ simp_rw [not_forall] at h₂ h₃ - haveI : Nonempty (⟨Sᶜ, hS.1⟩ : Opens X.carrier) := ⟨⟨_, h₂.choose_spec.choose_spec⟩⟩ - haveI : Nonempty (⟨Tᶜ, hT.1⟩ : Opens X.carrier) := ⟨⟨_, h₃.choose_spec.choose_spec⟩⟩ - haveI : Nonempty (⟨Sᶜ, hS.1⟩ ⊔ ⟨Tᶜ, hT.1⟩ : Opens X.carrier) := + haveI : Nonempty (⟨Sᶜ, hS.1⟩ : Opens X) := ⟨⟨_, h₂.choose_spec.choose_spec⟩⟩ + haveI : Nonempty (⟨Tᶜ, hT.1⟩ : Opens X) := ⟨⟨_, h₃.choose_spec.choose_spec⟩⟩ + haveI : Nonempty (⟨Sᶜ, hS.1⟩ ⊔ ⟨Tᶜ, hT.1⟩ : Opens X) := ⟨⟨_, Or.inl h₂.choose_spec.choose_spec⟩⟩ - let e : X.presheaf.obj _ ≅ CommRingCat.of _ := + let e : Γ(X, _) ≅ CommRingCat.of _ := (X.sheaf.isProductOfDisjoint ⟨_, hS.1⟩ ⟨_, hT.1⟩ ?_).conePointUniqueUpToIso (CommRingCat.prodFanIsLimit _ _) · apply (config := { allowSynthFailures := true }) false_of_nontrivial_of_product_domain @@ -281,46 +278,44 @@ theorem isIntegral_of_irreducibleSpace_of_isReduced [IsReduced X] [H : Irreducib #align algebraic_geometry.is_integral_of_is_irreducible_is_reduced AlgebraicGeometry.isIntegral_of_irreducibleSpace_of_isReduced theorem isIntegral_iff_irreducibleSpace_and_isReduced : - IsIntegral X ↔ IrreducibleSpace X.carrier ∧ IsReduced X := + IsIntegral X ↔ IrreducibleSpace X ∧ IsReduced X := ⟨fun _ => ⟨inferInstance, inferInstance⟩, fun ⟨_, _⟩ => isIntegral_of_irreducibleSpace_of_isReduced X⟩ #align algebraic_geometry.is_integral_iff_is_irreducible_and_is_reduced AlgebraicGeometry.isIntegral_iff_irreducibleSpace_and_isReduced theorem isIntegral_of_isOpenImmersion {X Y : Scheme} (f : X ⟶ Y) [H : IsOpenImmersion f] - [IsIntegral Y] [Nonempty X.carrier] : IsIntegral X := by + [IsIntegral Y] [Nonempty X] : IsIntegral X := by constructor; · infer_instance intro U hU - have : U = (Opens.map f.1.base).obj (H.base_open.isOpenMap.functor.obj U) := by - ext1; exact (Set.preimage_image_eq _ H.base_open.inj).symm + have : U = f ⁻¹ᵁ f ''ᵁ U := by ext1; exact (Set.preimage_image_eq _ H.base_open.inj).symm rw [this] - have : IsDomain (Y.presheaf.obj (op (H.base_open.isOpenMap.functor.obj U))) := by + have : IsDomain Γ(Y, f ''ᵁ U) := by apply (config := { allowSynthFailures := true }) IsIntegral.component_integral exact ⟨⟨_, _, hU.some.prop, rfl⟩⟩ - exact (asIso <| f.1.c.app (op <| H.base_open.isOpenMap.functor.obj U) : - Y.presheaf.obj _ ≅ _).symm.commRingCatIsoToRingEquiv.toMulEquiv.isDomain _ + exact (asIso <| f.1.c.app (op <| f ''ᵁ U) : + Γ(Y, f ''ᵁ U) ≅ _).symm.commRingCatIsoToRingEquiv.toMulEquiv.isDomain _ #align algebraic_geometry.is_integral_of_open_immersion AlgebraicGeometry.isIntegral_of_isOpenImmersion -instance {R : CommRingCat} [H : IsDomain R] : - IrreducibleSpace (Scheme.Spec.obj <| op R).carrier := by +instance {R : CommRingCat} [IsDomain R] : IrreducibleSpace (𝖲𝗉𝖾𝖼 R) := by convert PrimeSpectrum.irreducibleSpace (R := R) -instance {R : CommRingCat} [IsDomain R] : IsIntegral (Scheme.Spec.obj <| op R) := +instance {R : CommRingCat} [IsDomain R] : IsIntegral (𝖲𝗉𝖾𝖼 R) := isIntegral_of_irreducibleSpace_of_isReduced _ theorem affine_isIntegral_iff (R : CommRingCat) : - IsIntegral (Scheme.Spec.obj <| op R) ↔ IsDomain R := - ⟨fun _ => MulEquiv.isDomain ((Scheme.Spec.obj <| op R).presheaf.obj (op ⊤)) + IsIntegral (𝖲𝗉𝖾𝖼 R) ↔ IsDomain R := + ⟨fun _ => MulEquiv.isDomain Γ(𝖲𝗉𝖾𝖼 R, ⊤) (asIso <| toSpecΓ R).commRingCatIsoToRingEquiv.toMulEquiv, fun _ => inferInstance⟩ #align algebraic_geometry.affine_is_integral_iff AlgebraicGeometry.affine_isIntegral_iff -theorem isIntegral_of_isAffine_of_isDomain [IsAffine X] [Nonempty X.carrier] - [h : IsDomain (X.presheaf.obj (op ⊤))] : IsIntegral X := +theorem isIntegral_of_isAffine_of_isDomain [IsAffine X] [Nonempty X] + [h : IsDomain Γ(X, ⊤)] : IsIntegral X := haveI : IsIntegral (Scheme.Spec.obj (op (Scheme.Γ.obj (op X)))) := by rw [affine_isIntegral_iff]; exact h isIntegral_of_isOpenImmersion X.isoSpec.hom #align algebraic_geometry.is_integral_of_is_affine_is_domain AlgebraicGeometry.isIntegral_of_isAffine_of_isDomain -theorem map_injective_of_isIntegral [IsIntegral X] {U V : Opens X.carrier} (i : U ⟶ V) +theorem map_injective_of_isIntegral [IsIntegral X] {U V : Opens X} (i : U ⟶ V) [H : Nonempty U] : Function.Injective (X.presheaf.map i.op) := by rw [injective_iff_map_eq_zero] intro x hx diff --git a/Mathlib/AlgebraicGeometry/Restrict.lean b/Mathlib/AlgebraicGeometry/Restrict.lean index ffacf103f4a3fc..124288f6f56c25 100644 --- a/Mathlib/AlgebraicGeometry/Restrict.lean +++ b/Mathlib/AlgebraicGeometry/Restrict.lean @@ -37,22 +37,18 @@ section variable (X : Scheme.{u}) -/-- `f ⁻¹ᵁ U` is notation for `(Opens.map f.1.base).obj U`, - the preimage of an open set `U` under `f`. -/ -notation3:90 f:91 "⁻¹ᵁ " U:90 => (Opens.map (f : LocallyRingedSpace.Hom _ _).val.base).obj U - /-- `X ∣_ᵤ U` is notation for `X.restrict U.openEmbedding`, the restriction of `X` to an open set `U` of `X`. -/ notation3:60 X:60 " ∣_ᵤ " U:61 => Scheme.restrict X (U : Opens X).openEmbedding /-- The restriction of a scheme to an open subset. -/ -abbrev Scheme.ιOpens {X : Scheme.{u}} (U : Opens X.carrier) : X ∣_ᵤ U ⟶ X := X.ofRestrict _ +abbrev Scheme.ιOpens {X : Scheme.{u}} (U : Opens X) : X ∣_ᵤ U ⟶ X := X.ofRestrict _ lemma Scheme.ofRestrict_val_c_app_self {X : Scheme.{u}} (U : Opens X) : - (X.ofRestrict U.openEmbedding).1.c.app (op U) = X.presheaf.map (eqToHom (by simp)).op := rfl + (ιOpens U).1.c.app (op U) = X.presheaf.map (eqToHom (by simp)).op := rfl lemma Scheme.eq_restrict_presheaf_map_eqToHom {X : Scheme.{u}} (U : Opens X) {V W : Opens U} - (e : U.openEmbedding.isOpenMap.functor.obj V = U.openEmbedding.isOpenMap.functor.obj W) : + (e : Scheme.ιOpens U ''ᵁ V = ιOpens U ''ᵁ W) : X.presheaf.map (eqToHom e).op = (X ∣_ᵤ U).presheaf.map (eqToHom <| U.openEmbedding.functor_obj_injective e).op := rfl @@ -61,8 +57,8 @@ instance ΓRestrictAlgebra {X : Scheme.{u}} {Y : TopCat.{u}} {f : Y ⟶ X} (hf : (Scheme.Γ.map (X.ofRestrict hf).op).toAlgebra #align algebraic_geometry.Γ_restrict_algebra AlgebraicGeometry.ΓRestrictAlgebra -lemma Scheme.map_basicOpen' (X : Scheme.{u}) (U : Opens X) (r : Scheme.Γ.obj (op <| X ∣_ᵤ U)) : - U.openEmbedding.isOpenMap.functor.obj ((X ∣_ᵤ U).basicOpen r) = X.basicOpen +lemma Scheme.map_basicOpen' (X : Scheme.{u}) (U : Opens X) (r : Γ(X ∣_ᵤ U, ⊤)) : + Scheme.ιOpens U ''ᵁ ((X ∣_ᵤ U).basicOpen r) = X.basicOpen (X.presheaf.map (eqToHom U.openEmbedding_obj_top.symm).op r) := by refine (Scheme.image_basicOpen (X.ofRestrict U.openEmbedding) r).trans ?_ erw [← Scheme.basicOpen_res_eq _ _ (eqToHom U.openEmbedding_obj_top).op] @@ -71,12 +67,12 @@ lemma Scheme.map_basicOpen' (X : Scheme.{u}) (U : Opens X) (r : Scheme.Γ.obj (o congr exact PresheafedSpace.IsOpenImmersion.ofRestrict_invApp _ _ _ -lemma Scheme.map_basicOpen (X : Scheme.{u}) (U : Opens X) (r : Scheme.Γ.obj (op <| X ∣_ᵤ U)) : - U.openEmbedding.isOpenMap.functor.obj ((X ∣_ᵤ U).basicOpen r) = X.basicOpen r := by +lemma Scheme.map_basicOpen (X : Scheme.{u}) (U : Opens X) (r : Γ(X ∣_ᵤ U, ⊤)) : + ιOpens U ''ᵁ ((X ∣_ᵤ U).basicOpen r) = X.basicOpen r := by rw [Scheme.map_basicOpen', Scheme.basicOpen_res_eq] -lemma Scheme.map_basicOpen_map (X : Scheme.{u}) (U : Opens X) (r : X.presheaf.obj (op U)) : - U.openEmbedding.isOpenMap.functor.obj ((X ∣_ᵤ U).basicOpen <| +lemma Scheme.map_basicOpen_map (X : Scheme.{u}) (U : Opens X) (r : Γ(X, U)) : + ιOpens U ''ᵁ ((X ∣_ᵤ U).basicOpen <| X.presheaf.map (eqToHom U.openEmbedding_obj_top).op r) = X.basicOpen r := by rw [Scheme.map_basicOpen', Scheme.basicOpen_res_eq, Scheme.basicOpen_res_eq] @@ -136,8 +132,7 @@ theorem Scheme.restrictFunctor_map_base {U V : Opens X} (i : U ⟶ V) : #align algebraic_geometry.Scheme.restrict_functor_map_base AlgebraicGeometry.Scheme.restrictFunctor_map_base theorem Scheme.restrictFunctor_map_app_aux {U V : Opens X} (i : U ⟶ V) (W : Opens V) : - U.openEmbedding.isOpenMap.functor.obj ((X.restrictFunctor.map i).1 ⁻¹ᵁ W) ≤ - V.openEmbedding.isOpenMap.functor.obj W := by + ιOpens U ''ᵁ ((X.restrictFunctor.map i).1 ⁻¹ᵁ W) ≤ ιOpens V ''ᵁ W := by simp only [← SetLike.coe_subset_coe, IsOpenMap.functor_obj_coe, Set.image_subset_iff, Scheme.restrictFunctor_map_base, Opens.map_coe, Opens.inclusion_apply] rintro _ h @@ -178,7 +173,7 @@ def Scheme.restrictFunctorΓ : X.restrictFunctor.op ⋙ (Over.forget X).op ⋙ S /-- `X ∣_ U ∣_ V` is isomorphic to `X ∣_ V ∣_ U` -/ noncomputable -def Scheme.restrictRestrictComm (X : Scheme.{u}) (U V : Opens X.carrier) : +def Scheme.restrictRestrictComm (X : Scheme.{u}) (U V : Opens X) : X ∣_ᵤ U ∣_ᵤ ιOpens U ⁻¹ᵁ V ≅ X ∣_ᵤ V ∣_ᵤ ιOpens V ⁻¹ᵁ U := by refine IsOpenImmersion.isoOfRangeEq (ιOpens _ ≫ ιOpens U) (ιOpens _ ≫ ιOpens V) ?_ simp only [Scheme.restrict_carrier, Scheme.ofRestrict_val_base, Scheme.comp_coeBase, @@ -190,8 +185,8 @@ def Scheme.restrictRestrictComm (X : Scheme.{u}) (U V : Opens X.carrier) : /-- If `V` is an open subset of `U`, then `X ∣_ U ∣_ V` is isomorphic to `X ∣_ V`. -/ noncomputable -def Scheme.restrictRestrict (X : Scheme.{u}) (U : Opens X.carrier) (V : Opens (X ∣_ᵤ U).carrier) : - X ∣_ᵤ U ∣_ᵤ V ≅ X ∣_ᵤ U.openEmbedding.isOpenMap.functor.obj V := by +def Scheme.restrictRestrict (X : Scheme.{u}) (U : Opens X) (V : Opens (X ∣_ᵤ U)) : + X ∣_ᵤ U ∣_ᵤ V ≅ X ∣_ᵤ ιOpens U ''ᵁ V := by refine IsOpenImmersion.isoOfRangeEq (ιOpens _ ≫ ιOpens U) (ιOpens _) ?_ simp only [Scheme.restrict_carrier, Scheme.ofRestrict_val_base, Scheme.comp_coeBase, TopCat.coe_comp, Opens.coe_inclusion, Set.range_comp, Opens.map] @@ -199,20 +194,20 @@ def Scheme.restrictRestrict (X : Scheme.{u}) (U : Opens X.carrier) (V : Opens (X rfl @[simp, reassoc] -lemma Scheme.restrictRestrict_hom_restrict (X : Scheme.{u}) (U : Opens X.carrier) - (V : Opens (X ∣_ᵤ U).carrier) : +lemma Scheme.restrictRestrict_hom_restrict (X : Scheme.{u}) (U : Opens X) + (V : Opens (X ∣_ᵤ U)) : (X.restrictRestrict U V).hom ≫ ιOpens _ = ιOpens V ≫ ιOpens U := IsOpenImmersion.isoOfRangeEq_hom_fac _ _ _ @[simp, reassoc] -lemma Scheme.restrictRestrict_inv_restrict_restrict (X : Scheme.{u}) (U : Opens X.carrier) - (V : Opens (X ∣_ᵤ U).carrier) : +lemma Scheme.restrictRestrict_inv_restrict_restrict (X : Scheme.{u}) (U : Opens X) + (V : Opens (X ∣_ᵤ U)) : (X.restrictRestrict U V).inv ≫ ιOpens V ≫ ιOpens U = ιOpens _ := IsOpenImmersion.isoOfRangeEq_inv_fac _ _ _ /-- If `U = V`, then `X ∣_ U` is isomorphic to `X ∣_ V`. -/ noncomputable -def Scheme.restrictIsoOfEq (X : Scheme.{u}) {U V : Opens X.carrier} (e : U = V) : +def Scheme.restrictIsoOfEq (X : Scheme.{u}) {U V : Opens X} (e : U = V) : X ∣_ᵤ U ≅ X ∣_ᵤ V := by exact IsOpenImmersion.isoOfRangeEq (ιOpens U) (ιOpens V) (by rw [e]) @@ -393,7 +388,7 @@ def morphismRestrictEq {X Y : Scheme.{u}} (f : X ⟶ Y) {U V : Opens Y} (e : U = /-- Restricting a morphism twice is isomorphic to one restriction. -/ def morphismRestrictRestrict {X Y : Scheme.{u}} (f : X ⟶ Y) (U : Opens Y) (V : Opens (Y ∣_ᵤ U)) : - Arrow.mk (f ∣_ U ∣_ V) ≅ Arrow.mk (f ∣_ U.openEmbedding.isOpenMap.functor.obj V) := by + Arrow.mk (f ∣_ U ∣_ V) ≅ Arrow.mk (f ∣_ Scheme.ιOpens U ''ᵁ V) := by refine Arrow.isoMk' _ _ (Scheme.restrictRestrict _ _ _ ≪≫ Scheme.restrictIsoOfEq _ ?_) (Scheme.restrictRestrict _ _ _) ?_ · ext x @@ -413,10 +408,8 @@ def morphismRestrictRestrict {X Y : Scheme.{u}} (f : X ⟶ Y) (U : Opens Y) (V : #align algebraic_geometry.morphism_restrict_restrict AlgebraicGeometry.morphismRestrictRestrict /-- Restricting a morphism twice onto a basic open set is isomorphic to one restriction. -/ -def morphismRestrictRestrictBasicOpen {X Y : Scheme.{u}} (f : X ⟶ Y) (U : Opens Y) - (r : Y.presheaf.obj (op U)) : - Arrow.mk - (f ∣_ U ∣_ +def morphismRestrictRestrictBasicOpen {X Y : Scheme.{u}} (f : X ⟶ Y) (U : Opens Y) (r : Γ(Y, U)) : + Arrow.mk (f ∣_ U ∣_ (Y ∣_ᵤ U).basicOpen (Y.presheaf.map (eqToHom U.openEmbedding_obj_top).op r)) ≅ Arrow.mk (f ∣_ Y.basicOpen r) := by refine morphismRestrictRestrict _ _ _ ≪≫ morphismRestrictEq _ ?_ diff --git a/Mathlib/AlgebraicGeometry/Scheme.lean b/Mathlib/AlgebraicGeometry/Scheme.lean index 166caa04d3d53f..89868d867a326a 100644 --- a/Mathlib/AlgebraicGeometry/Scheme.lean +++ b/Mathlib/AlgebraicGeometry/Scheme.lean @@ -65,6 +65,16 @@ def Hom (X Y : Scheme) : Type* := instance : Category Scheme := { InducedCategory.category Scheme.toLocallyRingedSpace with Hom := Hom } +/-- `f ⁻¹ᵁ U` is notation for `(Opens.map f.1.base).obj U`, + the preimage of an open set `U` under `f`. -/ +scoped[AlgebraicGeometry] notation3:90 f:91 " ⁻¹ᵁ " U:90 => + (Opens.map (f : LocallyRingedSpace.Hom _ _).val.base).obj U + +/-- `Γ(X, U)` is notation for `X.presheaf.obj (op U)`. -/ +scoped[AlgebraicGeometry] notation3 "Γ(" X ", " U ")" => + (PresheafedSpace.presheaf (SheafedSpace.toPresheafedSpace + (LocallyRingedSpace.toSheafedSpace (Scheme.toLocallyRingedSpace X)))).obj (op U) + @[continuity, fun_prop] lemma Hom.continuous {X Y : Scheme} (f : X ⟶ Y) : Continuous f.1.base := f.1.base.2 @@ -116,7 +126,7 @@ theorem id_val_base (X : Scheme) : (𝟙 X : _).1.base = 𝟙 _ := #align algebraic_geometry.Scheme.id_val_base AlgebraicGeometry.Scheme.id_val_base @[simp] -theorem id_app {X : Scheme} (U : (Opens X.carrier)ᵒᵖ) : +theorem id_app {X : Scheme} (U : (Opens X)ᵒᵖ) : (𝟙 X : _).val.c.app U = X.presheaf.map (eqToHom (by induction' U with U; cases U; rfl)) := PresheafedSpace.id_c_app X.toPresheafedSpace U @@ -166,6 +176,9 @@ theorem app_eq {X Y : Scheme} (f : X ⟶ Y) {U V : Opens Y.carrier} (e : U = V) rfl #align algebraic_geometry.Scheme.app_eq AlgebraicGeometry.Scheme.app_eq +theorem eqToHom_c_app {X Y : Scheme} (e : X = Y) (U) : + (eqToHom e).val.c.app U = eqToHom (by subst e; rfl) := by subst e; rfl + -- Porting note: in `AffineScheme.lean` file, `eqToHom_op` can't be used in `(e)rw` or `simp(_rw)` -- when terms get very complicated. See `AlgebraicGeometry.IsAffineOpen.isLocalization_stalk_aux`. lemma presheaf_map_eqToHom_op (X : Scheme) (U V : Opens X) (i : U = V) : @@ -187,7 +200,7 @@ instance {X Y : Scheme} (f : X ⟶ Y) [IsIso f] (U) : IsIso (f.val.c.app U) := NatIso.isIso_app_of_isIso _ _ @[simp] -theorem inv_val_c_app {X Y : Scheme} (f : X ⟶ Y) [IsIso f] (U : Opens X.carrier) : +theorem inv_val_c_app {X Y : Scheme} (f : X ⟶ Y) [IsIso f] (U : Opens X) : (inv f).val.c.app (op U) = X.presheaf.map (eqToHom <| by rw [IsIso.hom_inv_id]; ext1; rfl : @@ -204,8 +217,8 @@ theorem inv_val_c_app_top {X Y : Scheme} (f : X ⟶ Y) [IsIso f] : /-- Given a morphism of schemes `f : X ⟶ Y`, and open sets `U ⊆ Y`, `V ⊆ f ⁻¹' U`, this is the induced map `Γ(Y, U) ⟶ Γ(X, V)`. -/ -abbrev Hom.appLe {X Y : Scheme} (f : X ⟶ Y) {V : Opens X.carrier} {U : Opens Y.carrier} - (e : V ≤ (Opens.map f.1.base).obj U) : Y.presheaf.obj (op U) ⟶ X.presheaf.obj (op V) := +abbrev Hom.appLe {X Y : Scheme} (f : X ⟶ Y) {V : Opens X} {U : Opens Y} + (e : V ≤ f ⁻¹ᵁ U) : Γ(Y, U) ⟶ Γ(X, V) := f.1.c.app (op U) ≫ X.presheaf.map (homOfLE e).op #align algebraic_geometry.Scheme.hom.app_le AlgebraicGeometry.Scheme.Hom.appLe @@ -239,11 +252,10 @@ theorem specMap_comp {R S T : CommRingCat} (f : R ⟶ S) (g : S ⟶ T) : #align algebraic_geometry.Scheme.Spec_map_comp AlgebraicGeometry.Scheme.specMap_comp /-- The spectrum, as a contravariant functor from commutative rings to schemes. + +The simp normal form should be `Scheme.Spec.obj (op R)` (with the notation `𝖲𝗉𝖾𝖼 R`) and +`Scheme.Spec.map f.op` (with the notation `𝖲𝗉𝖾𝖼(f)`). -/ --- Porting note: removed @[simps] --- TODO: We need to decide whether `Spec_obj` or `Spec.obj` the simp-normal form. --- We probably want `Spec.obj`, but note --- `locallyRingedSpaceObj` is currently the simp-normal form of `toLocallyRingedSpace.obj`. def Spec : CommRingCatᵒᵖ ⥤ Scheme where obj R := specObj (unop R) map f := specMap f.unop @@ -251,6 +263,31 @@ def Spec : CommRingCatᵒᵖ ⥤ Scheme where map_comp f g := by simp [specMap_comp] #align algebraic_geometry.Scheme.Spec AlgebraicGeometry.Scheme.Spec +/-- `𝖲𝗉𝖾𝖼 R` is notation for `Sceme.Spec.obj (op R)`. -/ +scoped[AlgebraicGeometry] notation3 "𝖲𝗉𝖾𝖼 " R:20 => Scheme.Spec.obj (op R) + +/-- `𝖲𝗉𝖾𝖼(f)` is notation for `Sceme.Spec.map f.op`. -/ +scoped[AlgebraicGeometry] notation3 "𝖲𝗉𝖾𝖼(" f ")" => Scheme.Spec.map (Quiver.Hom.op f) + +section + +variable {R S : CommRingCat} (f : R ⟶ S) + +-- The lemmas below are not tagged simp to respect the abstraction. +lemma Spec_obj_carrier (R) : (𝖲𝗉𝖾𝖼 R).carrier = PrimeSpectrum R := rfl +lemma Spec_obj_sheaf (R) : (𝖲𝗉𝖾𝖼 R).sheaf = Spec.structureSheaf R := rfl +lemma Spec_obj_presheaf (R) : (𝖲𝗉𝖾𝖼 R).presheaf = (Spec.structureSheaf R).1 := rfl +lemma Spec_map_base : 𝖲𝗉𝖾𝖼(f).1.base = PrimeSpectrum.comap f := rfl + +set_option maxHeartbeats 800000 in +lemma Spec_map_c_app (U) : + 𝖲𝗉𝖾𝖼(f).1.c.app (op U) = StructureSheaf.comap f U (𝖲𝗉𝖾𝖼(f) ⁻¹ᵁ U) le_rfl := rfl + +lemma Spec_map_appLE {U V} (e : U ≤ 𝖲𝗉𝖾𝖼(f) ⁻¹ᵁ V) : + Hom.appLe 𝖲𝗉𝖾𝖼(f) e = StructureSheaf.comap f V U e := rfl + +end + /-- The empty scheme. -/ @[simps] @@ -283,7 +320,7 @@ theorem Γ_obj (X : Schemeᵒᵖ) : Γ.obj X = (unop X).presheaf.obj (op ⊤) := rfl #align algebraic_geometry.Scheme.Γ_obj AlgebraicGeometry.Scheme.Γ_obj -theorem Γ_obj_op (X : Scheme) : Γ.obj (op X) = X.presheaf.obj (op ⊤) := +theorem Γ_obj_op (X : Scheme) : Γ.obj (op X) = Γ(X, ⊤) := rfl #align algebraic_geometry.Scheme.Γ_obj_op AlgebraicGeometry.Scheme.Γ_obj_op @@ -296,12 +333,20 @@ theorem Γ_map_op {X Y : Scheme} (f : X ⟶ Y) : Γ.map f.op = f.1.c.app (op ⊤ rfl #align algebraic_geometry.Scheme.Γ_map_op AlgebraicGeometry.Scheme.Γ_map_op +/-- The counit (`SpecΓIdentity.inv.op`) of the adjunction `Γ ⊣ Spec` as an isomorphism. -/ +-- This is not marked simp to respect the abstraction +@[simps! (config := .lemmasOnly) hom_app inv_app] +def SpecΓIdentity : Scheme.Spec.rightOp ⋙ Scheme.Γ ≅ 𝟭 _ := + Iso.symm <| NatIso.ofComponents.{u,u,u+1,u+1} + (fun R => asIso (StructureSheaf.toOpen R ⊤)) + (fun {X Y} f => by convert Spec_Γ_naturality (R := X) (S := Y) f) + section BasicOpen -variable (X : Scheme) {V U : Opens X.carrier} (f g : X.presheaf.obj (op U)) +variable (X : Scheme) {V U : Opens X} (f g : Γ(X, U)) /-- The subset of the underlying space where the given section does not vanish. -/ -def basicOpen : Opens X.carrier := +def basicOpen : Opens X := X.toLocallyRingedSpace.toRingedSpace.basicOpen f #align algebraic_geometry.Scheme.basic_open AlgebraicGeometry.Scheme.basicOpen @@ -310,7 +355,7 @@ theorem mem_basicOpen (x : U) : ↑x ∈ X.basicOpen f ↔ IsUnit (X.presheaf.ge RingedSpace.mem_basicOpen _ _ _ #align algebraic_geometry.Scheme.mem_basic_open AlgebraicGeometry.Scheme.mem_basicOpen -theorem mem_basicOpen_top' {U : Opens X} (f : X.presheaf.obj (op U)) (x : X.carrier) : +theorem mem_basicOpen_top' {U : Opens X} (f : Γ(X, U)) (x : X) : x ∈ X.basicOpen f ↔ ∃ (m : x ∈ U), IsUnit (X.presheaf.germ (⟨x, m⟩ : U) f) := by fconstructor · rintro ⟨y, hy1, rfl⟩ @@ -319,7 +364,7 @@ theorem mem_basicOpen_top' {U : Opens X} (f : X.presheaf.obj (op U)) (x : X.carr exact ⟨⟨x, m⟩, hm, rfl⟩ @[simp] -theorem mem_basicOpen_top (f : X.presheaf.obj (op ⊤)) (x : X.carrier) : +theorem mem_basicOpen_top (f : Γ(X, ⊤)) (x : X) : x ∈ X.basicOpen f ↔ IsUnit (X.presheaf.germ (⟨x, trivial⟩ : (⊤ : Opens _)) f) := RingedSpace.mem_basicOpen _ f ⟨x, trivial⟩ #align algebraic_geometry.Scheme.mem_basic_open_top AlgebraicGeometry.Scheme.mem_basicOpen_top @@ -342,20 +387,18 @@ theorem basicOpen_le : X.basicOpen f ≤ U := #align algebraic_geometry.Scheme.basic_open_le AlgebraicGeometry.Scheme.basicOpen_le @[sheaf_restrict] -lemma basicOpen_restrict (i : V ⟶ U) (f : X.presheaf.obj (op U)) : +lemma basicOpen_restrict (i : V ⟶ U) (f : Γ(X, U)) : X.basicOpen (f |_ₕ i) ≤ X.basicOpen f := (Scheme.basicOpen_res _ _ _).trans_le inf_le_right @[simp] -theorem preimage_basicOpen {X Y : Scheme} (f : X ⟶ Y) {U : Opens Y.carrier} - (r : Y.presheaf.obj <| op U) : - (Opens.map f.1.base).obj (Y.basicOpen r) = - @Scheme.basicOpen X ((Opens.map f.1.base).obj U) (f.1.c.app (op U) r) := +theorem preimage_basicOpen {X Y : Scheme} (f : X ⟶ Y) {U : Opens Y} (r : Γ(Y, U)) : + f ⁻¹ᵁ (Y.basicOpen r) = X.basicOpen (f.1.c.app (op U) r) := LocallyRingedSpace.preimage_basicOpen f r #align algebraic_geometry.Scheme.preimage_basic_open AlgebraicGeometry.Scheme.preimage_basicOpen @[simp] -theorem basicOpen_zero (U : Opens X.carrier) : X.basicOpen (0 : X.presheaf.obj <| op U) = ⊥ := +theorem basicOpen_zero (U : Opens X) : X.basicOpen (0 : Γ(X, U)) = ⊥ := LocallyRingedSpace.basicOpen_zero _ U #align algebraic_geometry.Scheme.basic_open_zero AlgebraicGeometry.Scheme.basicOpen_zero @@ -364,12 +407,12 @@ theorem basicOpen_mul : X.basicOpen (f * g) = X.basicOpen f ⊓ X.basicOpen g := RingedSpace.basicOpen_mul _ _ _ #align algebraic_geometry.Scheme.basic_open_mul AlgebraicGeometry.Scheme.basicOpen_mul -theorem basicOpen_of_isUnit {f : X.presheaf.obj (op U)} (hf : IsUnit f) : X.basicOpen f = U := +theorem basicOpen_of_isUnit {f : Γ(X, U)} (hf : IsUnit f) : X.basicOpen f = U := RingedSpace.basicOpen_of_isUnit _ hf #align algebraic_geometry.Scheme.basic_open_of_is_unit AlgebraicGeometry.Scheme.basicOpen_of_isUnit -instance algebra_section_section_basicOpen {X : Scheme} {U : Opens X} (f : X.presheaf.obj (op U)) : - Algebra (X.presheaf.obj (op U)) (X.presheaf.obj (op <| X.basicOpen f)) := +instance algebra_section_section_basicOpen {X : Scheme} {U : Opens X} (f : Γ(X, U)) : + Algebra Γ(X, U) Γ(X, X.basicOpen f) := (X.presheaf.map (homOfLE <| X.basicOpen_le f : _ ⟶ U).op).toAlgebra end BasicOpen @@ -377,8 +420,7 @@ end BasicOpen end Scheme theorem basicOpen_eq_of_affine {R : CommRingCat} (f : R) : - (Scheme.Spec.obj <| op R).basicOpen ((SpecΓIdentity.app R).inv f) = - PrimeSpectrum.basicOpen f := by + (𝖲𝗉𝖾𝖼 R).basicOpen ((Scheme.SpecΓIdentity.app R).inv f) = PrimeSpectrum.basicOpen f := by ext x erw [Scheme.mem_basicOpen_top] suffices IsUnit (StructureSheaf.toStalk R x f) ↔ f ∉ PrimeSpectrum.asIdeal x by exact this @@ -391,16 +433,14 @@ theorem basicOpen_eq_of_affine {R : CommRingCat} (f : R) : #align algebraic_geometry.basic_open_eq_of_affine AlgebraicGeometry.basicOpen_eq_of_affine @[simp] -theorem basicOpen_eq_of_affine' {R : CommRingCat} - (f : (Spec.toSheafedSpace.obj (op R)).presheaf.obj (op ⊤)) : - (Scheme.Spec.obj <| op R).basicOpen f = - PrimeSpectrum.basicOpen ((SpecΓIdentity.app R).hom f) := by - convert basicOpen_eq_of_affine ((SpecΓIdentity.app R).hom f) - exact (Iso.hom_inv_id_apply (SpecΓIdentity.app R) f).symm +theorem basicOpen_eq_of_affine' {R : CommRingCat} (f : Γ(𝖲𝗉𝖾𝖼 R, ⊤)) : + (𝖲𝗉𝖾𝖼 R).basicOpen f = PrimeSpectrum.basicOpen ((Scheme.SpecΓIdentity.app R).hom f) := by + convert basicOpen_eq_of_affine ((Scheme.SpecΓIdentity.app R).hom f) + exact (Iso.hom_inv_id_apply (Scheme.SpecΓIdentity.app R) f).symm #align algebraic_geometry.basic_open_eq_of_affine' AlgebraicGeometry.basicOpen_eq_of_affine' theorem Scheme.Spec_map_presheaf_map_eqToHom {X : Scheme} {U V : Opens X} (h : U = V) (W) : - (Scheme.Spec.map (X.presheaf.map (eqToHom h).op).op).val.c.app W = + 𝖲𝗉𝖾𝖼(X.presheaf.map (eqToHom h).op).val.c.app W = eqToHom (by cases h; induction W using Opposite.rec'; dsimp; simp) := by have : Scheme.Spec.map (X.presheaf.map (𝟙 (op U))).op = 𝟙 _ := by rw [X.presheaf.map_id, op_id, Scheme.Spec.map_id] diff --git a/Mathlib/AlgebraicGeometry/Spec.lean b/Mathlib/AlgebraicGeometry/Spec.lean index a427183f9dfd9c..9302305d244075 100644 --- a/Mathlib/AlgebraicGeometry/Spec.lean +++ b/Mathlib/AlgebraicGeometry/Spec.lean @@ -351,13 +351,13 @@ set_option backward.isDefEq.lazyWhnfCore false in -- See https://github.com/lean set_option maxHeartbeats 40000 in /-- The counit (`SpecΓIdentity.inv.op`) of the adjunction `Γ ⊣ Spec` is an isomorphism. -/ @[simps! hom_app inv_app] -def SpecΓIdentity : Spec.toLocallyRingedSpace.rightOp ⋙ Γ ≅ 𝟭 _ := +def LocallyRingedSpace.SpecΓIdentity : Spec.toLocallyRingedSpace.rightOp ⋙ Γ ≅ 𝟭 _ := Iso.symm <| NatIso.ofComponents.{u,u,u+1,u+1} (fun R => -- Porting note: In Lean3, this `IsIso` is synthesized automatically letI : IsIso (toSpecΓ R) := StructureSheaf.isIso_to_global _ asIso (toSpecΓ R)) fun {X Y} f => by convert Spec_Γ_naturality (R := X) (S := Y) f set_option linter.uppercaseLean3 false in -#align algebraic_geometry.Spec_Γ_identity AlgebraicGeometry.SpecΓIdentity +#align algebraic_geometry.Spec_Γ_identity AlgebraicGeometry.LocallyRingedSpace.SpecΓIdentity end SpecΓ From 2985a848ad78dc5deda3530e84e17c834cd7c8f7 Mon Sep 17 00:00:00 2001 From: Jeremy Tan Jie Rui Date: Sat, 22 Jun 2024 19:13:46 +0000 Subject: [PATCH 11/19] =?UTF-8?q?feat:=20forward=20direction=20of=20Tur?= =?UTF-8?q?=C3=A1n's=20theorem=20(#11990)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Part of #9317. --- Mathlib/Combinatorics/SimpleGraph/Turan.lean | 197 ++++++++++++++++++- Mathlib/Order/Partition/Finpartition.lean | 14 +- 2 files changed, 204 insertions(+), 7 deletions(-) diff --git a/Mathlib/Combinatorics/SimpleGraph/Turan.lean b/Mathlib/Combinatorics/SimpleGraph/Turan.lean index db59c0da67d7dd..339d7f6030974e 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Turan.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Turan.lean @@ -4,29 +4,49 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Tan -/ import Mathlib.Combinatorics.SimpleGraph.Clique +import Mathlib.Order.Partition.Equipartition /-! -# The Turán graph +# Turán's theorem -This file defines the Turán graph and proves some of its basic properties. +In this file we prove Turán's theorem, the first important result of extremal graph theory, +which states that the `r + 1`-cliquefree graph on `n` vertices with the most edges is the complete +`r`-partite graph with part sizes as equal as possible (`turanGraph n r`). + +The forward direction of the proof performs "Zykov symmetrisation", which first shows +constructively that non-adjacency is an equivalence relation in a maximal graph, so it must be +complete multipartite with the parts being the equivalence classes. Then basic manipulations +show that the graph is isomorphic to the Turán graph for the given parameters. ## Main declarations * `SimpleGraph.IsTuranMaximal`: `G.IsTuranMaximal r` means that `G` has the most number of edges for its number of vertices while still being `r + 1`-cliquefree. * `SimpleGraph.turanGraph n r`: The canonical `r + 1`-cliquefree Turán graph on `n` vertices. +* `SimpleGraph.IsTuranMaximal.finpartition`: The result of Zykov symmetrisation, a finpartition of + the vertices such that two vertices are in the same part iff they are non-adjacent. +* `SimpleGraph.IsTuranMaximal.nonempty_iso_turanGraph`: The forward direction, an isomorphism + between `G` satisfying `G.IsTuranMaximal r` and `turanGraph n r`. + +## References + +* https://en.wikipedia.org/wiki/Turán%27s_theorem ## TODO -* Port the rest of Turán's theorem from https://github.com/leanprover-community/mathlib4/pull/9317 +* Prove the reverse direction of Turán's theorem at + https://github.com/leanprover-community/mathlib4/pull/9317 -/ open Finset namespace SimpleGraph + variable {V : Type*} [Fintype V] [DecidableEq V] (G H : SimpleGraph V) [DecidableRel G.Adj] {n r : ℕ} +section Defs + /-- An `r + 1`-cliquefree graph is `r`-Turán-maximal if any other `r + 1`-cliquefree graph on the same vertex set has the same or fewer number of edges. -/ def IsTuranMaximal (r : ℕ) : Prop := @@ -91,4 +111,175 @@ theorem not_cliqueFree_of_isTuranMaximal (hn : r ≤ Fintype.card V) (hG : G.IsT exact hGab <| le_sup_right.trans_eq ((hG.le_iff_eq <| h.sup_edge _ _).1 le_sup_left).symm <| (edge_adj ..).2 ⟨Or.inl ⟨rfl, rfl⟩, hab⟩ +lemma exists_isTuranMaximal : + ∃ H : SimpleGraph V, ∃ _ : DecidableRel H.Adj, H.IsTuranMaximal r := by + classical + let c := {H : SimpleGraph V | H.CliqueFree (r + 1)} + have cn : c.toFinset.Nonempty := ⟨⊥, by + simp only [Set.toFinset_setOf, mem_filter, mem_univ, true_and, c] + exact cliqueFree_bot (by omega)⟩ + obtain ⟨S, Sm, Sl⟩ := exists_max_image c.toFinset (·.edgeFinset.card) cn + use S, inferInstance + rw [Set.mem_toFinset] at Sm + refine ⟨Sm, ?_⟩ + intro I _ cf + by_cases Im : I ∈ c.toFinset + · convert Sl I Im + · rw [Set.mem_toFinset] at Im + contradiction + +end Defs + +section Forward + +variable {G} {s t u : V} (h : G.IsTuranMaximal r) + +namespace IsTuranMaximal + +/-- In a Turán-maximal graph, non-adjacent vertices have the same degree. -/ +lemma degree_eq_of_not_adj (hn : ¬G.Adj s t) : G.degree s = G.degree t := by + rw [IsTuranMaximal] at h; contrapose! h; intro cf + wlog hd : G.degree t < G.degree s generalizing G t s + · replace hd : G.degree s < G.degree t := lt_of_le_of_ne (le_of_not_lt hd) h + exact this (by rwa [adj_comm] at hn) hd.ne' cf hd + use G.replaceVertex s t, inferInstance, cf.replaceVertex s t + have := G.card_edgeFinset_replaceVertex_of_not_adj hn + omega + +/-- In a Turán-maximal graph, non-adjacency is transitive. -/ +lemma not_adj_trans (hst : ¬G.Adj s t) (hsu : ¬G.Adj s u) : ¬G.Adj t u := by + have dst := h.degree_eq_of_not_adj hst + have dsu := h.degree_eq_of_not_adj hsu + rw [IsTuranMaximal] at h; contrapose! h; intro cf + use (G.replaceVertex s t).replaceVertex s u, inferInstance, + (cf.replaceVertex s t).replaceVertex s u + have nst : s ≠ t := fun a ↦ hsu (a ▸ h) + have ntu : t ≠ u := G.ne_of_adj h + have := (G.adj_replaceVertex_iff_of_ne s nst ntu.symm).not.mpr hsu + rw [card_edgeFinset_replaceVertex_of_not_adj _ this, + card_edgeFinset_replaceVertex_of_not_adj _ hst, dst, Nat.add_sub_cancel] + have l1 : (G.replaceVertex s t).degree s = G.degree s := by + unfold degree; congr 1; ext v + simp only [mem_neighborFinset, SimpleGraph.irrefl, ite_self] + by_cases eq : v = t + · simpa only [eq, not_adj_replaceVertex_same, false_iff] + · rw [G.adj_replaceVertex_iff_of_ne s nst eq] + have l2 : (G.replaceVertex s t).degree u = G.degree u - 1 := by + rw [degree, degree, ← card_singleton t, ← card_sdiff (by simp [h.symm])] + congr 1; ext v + simp only [mem_neighborFinset, mem_sdiff, mem_singleton, replaceVertex] + split_ifs <;> simp_all [adj_comm] + have l3 : 0 < G.degree u := by rw [G.degree_pos_iff_exists_adj u]; use t, h.symm + omega + +/-- In a Turán-maximal graph, non-adjacency is an equivalence relation. -/ +theorem equivalence_not_adj : Equivalence fun x y ↦ ¬G.Adj x y where + refl x := by simp + symm xy := by simp [xy, adj_comm] + trans xy yz := by + rw [adj_comm] at xy + exact h.not_adj_trans xy yz + +/-- The non-adjacency setoid over the vertices of a Turán-maximal graph +induced by `equivalence_not_adj`. -/ +def setoid : Setoid V := ⟨_, h.equivalence_not_adj⟩ + +instance : DecidableRel h.setoid.r := + inferInstanceAs <| DecidableRel fun v w ↦ ¬G.Adj v w + +/-- The finpartition derived from `h.setoid`. -/ +def finpartition : Finpartition (univ : Finset V) := Finpartition.ofSetoid h.setoid + +lemma not_adj_iff_part_eq : ¬G.Adj s t ↔ h.finpartition.part s = h.finpartition.part t := by + change h.setoid.r s t ↔ _ + rw [← Finpartition.mem_part_ofSetoid_iff_rel] + let fp := h.finpartition + change t ∈ fp.part s ↔ fp.part s = fp.part t + rw [fp.mem_part_iff_part_eq_part (mem_univ t) (mem_univ s), eq_comm] + +lemma degree_eq_card_sub_part_card : G.degree s = Fintype.card V - (h.finpartition.part s).card := + calc + _ = (univ.filter fun b ↦ G.Adj s b).card := by + simp [← card_neighborFinset_eq_degree, neighborFinset] + _ = Fintype.card V - (univ.filter fun b ↦ ¬G.Adj s b).card := + eq_tsub_of_add_eq (filter_card_add_filter_neg_card_eq_card _) + _ = _ := by + congr; ext; rw [mem_filter] + convert Finpartition.mem_part_ofSetoid_iff_rel.symm + simp [setoid] + +/-- The parts of a Turán-maximal graph form an equipartition. -/ +theorem isEquipartition : h.finpartition.IsEquipartition := by + set fp := h.finpartition + by_contra hn + rw [Finpartition.not_isEquipartition] at hn + obtain ⟨large, hl, small, hs, ineq⟩ := hn + obtain ⟨w, hw⟩ := fp.nonempty_of_mem_parts hl + obtain ⟨v, hv⟩ := fp.nonempty_of_mem_parts hs + apply absurd h + rw [IsTuranMaximal]; push_neg; intro cf + use G.replaceVertex v w, inferInstance, cf.replaceVertex v w + have large_eq := fp.part_eq_of_mem hl hw + have small_eq := fp.part_eq_of_mem hs hv + have ha : G.Adj v w := by + by_contra hn; rw [h.not_adj_iff_part_eq, small_eq, large_eq] at hn + rw [hn] at ineq; omega + rw [G.card_edgeFinset_replaceVertex_of_adj ha, + degree_eq_card_sub_part_card h, small_eq, degree_eq_card_sub_part_card h, large_eq] + have : large.card ≤ Fintype.card V := by simpa using card_le_card large.subset_univ + omega + +lemma card_parts_le : h.finpartition.parts.card ≤ r := by + by_contra! l + obtain ⟨z, -, hz⟩ := h.finpartition.exists_subset_part_bijOn + have ncf : ¬G.CliqueFree z.card := by + refine IsNClique.not_cliqueFree ⟨fun v hv w hw hn ↦ ?_, rfl⟩ + contrapose! hn + exact hz.injOn hv hw (by rwa [← h.not_adj_iff_part_eq]) + rw [Finset.card_eq_of_equiv hz.equiv] at ncf + exact absurd (h.1.mono (Nat.succ_le_of_lt l)) ncf + +/-- There are `min n r` parts in a graph on `n` vertices satisfying `G.IsTuranMaximal r`. +`min` handles the `n < r` case, when `G` is complete but still `r + 1`-cliquefree +for having insufficiently many vertices. -/ +theorem card_parts : h.finpartition.parts.card = min (Fintype.card V) r := by + set fp := h.finpartition + apply le_antisymm (le_min fp.card_parts_le_card h.card_parts_le) + by_contra! l + rw [lt_min_iff] at l + obtain ⟨x, -, y, -, hn, he⟩ := + exists_ne_map_eq_of_card_lt_of_maps_to l.1 fun a _ ↦ fp.part_mem (mem_univ a) + apply absurd h + rw [IsTuranMaximal]; push_neg; rintro - + have cf : G.CliqueFree r := by + simp_rw [← cliqueFinset_eq_empty_iff, cliqueFinset, filter_eq_empty_iff, mem_univ, + forall_true_left, isNClique_iff, and_comm, not_and, isClique_iff, Set.Pairwise] + intro z zc; push_neg; simp_rw [h.not_adj_iff_part_eq] + exact exists_ne_map_eq_of_card_lt_of_maps_to (zc.symm ▸ l.2) fun a _ ↦ fp.part_mem (mem_univ a) + use G ⊔ edge x y, inferInstance, cf.sup_edge x y + convert Nat.lt.base G.edgeFinset.card + convert G.card_edgeFinset_sup_edge _ hn + rwa [h.not_adj_iff_part_eq] + +/-- **Turán's theorem**, forward direction. + +Any `r + 1`-cliquefree Turán-maximal graph on `n` vertices is isomorphic to `turanGraph n r`. -/ +theorem nonempty_iso_turanGraph : Nonempty (G ≃g turanGraph (Fintype.card V) r) := by + obtain ⟨zm, zp⟩ := h.isEquipartition.exists_partPreservingEquiv + use (Equiv.subtypeUnivEquiv mem_univ).symm.trans zm + intro a b + simp_rw [turanGraph, Equiv.trans_apply, Equiv.subtypeUnivEquiv_symm_apply] + have := zp ⟨a, mem_univ a⟩ ⟨b, mem_univ b⟩ + rw [← h.not_adj_iff_part_eq] at this + rw [← not_iff_not, not_ne_iff, this, card_parts] + rcases le_or_lt r (Fintype.card V) with c | c + · rw [min_eq_right c]; rfl + · have lc : ∀ x, zm ⟨x, _⟩ < Fintype.card V := fun x ↦ (zm ⟨x, mem_univ x⟩).2 + rw [min_eq_left c.le, Nat.mod_eq_of_lt (lc a), Nat.mod_eq_of_lt (lc b), + ← Nat.mod_eq_of_lt ((lc a).trans c), ← Nat.mod_eq_of_lt ((lc b).trans c)]; rfl + +end IsTuranMaximal + +end Forward + end SimpleGraph diff --git a/Mathlib/Order/Partition/Finpartition.lean b/Mathlib/Order/Partition/Finpartition.lean index fa581d59aa13bf..dec352a3d4aec6 100644 --- a/Mathlib/Order/Partition/Finpartition.lean +++ b/Mathlib/Order/Partition/Finpartition.lean @@ -498,9 +498,16 @@ theorem existsUnique_mem (ha : a ∈ s) : ∃! t, t ∈ P.parts ∧ a ∈ t := b /-- The part of the finpartition that `a` lies in. -/ def part (a : α) : Finset α := if ha : a ∈ s then choose (hp := P.existsUnique_mem ha) else ∅ -theorem part_mem (ha : a ∈ s) : P.part a ∈ P.parts := by simp [part, ha, choose_mem] +lemma part_mem (ha : a ∈ s) : P.part a ∈ P.parts := by simp [part, ha, choose_mem] -theorem mem_part (ha : a ∈ s) : a ∈ P.part a := by simp [part, ha, choose_property] +lemma mem_part (ha : a ∈ s) : a ∈ P.part a := by simp [part, ha, choose_property] + +lemma part_eq_of_mem (ht : t ∈ P.parts) (hat : a ∈ t) : P.part a = t := by + apply P.eq_of_mem_parts (P.part_mem _) ht (P.mem_part _) hat <;> exact mem_of_subset (P.le ht) hat + +lemma mem_part_iff_part_eq_part {b : α} (ha : a ∈ s) (hb : b ∈ s) : + a ∈ P.part b ↔ P.part a = P.part b := + ⟨fun c ↦ (P.part_eq_of_mem (P.part_mem hb) c), fun c ↦ c ▸ P.mem_part ha⟩ theorem part_surjOn : Set.SurjOn P.part s P.parts := fun p hp ↦ by obtain ⟨x, hx⟩ := P.nonempty_of_mem_parts hp @@ -521,8 +528,7 @@ def equivSigmaParts : s ≃ Σ t : P.parts, t.1 where ext e · obtain ⟨⟨p, mp⟩, ⟨f, mf⟩⟩ := x dsimp only at mf ⊢ - have mfs := mem_of_subset (P.le mp) mf - rw [P.eq_of_mem_parts mp (P.part_mem mfs) mf (P.mem_part mfs)] + rw [P.part_eq_of_mem mp mf] · simp lemma exists_enumeration : ∃ f : s ≃ Σ t : P.parts, Fin t.1.card, From 78e28c0c005576a18354ecbabd3506bbc48cf810 Mon Sep 17 00:00:00 2001 From: Peter Nelson <71660771+apnelson1@users.noreply.github.com> Date: Sat, 22 Jun 2024 19:24:46 +0000 Subject: [PATCH 12/19] feat(SimpleGraph/Clique): maps of cliques (#12820) We add some API for cliques in maps of graphs. Co-authored-by: Rida Hamadani --- Mathlib/Combinatorics/SimpleGraph/Clique.lean | 87 +++++++++++++++++-- 1 file changed, 81 insertions(+), 6 deletions(-) diff --git a/Mathlib/Combinatorics/SimpleGraph/Clique.lean b/Mathlib/Combinatorics/SimpleGraph/Clique.lean index 04fc743a4ad362..ef1a5fb0924f68 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Clique.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Clique.lean @@ -77,6 +77,9 @@ lemma isClique_empty : G.IsClique ∅ := by simp lemma isClique_singleton (a : α) : G.IsClique {a} := by simp #align simple_graph.is_clique_singleton SimpleGraph.isClique_singleton +theorem IsClique.of_subsingleton {G : SimpleGraph α} (hs : s.Subsingleton) : G.IsClique s := + hs.pairwise G.Adj + lemma isClique_pair : G.IsClique {a, b} ↔ a ≠ b → G.Adj a b := Set.pairwise_pair_of_symmetric G.symm #align simple_graph.is_clique_pair SimpleGraph.isClique_pair @@ -100,12 +103,6 @@ theorem IsClique.mono (h : G ≤ H) : G.IsClique s → H.IsClique s := Set.Pairw theorem IsClique.subset (h : t ⊆ s) : G.IsClique s → G.IsClique t := Set.Pairwise.mono h #align simple_graph.is_clique.subset SimpleGraph.IsClique.subset -protected theorem IsClique.map {s : Set α} (h : G.IsClique s) {f : α ↪ β} : - (G.map f).IsClique (f '' s) := by - rintro _ ⟨a, ha, rfl⟩ _ ⟨b, hb, rfl⟩ hab - exact ⟨a, b, h ha hb <| ne_of_apply_ne _ hab, rfl, rfl⟩ -#align simple_graph.is_clique.map SimpleGraph.IsClique.map - @[simp] theorem isClique_bot_iff : (⊥ : SimpleGraph α).IsClique s ↔ (s : Set α).Subsingleton := Set.pairwise_bot_iff @@ -114,6 +111,66 @@ theorem isClique_bot_iff : (⊥ : SimpleGraph α).IsClique s ↔ (s : Set α).Su alias ⟨IsClique.subsingleton, _⟩ := isClique_bot_iff #align simple_graph.is_clique.subsingleton SimpleGraph.IsClique.subsingleton +protected theorem IsClique.map (h : G.IsClique s) {f : α ↪ β} : (G.map f).IsClique (f '' s) := by + rintro _ ⟨a, ha, rfl⟩ _ ⟨b, hb, rfl⟩ hab + exact ⟨a, b, h ha hb <| ne_of_apply_ne _ hab, rfl, rfl⟩ +#align simple_graph.is_clique.map SimpleGraph.IsClique.map + +theorem isClique_map_iff_of_nontrivial {f : α ↪ β} {t : Set β} (ht : t.Nontrivial) : + (G.map f).IsClique t ↔ ∃ (s : Set α), G.IsClique s ∧ f '' s = t := by + refine ⟨fun h ↦ ⟨f ⁻¹' t, ?_, ?_⟩, by rintro ⟨x, hs, rfl⟩; exact hs.map⟩ + · rintro x (hx : f x ∈ t) y (hy : f y ∈ t) hne + obtain ⟨u,v, huv, hux, hvy⟩ := h hx hy (by simpa) + rw [EmbeddingLike.apply_eq_iff_eq] at hux hvy + rwa [← hux, ← hvy] + rw [Set.image_preimage_eq_iff] + intro x hxt + obtain ⟨y,hyt, hyne⟩ := ht.exists_ne x + obtain ⟨u,v, -, rfl, rfl⟩ := h hyt hxt hyne + exact Set.mem_range_self _ + +theorem isClique_map_iff {f : α ↪ β} {t : Set β} : + (G.map f).IsClique t ↔ t.Subsingleton ∨ ∃ (s : Set α), G.IsClique s ∧ f '' s = t := by + obtain (ht | ht) := t.subsingleton_or_nontrivial + · simp [IsClique.of_subsingleton, ht] + simp [isClique_map_iff_of_nontrivial ht, ht.not_subsingleton] + +@[simp] theorem isClique_map_image_iff {f : α ↪ β} : + (G.map f).IsClique (f '' s) ↔ G.IsClique s := by + rw [isClique_map_iff, f.injective.subsingleton_image_iff] + obtain (hs | hs) := s.subsingleton_or_nontrivial + · simp [hs, IsClique.of_subsingleton] + simp [or_iff_right hs.not_subsingleton, Set.image_eq_image f.injective] +section DecidableEq + +variable [DecidableEq β] {f : α ↪ β} {t : Finset β} + +theorem isClique_map_finset_iff_of_nontrivial (ht : t.Nontrivial) : + (G.map f).IsClique t ↔ ∃ (s : Finset α), G.IsClique s ∧ s.map f = t := by + constructor + · rw [isClique_map_iff_of_nontrivial (by simpa)] + rintro ⟨s, hs, hst⟩ + obtain ⟨s, rfl⟩ := Set.Finite.exists_finset_coe <| + (show s.Finite from Set.Finite.of_finite_image (by simp [hst]) f.injective.injOn) + exact ⟨s,hs, Finset.coe_inj.1 (by simpa)⟩ + rintro ⟨s, hs, rfl⟩ + simpa using hs.map (f := f) + +theorem isClique_map_finset_iff : + (G.map f).IsClique t ↔ t.card ≤ 1 ∨ ∃ (s : Finset α), G.IsClique s ∧ s.map f = t := by + obtain (ht | ht) := le_or_lt t.card 1 + · simp only [ht, true_or, iff_true] + exact IsClique.of_subsingleton <| card_le_one.1 ht + rw [isClique_map_finset_iff_of_nontrivial, ← not_lt] + · simp [ht, Finset.map_eq_image] + exact Finset.one_lt_card_iff_nontrivial.mp ht + +protected theorem IsClique.finsetMap {f : α ↪ β} {s : Finset α} (h : G.IsClique s) : + (G.map f).IsClique (s.map f) := by + simpa + +end DecidableEq + end Clique /-! ### `n`-cliques -/ @@ -156,6 +213,16 @@ protected theorem IsNClique.map (h : G.IsNClique n s) {f : α ↪ β} : ⟨by rw [coe_map]; exact h.1.map, (card_map _).trans h.2⟩ #align simple_graph.is_n_clique.map SimpleGraph.IsNClique.map +theorem isNClique_map_iff [DecidableEq β] (hn : 1 < n) {t : Finset β} {f : α ↪ β} : + (G.map f).IsNClique n t ↔ ∃ s : Finset α, G.IsNClique n s ∧ s.map f = t := by + rw [isNClique_iff, isClique_map_finset_iff, or_and_right, + or_iff_right (by rintro ⟨h', rfl⟩; exact h'.not_lt hn)] + constructor + · rintro ⟨⟨s, hs, rfl⟩, rfl⟩ + simp [isNClique_iff, hs] + rintro ⟨s, hs, rfl⟩ + simp [hs.card_eq, hs.clique] + @[simp] theorem isNClique_bot_iff : (⊥ : SimpleGraph α).IsNClique n s ↔ n ≤ 1 ∧ s.card = n := by rw [isNClique_iff, isClique_bot_iff] @@ -297,6 +364,14 @@ theorem CliqueFree.comap {H : SimpleGraph β} (f : H ↪g G) : G.CliqueFree n intro h; contrapose h exact not_cliqueFree_of_top_embedding <| f.comp (topEmbeddingOfNotCliqueFree h) +@[simp] theorem cliqueFree_map_iff {f : α ↪ β} [DecidableEq β] [Nonempty α] : + (G.map f).CliqueFree n ↔ G.CliqueFree n := by + obtain (hle | hlt) := le_or_lt n 1 + · obtain (rfl | rfl) := Nat.le_one_iff_eq_zero_or_eq_one.1 hle + · simp [CliqueFree] + simp [CliqueFree, show ∃ (_ : β), True from ⟨f (Classical.arbitrary _), trivial⟩] + simp [CliqueFree, isNClique_map_iff hlt] + /-- See `SimpleGraph.cliqueFree_of_chromaticNumber_lt` for a tighter bound. -/ theorem cliqueFree_of_card_lt [Fintype α] (hc : card α < n) : G.CliqueFree n := by by_contra h From 618674590feb59da107895fab7576eb69796db11 Mon Sep 17 00:00:00 2001 From: Jon Eugster Date: Sat, 22 Jun 2024 19:24:47 +0000 Subject: [PATCH 13/19] chore(LinearAlgebra/TensorProduct/Tower): remove superfluous porting notes (#13987) --- Mathlib/LinearAlgebra/TensorProduct/Tower.lean | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Mathlib/LinearAlgebra/TensorProduct/Tower.lean b/Mathlib/LinearAlgebra/TensorProduct/Tower.lean index 7d9cbe8864980f..6c6c9e70f419b4 100644 --- a/Mathlib/LinearAlgebra/TensorProduct/Tower.lean +++ b/Mathlib/LinearAlgebra/TensorProduct/Tower.lean @@ -150,7 +150,6 @@ def uncurry : (M →ₗ[A] N →ₗ[R] P) →ₗ[B] M ⊗[R] N →ₗ[A] P where toFun := lift map_add' _ _ := ext fun x y => by simp only [lift_tmul, add_apply] map_smul' _ _ := ext fun x y => by simp only [lift_tmul, smul_apply, RingHom.id_apply] --- Porting note: new `B` argument #align tensor_product.algebra_tensor_module.uncurry TensorProduct.AlgebraTensorModule.uncurryₓ /-- Heterobasic version of `TensorProduct.lcurry`: @@ -162,7 +161,6 @@ def lcurry : (M ⊗[R] N →ₗ[A] P) →ₗ[B] M →ₗ[A] N →ₗ[R] P where toFun := curry map_add' _ _ := rfl map_smul' _ _ := rfl --- Porting note: new `B` argument #align tensor_product.algebra_tensor_module.lcurry TensorProduct.AlgebraTensorModule.lcurryₓ /-- Heterobasic version of `TensorProduct.lift.equiv`: @@ -174,7 +172,6 @@ def lift.equiv : (M →ₗ[A] N →ₗ[R] P) ≃ₗ[B] M ⊗[R] N →ₗ[A] P := LinearEquiv.ofLinear (uncurry R A B M N P) (lcurry R A B M N P) (LinearMap.ext fun _ => ext fun x y => lift_tmul _ x y) (LinearMap.ext fun f => LinearMap.ext fun x => LinearMap.ext fun y => lift_tmul f x y) --- Porting note: new `B` argument #align tensor_product.algebra_tensor_module.lift.equiv TensorProduct.AlgebraTensorModule.lift.equivₓ /-- Heterobasic version of `TensorProduct.mk`: @@ -341,7 +338,6 @@ def assoc : (M ⊗[A] P) ⊗[R] Q ≃ₗ[B] M ⊗[A] (P ⊗[R] Q) := (lift <| uncurry R A B P Q _ ∘ₗ curry (mk R B _ Q)) (by ext; rfl) (by ext; rfl) --- Porting note: new `B` argument #align tensor_product.algebra_tensor_module.assoc TensorProduct.AlgebraTensorModule.assocₓ variable {M P N Q} From 8ca314116d1ae0e908c2a57d9840866059536360 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Dupuis?= Date: Sun, 23 Jun 2024 01:13:07 +0000 Subject: [PATCH 14/19] feat(ContinuousFunctionalCalculus): add lemmas about the CFC applied to finite sums (#13842) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Frédéric Dupuis <31101893+dupuisf@users.noreply.github.com> --- .../ContinuousFunction/ContinuousMapZero.lean | 10 ++++++ .../FunctionalCalculus.lean | 28 +++++++++++++++++ .../NonUnitalFunctionalCalculus.lean | 31 +++++++++++++++++++ 3 files changed, 69 insertions(+) diff --git a/Mathlib/Topology/ContinuousFunction/ContinuousMapZero.lean b/Mathlib/Topology/ContinuousFunction/ContinuousMapZero.lean index 0c1d2154e1e00a..ffca5a0579efdf 100644 --- a/Mathlib/Topology/ContinuousFunction/ContinuousMapZero.lean +++ b/Mathlib/Topology/ContinuousFunction/ContinuousMapZero.lean @@ -194,6 +194,16 @@ lemma coe_toContinuousMapHom [StarRing R] [ContinuousStar R] : ⇑(toContinuousMapHom (X := X) (R := R)) = (↑) := rfl +/-- Coercion to a function as an `AddMonoidHom`. Similar to `ContinuousMap.coeFnAddMonoidHom`. -/ +def coeFnAddMonoidHom : C(X, R)₀ →+ X → R where + toFun f := f + map_zero' := coe_zero + map_add' f g := by simp + +@[simp] lemma coe_sum {ι : Type*} (s : Finset ι) + (f : ι → C(X, R)₀) : ⇑(s.sum f) = s.sum (fun i => ⇑(f i)) := + map_sum coeFnAddMonoidHom f s + end Semiring section Ring diff --git a/Mathlib/Topology/ContinuousFunction/FunctionalCalculus.lean b/Mathlib/Topology/ContinuousFunction/FunctionalCalculus.lean index f7df5f33d92981..98571c6306f006 100644 --- a/Mathlib/Topology/ContinuousFunction/FunctionalCalculus.lean +++ b/Mathlib/Topology/ContinuousFunction/FunctionalCalculus.lean @@ -294,6 +294,12 @@ variable (hg : ContinuousOn g (spectrum R a) := by cfc_cont_tac) lemma cfc_apply : cfc f a = cfcHom (a := a) ha ⟨_, hf.restrict⟩ := by rw [cfc_def, dif_pos ⟨ha, hf⟩] +lemma cfc_apply_pi {ι : Type*} (f : ι → R → R) (a : A) (ha : p a := by cfc_tac) + (hf : ∀ i, ContinuousOn (f i) (spectrum R a) := by cfc_cont_tac) : + (fun i => cfc (f i) a) = (fun i => cfcHom (a := a) ha ⟨_, (hf i).restrict⟩) := by + ext i + simp only [cfc_apply (f i) a ha (hf i)] + lemma cfc_apply_of_not_and {f : R → R} (a : A) (ha : ¬ (p a ∧ ContinuousOn f (spectrum R a))) : cfc f a = 0 := by rw [cfc_def, dif_neg ha] @@ -410,6 +416,28 @@ lemma cfc_add (f g : R → R) (hf : ContinuousOn f (spectrum R a) := by cfc_cont congr · simp [cfc_apply_of_not_predicate a ha] +open Finset in +lemma cfc_sum {ι : Type*} (f : ι → R → R) (a : A) (s : Finset ι) + (hf : ∀ i ∈ s, ContinuousOn (f i) (spectrum R a) := by cfc_cont_tac) : + cfc (∑ i in s, f i) a = ∑ i in s, cfc (f i) a := by + by_cases ha : p a + · have hsum : s.sum f = fun z => ∑ i ∈ s, f i z := by ext; simp + have hf' : ContinuousOn (∑ i : s, f i) (spectrum R a) := by + rw [sum_coe_sort s, hsum] + exact continuousOn_finset_sum s fun i hi => hf i hi + rw [← sum_coe_sort s, ← sum_coe_sort s] + rw [cfc_apply_pi _ a _ (fun ⟨i, hi⟩ => hf i hi), ← map_sum, cfc_apply _ a ha hf'] + congr 1 + ext + simp + · simp [cfc_apply_of_not_predicate a ha] + +open Finset in +lemma cfc_sum_univ {ι : Type*} [Fintype ι] (f : ι → R → R) (a : A) + (hf : ∀ i, ContinuousOn (f i) (spectrum R a) := by cfc_cont_tac) : + cfc (∑ i, f i) a = ∑ i, cfc (f i) a := + cfc_sum f a _ fun i _ ↦ hf i + lemma cfc_smul {S : Type*} [SMul S R] [ContinuousConstSMul S R] [SMulZeroClass S A] [IsScalarTower S R A] [IsScalarTower S R (R → R)] (s : S) (f : R → R) (a : A) (hf : ContinuousOn f (spectrum R a) := by cfc_cont_tac) : diff --git a/Mathlib/Topology/ContinuousFunction/NonUnitalFunctionalCalculus.lean b/Mathlib/Topology/ContinuousFunction/NonUnitalFunctionalCalculus.lean index c32fe9ba37ad9f..c968cc88470129 100644 --- a/Mathlib/Topology/ContinuousFunction/NonUnitalFunctionalCalculus.lean +++ b/Mathlib/Topology/ContinuousFunction/NonUnitalFunctionalCalculus.lean @@ -200,6 +200,13 @@ variable (ha : p a := by cfc_tac) lemma cfcₙ_apply : cfcₙ f a = cfcₙHom (a := a) ha ⟨⟨_, hf.restrict⟩, hf0⟩ := by rw [cfcₙ_def, dif_pos ⟨ha, hf, hf0⟩] +lemma cfcₙ_apply_pi {ι : Type*} (f : ι → R → R) (a : A) (ha := by cfc_tac) + (hf : ∀ i, ContinuousOn (f i) (σₙ R a) := by cfc_cont_tac) + (hf0 : ∀ i, f i 0 = 0 := by cfc_zero_tac) : + (fun i => cfcₙ (f i) a) = (fun i => cfcₙHom (a := a) ha ⟨⟨_, (hf i).restrict⟩, hf0 i⟩) := by + ext i + simp only [cfcₙ_apply (f i) a (hf i) (hf0 i)] + lemma cfcₙ_apply_of_not_and_and {f : R → R} (a : A) (ha : ¬ (p a ∧ ContinuousOn f (σₙ R a) ∧ f 0 = 0)) : cfcₙ f a = 0 := by @@ -311,6 +318,30 @@ lemma cfcₙ_add : cfcₙ (fun x ↦ f x + g x) a = cfcₙ f a + cfcₙ g a := b congr · simp [cfcₙ_apply_of_not_predicate a ha] +open Finset in +lemma cfcₙ_sum {ι : Type*} (f : ι → R → R) (a : A) (s : Finset ι) + (hf : ∀ i ∈ s, ContinuousOn (f i) (σₙ R a) := by cfc_cont_tac) + (hf0 : ∀ i ∈ s, f i 0 = 0 := by cfc_zero_tac) : + cfcₙ (∑ i in s, f i) a = ∑ i in s, cfcₙ (f i) a := by + by_cases ha : p a + · have hsum : s.sum f = fun z => ∑ i ∈ s, f i z := by ext; simp + have hf' : ContinuousOn (∑ i : s, f i) (σₙ R a) := by + rw [sum_coe_sort s, hsum] + exact continuousOn_finset_sum s fun i hi => hf i hi + rw [← sum_coe_sort s, ← sum_coe_sort s] + rw [cfcₙ_apply_pi _ a _ (fun ⟨i, hi⟩ => hf i hi), ← map_sum, cfcₙ_apply _ a hf'] + congr 1 + ext + simp + · simp [cfcₙ_apply_of_not_predicate a ha] + +open Finset in +lemma cfcₙ_sum_univ {ι : Type*} [Fintype ι] (f : ι → R → R) (a : A) + (hf : ∀ i, ContinuousOn (f i) (σₙ R a) := by cfc_cont_tac) + (hf0 : ∀ i, f i 0 = 0 := by cfc_zero_tac) : + cfcₙ (∑ i, f i) a = ∑ i, cfcₙ (f i) a := + cfcₙ_sum f a _ (fun i _ ↦ hf i) (fun i _ ↦ hf0 i) + lemma cfcₙ_smul {S : Type*} [SMulZeroClass S R] [ContinuousConstSMul S R] [SMulZeroClass S A] [IsScalarTower S R A] [IsScalarTower S R (R → R)] (s : S) (f : R → R) (a : A) (hf : ContinuousOn f (σₙ R a) := by cfc_cont_tac) From 92377b4d13c739dc9c0bf6419c537695a783b173 Mon Sep 17 00:00:00 2001 From: Jujian Zhang Date: Sun, 23 Jun 2024 05:04:34 +0000 Subject: [PATCH 15/19] chore(AlgebraicGeometry/OpenImmersion): resolve some outdated porting note (#14037) Co-authored-by: zjj --- .../Geometry/RingedSpace/OpenImmersion.lean | 110 ++++++------------ 1 file changed, 34 insertions(+), 76 deletions(-) diff --git a/Mathlib/Geometry/RingedSpace/OpenImmersion.lean b/Mathlib/Geometry/RingedSpace/OpenImmersion.lean index c2c7080737aae2..a0787f0d69eeaf 100644 --- a/Mathlib/Geometry/RingedSpace/OpenImmersion.lean +++ b/Mathlib/Geometry/RingedSpace/OpenImmersion.lean @@ -157,10 +157,8 @@ instance comp {Z : PresheafedSpace C} (f : X ⟶ Y) [hf : IsOpenImmersion f] (g generalize_proofs h dsimp only [AlgebraicGeometry.PresheafedSpace.comp_c_app, unop_op, Functor.op, comp_base, TopCat.Presheaf.pushforwardObj_obj, Opens.map_comp_obj] - -- Porting note: was `apply (config := { instances := False }) ...` - -- See https://github.com/leanprover/lean4/issues/2273 - have : IsIso (g.c.app (op <| (h.functor).obj U)) := by - have : h.functor.obj U = hg.openFunctor.obj (hf.openFunctor.obj U) := by + apply (config := { allowSynthFailures := true }) IsIso.comp_isIso + · have : h.functor.obj U = hg.openFunctor.obj (hf.openFunctor.obj U) := by ext1 dsimp only [IsOpenMap.functor_obj_coe] -- Porting note: slightly more hand holding here: `g ∘ f` and `fun x => g (f x)` @@ -168,8 +166,7 @@ instance comp {Z : PresheafedSpace C} (f : X ⟶ Y) [hf : IsOpenImmersion f] (g ← Set.image_image] -- now `erw` after #13170 rw [this] infer_instance - have : IsIso (f.c.app (op <| (Opens.map g.base).obj ((IsOpenMap.functor h).obj U))) := by - have : (Opens.map g.base).obj (h.functor.obj U) = hf.openFunctor.obj U := by + · have : (Opens.map g.base).obj (h.functor.obj U) = hf.openFunctor.obj U := by ext1 dsimp only [Opens.map_coe, IsOpenMap.functor_obj_coe, comp_base] -- Porting note: slightly more hand holding here: `g ∘ f` and `fun x => g (f x)` @@ -178,20 +175,13 @@ instance comp {Z : PresheafedSpace C} (f : X ⟶ Y) [hf : IsOpenImmersion f] (g -- now `erw` after #13170 rw [this] infer_instance - apply IsIso.comp_isIso + #align algebraic_geometry.PresheafedSpace.is_open_immersion.comp AlgebraicGeometry.PresheafedSpace.IsOpenImmersion.comp /-- For an open immersion `f : X ⟶ Y` and an open set `U ⊆ X`, we have the map `X(U) ⟶ Y(U)`. -/ noncomputable def invApp (U : Opens X) : X.presheaf.obj (op U) ⟶ Y.presheaf.obj (op (H.openFunctor.obj U)) := - X.presheaf.map (eqToHom (by - -- Porting note: was just `simp [opens.map, Set.preimage_image_eq _ H.base_open.inj]` - -- See https://github.com/leanprover-community/mathlib4/issues/5026 - -- I think this is because `Set.preimage_image_eq _ H.base_open.inj` can't see through a - -- structure - congr; ext - dsimp [openFunctor, IsOpenMap.functor] - rw [Set.preimage_image_eq _ H.base_open.inj])) ≫ + X.presheaf.map (eqToHom (by simp [Opens.map, Set.preimage_image_eq _ H.base_open.inj])) ≫ inv (f.c.app (op (H.openFunctor.obj U))) #align algebraic_geometry.PresheafedSpace.is_open_immersion.inv_app AlgebraicGeometry.PresheafedSpace.IsOpenImmersion.invApp @@ -201,12 +191,9 @@ theorem inv_naturality {U V : (Opens X)ᵒᵖ} (i : U ⟶ V) : H.invApp (unop U) ≫ Y.presheaf.map (H.openFunctor.op.map i) := by simp only [invApp, ← Category.assoc] rw [IsIso.comp_inv_eq] - -- Porting note: `simp` can't pick up `f.c.naturality` - -- See https://github.com/leanprover-community/mathlib4/issues/5026 - simp only [Category.assoc, ← X.presheaf.map_comp] - erw [f.c.naturality] - simp only [IsIso.inv_hom_id_assoc, ← X.presheaf.map_comp] - erw [← X.presheaf.map_comp] + simp only [Functor.op_obj, op_unop, ← X.presheaf.map_comp, Functor.op_map, Category.assoc, + NatTrans.naturality, TopCat.Presheaf.pushforwardObj_obj, TopCat.Presheaf.pushforwardObj_map, + Quiver.Hom.unop_op, IsIso.inv_hom_id_assoc] congr 1 #align algebraic_geometry.PresheafedSpace.is_open_immersion.inv_naturality AlgebraicGeometry.PresheafedSpace.IsOpenImmersion.inv_naturality @@ -215,14 +202,8 @@ instance (U : Opens X) : IsIso (H.invApp U) := by delta invApp; infer_instance theorem inv_invApp (U : Opens X) : inv (H.invApp U) = f.c.app (op (H.openFunctor.obj U)) ≫ - X.presheaf.map (eqToHom (by - -- Porting note: was just `simp [opens.map, Set.preimage_image_eq _ H.base_open.inj]` - -- See https://github.com/leanprover-community/mathlib4/issues/5026 - -- I think this is because `Set.preimage_image_eq _ H.base_open.inj` can't see through a - -- structure - apply congr_arg (op ·); ext - dsimp [openFunctor, IsOpenMap.functor] - rw [Set.preimage_image_eq _ H.base_open.inj])) := by + X.presheaf.map + (eqToHom (by simp [Opens.map, Set.preimage_image_eq _ H.base_open.inj])) := by rw [← cancel_epi (H.invApp U), IsIso.hom_inv_id] delta invApp simp [← Functor.map_comp] @@ -231,14 +212,7 @@ theorem inv_invApp (U : Opens X) : @[simp, reassoc, elementwise] theorem invApp_app (U : Opens X) : H.invApp U ≫ f.c.app (op (H.openFunctor.obj U)) = - X.presheaf.map (eqToHom (by - -- Porting note: was just `simp [opens.map, Set.preimage_image_eq _ H.base_open.inj]` - -- See https://github.com/leanprover-community/mathlib4/issues/5026 - -- I think this is because `Set.preimage_image_eq _ H.base_open.inj` can't see through a - -- structure - apply congr_arg (op ·); ext - dsimp [openFunctor, IsOpenMap.functor] - rw [Set.preimage_image_eq _ H.base_open.inj])) := by + X.presheaf.map (eqToHom (by simp [Opens.map, Set.preimage_image_eq _ H.base_open.inj])) := by rw [invApp, Category.assoc, IsIso.inv_hom_id, Category.comp_id] #align algebraic_geometry.PresheafedSpace.is_open_immersion.inv_app_app AlgebraicGeometry.PresheafedSpace.IsOpenImmersion.invApp_app @@ -310,8 +284,6 @@ theorem ofRestrict_invApp {C : Type*} [Category C] (X : PresheafedSpace C) {Y : /-- An open immersion is an iso if the underlying continuous map is epi. -/ theorem to_iso (f : X ⟶ Y) [h : IsOpenImmersion f] [h' : Epi f.base] : IsIso f := by - -- Porting note: was `apply (config := { instances := False }) ...` - -- See https://github.com/leanprover/lean4/issues/2273 have : ∀ (U : (Opens Y)ᵒᵖ), IsIso (f.c.app U) := by intro U have : U = op (h.openFunctor.obj ((Opens.map f.base).obj (unop U))) := by @@ -321,17 +293,18 @@ theorem to_iso (f : X ⟶ Y) [h : IsOpenImmersion f] [h' : Epi f.base] : IsIso f congr exact (Set.image_preimage_eq _ ((TopCat.epi_iff_surjective _).mp h')).symm convert @IsOpenImmersion.c_iso _ _ _ _ _ h ((Opens.map f.base).obj (unop U)) - have : IsIso f.base := by - let t : X ≃ₜ Y := - (Homeomorph.ofEmbedding _ h.base_open.toEmbedding).trans - { toFun := Subtype.val - invFun := fun x => - ⟨x, by rw [Set.range_iff_surjective.mpr ((TopCat.epi_iff_surjective _).mp h')]; trivial⟩ - left_inv := fun ⟨_, _⟩ => rfl - right_inv := fun _ => rfl } - convert (TopCat.isoOfHomeo t).isIso_hom - have : IsIso f.c := by apply NatIso.isIso_of_isIso_app - apply isIso_of_components + + have : IsIso f.c := NatIso.isIso_of_isIso_app _ + + apply (config := { allowSynthFailures := true }) isIso_of_components + let t : X ≃ₜ Y := (Homeomorph.ofEmbedding _ h.base_open.toEmbedding).trans + { toFun := Subtype.val + invFun := fun x => + ⟨x, by rw [Set.range_iff_surjective.mpr ((TopCat.epi_iff_surjective _).mp h')]; trivial⟩ + left_inv := fun ⟨_, _⟩ => rfl + right_inv := fun _ => rfl } + exact (TopCat.isoOfHomeo t).isIso_hom + #align algebraic_geometry.PresheafedSpace.is_open_immersion.to_iso AlgebraicGeometry.PresheafedSpace.IsOpenImmersion.to_iso instance stalk_iso [HasColimits C] [H : IsOpenImmersion f] (x : X) : IsIso (stalkMap f x) := by @@ -384,15 +357,14 @@ def pullbackConeOfLeftFst : intro U V i induction U using Opposite.rec' induction V using Opposite.rec' - simp only [Quiver.Hom.unop_op, Category.assoc, Functor.op_map] -- Note: this doesn't fire in `simp` because of reduction of the term via structure eta -- before discrimination tree key generation rw [inv_naturality_assoc] - -- Porting note: the following lemmas are not picked up by `simp` - -- See https://github.com/leanprover-community/mathlib4/issues/5026 - erw [g.c.naturality_assoc, TopCat.Presheaf.pushforwardObj_map, ← Y.presheaf.map_comp, - ← Y.presheaf.map_comp] - congr 1 } + simp only [restrict_carrier, restrict_presheaf, TopCat.Presheaf.pushforwardObj_obj, + Functor.op_obj, Functor.comp_obj, Functor.op_map, NatTrans.naturality_assoc, + TopCat.Presheaf.pushforwardObj_map, Quiver.Hom.unop_op, ← Y.presheaf.map_comp, + Functor.comp_map, Category.assoc] + rfl } #align algebraic_geometry.PresheafedSpace.is_open_immersion.pullback_cone_of_left_fst AlgebraicGeometry.PresheafedSpace.IsOpenImmersion.pullbackConeOfLeftFst theorem pullback_cone_of_left_condition : pullbackConeOfLeftFst f g ≫ f = Y.ofRestrict _ ≫ g := by @@ -579,8 +551,6 @@ def lift (H : Set.range g.base ⊆ Set.range f.base) : Y ⟶ X := @[simp, reassoc] theorem lift_fac (H : Set.range g.base ⊆ Set.range f.base) : lift f g H ≫ f = g := by - -- Porting note: this instance was automatic - letI := pullback_snd_isIso_of_range_subset _ _ H erw [Category.assoc]; rw [IsIso.inv_comp_eq]; exact pullback.condition #align algebraic_geometry.PresheafedSpace.is_open_immersion.lift_fac AlgebraicGeometry.PresheafedSpace.IsOpenImmersion.lift_fac @@ -849,11 +819,9 @@ theorem of_stalk_iso {X Y : SheafedSpace C} (f : X ⟶ Y) (hf : OpenEmbedding f. [H : ∀ x : X.1, IsIso (PresheafedSpace.stalkMap f x)] : SheafedSpace.IsOpenImmersion f := { base_open := hf c_iso := fun U => by - -- Porting note: was `apply (config := { instances := False }) ...` - -- See https://github.com/leanprover/lean4/issues/2273 - have h := TopCat.Presheaf.app_isIso_of_stalkFunctor_map_iso + apply (config := {allowSynthFailures := true}) + TopCat.Presheaf.app_isIso_of_stalkFunctor_map_iso (show Y.sheaf ⟶ (TopCat.Sheaf.pushforward _ f.base).obj X.sheaf from ⟨f.c⟩) - refine @h _ ?_ rintro ⟨_, y, hy, rfl⟩ specialize H y delta PresheafedSpace.stalkMap at H @@ -903,8 +871,6 @@ theorem image_preimage_is_empty (j : Discrete ι) (h : i ≠ j) (U : Opens (F.ob HasColimit.isoOfNatIso Discrete.natIsoFunctor ≪≫ TopCat.sigmaIsoSigma.{v, v} _).hom eq simp_rw [CategoryTheory.Iso.trans_hom, ← TopCat.comp_app, ← PresheafedSpace.comp_base] at eq rw [ι_preservesColimitsIso_inv] at eq - -- Porting note: without this `erw`, change does not work - erw [← comp_apply, ← comp_apply] at eq change ((SheafedSpace.forget C).map (colimit.ι F i) ≫ _) y = ((SheafedSpace.forget C).map (colimit.ι F j) ≫ _) x at eq @@ -1138,16 +1104,10 @@ instance forgetToPresheafedSpaceReflectsPullbackOfRight : theorem pullback_snd_isIso_of_range_subset (H' : Set.range g.1.base ⊆ Set.range f.1.base) : IsIso (pullback.snd : pullback f g ⟶ _) := by - -- Porting note: was `apply (config := { instances := False }) ...` - -- See https://github.com/leanprover/lean4/issues/2273 - have h1 := @Functor.ReflectsIsomorphisms.reflects - (F := LocallyRingedSpace.forgetToSheafedSpace) _ _ _ - refine @h1 _ _ _ ?_; clear h1 - -- Porting note: was `apply (config := { instances := False }) ...` - -- See https://github.com/leanprover/lean4/issues/2273 - have h2 := @Functor.ReflectsIsomorphisms.reflects - (F := SheafedSpace.forgetToPresheafedSpace (C := CommRingCat)) _ _ _ - refine @h2 _ _ _ ?_; clear h2 + apply (config := {allowSynthFailures := true}) Functor.ReflectsIsomorphisms.reflects + (F := LocallyRingedSpace.forgetToSheafedSpace) + apply (config := {allowSynthFailures := true}) Functor.ReflectsIsomorphisms.reflects + (F := SheafedSpace.forgetToPresheafedSpace) erw [← PreservesPullback.iso_hom_snd (LocallyRingedSpace.forgetToSheafedSpace ⋙ SheafedSpace.forgetToPresheafedSpace) f g] -- Porting note: was `inferInstance` @@ -1168,8 +1128,6 @@ def lift (H' : Set.range g.1.base ⊆ Set.range f.1.base) : Y ⟶ X := @[simp, reassoc] theorem lift_fac (H' : Set.range g.1.base ⊆ Set.range f.1.base) : lift f g H' ≫ f = g := by - -- Porting note (#10754): added instance manually - haveI := pullback_snd_isIso_of_range_subset f g H' erw [Category.assoc]; rw [IsIso.inv_comp_eq]; exact pullback.condition #align algebraic_geometry.LocallyRingedSpace.is_open_immersion.lift_fac AlgebraicGeometry.LocallyRingedSpace.IsOpenImmersion.lift_fac From 756e653793d42719b332f77a3f0fe008939e7657 Mon Sep 17 00:00:00 2001 From: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> Date: Sun, 23 Jun 2024 06:39:04 +0000 Subject: [PATCH 16/19] chore: split some results out of Analysis.Normed.Group.Basic (#14035) This flips the longest pole back to ring theory / linear algebra. --- Mathlib.lean | 3 + Mathlib/Analysis/Normed/Field/Basic.lean | 2 + Mathlib/Analysis/Normed/Group/AddTorsor.lean | 1 + Mathlib/Analysis/Normed/Group/Basic.lean | 120 +----------------- .../Analysis/Normed/Group/CocompactMap.lean | 1 + Mathlib/Analysis/Normed/Group/Hom.lean | 1 + Mathlib/Analysis/Normed/Group/Int.lean | 68 ++++++++++ Mathlib/Analysis/Normed/Group/Rat.lean | 29 +++++ Mathlib/Analysis/Normed/Group/Submodule.lean | 51 ++++++++ Mathlib/Analysis/Normed/Order/Lattice.lean | 1 + .../Analysis/NormedSpace/LinearIsometry.lean | 1 + Mathlib/InformationTheory/Hamming.lean | 1 + .../Constructions/BorelSpace/Basic.lean | 4 +- .../Constructions/BorelSpace/Metric.lean | 3 +- Mathlib/MeasureTheory/Integral/Lebesgue.lean | 1 + 15 files changed, 167 insertions(+), 120 deletions(-) create mode 100644 Mathlib/Analysis/Normed/Group/Int.lean create mode 100644 Mathlib/Analysis/Normed/Group/Rat.lean create mode 100644 Mathlib/Analysis/Normed/Group/Submodule.lean diff --git a/Mathlib.lean b/Mathlib.lean index 5009a8d559f4ef..dc604ebbd3198d 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1038,13 +1038,16 @@ import Mathlib.Analysis.Normed.Group.ControlledClosure import Mathlib.Analysis.Normed.Group.Hom import Mathlib.Analysis.Normed.Group.HomCompletion import Mathlib.Analysis.Normed.Group.InfiniteSum +import Mathlib.Analysis.Normed.Group.Int import Mathlib.Analysis.Normed.Group.Lemmas import Mathlib.Analysis.Normed.Group.Pointwise import Mathlib.Analysis.Normed.Group.Quotient +import Mathlib.Analysis.Normed.Group.Rat import Mathlib.Analysis.Normed.Group.SemiNormedGrp import Mathlib.Analysis.Normed.Group.SemiNormedGrp.Completion import Mathlib.Analysis.Normed.Group.SemiNormedGrp.Kernels import Mathlib.Analysis.Normed.Group.Seminorm +import Mathlib.Analysis.Normed.Group.Submodule import Mathlib.Analysis.Normed.Group.Tannery import Mathlib.Analysis.Normed.Group.Uniform import Mathlib.Analysis.Normed.Group.ZeroAtInfty diff --git a/Mathlib/Analysis/Normed/Field/Basic.lean b/Mathlib/Analysis/Normed/Field/Basic.lean index 08516ecdd25e41..3af6ed7eb888a1 100644 --- a/Mathlib/Analysis/Normed/Field/Basic.lean +++ b/Mathlib/Analysis/Normed/Field/Basic.lean @@ -8,6 +8,8 @@ import Mathlib.Algebra.Algebra.Subalgebra.Basic import Mathlib.Algebra.Order.Ring.Finset import Mathlib.Analysis.Normed.Group.Bounded import Mathlib.Analysis.Normed.Group.Constructions +import Mathlib.Analysis.Normed.Group.Rat +import Mathlib.Analysis.Normed.Group.Submodule import Mathlib.Analysis.Normed.Group.Uniform import Mathlib.GroupTheory.OrderOfElement import Mathlib.Topology.Instances.NNReal diff --git a/Mathlib/Analysis/Normed/Group/AddTorsor.lean b/Mathlib/Analysis/Normed/Group/AddTorsor.lean index 61db36a27de95e..fbccd4834b120d 100644 --- a/Mathlib/Analysis/Normed/Group/AddTorsor.lean +++ b/Mathlib/Analysis/Normed/Group/AddTorsor.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Joseph Myers, Yury Kudryashov -/ import Mathlib.Analysis.Normed.Group.Basic +import Mathlib.Analysis.Normed.Group.Submodule import Mathlib.LinearAlgebra.AffineSpace.AffineSubspace import Mathlib.LinearAlgebra.AffineSpace.Midpoint import Mathlib.Topology.MetricSpace.IsometricSMul diff --git a/Mathlib/Analysis/Normed/Group/Basic.lean b/Mathlib/Analysis/Normed/Group/Basic.lean index f3ec5453a417d4..2843a13c8498a2 100644 --- a/Mathlib/Analysis/Normed/Group/Basic.lean +++ b/Mathlib/Analysis/Normed/Group/Basic.lean @@ -3,8 +3,10 @@ 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, Yaël Dillies -/ +import Mathlib.Algebra.CharP.Defs +import Mathlib.Algebra.Group.Subgroup.Basic import Mathlib.Analysis.Normed.Group.Seminorm -import Mathlib.Topology.Instances.Rat +import Mathlib.Topology.Metrizable.Uniformity import Mathlib.Topology.Sequences #align_import analysis.normed.group.basic from "leanprover-community/mathlib"@"41bef4ae1254365bc190aee63b947674d2977f01" @@ -1513,80 +1515,6 @@ instance : NNNorm ℝ≥0 where end NNReal -namespace Int - -instance instNormedAddCommGroup : NormedAddCommGroup ℤ where - norm n := ‖(n : ℝ)‖ - dist_eq m n := by simp only [Int.dist_eq, norm, Int.cast_sub] - -@[norm_cast] -theorem norm_cast_real (m : ℤ) : ‖(m : ℝ)‖ = ‖m‖ := - rfl -#align int.norm_cast_real Int.norm_cast_real - -theorem norm_eq_abs (n : ℤ) : ‖n‖ = |(n : ℝ)| := - rfl -#align int.norm_eq_abs Int.norm_eq_abs - -@[simp] -theorem norm_natCast (n : ℕ) : ‖(n : ℤ)‖ = n := by simp [Int.norm_eq_abs] -#align int.norm_coe_nat Int.norm_natCast - -@[deprecated (since := "2024-04-05")] alias norm_coe_nat := norm_natCast - -theorem _root_.NNReal.natCast_natAbs (n : ℤ) : (n.natAbs : ℝ≥0) = ‖n‖₊ := - NNReal.eq <| - calc - ((n.natAbs : ℝ≥0) : ℝ) = (n.natAbs : ℤ) := by simp only [Int.cast_natCast, NNReal.coe_natCast] - _ = |(n : ℝ)| := by simp only [Int.natCast_natAbs, Int.cast_abs] - _ = ‖n‖ := (norm_eq_abs n).symm -#align nnreal.coe_nat_abs NNReal.natCast_natAbs - -theorem abs_le_floor_nnreal_iff (z : ℤ) (c : ℝ≥0) : |z| ≤ ⌊c⌋₊ ↔ ‖z‖₊ ≤ c := by - rw [Int.abs_eq_natAbs, Int.ofNat_le, Nat.le_floor_iff (zero_le c), NNReal.natCast_natAbs z] -#align int.abs_le_floor_nnreal_iff Int.abs_le_floor_nnreal_iff - -end Int - -namespace Rat - -instance instNormedAddCommGroup : NormedAddCommGroup ℚ where - norm r := ‖(r : ℝ)‖ - dist_eq r₁ r₂ := by simp only [Rat.dist_eq, norm, Rat.cast_sub] - -@[norm_cast, simp 1001] --- Porting note: increase priority to prevent the left-hand side from simplifying -theorem norm_cast_real (r : ℚ) : ‖(r : ℝ)‖ = ‖r‖ := - rfl -#align rat.norm_cast_real Rat.norm_cast_real - -@[norm_cast, simp] -theorem _root_.Int.norm_cast_rat (m : ℤ) : ‖(m : ℚ)‖ = ‖m‖ := by - rw [← Rat.norm_cast_real, ← Int.norm_cast_real]; congr 1 -#align int.norm_cast_rat Int.norm_cast_rat - -end Rat - --- Now that we've installed the norm on `ℤ`, --- we can state some lemmas about `zsmul`. -section - -variable [SeminormedCommGroup α] - -@[to_additive norm_zsmul_le] -theorem norm_zpow_le_mul_norm (n : ℤ) (a : α) : ‖a ^ n‖ ≤ ‖n‖ * ‖a‖ := by - rcases n.eq_nat_or_neg with ⟨n, rfl | rfl⟩ <;> simpa using norm_pow_le_mul_norm n a -#align norm_zpow_le_mul_norm norm_zpow_le_mul_norm -#align norm_zsmul_le norm_zsmul_le - -@[to_additive nnnorm_zsmul_le] -theorem nnnorm_zpow_le_mul_norm (n : ℤ) (a : α) : ‖a ^ n‖₊ ≤ ‖n‖₊ * ‖a‖₊ := by - simpa only [← NNReal.coe_le_coe, NNReal.coe_mul] using norm_zpow_le_mul_norm n a -#align nnnorm_zpow_le_mul_norm nnnorm_zpow_le_mul_norm -#align nnnorm_zsmul_le nnnorm_zsmul_le - -end - end SeminormedCommGroup section NormedGroup @@ -1765,45 +1693,3 @@ instance normedCommGroup [NormedCommGroup E] {s : Subgroup E} : NormedCommGroup #align add_subgroup.normed_add_comm_group AddSubgroup.normedAddCommGroup end Subgroup - -/-! ### Submodules of normed groups -/ - - -namespace Submodule - --- See note [implicit instance arguments] -/-- A submodule of a seminormed group is also a seminormed group, with the restriction of the norm. --/ -instance seminormedAddCommGroup [Ring 𝕜] [SeminormedAddCommGroup E] [Module 𝕜 E] - (s : Submodule 𝕜 E) : SeminormedAddCommGroup s := - SeminormedAddCommGroup.induced _ _ s.subtype.toAddMonoidHom -#align submodule.seminormed_add_comm_group Submodule.seminormedAddCommGroup - --- See note [implicit instance arguments]. -/-- If `x` is an element of a submodule `s` of a normed group `E`, its norm in `s` is equal to its -norm in `E`. -/ -@[simp] -theorem coe_norm [Ring 𝕜] [SeminormedAddCommGroup E] [Module 𝕜 E] {s : Submodule 𝕜 E} - (x : s) : ‖x‖ = ‖(x : E)‖ := - rfl -#align submodule.coe_norm Submodule.coe_norm - --- See note [implicit instance arguments]. -/-- If `x` is an element of a submodule `s` of a normed group `E`, its norm in `E` is equal to its -norm in `s`. - -This is a reversed version of the `simp` lemma `Submodule.coe_norm` for use by `norm_cast`. -/ -@[norm_cast] -theorem norm_coe [Ring 𝕜] [SeminormedAddCommGroup E] [Module 𝕜 E] {s : Submodule 𝕜 E} - (x : s) : ‖(x : E)‖ = ‖x‖ := - rfl -#align submodule.norm_coe Submodule.norm_coe - --- See note [implicit instance arguments]. -/-- A submodule of a normed group is also a normed group, with the restriction of the norm. -/ -instance normedAddCommGroup [Ring 𝕜] [NormedAddCommGroup E] [Module 𝕜 E] - (s : Submodule 𝕜 E) : NormedAddCommGroup s := - { Submodule.seminormedAddCommGroup s with - eq_of_dist_eq_zero := eq_of_dist_eq_zero } - -end Submodule diff --git a/Mathlib/Analysis/Normed/Group/CocompactMap.lean b/Mathlib/Analysis/Normed/Group/CocompactMap.lean index 919f345193ef68..0a85b81d0c3be7 100644 --- a/Mathlib/Analysis/Normed/Group/CocompactMap.lean +++ b/Mathlib/Analysis/Normed/Group/CocompactMap.lean @@ -6,6 +6,7 @@ Authors: Moritz Doll import Mathlib.Analysis.Normed.Group.Basic import Mathlib.Topology.ContinuousFunction.CocompactMap +import Mathlib.Topology.MetricSpace.Bounded /-! # Cocompact maps in normed groups diff --git a/Mathlib/Analysis/Normed/Group/Hom.lean b/Mathlib/Analysis/Normed/Group/Hom.lean index ca46ed9e4c4048..69ec3db8c5c98e 100644 --- a/Mathlib/Analysis/Normed/Group/Hom.lean +++ b/Mathlib/Analysis/Normed/Group/Hom.lean @@ -3,6 +3,7 @@ Copyright (c) 2021 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin -/ +import Mathlib.Analysis.Normed.Group.Int import Mathlib.Analysis.Normed.Group.Uniform #align_import analysis.normed.group.hom from "leanprover-community/mathlib"@"3c4225288b55380a90df078ebae0991080b12393" diff --git a/Mathlib/Analysis/Normed/Group/Int.lean b/Mathlib/Analysis/Normed/Group/Int.lean new file mode 100644 index 00000000000000..5d644fe62e6c17 --- /dev/null +++ b/Mathlib/Analysis/Normed/Group/Int.lean @@ -0,0 +1,68 @@ +/- +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, Yaël Dillies +-/ + +import Mathlib.Analysis.Normed.Group.Basic +import Mathlib.Topology.Instances.Int + +/-! # ℤ as a normed group -/ + +open NNReal + +variable {α : Type*} +namespace Int + +instance instNormedAddCommGroup : NormedAddCommGroup ℤ where + norm n := ‖(n : ℝ)‖ + dist_eq m n := by simp only [Int.dist_eq, norm, Int.cast_sub] + +@[norm_cast] +theorem norm_cast_real (m : ℤ) : ‖(m : ℝ)‖ = ‖m‖ := + rfl +#align int.norm_cast_real Int.norm_cast_real + +theorem norm_eq_abs (n : ℤ) : ‖n‖ = |(n : ℝ)| := + rfl +#align int.norm_eq_abs Int.norm_eq_abs + +@[simp] +theorem norm_natCast (n : ℕ) : ‖(n : ℤ)‖ = n := by simp [Int.norm_eq_abs] +#align int.norm_coe_nat Int.norm_natCast + +@[deprecated (since := "2024-04-05")] alias norm_coe_nat := norm_natCast + +theorem _root_.NNReal.natCast_natAbs (n : ℤ) : (n.natAbs : ℝ≥0) = ‖n‖₊ := + NNReal.eq <| + calc + ((n.natAbs : ℝ≥0) : ℝ) = (n.natAbs : ℤ) := by simp only [Int.cast_natCast, NNReal.coe_natCast] + _ = |(n : ℝ)| := by simp only [Int.natCast_natAbs, Int.cast_abs] + _ = ‖n‖ := (norm_eq_abs n).symm +#align nnreal.coe_nat_abs NNReal.natCast_natAbs + +theorem abs_le_floor_nnreal_iff (z : ℤ) (c : ℝ≥0) : |z| ≤ ⌊c⌋₊ ↔ ‖z‖₊ ≤ c := by + rw [Int.abs_eq_natAbs, Int.ofNat_le, Nat.le_floor_iff (zero_le c), NNReal.natCast_natAbs z] +#align int.abs_le_floor_nnreal_iff Int.abs_le_floor_nnreal_iff + +end Int + +-- Now that we've installed the norm on `ℤ`, +-- we can state some lemmas about `zsmul`. +section + +variable [SeminormedCommGroup α] + +@[to_additive norm_zsmul_le] +theorem norm_zpow_le_mul_norm (n : ℤ) (a : α) : ‖a ^ n‖ ≤ ‖n‖ * ‖a‖ := by + rcases n.eq_nat_or_neg with ⟨n, rfl | rfl⟩ <;> simpa using norm_pow_le_mul_norm n a +#align norm_zpow_le_mul_norm norm_zpow_le_mul_norm +#align norm_zsmul_le norm_zsmul_le + +@[to_additive nnnorm_zsmul_le] +theorem nnnorm_zpow_le_mul_norm (n : ℤ) (a : α) : ‖a ^ n‖₊ ≤ ‖n‖₊ * ‖a‖₊ := by + simpa only [← NNReal.coe_le_coe, NNReal.coe_mul] using norm_zpow_le_mul_norm n a +#align nnnorm_zpow_le_mul_norm nnnorm_zpow_le_mul_norm +#align nnnorm_zsmul_le nnnorm_zsmul_le + +end diff --git a/Mathlib/Analysis/Normed/Group/Rat.lean b/Mathlib/Analysis/Normed/Group/Rat.lean new file mode 100644 index 00000000000000..763b24deb91fcc --- /dev/null +++ b/Mathlib/Analysis/Normed/Group/Rat.lean @@ -0,0 +1,29 @@ +/- +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, Yaël Dillies +-/ + +import Mathlib.Analysis.Normed.Group.Int +import Mathlib.Topology.Instances.Rat + +/-! # ℚ as a normed group -/ + +namespace Rat + +instance instNormedAddCommGroup : NormedAddCommGroup ℚ where + norm r := ‖(r : ℝ)‖ + dist_eq r₁ r₂ := by simp only [Rat.dist_eq, norm, Rat.cast_sub] + +@[norm_cast, simp 1001] +-- Porting note: increase priority to prevent the left-hand side from simplifying +theorem norm_cast_real (r : ℚ) : ‖(r : ℝ)‖ = ‖r‖ := + rfl +#align rat.norm_cast_real Rat.norm_cast_real + +@[norm_cast, simp] +theorem _root_.Int.norm_cast_rat (m : ℤ) : ‖(m : ℚ)‖ = ‖m‖ := by + rw [← Rat.norm_cast_real, ← Int.norm_cast_real]; congr 1 +#align int.norm_cast_rat Int.norm_cast_rat + +end Rat diff --git a/Mathlib/Analysis/Normed/Group/Submodule.lean b/Mathlib/Analysis/Normed/Group/Submodule.lean new file mode 100644 index 00000000000000..59ac297b246bf4 --- /dev/null +++ b/Mathlib/Analysis/Normed/Group/Submodule.lean @@ -0,0 +1,51 @@ +/- +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, Yaël Dillies +-/ + +import Mathlib.Algebra.Module.Submodule.LinearMap +import Mathlib.Analysis.Normed.Group.Basic + +/-! # Submodules of normed groups -/ + +variable {𝕜 E : Type*} + +namespace Submodule + +-- See note [implicit instance arguments] +/-- A submodule of a seminormed group is also a seminormed group, with the restriction of the norm. +-/ +instance seminormedAddCommGroup [Ring 𝕜] [SeminormedAddCommGroup E] [Module 𝕜 E] + (s : Submodule 𝕜 E) : SeminormedAddCommGroup s := + SeminormedAddCommGroup.induced _ _ s.subtype.toAddMonoidHom +#align submodule.seminormed_add_comm_group Submodule.seminormedAddCommGroup + +-- See note [implicit instance arguments]. +/-- If `x` is an element of a submodule `s` of a normed group `E`, its norm in `s` is equal to its +norm in `E`. -/ +@[simp] +theorem coe_norm [Ring 𝕜] [SeminormedAddCommGroup E] [Module 𝕜 E] {s : Submodule 𝕜 E} + (x : s) : ‖x‖ = ‖(x : E)‖ := + rfl +#align submodule.coe_norm Submodule.coe_norm + +-- See note [implicit instance arguments]. +/-- If `x` is an element of a submodule `s` of a normed group `E`, its norm in `E` is equal to its +norm in `s`. + +This is a reversed version of the `simp` lemma `Submodule.coe_norm` for use by `norm_cast`. -/ +@[norm_cast] +theorem norm_coe [Ring 𝕜] [SeminormedAddCommGroup E] [Module 𝕜 E] {s : Submodule 𝕜 E} + (x : s) : ‖(x : E)‖ = ‖x‖ := + rfl +#align submodule.norm_coe Submodule.norm_coe + +-- See note [implicit instance arguments]. +/-- A submodule of a normed group is also a normed group, with the restriction of the norm. -/ +instance normedAddCommGroup [Ring 𝕜] [NormedAddCommGroup E] [Module 𝕜 E] + (s : Submodule 𝕜 E) : NormedAddCommGroup s := + { Submodule.seminormedAddCommGroup s with + eq_of_dist_eq_zero := eq_of_dist_eq_zero } + +end Submodule diff --git a/Mathlib/Analysis/Normed/Order/Lattice.lean b/Mathlib/Analysis/Normed/Order/Lattice.lean index c37f0a935a497f..f10f580afe62e1 100644 --- a/Mathlib/Analysis/Normed/Order/Lattice.lean +++ b/Mathlib/Analysis/Normed/Order/Lattice.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Christopher Hoskin -/ import Mathlib.Analysis.Normed.Group.Constructions +import Mathlib.Analysis.Normed.Group.Rat import Mathlib.Analysis.Normed.Group.Uniform import Mathlib.Topology.Order.Lattice diff --git a/Mathlib/Analysis/NormedSpace/LinearIsometry.lean b/Mathlib/Analysis/NormedSpace/LinearIsometry.lean index 13385f340fc414..9c0ff94b022d56 100644 --- a/Mathlib/Analysis/NormedSpace/LinearIsometry.lean +++ b/Mathlib/Analysis/NormedSpace/LinearIsometry.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov, Frédéric Dupuis, Heather Macbeth -/ import Mathlib.Analysis.Normed.Group.Constructions +import Mathlib.Analysis.Normed.Group.Submodule import Mathlib.Analysis.Normed.Group.Uniform import Mathlib.Topology.Algebra.Module.Basic import Mathlib.LinearAlgebra.Basis diff --git a/Mathlib/InformationTheory/Hamming.lean b/Mathlib/InformationTheory/Hamming.lean index 2135e54ab4f871..94da66cf4417b7 100644 --- a/Mathlib/InformationTheory/Hamming.lean +++ b/Mathlib/InformationTheory/Hamming.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Wrenna Robson -/ import Mathlib.Analysis.Normed.Group.Basic +import Mathlib.Topology.Instances.Discrete #align_import information_theory.hamming from "leanprover-community/mathlib"@"17ef379e997badd73e5eabb4d38f11919ab3c4b3" diff --git a/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean b/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean index 3623ca0c527c4b..400fc165d157db 100644 --- a/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean +++ b/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean @@ -3,10 +3,10 @@ Copyright (c) 2017 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Yury Kudryashov -/ -import Mathlib.Topology.GDelta import Mathlib.MeasureTheory.Group.Arithmetic +import Mathlib.Topology.GDelta import Mathlib.Topology.Instances.EReal -import Mathlib.Analysis.Normed.Group.Basic +import Mathlib.Topology.Instances.Rat #align_import measure_theory.constructions.borel_space.basic from "leanprover-community/mathlib"@"9f55d0d4363ae59948c33864cbc52e0b12e0e8ce" diff --git a/Mathlib/MeasureTheory/Constructions/BorelSpace/Metric.lean b/Mathlib/MeasureTheory/Constructions/BorelSpace/Metric.lean index 5748b7ada37102..15e8107b27755d 100644 --- a/Mathlib/MeasureTheory/Constructions/BorelSpace/Metric.lean +++ b/Mathlib/MeasureTheory/Constructions/BorelSpace/Metric.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, Yury Kudryashov -/ -import Mathlib.Topology.MetricSpace.Thickening +import Mathlib.Analysis.Normed.Group.Basic import Mathlib.MeasureTheory.Constructions.BorelSpace.Real +import Mathlib.Topology.MetricSpace.Thickening #align_import measure_theory.constructions.borel_space.basic from "leanprover-community/mathlib"@"9f55d0d4363ae59948c33864cbc52e0b12e0e8ce" diff --git a/Mathlib/MeasureTheory/Integral/Lebesgue.lean b/Mathlib/MeasureTheory/Integral/Lebesgue.lean index dea18f620273fa..a90b4d21b65153 100644 --- a/Mathlib/MeasureTheory/Integral/Lebesgue.lean +++ b/Mathlib/MeasureTheory/Integral/Lebesgue.lean @@ -3,6 +3,7 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Johannes Hölzl -/ +import Mathlib.Analysis.Normed.Group.Basic import Mathlib.Dynamics.Ergodic.MeasurePreserving import Mathlib.MeasureTheory.Function.SimpleFunc import Mathlib.MeasureTheory.Measure.MutuallySingular From ca9e9db115e3be073fd4072551e646990c1ca24b Mon Sep 17 00:00:00 2001 From: grunweg Date: Sun, 23 Jun 2024 07:52:07 +0000 Subject: [PATCH 17/19] feat(lint-style): fix `update-style-exceptions.py`; produce human-readable output by default (#14012) - Fix the output of `update-style-exceptions.py` by making `lake exe lint_style` optionally produce output in the right format: this regressed in #13620 - The current error messages are tailored for github annotations, which are not very readable for running the linter locally. Produce a human-readable and clickable error by default, but add a flag (which CI sets) for producing github-style output. This entails adding a small CLI for the lint-style executable. --- Mathlib/Tactic/Linter/TextBased.lean | 101 ++++++++++++++++++++------- scripts/lint-style.sh | 2 +- scripts/update-style-exceptions.sh | 2 +- 3 files changed, 79 insertions(+), 26 deletions(-) diff --git a/Mathlib/Tactic/Linter/TextBased.lean b/Mathlib/Tactic/Linter/TextBased.lean index c46b61d6d176e6..09a1291ce579ce 100644 --- a/Mathlib/Tactic/Linter/TextBased.lean +++ b/Mathlib/Tactic/Linter/TextBased.lean @@ -5,6 +5,7 @@ Authors: Michael Rothgang -/ import Batteries.Data.String.Basic +import Cli.Basic import Mathlib.Init.Data.Nat.Notation /-! @@ -30,10 +31,27 @@ inductive StyleError where | fileTooLong (number_lines : ℕ) (new_size_limit : ℕ) : StyleError deriving BEq +/-- How to format style errors -/ +inductive ErrorFormat + /-- Produce style error output aimed at humans: no error code, clickable file name -/ + | humanReadable : ErrorFormat + /-- Produce an entry in the style-exceptions file: mention the error code, slightly uglier + than humand-readable output -/ + | exceptionsFile : ErrorFormat + /-- Produce output suitable for Github error annotations: in particular, + duplicate the file path, line number and error code -/ + | github : ErrorFormat + deriving BEq + /-- Create the underlying error message for a given `StyleError`. -/ -def StyleError.errorMessage (err : StyleError) : String := match err with +def StyleError.errorMessage (err : StyleError) (style : ErrorFormat) : String := match err with | StyleError.fileTooLong current_size size_limit => - s!"{size_limit} file contains {current_size} lines, try to split it up" + match style with + | ErrorFormat.github => + s!"file contains {current_size} lines (at most {size_limit} allowed), try to split it up" + | ErrorFormat.exceptionsFile => + s!"{size_limit} file contains {current_size} lines, try to split it up" + | ErrorFormat.humanReadable => s!"file contains {current_size} lines, try to split it up" /-- The error code for a given style error. Keep this in sync with `parse?_errorContext` below! -/ -- FUTURE: we're matching the old codes in `lint-style.py` for compatibility; @@ -65,14 +83,24 @@ instance : BEq ErrorContext where -- We normalise errors before comparing them. && (ctx.error).normalise == (ctx'.error).normalise -/-- Output the formatted error message, containing its context. -/ -def outputMessage (errctx : ErrorContext) : String := - -- We are outputting for github: duplicate file path, line number and error code, - -- so that they are also visible in the plain text output. - let path := errctx.path - let nr := errctx.lineNumber - let code := errctx.error.errorCode - s!"::ERR file={path},line={nr},code={code}::{path}:{nr} {code}: {errctx.error.errorMessage}" +/-- Output the formatted error message, containing its context. +`style` specifies if the error should be formatted for humans or for github output matchers -/ +def outputMessage (errctx : ErrorContext) (style : ErrorFormat) : String := + let error_message := errctx.error.errorMessage style + match style with + | ErrorFormat.github => + -- We are outputting for github: duplicate file path, line number and error code, + -- so that they are also visible in the plain text output. + let path := errctx.path + let nr := errctx.lineNumber + let code := errctx.error.errorCode + s!"::ERR file={path},line={nr},code={code}::{path}:{nr} {code}: {error_message}" + | ErrorFormat.exceptionsFile => + -- Produce an entry in the exceptions file: with error code and "line" in front of the number. + s!"{errctx.path} : line {errctx.lineNumber} : {errctx.error.errorCode} : {error_message}" + | ErrorFormat.humanReadable => + -- Print for humans: clickable file name and omit the error code + s!"error: {errctx.path}:{errctx.lineNumber}: {error_message}" /-- Try parsing an `ErrorContext` from a string: return `some` if successful, `none` otherwise. -/ def parse?_errorContext (line : String) : Option ErrorContext := Id.run do @@ -111,10 +139,11 @@ def parseStyleExceptions (lines : Array String) : Array ErrorContext := Id.run d -- We treat all lines starting with "--" as a comment and ignore them. Array.filterMap (parse?_errorContext ·) (lines.filter (fun line ↦ !line.startsWith "--")) -/-- Print information about all errors encountered to standard output. -/ -def formatErrors (errors : Array ErrorContext) : IO Unit := do +/-- Print information about all errors encountered to standard output. +`style` specifies if we print errors for humand or github consumption. -/ +def formatErrors (errors : Array ErrorContext) (style : ErrorFormat) : IO Unit := do for e in errors do - IO.println (outputMessage e) + IO.println (outputMessage e style) /-- Core logic of a text based linter: given a collection of lines, return an array of all style errors with line numbers. -/ @@ -150,8 +179,9 @@ end /-- Read a file, apply all text-based linters and print formatted errors. Return `true` if there were new errors (and `false` otherwise). -`sizeLimit` is any pre-existing limit on this file's size. -/ -def lintFile (path : FilePath) (sizeLimit : Option ℕ) : IO Bool := do +`sizeLimit` is any pre-existing limit on this file's size. +`style` specifies if errors should be formatted for github or human consumption. -/ +def lintFile (path : FilePath) (sizeLimit : Option ℕ) (style : ErrorFormat) : IO Bool := do let lines ← IO.FS.lines path -- We don't need to run any checks on imports-only files. -- NB. The Python script used to still run a few linters; this is in fact not necessary. @@ -159,13 +189,14 @@ def lintFile (path : FilePath) (sizeLimit : Option ℕ) : IO Bool := do return false if let some (StyleError.fileTooLong n limit) := checkFileLength lines sizeLimit then let arr := Array.mkArray1 (ErrorContext.mk (StyleError.fileTooLong n limit) 1 path) - formatErrors arr + formatErrors arr style return true return false /-- Lint all files referenced in a given import-only file. -Return the number of files which had new style errors. -/ -def lintAllFiles (path : FilePath) : IO UInt32 := do +Return the number of files which had new style errors. +`style` specifies if errors should be formatted for github or human consumption. -/ +def lintAllFiles (path : FilePath) (style : ErrorFormat) : IO UInt32 := do -- Read all module names from the file at `path`. let allModules ← IO.FS.lines path -- Read the style exceptions file. @@ -181,14 +212,36 @@ def lintAllFiles (path : FilePath) : IO UInt32 := do let size_limits := (style_exceptions.filter (·.path == path)).filterMap (fun errctx ↦ match errctx.error with | StyleError.fileTooLong _ limit => some limit) - if ← lintFile path (size_limits.get? 0) then + if ← lintFile path (size_limits.get? 0) style then number_error_files := number_error_files + 1 return number_error_files -/-- The entry point to the `lake exe lint_style` command. -/ -def main : IO UInt32 := do - let mut number_error_files := 0 +open Cli in +/-- Implementation of the `lint_style` command line program. -/ +def lintStyleCli (args : Cli.Parsed) : IO UInt32 := do + let errorStyle := match (args.hasFlag "github", args.hasFlag "update") with + | (true, _) => ErrorFormat.github + | (false, true) => ErrorFormat.exceptionsFile + | (false, false) => ErrorFormat.humanReadable + let mut number_error_files : UInt32 := 0 for s in ["Archive.lean", "Counterexamples.lean", "Mathlib.lean"] do - let n ← lintAllFiles (mkFilePath [s]) + let n ← lintAllFiles (mkFilePath [s]) errorStyle number_error_files := number_error_files + n - return number_error_files + return number_error_files + +open Cli in +/-- Setting up command line options and help text for `lake exe lint_style`. -/ +-- so far, no help options or so: perhaps that is fine? +def lint_style : Cmd := `[Cli| + lint_style VIA lintStyleCli; ["0.0.1"] + "Run text-based style linters on every Lean file in Mathlib/, Archive/ and Counterexamples/. + Print errors about any unexpected style errors to standard output." + + FLAGS: + github; "Print errors in a format suitable for github problem matchers\n\ + otherwise, produce human-readable output" + update; "Print errors solely for the style exceptions file" +] + +/-- The entry point to the `lake exe lint_style` command. -/ +def main (args : List String) : IO UInt32 := do lint_style.validate args diff --git a/scripts/lint-style.sh b/scripts/lint-style.sh index a6551a73abf8ee..bf3e47f33d306d 100755 --- a/scripts/lint-style.sh +++ b/scripts/lint-style.sh @@ -43,7 +43,7 @@ git ls-files 'Archive/*.lean' | xargs ./scripts/lint-style.py "$@" git ls-files 'Counterexamples/*.lean' | xargs ./scripts/lint-style.py "$@" # Call the in-progress Lean rewrite of these Python lints. -lake exe lint_style +lake exe lint_style --github # 2. Global checks on the mathlib repository diff --git a/scripts/update-style-exceptions.sh b/scripts/update-style-exceptions.sh index f1d66af2309019..fb9496615fedb7 100755 --- a/scripts/update-style-exceptions.sh +++ b/scripts/update-style-exceptions.sh @@ -18,4 +18,4 @@ find Mathlib -name '*.lean' | xargs ./scripts/lint-style.py | LC_ALL=C sort > scripts/style-exceptions.txt # Append the warnings of the Lean linter, on the file length. -lake exe lint_style >> scripts/style-exceptions.txt +lake exe lint_style --update >> scripts/style-exceptions.txt From 7cac44b5d262db60fc8fa1093e5ba4e66ffa0373 Mon Sep 17 00:00:00 2001 From: damiano Date: Sun, 23 Jun 2024 08:02:27 +0000 Subject: [PATCH 18/19] cleanup: remove `summarize_declarations` and tooling for `move-decls` (#14047) This PR cleans up the tooling around the `move-decls` label that is now obsolete, thanks to the new `PR summary` comment on PRs. Here is a short description of what the removed code did: * the `summarize_declarations` CI step produced a formatted output of `./scripts/no_lost_declarations` that I suspect no one except for me ever looked at; * `.github/workflows/move_decl.yaml` is the (working) action that adds the output of `./scripts/no_lost_declarations short` to the PR as a comment -- this has been made obsolete by the `PR summary` comment; * `.github/workflows/move_decl_comment.yml` is a (failed) action that should have posted the short diff on all PRs, but never actually worked -- besides being broken, this has also been made obsolete by the `PR summary` comment. --- .github/workflows/bors.yml | 17 ------------- .github/workflows/build.yml | 17 ------------- .github/workflows/build.yml.in | 17 ------------- .github/workflows/build_fork.yml | 17 ------------- .github/workflows/move_decl.yaml | 30 ----------------------- .github/workflows/move_decl_comment.yml | 32 ------------------------- 6 files changed, 130 deletions(-) delete mode 100644 .github/workflows/move_decl.yaml delete mode 100644 .github/workflows/move_decl_comment.yml diff --git a/.github/workflows/bors.yml b/.github/workflows/bors.yml index ffa4171c1d6b10..73594f78a73b9e 100644 --- a/.github/workflows/bors.yml +++ b/.github/workflows/bors.yml @@ -90,23 +90,6 @@ jobs: - name: check that workflows were consistent run: git diff --exit-code - summarize_declarations: - if: github.repository == 'leanprover-community/mathlib4' - name: summarize_declarations - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ## fetch the whole repository, useful to find a common fork - fetch-depth: 0 - - name: print_lost_declarations - run: | - ## back and forth to settle a "detached head" (maybe?) - git checkout -q master - git checkout -q - - printf '### Summary\n\n' > "${GITHUB_STEP_SUMMARY}" - ./scripts/no_lost_declarations.sh >> "${GITHUB_STEP_SUMMARY}" - build: if: github.repository == 'leanprover-community/mathlib4' name: Build diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a2d4113608c15e..c51f36bc9c8450 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -97,23 +97,6 @@ jobs: - name: check that workflows were consistent run: git diff --exit-code - summarize_declarations: - if: github.repository == 'leanprover-community/mathlib4' - name: summarize_declarations - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ## fetch the whole repository, useful to find a common fork - fetch-depth: 0 - - name: print_lost_declarations - run: | - ## back and forth to settle a "detached head" (maybe?) - git checkout -q master - git checkout -q - - printf '### Summary\n\n' > "${GITHUB_STEP_SUMMARY}" - ./scripts/no_lost_declarations.sh >> "${GITHUB_STEP_SUMMARY}" - build: if: github.repository == 'leanprover-community/mathlib4' name: Build diff --git a/.github/workflows/build.yml.in b/.github/workflows/build.yml.in index 0468e0a4098689..6f0e4ef2e2fac3 100644 --- a/.github/workflows/build.yml.in +++ b/.github/workflows/build.yml.in @@ -76,23 +76,6 @@ jobs: - name: check that workflows were consistent run: git diff --exit-code - summarize_declarations: - if: github.repository MAIN_OR_FORK 'leanprover-community/mathlib4' - name: summarize_declarations - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ## fetch the whole repository, useful to find a common fork - fetch-depth: 0 - - name: print_lost_declarations - run: | - ## back and forth to settle a "detached head" (maybe?) - git checkout -q master - git checkout -q - - printf '### Summary\n\n' > "${GITHUB_STEP_SUMMARY}" - ./scripts/no_lost_declarations.sh >> "${GITHUB_STEP_SUMMARY}" - build: if: github.repository MAIN_OR_FORK 'leanprover-community/mathlib4' name: BuildJOB_NAME diff --git a/.github/workflows/build_fork.yml b/.github/workflows/build_fork.yml index 16d0ad83ffd4e7..c30deaffc01528 100644 --- a/.github/workflows/build_fork.yml +++ b/.github/workflows/build_fork.yml @@ -94,23 +94,6 @@ jobs: - name: check that workflows were consistent run: git diff --exit-code - summarize_declarations: - if: github.repository != 'leanprover-community/mathlib4' - name: summarize_declarations - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ## fetch the whole repository, useful to find a common fork - fetch-depth: 0 - - name: print_lost_declarations - run: | - ## back and forth to settle a "detached head" (maybe?) - git checkout -q master - git checkout -q - - printf '### Summary\n\n' > "${GITHUB_STEP_SUMMARY}" - ./scripts/no_lost_declarations.sh >> "${GITHUB_STEP_SUMMARY}" - build: if: github.repository != 'leanprover-community/mathlib4' name: Build (fork) diff --git a/.github/workflows/move_decl.yaml b/.github/workflows/move_decl.yaml deleted file mode 100644 index 85495abf7b420d..00000000000000 --- a/.github/workflows/move_decl.yaml +++ /dev/null @@ -1,30 +0,0 @@ -name: move-decls (label) -on: - pull_request: - types: - - labeled - -jobs: - add-comment: - if: github.event.label.name == 'move-decls' - runs-on: ubuntu-latest - permissions: - pull-requests: write - steps: - - uses: actions/checkout@v4 - with: - ## fetch the whole repository, useful to find a common fork - fetch-depth: 0 - - id: short_diff - run: | - ## back and forth to settle a "detached head" (maybe?) - git checkout -q master - git checkout -q - - printf $'summary<> "$GITHUB_OUTPUT" - - name: Add comment - run: gh pr comment "$NUMBER" --body "$BODY" - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GH_REPO: ${{ github.repository }} - NUMBER: ${{ github.event.pull_request.number }} - BODY: ${{ steps.short_diff.outputs.summary }} diff --git a/.github/workflows/move_decl_comment.yml b/.github/workflows/move_decl_comment.yml deleted file mode 100644 index 2a94fa5e3bf51b..00000000000000 --- a/.github/workflows/move_decl_comment.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: move-decls (comment) - -on: - issue_comment: - types: [created, edited] - pull_request_review_comment: - types: [created, edited] - -jobs: - move-decls-add-comment: - if: contains(github.event.comment.body, 'move-decls') || ((github.event.issue.pull_request != 'null') && (startsWith(github.event.comment.body, 'move-decls') || contains(toJSON(github.event.comment.body), '\r\nmove-decls'))) - runs-on: ubuntu-latest - permissions: - pull-requests: write - steps: - - uses: actions/checkout@v4 - with: - ## fetch the whole repository, useful to find a common fork - fetch-depth: 0 - - id: short_diff - run: | - ## back and forth to settle a "detached head" (maybe?) - git checkout -q master - git checkout -q - - printf $'summary<> "$GITHUB_OUTPUT" - - name: Add comment - run: gh pr comment "$NUMBER" --body "$BODY" - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GH_REPO: ${{ github.repository }} - NUMBER: ${{ github.event.pull_request.number }} - BODY: ${{ steps.short_diff.outputs.summary }} From a6a6c6bacf8c8dad34efd1d73929ff18744f63c8 Mon Sep 17 00:00:00 2001 From: Rida Hamadani Date: Sun, 23 Jun 2024 11:05:29 +0000 Subject: [PATCH 19/19] chore(Data/ENat): unbundle `ENat.toNat` (#13936) This will allow us to write `n.toNat` instead of `ENat.toNat n` --- Mathlib/Data/ENat/Basic.lean | 13 ++++++++++--- Mathlib/Data/Set/Card.lean | 2 +- Mathlib/SetTheory/Cardinal/ToNat.lean | 2 +- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Mathlib/Data/ENat/Basic.lean b/Mathlib/Data/ENat/Basic.lean index dcead842bf6ef2..82fa61721c0374 100644 --- a/Mathlib/Data/ENat/Basic.lean +++ b/Mathlib/Data/ENat/Basic.lean @@ -97,12 +97,19 @@ instance : WellFoundedRelation ℕ∞ where wf := IsWellFounded.wf /-- Conversion of `ℕ∞` to `ℕ` sending `∞` to `0`. -/ -def toNat : MonoidWithZeroHom ℕ∞ ℕ where - toFun := WithTop.untop' 0 +def toNat : ℕ∞ → ℕ := WithTop.untop' 0 + +/-- Homomorphism from `ℕ∞` to `ℕ` sending `∞` to `0`. -/ +def toNatHom : MonoidWithZeroHom ℕ∞ ℕ where + toFun := toNat map_one' := rfl map_zero' := rfl map_mul' := WithTop.untop'_zero_mul -#align enat.to_nat ENat.toNat +#align enat.to_nat ENat.toNatHom + +@[simp, norm_cast] lemma coe_toNatHom : toNatHom = toNat := rfl + +lemma toNatHom_apply (n : ℕ) : toNatHom n = toNat n := rfl @[simp] theorem toNat_coe (n : ℕ) : toNat n = n := diff --git a/Mathlib/Data/Set/Card.lean b/Mathlib/Data/Set/Card.lean index 71c5850d9d2cc2..15c3b812ff646c 100644 --- a/Mathlib/Data/Set/Card.lean +++ b/Mathlib/Data/Set/Card.lean @@ -558,7 +558,7 @@ theorem nonempty_of_ncard_ne_zero (hs : s.ncard ≠ 0) : s.Nonempty := by #align set.nonempty_of_ncard_ne_zero Set.nonempty_of_ncard_ne_zero @[simp] theorem ncard_singleton (a : α) : ({a} : Set α).ncard = 1 := by - simp [ncard, ncard_eq_toFinset_card] + simpa [ncard, encard_singleton] using ENat.toNat_coe 1 #align set.ncard_singleton Set.ncard_singleton theorem ncard_singleton_inter (a : α) (s : Set α) : ({a} ∩ s).ncard ≤ 1 := by diff --git a/Mathlib/SetTheory/Cardinal/ToNat.lean b/Mathlib/SetTheory/Cardinal/ToNat.lean index 6e77199ef85d0f..22bbe3be48bfcd 100644 --- a/Mathlib/SetTheory/Cardinal/ToNat.lean +++ b/Mathlib/SetTheory/Cardinal/ToNat.lean @@ -25,7 +25,7 @@ variable {α : Type u} {c d : Cardinal.{u}} /-- This function sends finite cardinals to the corresponding natural, and infinite cardinals to 0. -/ noncomputable def toNat : Cardinal →*₀ ℕ := - ENat.toNat.comp toENat + ENat.toNatHom.comp toENat #align cardinal.to_nat Cardinal.toNat #align cardinal.to_nat_hom Cardinal.toNat