[System] You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.RingTheory.Etale.StandardEtale).

[User]
Prove the following theorem. The retrieved context below may help.

```lean
lemma inv_aeval_X_g :
    (↑P.hasMap_X.2.unit⁻¹ : P.Ring) = Ideal.Quotient.mk _ .X
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.HasMap (L75-L78)
def HasMap (x : S) : Prop :=
aeval x P.f = 0 ∧ IsUnit (aeval x P.g)

/-- The map `R[X][Y]/⟨f, Yg-1⟩ →ₐ[R] S` sending `X` to `x`, given `P.HasMap x`. -/
```

-- snippet 2
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.lift (L79-L83)
def lift (x : S) (h : P.HasMap x) : P.Ring →ₐ[R] S :=
Ideal.Quotient.liftₐ _ (aevalAeval x ↑(h.2.unit⁻¹))
    (Ideal.span_le (I := RingHom.ker _).mpr (by simp [Set.pair_subset_iff, h.1]))

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 3
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.lift_X (L85-L88)
lemma lift_X (x : S) (h : P.HasMap x) : P.lift x h P.X = x := by
simp [lift, StandardEtalePair.Ring, StandardEtalePair.X]

variable {P} in
```

-- snippet 4
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.HasMap (L89-L91)
lemma HasMap.map {x : S} (h : P.HasMap x) (f : S →ₐ[R] T) : P.HasMap (f x) :=
⟨by simp [aeval_algHom, h.1], by simpa [aeval_algHom] using h.2.map f⟩
```

-- snippet 5
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.HasMap (L92-L99)
lemma HasMap.isUnit_derivative_f {x : S} (h : P.HasMap x) :
    IsUnit (P.f.derivative.aeval x) := by
obtain ⟨p₁, p₂, n, e⟩ := P.cond
  have : aeval x P.f.derivative ∣ aeval x P.g ^ n :=
    ⟨_, by simpa [h.1] using congr(aeval x $e.symm)⟩
  exact isUnit_of_dvd_unit this (.pow _ h.2)

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 6
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.aeval_X_g_mul_mk_X (L100-L109)
lemma aeval_X_g_mul_mk_X : aeval P.X P.g * Ideal.Quotient.mk _ .X = 1 := by
have : aeval (R := R) P.X = (Ideal.Quotient.mkₐ _ _).comp Polynomial.CAlgHom := by
    ext; simp [StandardEtalePair.Ring, StandardEtalePair.X]
  rw [this]
  dsimp [StandardEtalePair.Ring]
  rw [← map_mul, ← map_one (Ideal.Quotient.mk _), ← sub_eq_zero, ← map_sub, mul_comm]
  exact Ideal.Quotient.eq_zero_iff_mem.mpr (Ideal.subset_span (Set.mem_insert_of_mem _ rfl))

set_option backward.isDefEq.respectTransparency false in
variable {P} in
```

-- snippet 7
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.hasMap_X (L110-L117)
lemma hasMap_X : P.HasMap P.X :=
have : aeval (R := R) P.X = (Ideal.Quotient.mkₐ _ _).comp Polynomial.CAlgHom := by
    ext; simp [StandardEtalePair.Ring, StandardEtalePair.X]
  ⟨this ▸ Ideal.Quotient.eq_zero_iff_mem.mpr (Ideal.subset_span (Set.mem_insert _ _)),
    IsUnit.of_mul_eq_one _ P.aeval_X_g_mul_mk_X⟩

set_option backward.isDefEq.respectTransparency false in
variable {P} in
```

-- snippet 8
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.hom_ext (L119-L131)
lemma hom_ext {f g : P.Ring →ₐ[R] S} (H : f P.X = g P.X) : f = g := by
have H : (f.comp (Ideal.Quotient.mkₐ R _)).comp CAlgHom =
    (g.comp (Ideal.Quotient.mkₐ R _)).comp CAlgHom := Polynomial.algHom_ext (by simpa)
  have H' : aeval (R := R) P.X = (Ideal.Quotient.mkₐ _ _).comp Polynomial.CAlgHom := by
    ext; simp [StandardEtalePair.Ring, StandardEtalePair.X]
  refine Ideal.Quotient.algHom_ext _ (Polynomial.algHom_ext' H ?_)
  change f.toMonoidHom (Ideal.Quotient.mk _ .X) = g.toMonoidHom (Ideal.Quotient.mk _ .X)
  rw [← show (↑P.hasMap_X.2.unit⁻¹ : P.Ring) = Ideal.Quotient.mk _ .X from
    Units.mul_eq_one_iff_inv_eq.mp P.aeval_X_g_mul_mk_X, ← Units.coe_map_inv, ← Units.coe_map_inv]
  congr 2
  ext
  simpa [H'] using congr($H _)
```

-- snippet 9
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.lift_X_left (L133-L135)
lemma lift_X_left : P.lift P.X P.hasMap_X = .id _ _ :=
P.hom_ext (by simp)
```

-- snippet 10
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.homEquiv (L143-L148)
def homEquiv : (P.Ring →ₐ[R] S) ≃ { x : S // P.HasMap x } where
  toFun f := ⟨f P.X, hasMap_X.map f⟩
invFun x := P.lift x.1 x.2
  left_inv f := P.hom_ext (by simp)
  right_inv x := by simp
```

-- snippet 11
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.existsUnique_hasMap_of_hasMap_quotient_of_sq_eq_bot (L149-L179)
lemma existsUnique_hasMap_of_hasMap_quotient_of_sq_eq_bot
    (I : Ideal S) (hI : I ^ 2 = ⊥) (x : S) (hx : P.HasMap (Ideal.Quotient.mk I x)) :
    ∃! ε, ε ∈ I ∧ P.HasMap (x + ε) := by
have hf := Ideal.Quotient.eq_zero_iff_mem.mp
    ((aeval_algHom_apply (Ideal.Quotient.mkₐ R I) _ _).symm.trans hx.1)
  obtain ⟨⟨_, a, ha, -⟩, rfl⟩ := hx.2
  obtain ⟨a, rfl⟩ := Ideal.Quotient.mk_surjective a
  simp_rw [← Ideal.Quotient.mkₐ_eq_mk R, aeval_algHom_apply, ← map_mul, ← map_one
    (Ideal.Quotient.mkₐ R I), Ideal.Quotient.mkₐ_eq_mk, Ideal.Quotient.mk_eq_mk_iff_sub_mem] at ha
  obtain ⟨p₁, p₂, n, e⟩ := P.cond
  apply_fun aeval x at e
  simp only [map_add, map_mul, map_pow] at e
  obtain ⟨ε, hεI, b, hb⟩ : ∃ ε ∈ I, ∃ b, aeval x (derivative P.f) * b = 1 + ε := by
    refine ⟨_, ?_, (a ^ n * aeval x p₁), sub_eq_iff_eq_add'.mp rfl⟩
    convert_to (aeval x P.g * a) ^ n - 1 - aeval x P.f * (a ^ n * aeval x p₂) ∈ I
    · linear_combination a ^ n * e
    · exact sub_mem (Ideal.mem_of_dvd _ (sub_one_dvd_pow_sub_one _ _) ha) (I.mul_mem_right _ hf)
  have : aeval x P.f ^ 2 = 0 := hI.le (Ideal.pow_mem_pow hf 2)
  have : aeval x P.f * ε = 0 := ((pow_two _).symm.trans hI).le (Ideal.mul_mem_mul hf hεI)
  refine ⟨aeval x P.f * -b, ⟨I.mul_mem_right _ hf, ?_, ?_⟩, ?_⟩
  · rw [Polynomial.aeval_add_of_sq_eq_zero _ _ _ (by grind)]; grind
  · rw [← IsNilpotent.isUnit_quotient_mk_iff (I := I) ⟨2, hI⟩, ← Ideal.Quotient.mkₐ_eq_mk R,
      ← aeval_algHom_apply, Ideal.Quotient.mkₐ_eq_mk, map_add,
      Ideal.Quotient.eq_zero_iff_mem.mpr (I.mul_mem_right _ hf), add_zero]
    exact hx.2
  · rintro ε' ⟨hε'I, hε', hε''⟩
    rw [Polynomial.aeval_add_of_sq_eq_zero _ _ _ (hI.le (Ideal.pow_mem_pow hε'I 2))] at hε'
    have : ε * ε' = 0 := ((pow_two _).symm.trans hI).le (Ideal.mul_mem_mul hεI hε'I)
    grind

-- This works even if `f` is not monic. Generalize if we care.
```

-- snippet 12
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.equivPolynomialQuotient (L196-L199)
def equivPolynomialQuotient :
    P.Ring ≃ₐ[R] R[X][Y] ⧸ Ideal.span {C P.f, Y * C P.g - 1} := .refl ..
/-- `R[X][Y]/⟨f, Yg-1⟩ ≃ (R[X]/f)[1/g]` -/
```

-- snippet 13
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.equivAwayAdjoinRoot (L200-L213)
def equivAwayAdjoinRoot :
    P.Ring ≃ₐ[R] Localization.Away (AdjoinRoot.mk P.f P.g) := by
refine .ofAlgHom (P.lift (algebraMap (AdjoinRoot P.f) _ (.root P.f)) ⟨?_, ?_⟩)
    (IsLocalization.liftAlgHom (M := .powers <| AdjoinRoot.mk P.f P.g)
      (f := AdjoinRoot.liftAlgHom _ _ P.X P.hasMap_X.1) <| Subtype.forall.mpr ?_) ?_ ?_
  · rw [aeval_algebraMap_apply, AdjoinRoot.aeval_eq, AdjoinRoot.mk_self, map_zero]
  · rw [aeval_algebraMap_apply, AdjoinRoot.aeval_eq]
    exact IsLocalization.Away.algebraMap_isUnit ..
  · change Submonoid.powers _ ≤ (IsUnit.submonoid _).comap _
    simpa [Submonoid.powers_le, IsUnit.mem_submonoid_iff] using P.hasMap_X.2
  · ext; simp [Algebra.algHom]
  · ext; simp

/-- `R[X][Y]/⟨f, Yg-1⟩ ≃ R[X][1/g]/f` -/
```

-- snippet 14
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.equivAwayQuotient (L214-L236)
def equivAwayQuotient :
    P.Ring ≃ₐ[R] Localization.Away P.g ⧸ Ideal.span {algebraMap _ (Localization.Away P.g) P.f} := by
refine .ofAlgHom (P.lift (algebraMap R[X] _ .X) ⟨?_, ?_⟩)
    (Ideal.Quotient.liftₐ _ (IsLocalization.liftAlgHom (M := .powers <| P.g)
      (f := aeval P.X) <| Subtype.forall.mpr ?_) ?_)
      ?_ ?_
  · rw [aeval_algebraMap_apply, IsScalarTower.algebraMap_apply _ (Localization.Away P.g) (_ ⧸ _),
      Ideal.Quotient.algebraMap_eq, aeval_X_left_apply, Ideal.Quotient.mk_singleton_self]
  · rw [aeval_algebraMap_apply, IsScalarTower.algebraMap_apply _ (Localization.Away P.g) (_ ⧸ _),
      aeval_X_left_apply]
    exact (IsLocalization.Away.algebraMap_isUnit ..).map _
  · change Submonoid.powers _ ≤ (IsUnit.submonoid _).comap _
    simpa [Submonoid.powers_le, IsUnit.mem_submonoid_iff] using P.hasMap_X.2
  · change Ideal.span _ ≤ RingHom.ker _
    simpa [Ideal.span_le] using P.hasMap_X.1
  · apply Ideal.Quotient.algHom_ext
    ext
    simp [Algebra.algHom, IsScalarTower.algebraMap_apply R[X] (Localization.Away P.g) (_ ⧸ _),
      -Ideal.Quotient.mk_algebraMap]
  · ext; simp [IsScalarTower.algebraMap_apply R[X] (Localization.Away P.g) (_ ⧸ _),
      -Ideal.Quotient.mk_algebraMap]

/-- `R[X][Y]/⟨f, Yg-1⟩ ≃ R[X, Y]/⟨f, Yg-1⟩` -/
```

-- snippet 15
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.equivMvPolynomialQuotient (L237-L243)
def equivMvPolynomialQuotient :
    P.Ring ≃ₐ[R] MvPolynomial (Fin 2) R ⧸ Ideal.span
      {Bivariate.equivMvPolynomial R (C P.f), Bivariate.equivMvPolynomial R (.X * C P.g - 1)} :=
Ideal.quotientEquivAlg _ _ (Bivariate.equivMvPolynomial R)
    (by simp only [Ideal.map_span, Set.image_insert_eq, Set.image_singleton]; rfl)

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 16
```lean
-- Mathlib.RingTheory.Etale.Basic.of_equiv (L104-L107)
theorem of_equiv [FormallyEtale R A] (e : A ≃ₐ[R] B) : FormallyEtale R B :=
FormallyEtale.iff_formallyUnramified_and_formallySmooth.mpr
    ⟨FormallyUnramified.of_equiv e, FormallySmooth.of_equiv e⟩
```

-- snippet 17
```lean
-- Mathlib.RingTheory.Etale.Basic.comp_bijective (L81-L89)
lemma comp_bijective [FormallyEtale R A] (I : Ideal B) (hI : I ^ 2 = ⊥) :
    Function.Bijective ((Ideal.Quotient.mkₐ R I).comp : (A →ₐ[R] B) → A →ₐ[R] B ⧸ I) :=
⟨FormallyUnramified.comp_injective I hI, FormallySmooth.comp_surjective R A I hI⟩

/--
An `R`-algebra `A` is formally etale iff "for every `R`-algebra `B`,
every square-zero ideal `I : Ideal B` and `f : A →ₐ[R] B ⧸ I`, there exists
a unique lift `A →ₐ[R] B`".
-/
```

-- snippet 18
```lean
-- Mathlib.RingTheory.Etale.Basic.iff_comp_bijective (L90-L99)
theorem iff_comp_bijective :
   FormallyEtale R A ↔ ∀ ⦃B : Type max u v⦄ [CommRing B] [Algebra R B] (I : Ideal B), I ^ 2 = ⊥ →
      Function.Bijective ((Ideal.Quotient.mkₐ R I).comp : (A →ₐ[R] B) → A →ₐ[R] B ⧸ I) :=
⟨fun _ _ ↦ comp_bijective R A, fun H ↦
    have : FormallyUnramified R A := FormallyUnramified.iff_comp_injective_of_small.{max u v}.mpr
      (by aesop (add safe Function.Bijective.injective))
    have : FormallySmooth R A := FormallySmooth.of_comp_surjective
      (by aesop (add safe Function.Bijective.surjective))
   .of_formallyUnramified_and_formallySmooth⟩
```

-- snippet 19
```lean
-- Mathlib.RingTheory.Etale.Basic.of_restrictScalars (L123-L128)
lemma of_restrictScalars [FormallyUnramified R A] [FormallyEtale R B] :
    FormallyEtale A B :=
have := FormallyUnramified.of_restrictScalars R A B
  have := FormallySmooth.of_restrictScalars R A B
  .of_formallyUnramified_and_formallySmooth
```

-- snippet 20
```lean
-- Mathlib.RingTheory.Etale.Kaehler.KaehlerDifferential (L38-L46)
def KaehlerDifferential.tensorKaehlerEquivOfFormallyEtale [Algebra.FormallyEtale S T] :
    T ⊗[S] Ω[S⁄R] ≃ₗ[T] Ω[T⁄R] := by
refine LinearEquiv.ofBijective (mapBaseChange R S T)
    ⟨?_, fun x ↦ (KaehlerDifferential.exact_mapBaseChange_map R S T x).mp (Subsingleton.elim _ _)⟩
  rw [injective_iff_map_eq_zero]
  intro x hx
  obtain ⟨x, rfl⟩ := (Algebra.H1Cotangent.exact_δ_mapBaseChange R S T x).mp hx
  rw [Subsingleton.elim x 0, map_zero]
```

-- snippet 21
```lean
-- Mathlib.RingTheory.Etale.Field.iff_exists_algEquiv_prod (L182-L207)
theorem iff_exists_algEquiv_prod [EssFiniteType K A] :
    FormallyEtale K A ↔
      ∃ (I : Type u) (_ : Finite I) (Ai : I → Type u) (_ : ∀ i, Field (Ai i))
        (_ : ∀ i, Algebra K (Ai i)) (_ : A ≃ₐ[K] Π i, Ai i),
        ∀ i, Algebra.IsSeparable K (Ai i) := by
classical
  constructor
  · intro H
    have := FormallyUnramified.finite_of_free K A
    have := FormallyUnramified.isReduced_of_field K A
    have : IsArtinianRing A := isArtinian_of_tower K inferInstance
    let v (i : MaximalSpectrum A) : A := (IsArtinianRing.equivPi A).symm (Pi.single i 1)
    rw [FormallyEtale.iff_of_equiv ((IsArtinianRing.equivPi A).restrictScalars K),
      FormallyEtale.pi_iff] at H
    exact ⟨_, inferInstance, _, _, _, (IsArtinianRing.equivPi A).restrictScalars K,
      fun I ↦ (iff_isSeparable _ _).mp inferInstance⟩
  · intro ⟨I, _, Ai, _, _, e, _⟩
    rw [FormallyEtale.iff_of_equiv e, FormallyEtale.pi_iff]
    exact fun I ↦ of_isSeparable K (Ai I)

end Algebra.FormallyEtale

/--
`A` is étale over a field `K` if and only if
`A` is a finite product of finite separable field extensions.
-/
```

-- snippet 22
```lean
-- Mathlib.RingTheory.Etale.Kaehler.tensorCotangentSpaceOfFormallyEtale (L95-L142)
def tensorCotangentSpaceOfFormallyEtale
    (H : f.toRingHom.FormallyEtale) :
    T ⊗[S] P.CotangentSpace ≃ₗ[T] Q.CotangentSpace :=
letI := f.toRingHom.toAlgebra
  haveI : IsScalarTower R P.Ring Q.Ring :=
    .of_algebraMap_eq fun r ↦ (f.toRingHom_algebraMap r).symm
  letI := ((algebraMap S T).comp (algebraMap P.Ring S)).toAlgebra
  haveI : IsScalarTower P.Ring S T := .of_algebraMap_eq' rfl
  haveI : IsScalarTower P.Ring Q.Ring T :=
    .of_algebraMap_eq fun r ↦ (f.algebraMap_toRingHom r).symm
  haveI : FormallyEtale P.Ring Q.Ring := ‹_›
  { __ := (CotangentSpace.map f).liftBaseChange T
    invFun := LinearMap.liftBaseChange T (by
      refine LinearMap.liftBaseChange _ ?_ ∘ₗ
        (tensorKaehlerEquivOfFormallyEtale R P.Ring Q.Ring).symm.toLinearMap
      exact (TensorProduct.mk _ _ _ 1).restrictScalars P.Ring ∘ₗ
        (TensorProduct.mk _ _ _ 1).restrictScalars P.Ring)
    left_inv x := by
      change (LinearMap.liftBaseChange _ _ ∘ₗ LinearMap.liftBaseChange _ _) x =
        LinearMap.id (R := T) x
      congr 1
      ext : 4
      refine Derivation.liftKaehlerDifferential_unique
        (R := R) (S := P.Ring) (M := T ⊗[S] P.CotangentSpace) _ _ ?_
      ext a
      have : (tensorKaehlerEquivOfFormallyEtale R P.Ring Q.Ring).symm
          ((D R Q.Ring) (f.toRingHom a)) = 1 ⊗ₜ D _ _ a :=
        tensorKaehlerEquivOfFormallyEtale_symm_D_algebraMap R P.Ring Q.Ring a
      simp [this]
    right_inv x := by
      change (LinearMap.liftBaseChange _ _ ∘ₗ LinearMap.liftBaseChange _ _) x =
        LinearMap.id (R := T) x
      congr 1
      ext a
      dsimp
      obtain ⟨x, hx⟩ := (tensorKaehlerEquivOfFormallyEtale R P.Ring _).surjective (D R Q.Ring a)
      simp only [one_smul, ← hx, LinearEquiv.symm_apply_apply]
      change (((CotangentSpace.map f).liftBaseChange T).restrictScalars Q.Ring ∘ₗ
        LinearMap.liftBaseChange _ _) x = ((TensorProduct.mk _ _ _ 1) ∘ₗ
          (tensorKaehlerEquivOfFormallyEtale R P.Ring Q.Ring).toLinearMap) x
      congr 1
      ext a
      simp; rfl }

/-- (Implementation)
If `J ≃ Q ⊗ₚ I` (e.g. when `T = Q ⊗ₚ S` and `P → Q` is flat), then `T ⊗ₛ I/I² ≃ J/J²`.
This is the inverse. -/
noncomputable
```

-- snippet 23
```lean
-- Mathlib.RingTheory.Etale.Basic.of_isLocalizationAway (L249-L252)
theorem of_isLocalizationAway (r : R) [IsLocalization.Away r A] : Etale R A where
  formallyEtale := Algebra.FormallyEtale.of_isLocalization (Submonoid.powers r)
finitePresentation := IsLocalization.Away.finitePresentation r
```

-- snippet 24
```lean
-- Mathlib.RingTheory.Etale.Basic.of_formallyUnramified_and_formallySmooth (L73-L76)
theorem of_formallyUnramified_and_formallySmooth [FormallyUnramified R A]
    [FormallySmooth R A] : FormallyEtale R A :=
FormallyEtale.iff_formallyUnramified_and_formallySmooth.mpr ⟨‹_›, ‹_›⟩
```

-- snippet 25
```lean
-- Mathlib.RingTheory.Etale.Field.iff_isSeparable (L158-L161)
theorem iff_isSeparable [EssFiniteType K L] :
    FormallyEtale K L ↔ Algebra.IsSeparable K L :=
⟨fun _ ↦ FormallyUnramified.isSeparable K L, fun _ ↦ of_isSeparable K L⟩
```

-- snippet 26
```lean
-- Mathlib.RingTheory.Etale.Basic.comp (L118-L122)
theorem comp [FormallyEtale R A] [FormallyEtale A B] :
    FormallyEtale R B :=
FormallyEtale.iff_formallyUnramified_and_formallySmooth.mpr
    ⟨FormallyUnramified.comp R A B, FormallySmooth.comp R A B⟩
```

-- snippet 27
```lean
-- Mathlib.RingTheory.Etale.Basic.iff_of_equiv (L108-L117)
theorem iff_of_equiv (e : A ≃ₐ[R] B) : FormallyEtale R A ↔ FormallyEtale R B :=
⟨fun _ ↦ of_equiv e, fun _ ↦ of_equiv e.symm⟩

end OfEquiv

section Comp

variable [Algebra A B] [IsScalarTower R A B]

variable (R A B) in
```

-- snippet 28
```lean
-- Mathlib.RingTheory.Etale.Basic.localization_base (L197-L201)
theorem localization_base [FormallyEtale R Sₘ] : FormallyEtale Rₘ Sₘ :=
FormallyEtale.iff_formallyUnramified_and_formallySmooth.mpr
    ⟨FormallyUnramified.localization_base M, FormallySmooth.localization_base M⟩

/-- The localization of a formally étale map is formally étale. -/
```

-- snippet 29
```lean
-- Mathlib.RingTheory.Etale.Field.iff_formallyUnramified_of_field (L173-L176)
lemma iff_formallyUnramified_of_field [EssFiniteType K A] :
    FormallyEtale K A ↔ FormallyUnramified K A :=
⟨fun _ ↦ inferInstance, fun _ ↦ .of_formallyUnramified_of_field K A⟩
```

-- snippet 30
```lean
-- Mathlib.RingTheory.Etale.Basic.localization_map (L202-L210)
theorem localization_map [FormallyEtale R S] : FormallyEtale Rₘ Sₘ := by
haveI : FormallyEtale S Sₘ := FormallyEtale.of_isLocalization (M.map (algebraMap R S))
  haveI : FormallyEtale R Sₘ := FormallyEtale.comp R S Sₘ
  exact FormallyEtale.localization_base M

end Localization

end FormallyEtale
```

-- snippet 31
```lean
-- Mathlib.RingTheory.Etale.Basic.iff_of_surjective (L142-L148)
lemma iff_of_surjective
    {R S : Type*} [CommRing R] [CommRing S]
    [Algebra R S] (h : Function.Surjective (algebraMap R S)) :
    Algebra.FormallyEtale R S ↔ IsIdempotentElem (RingHom.ker (algebraMap R S)) := by
rw [FormallyEtale.iff_formallyUnramified_and_formallySmooth, ← FormallySmooth.iff_of_surjective h,
    and_iff_right (FormallyUnramified.of_surjective (Algebra.ofId R S) h)]
```

-- snippet 32
```lean
-- Mathlib.RingTheory.Etale.Basic.iff_formallyUnramified_and_formallySmooth (L66-L69)
theorem iff_formallyUnramified_and_formallySmooth :
    FormallyEtale R A ↔ FormallyUnramified R A ∧ FormallySmooth R A :=
⟨fun _ ↦ ⟨inferInstance, inferInstance⟩, fun ⟨_, _⟩ ↦ ⟨inferInstance, inferInstance⟩⟩
```

-- snippet 33
```lean
-- Mathlib.RingTheory.Etale.Basic.formallyEtale_algebraMap (L274-L277)
lemma formallyEtale_algebraMap [Algebra R S] :
    (algebraMap R S).FormallyEtale ↔ Algebra.FormallyEtale R S := by
rw [FormallyEtale, toAlgebra_algebraMap]
```

-- snippet 34
```lean
-- Mathlib.RingTheory.Etale.Field.Algebra (L208-L223)
theorem Algebra.Etale.iff_exists_algEquiv_prod :
    Etale K A ↔
      ∃ (I : Type u) (_ : Finite I) (Ai : I → Type u) (_ : ∀ i, Field (Ai i))
        (_ : ∀ i, Algebra K (Ai i)) (_ : A ≃ₐ[K] Π i, Ai i),
        ∀ i, Module.Finite K (Ai i) ∧ Algebra.IsSeparable K (Ai i) := by
constructor
  · intro H
    obtain ⟨I, _, Ai, _, _, e, _⟩ := (FormallyEtale.iff_exists_algEquiv_prod K A).mp inferInstance
    have := FormallyUnramified.finite_of_free K A
    exact ⟨_, ‹_›, _, _, _, e, fun i ↦ ⟨.of_surjective ((LinearMap.proj i).comp e.toLinearMap)
      ((Function.surjective_eval i).comp e.surjective), inferInstance⟩⟩
  · intro ⟨I, _, Ai, _, _, e, H⟩
    choose h₁ h₂ using H
    have := Module.Finite.of_surjective e.symm.toLinearMap e.symm.surjective
    refine ⟨?_, FinitePresentation.of_finiteType.mp inferInstance⟩
    exact (FormallyEtale.iff_exists_algEquiv_prod K A).mpr ⟨_, inferInstance, _, _, _, e, h₂⟩
```

-- snippet 35
```lean
-- Mathlib.RingTheory.Etale.Basic.FormallyEtale (L270-L273)
def FormallyEtale (f : R →+* S) : Prop :=
letI := f.toAlgebra
  Algebra.FormallyEtale R S
```

-- snippet 36
```lean
-- Mathlib.RingTheory.Etale.Field.of_formallyUnramified_of_field (L163-L172)
lemma of_formallyUnramified_of_field [EssFiniteType K A] [FormallyUnramified K A] :
    FormallyEtale K A := by
have := FormallyUnramified.isReduced_of_field K A
  have : IsArtinianRing A := .of_finite K A
  have (I : MaximalSpectrum A) : FormallyEtale K (A ⧸ I.asIdeal) := by
    rw [FormallyEtale.iff_isSeparable, ← FormallyUnramified.iff_isSeparable]
    infer_instance
  exact .of_equiv ((IsArtinianRing.equivPi A).restrictScalars K).symm

variable {K A} in
```

-- snippet 37
```lean
-- Mathlib.RingTheory.Etale.Field.of_isSeparable_aux (L56-L97)
theorem of_isSeparable_aux [Algebra.IsSeparable K L] [EssFiniteType K L] :
    FormallyEtale K L := by
-- We already know that for field extensions
  -- IsSeparable + EssFiniteType => FormallyUnramified + Finite
  have := FormallyUnramified.of_isSeparable K L
  have := FormallyUnramified.finite_of_free (R := K) (S := L)
  -- We shall show that any `f : L → B/I` can be lifted to `L → B` if `I^2 = ⊥`
  refine FormallyEtale.iff_comp_bijective.mpr fun B _ _ I h ↦ ?_
  refine ⟨FormallyUnramified.iff_comp_injective_of_small.mp
    (FormallyUnramified.of_isSeparable K L) I h, ?_⟩
  intro f
  -- By separability and finiteness, we may assume `L = K(α)` with `p` the minpoly of `α`.
  let pb := Field.powerBasisOfFiniteOfSeparable K L
  -- Let `x : B` such that `f(α) = x` in `B / I`.
  obtain ⟨x, hx⟩ := Ideal.Quotient.mk_surjective (f pb.gen)
  have helper : ∀ x, IsScalarTower.toAlgHom K B (B ⧸ I) x = Ideal.Quotient.mk I x := fun _ ↦ rfl
  -- Then `p(x) = 0 mod I`, and the goal is to find some `ε ∈ I` such that
  -- `p(x + ε) = p(x) + ε p'(x) = 0`, and we will get our lift into `B`.
  have hx' : Ideal.Quotient.mk I (aeval x (minpoly K pb.gen)) = 0 := by
    rw [← helper, ← aeval_algHom_apply, helper, hx, aeval_algHom_apply, minpoly.aeval, map_zero]
  -- Since `p` is separable, `-p'(x)` is invertible in `B ⧸ I`,
  obtain ⟨u, hu⟩ : ∃ u, (aeval x) (derivative (minpoly K pb.gen)) * u + 1 ∈ I := by
    have := (isUnit_iff_ne_zero.mpr ((Algebra.IsSeparable.isSeparable K
      pb.gen).aeval_derivative_ne_zero (minpoly.aeval K _))).map f
    rw [← aeval_algHom_apply, ← hx, ← helper, aeval_algHom_apply, helper] at this
    obtain ⟨u, hu⟩ := Ideal.Quotient.mk_surjective (-this.unit⁻¹ : B ⧸ I)
    use u
    rw [← Ideal.Quotient.eq_zero_iff_mem, map_add, map_mul, map_one, hu, mul_neg,
      IsUnit.mul_val_inv, neg_add_cancel]
  -- And `ε = p(x)/(-p'(x))` works.
  use pb.liftEquiv.symm ⟨x + u * aeval x (minpoly K pb.gen), ?_⟩
  · apply pb.algHom_ext
    simp [hx, hx']
  · rw [← eval_map_algebraMap, Polynomial.eval_add_of_sq_eq_zero, derivative_map,
      ← one_mul (eval x _), eval_map_algebraMap, eval_map_algebraMap, ← mul_assoc, ← add_mul,
      ← Ideal.mem_bot, ← h, pow_two, add_comm]
    · exact Ideal.mul_mem_mul hu (Ideal.Quotient.eq_zero_iff_mem.mp hx')
    rw [← Ideal.mem_bot, ← h]
    apply Ideal.pow_mem_pow
    rw [← Ideal.Quotient.eq_zero_iff_mem, map_mul, hx', mul_zero]

open scoped IntermediateField in
```

-- snippet 38
```lean
-- Mathlib.RingTheory.Etale.Basic.of_isLocalization (L190-L193)
theorem of_isLocalization : FormallyEtale R Rₘ :=
FormallyEtale.iff_formallyUnramified_and_formallySmooth.mpr
    ⟨FormallyUnramified.of_isLocalization M, FormallySmooth.of_isLocalization M⟩
```

-- snippet 39
```lean
-- Mathlib.RingTheory.Etale.Basic.iff_restrictScalars (L129-L132)
lemma iff_restrictScalars [FormallyEtale R A] :
    Algebra.FormallyEtale R B ↔ Algebra.FormallyEtale A B :=
⟨fun _ ↦ .of_restrictScalars (R := R), fun _ ↦ .comp _ A _⟩
```

-- snippet 40
```lean
-- Mathlib.RingTheory.Etale.Field.of_isSeparable (L98-L157)
lemma of_isSeparable [Algebra.IsSeparable K L] : FormallyEtale K L := by
-- We shall show that any `f : L → B/I` can be lifted to `L → B` if `I^2 = ⊥`.
  refine FormallyEtale.iff_comp_bijective.mpr fun B _ _ I h ↦ ?_
  -- But we already know that there exists a unique lift for every finite subfield of `L`
  -- by `of_isSeparable_aux`, so we can glue them all together.
  refine ⟨FormallyUnramified.iff_comp_injective_of_small.mp
    (FormallyUnramified.of_isSeparable K L) I h, ?_⟩
  intro f
  have : ∀ k : L, ∃! g : K⟮k⟯ →ₐ[K] B,
      (Ideal.Quotient.mkₐ K I).comp g = f.comp (IsScalarTower.toAlgHom K _ L) := by
    intro k
    have := IsSeparable.of_algHom _ _ (IsScalarTower.toAlgHom K (K⟮k⟯) L)
    have := IntermediateField.adjoin.finiteDimensional
      (Algebra.IsSeparable.isSeparable K k).isIntegral
    have := FormallyEtale.of_isSeparable_aux K (K⟮k⟯)
    have := FormallyEtale.comp_bijective (R := K) (A := K⟮k⟯) I h
    exact this.existsUnique _
  choose g hg₁ hg₂ using this
  have hg₃ : ∀ x y (h : x ∈ K⟮y⟯), g y ⟨x, h⟩ = g x (IntermediateField.AdjoinSimple.gen K x) := by
    intro x y h
    have e : K⟮x⟯ ≤ K⟮y⟯ := by
      rw [IntermediateField.adjoin_le_iff]
      rintro _ rfl
      exact h
    rw [← hg₂ _ ((g _).comp (IntermediateField.inclusion e))]
    · rfl
    apply AlgHom.ext
    rw [← AlgHom.comp_assoc, hg₁, AlgHom.comp_assoc]
    simp
  have H : ∀ x y : L, ∃ α : L, x ∈ K⟮α⟯ ∧ y ∈ K⟮α⟯ := by
    intro x y
    have : FiniteDimensional K K⟮x, y⟯ := by
      apply IntermediateField.finiteDimensional_adjoin
      intro x _; exact (Algebra.IsSeparable.isSeparable K x).isIntegral
    have := IsSeparable.of_algHom _ _ (IsScalarTower.toAlgHom K (K⟮x, y⟯) L)
    obtain ⟨⟨α, hα⟩, e⟩ := Field.exists_primitive_element K K⟮x, y⟯
    apply_fun (IntermediateField.map (IntermediateField.val _)) at e
    rw [IntermediateField.adjoin_map, ← AlgHom.fieldRange_eq_map] at e
    simp only [IntermediateField.coe_val, Set.image_singleton,
      IntermediateField.fieldRange_val] at e
    have hx : x ∈ K⟮α⟯ := e ▸ IntermediateField.subset_adjoin K {x, y} (by simp)
    have hy : y ∈ K⟮α⟯ := e ▸ IntermediateField.subset_adjoin K {x, y} (by simp)
    exact ⟨α, hx, hy⟩
  refine ⟨⟨⟨⟨⟨fun x ↦ g x (IntermediateField.AdjoinSimple.gen K x), ?_⟩, ?_⟩, ?_, ?_⟩, ?_⟩, ?_⟩
  · change g 1 1 = 1; rw [map_one]
  · intro x y
    obtain ⟨α, hx, hy⟩ := H x y
    simp only [← hg₃ _ _ hx, ← hg₃ _ _ hy, ← map_mul, ← hg₃ _ _ (mul_mem hx hy)]
    rfl
  · change g 0 0 = 0; rw [map_zero]
  · intro x y
    obtain ⟨α, hx, hy⟩ := H x y
    simp only [← hg₃ _ _ hx, ← hg₃ _ _ hy, ← map_add, ← hg₃ _ _ (add_mem hx hy)]
    rfl
  · intro r
    change g _ (algebraMap K _ r) = _
    rw [AlgHom.commutes]
  · ext x
    simpa using AlgHom.congr_fun (hg₁ x) (IntermediateField.AdjoinSimple.gen K x)
```

<s>[SYSTEM_PROMPT]You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.RingTheory.Etale.StandardEtale).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]Prove the following theorem. The retrieved context below may help.

```lean
lemma inv_aeval_X_g :
    (↑P.hasMap_X.2.unit⁻¹ : P.Ring) = Ideal.Quotient.mk _ .X
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.HasMap (L75-L78)
def HasMap (x : S) : Prop :=
aeval x P.f = 0 ∧ IsUnit (aeval x P.g)

/-- The map `R[X][Y]/⟨f, Yg-1⟩ →ₐ[R] S` sending `X` to `x`, given `P.HasMap x`. -/
```

-- snippet 2
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.lift (L79-L83)
def lift (x : S) (h : P.HasMap x) : P.Ring →ₐ[R] S :=
Ideal.Quotient.liftₐ _ (aevalAeval x ↑(h.2.unit⁻¹))
    (Ideal.span_le (I := RingHom.ker _).mpr (by simp [Set.pair_subset_iff, h.1]))

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 3
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.lift_X (L85-L88)
lemma lift_X (x : S) (h : P.HasMap x) : P.lift x h P.X = x := by
simp [lift, StandardEtalePair.Ring, StandardEtalePair.X]

variable {P} in
```

-- snippet 4
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.HasMap (L89-L91)
lemma HasMap.map {x : S} (h : P.HasMap x) (f : S →ₐ[R] T) : P.HasMap (f x) :=
⟨by simp [aeval_algHom, h.1], by simpa [aeval_algHom] using h.2.map f⟩
```

-- snippet 5
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.HasMap (L92-L99)
lemma HasMap.isUnit_derivative_f {x : S} (h : P.HasMap x) :
    IsUnit (P.f.derivative.aeval x) := by
obtain ⟨p₁, p₂, n, e⟩ := P.cond
  have : aeval x P.f.derivative ∣ aeval x P.g ^ n :=
    ⟨_, by simpa [h.1] using congr(aeval x $e.symm)⟩
  exact isUnit_of_dvd_unit this (.pow _ h.2)

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 6
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.aeval_X_g_mul_mk_X (L100-L109)
lemma aeval_X_g_mul_mk_X : aeval P.X P.g * Ideal.Quotient.mk _ .X = 1 := by
have : aeval (R := R) P.X = (Ideal.Quotient.mkₐ _ _).comp Polynomial.CAlgHom := by
    ext; simp [StandardEtalePair.Ring, StandardEtalePair.X]
  rw [this]
  dsimp [StandardEtalePair.Ring]
  rw [← map_mul, ← map_one (Ideal.Quotient.mk _), ← sub_eq_zero, ← map_sub, mul_comm]
  exact Ideal.Quotient.eq_zero_iff_mem.mpr (Ideal.subset_span (Set.mem_insert_of_mem _ rfl))

set_option backward.isDefEq.respectTransparency false in
variable {P} in
```

-- snippet 7
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.hasMap_X (L110-L117)
lemma hasMap_X : P.HasMap P.X :=
have : aeval (R := R) P.X = (Ideal.Quotient.mkₐ _ _).comp Polynomial.CAlgHom := by
    ext; simp [StandardEtalePair.Ring, StandardEtalePair.X]
  ⟨this ▸ Ideal.Quotient.eq_zero_iff_mem.mpr (Ideal.subset_span (Set.mem_insert _ _)),
    IsUnit.of_mul_eq_one _ P.aeval_X_g_mul_mk_X⟩

set_option backward.isDefEq.respectTransparency false in
variable {P} in
```

-- snippet 8
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.hom_ext (L119-L131)
lemma hom_ext {f g : P.Ring →ₐ[R] S} (H : f P.X = g P.X) : f = g := by
have H : (f.comp (Ideal.Quotient.mkₐ R _)).comp CAlgHom =
    (g.comp (Ideal.Quotient.mkₐ R _)).comp CAlgHom := Polynomial.algHom_ext (by simpa)
  have H' : aeval (R := R) P.X = (Ideal.Quotient.mkₐ _ _).comp Polynomial.CAlgHom := by
    ext; simp [StandardEtalePair.Ring, StandardEtalePair.X]
  refine Ideal.Quotient.algHom_ext _ (Polynomial.algHom_ext' H ?_)
  change f.toMonoidHom (Ideal.Quotient.mk _ .X) = g.toMonoidHom (Ideal.Quotient.mk _ .X)
  rw [← show (↑P.hasMap_X.2.unit⁻¹ : P.Ring) = Ideal.Quotient.mk _ .X from
    Units.mul_eq_one_iff_inv_eq.mp P.aeval_X_g_mul_mk_X, ← Units.coe_map_inv, ← Units.coe_map_inv]
  congr 2
  ext
  simpa [H'] using congr($H _)
```

-- snippet 9
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.lift_X_left (L133-L135)
lemma lift_X_left : P.lift P.X P.hasMap_X = .id _ _ :=
P.hom_ext (by simp)
```

-- snippet 10
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.homEquiv (L143-L148)
def homEquiv : (P.Ring →ₐ[R] S) ≃ { x : S // P.HasMap x } where
  toFun f := ⟨f P.X, hasMap_X.map f⟩
invFun x := P.lift x.1 x.2
  left_inv f := P.hom_ext (by simp)
  right_inv x := by simp
```

-- snippet 11
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.existsUnique_hasMap_of_hasMap_quotient_of_sq_eq_bot (L149-L179)
lemma existsUnique_hasMap_of_hasMap_quotient_of_sq_eq_bot
    (I : Ideal S) (hI : I ^ 2 = ⊥) (x : S) (hx : P.HasMap (Ideal.Quotient.mk I x)) :
    ∃! ε, ε ∈ I ∧ P.HasMap (x + ε) := by
have hf := Ideal.Quotient.eq_zero_iff_mem.mp
    ((aeval_algHom_apply (Ideal.Quotient.mkₐ R I) _ _).symm.trans hx.1)
  obtain ⟨⟨_, a, ha, -⟩, rfl⟩ := hx.2
  obtain ⟨a, rfl⟩ := Ideal.Quotient.mk_surjective a
  simp_rw [← Ideal.Quotient.mkₐ_eq_mk R, aeval_algHom_apply, ← map_mul, ← map_one
    (Ideal.Quotient.mkₐ R I), Ideal.Quotient.mkₐ_eq_mk, Ideal.Quotient.mk_eq_mk_iff_sub_mem] at ha
  obtain ⟨p₁, p₂, n, e⟩ := P.cond
  apply_fun aeval x at e
  simp only [map_add, map_mul, map_pow] at e
  obtain ⟨ε, hεI, b, hb⟩ : ∃ ε ∈ I, ∃ b, aeval x (derivative P.f) * b = 1 + ε := by
    refine ⟨_, ?_, (a ^ n * aeval x p₁), sub_eq_iff_eq_add'.mp rfl⟩
    convert_to (aeval x P.g * a) ^ n - 1 - aeval x P.f * (a ^ n * aeval x p₂) ∈ I
    · linear_combination a ^ n * e
    · exact sub_mem (Ideal.mem_of_dvd _ (sub_one_dvd_pow_sub_one _ _) ha) (I.mul_mem_right _ hf)
  have : aeval x P.f ^ 2 = 0 := hI.le (Ideal.pow_mem_pow hf 2)
  have : aeval x P.f * ε = 0 := ((pow_two _).symm.trans hI).le (Ideal.mul_mem_mul hf hεI)
  refine ⟨aeval x P.f * -b, ⟨I.mul_mem_right _ hf, ?_, ?_⟩, ?_⟩
  · rw [Polynomial.aeval_add_of_sq_eq_zero _ _ _ (by grind)]; grind
  · rw [← IsNilpotent.isUnit_quotient_mk_iff (I := I) ⟨2, hI⟩, ← Ideal.Quotient.mkₐ_eq_mk R,
      ← aeval_algHom_apply, Ideal.Quotient.mkₐ_eq_mk, map_add,
      Ideal.Quotient.eq_zero_iff_mem.mpr (I.mul_mem_right _ hf), add_zero]
    exact hx.2
  · rintro ε' ⟨hε'I, hε', hε''⟩
    rw [Polynomial.aeval_add_of_sq_eq_zero _ _ _ (hI.le (Ideal.pow_mem_pow hε'I 2))] at hε'
    have : ε * ε' = 0 := ((pow_two _).symm.trans hI).le (Ideal.mul_mem_mul hεI hε'I)
    grind

-- This works even if `f` is not monic. Generalize if we care.
```

-- snippet 12
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.equivPolynomialQuotient (L196-L199)
def equivPolynomialQuotient :
    P.Ring ≃ₐ[R] R[X][Y] ⧸ Ideal.span {C P.f, Y * C P.g - 1} := .refl ..
/-- `R[X][Y]/⟨f, Yg-1⟩ ≃ (R[X]/f)[1/g]` -/
```

-- snippet 13
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.equivAwayAdjoinRoot (L200-L213)
def equivAwayAdjoinRoot :
    P.Ring ≃ₐ[R] Localization.Away (AdjoinRoot.mk P.f P.g) := by
refine .ofAlgHom (P.lift (algebraMap (AdjoinRoot P.f) _ (.root P.f)) ⟨?_, ?_⟩)
    (IsLocalization.liftAlgHom (M := .powers <| AdjoinRoot.mk P.f P.g)
      (f := AdjoinRoot.liftAlgHom _ _ P.X P.hasMap_X.1) <| Subtype.forall.mpr ?_) ?_ ?_
  · rw [aeval_algebraMap_apply, AdjoinRoot.aeval_eq, AdjoinRoot.mk_self, map_zero]
  · rw [aeval_algebraMap_apply, AdjoinRoot.aeval_eq]
    exact IsLocalization.Away.algebraMap_isUnit ..
  · change Submonoid.powers _ ≤ (IsUnit.submonoid _).comap _
    simpa [Submonoid.powers_le, IsUnit.mem_submonoid_iff] using P.hasMap_X.2
  · ext; simp [Algebra.algHom]
  · ext; simp

/-- `R[X][Y]/⟨f, Yg-1⟩ ≃ R[X][1/g]/f` -/
```

-- snippet 14
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.equivAwayQuotient (L214-L236)
def equivAwayQuotient :
    P.Ring ≃ₐ[R] Localization.Away P.g ⧸ Ideal.span {algebraMap _ (Localization.Away P.g) P.f} := by
refine .ofAlgHom (P.lift (algebraMap R[X] _ .X) ⟨?_, ?_⟩)
    (Ideal.Quotient.liftₐ _ (IsLocalization.liftAlgHom (M := .powers <| P.g)
      (f := aeval P.X) <| Subtype.forall.mpr ?_) ?_)
      ?_ ?_
  · rw [aeval_algebraMap_apply, IsScalarTower.algebraMap_apply _ (Localization.Away P.g) (_ ⧸ _),
      Ideal.Quotient.algebraMap_eq, aeval_X_left_apply, Ideal.Quotient.mk_singleton_self]
  · rw [aeval_algebraMap_apply, IsScalarTower.algebraMap_apply _ (Localization.Away P.g) (_ ⧸ _),
      aeval_X_left_apply]
    exact (IsLocalization.Away.algebraMap_isUnit ..).map _
  · change Submonoid.powers _ ≤ (IsUnit.submonoid _).comap _
    simpa [Submonoid.powers_le, IsUnit.mem_submonoid_iff] using P.hasMap_X.2
  · change Ideal.span _ ≤ RingHom.ker _
    simpa [Ideal.span_le] using P.hasMap_X.1
  · apply Ideal.Quotient.algHom_ext
    ext
    simp [Algebra.algHom, IsScalarTower.algebraMap_apply R[X] (Localization.Away P.g) (_ ⧸ _),
      -Ideal.Quotient.mk_algebraMap]
  · ext; simp [IsScalarTower.algebraMap_apply R[X] (Localization.Away P.g) (_ ⧸ _),
      -Ideal.Quotient.mk_algebraMap]

/-- `R[X][Y]/⟨f, Yg-1⟩ ≃ R[X, Y]/⟨f, Yg-1⟩` -/
```

-- snippet 15
```lean
-- Mathlib.RingTheory.Etale.StandardEtale.equivMvPolynomialQuotient (L237-L243)
def equivMvPolynomialQuotient :
    P.Ring ≃ₐ[R] MvPolynomial (Fin 2) R ⧸ Ideal.span
      {Bivariate.equivMvPolynomial R (C P.f), Bivariate.equivMvPolynomial R (.X * C P.g - 1)} :=
Ideal.quotientEquivAlg _ _ (Bivariate.equivMvPolynomial R)
    (by simp only [Ideal.map_span, Set.image_insert_eq, Set.image_singleton]; rfl)

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 16
```lean
-- Mathlib.RingTheory.Etale.Basic.of_equiv (L104-L107)
theorem of_equiv [FormallyEtale R A] (e : A ≃ₐ[R] B) : FormallyEtale R B :=
FormallyEtale.iff_formallyUnramified_and_formallySmooth.mpr
    ⟨FormallyUnramified.of_equiv e, FormallySmooth.of_equiv e⟩
```

-- snippet 17
```lean
-- Mathlib.RingTheory.Etale.Basic.comp_bijective (L81-L89)
lemma comp_bijective [FormallyEtale R A] (I : Ideal B) (hI : I ^ 2 = ⊥) :
    Function.Bijective ((Ideal.Quotient.mkₐ R I).comp : (A →ₐ[R] B) → A →ₐ[R] B ⧸ I) :=
⟨FormallyUnramified.comp_injective I hI, FormallySmooth.comp_surjective R A I hI⟩

/--
An `R`-algebra `A` is formally etale iff "for every `R`-algebra `B`,
every square-zero ideal `I : Ideal B` and `f : A →ₐ[R] B ⧸ I`, there exists
a unique lift `A →ₐ[R] B`".
-/
```

-- snippet 18
```lean
-- Mathlib.RingTheory.Etale.Basic.iff_comp_bijective (L90-L99)
theorem iff_comp_bijective :
   FormallyEtale R A ↔ ∀ ⦃B : Type max u v⦄ [CommRing B] [Algebra R B] (I : Ideal B), I ^ 2 = ⊥ →
      Function.Bijective ((Ideal.Quotient.mkₐ R I).comp : (A →ₐ[R] B) → A →ₐ[R] B ⧸ I) :=
⟨fun _ _ ↦ comp_bijective R A, fun H ↦
    have : FormallyUnramified R A := FormallyUnramified.iff_comp_injective_of_small.{max u v}.mpr
      (by aesop (add safe Function.Bijective.injective))
    have : FormallySmooth R A := FormallySmooth.of_comp_surjective
      (by aesop (add safe Function.Bijective.surjective))
   .of_formallyUnramified_and_formallySmooth⟩
```

-- snippet 19
```lean
-- Mathlib.RingTheory.Etale.Basic.of_restrictScalars (L123-L128)
lemma of_restrictScalars [FormallyUnramified R A] [FormallyEtale R B] :
    FormallyEtale A B :=
have := FormallyUnramified.of_restrictScalars R A B
  have := FormallySmooth.of_restrictScalars R A B
  .of_formallyUnramified_and_formallySmooth
```

-- snippet 20
```lean
-- Mathlib.RingTheory.Etale.Kaehler.KaehlerDifferential (L38-L46)
def KaehlerDifferential.tensorKaehlerEquivOfFormallyEtale [Algebra.FormallyEtale S T] :
    T ⊗[S] Ω[S⁄R] ≃ₗ[T] Ω[T⁄R] := by
refine LinearEquiv.ofBijective (mapBaseChange R S T)
    ⟨?_, fun x ↦ (KaehlerDifferential.exact_mapBaseChange_map R S T x).mp (Subsingleton.elim _ _)⟩
  rw [injective_iff_map_eq_zero]
  intro x hx
  obtain ⟨x, rfl⟩ := (Algebra.H1Cotangent.exact_δ_mapBaseChange R S T x).mp hx
  rw [Subsingleton.elim x 0, map_zero]
```

-- snippet 21
```lean
-- Mathlib.RingTheory.Etale.Field.iff_exists_algEquiv_prod (L182-L207)
theorem iff_exists_algEquiv_prod [EssFiniteType K A] :
    FormallyEtale K A ↔
      ∃ (I : Type u) (_ : Finite I) (Ai : I → Type u) (_ : ∀ i, Field (Ai i))
        (_ : ∀ i, Algebra K (Ai i)) (_ : A ≃ₐ[K] Π i, Ai i),
        ∀ i, Algebra.IsSeparable K (Ai i) := by
classical
  constructor
  · intro H
    have := FormallyUnramified.finite_of_free K A
    have := FormallyUnramified.isReduced_of_field K A
    have : IsArtinianRing A := isArtinian_of_tower K inferInstance
    let v (i : MaximalSpectrum A) : A := (IsArtinianRing.equivPi A).symm (Pi.single i 1)
    rw [FormallyEtale.iff_of_equiv ((IsArtinianRing.equivPi A).restrictScalars K),
      FormallyEtale.pi_iff] at H
    exact ⟨_, inferInstance, _, _, _, (IsArtinianRing.equivPi A).restrictScalars K,
      fun I ↦ (iff_isSeparable _ _).mp inferInstance⟩
  · intro ⟨I, _, Ai, _, _, e, _⟩
    rw [FormallyEtale.iff_of_equiv e, FormallyEtale.pi_iff]
    exact fun I ↦ of_isSeparable K (Ai I)

end Algebra.FormallyEtale

/--
`A` is étale over a field `K` if and only if
`A` is a finite product of finite separable field extensions.
-/
```

-- snippet 22
```lean
-- Mathlib.RingTheory.Etale.Kaehler.tensorCotangentSpaceOfFormallyEtale (L95-L142)
def tensorCotangentSpaceOfFormallyEtale
    (H : f.toRingHom.FormallyEtale) :
    T ⊗[S] P.CotangentSpace ≃ₗ[T] Q.CotangentSpace :=
letI := f.toRingHom.toAlgebra
  haveI : IsScalarTower R P.Ring Q.Ring :=
    .of_algebraMap_eq fun r ↦ (f.toRingHom_algebraMap r).symm
  letI := ((algebraMap S T).comp (algebraMap P.Ring S)).toAlgebra
  haveI : IsScalarTower P.Ring S T := .of_algebraMap_eq' rfl
  haveI : IsScalarTower P.Ring Q.Ring T :=
    .of_algebraMap_eq fun r ↦ (f.algebraMap_toRingHom r).symm
  haveI : FormallyEtale P.Ring Q.Ring := ‹_›
  { __ := (CotangentSpace.map f).liftBaseChange T
    invFun := LinearMap.liftBaseChange T (by
      refine LinearMap.liftBaseChange _ ?_ ∘ₗ
        (tensorKaehlerEquivOfFormallyEtale R P.Ring Q.Ring).symm.toLinearMap
      exact (TensorProduct.mk _ _ _ 1).restrictScalars P.Ring ∘ₗ
        (TensorProduct.mk _ _ _ 1).restrictScalars P.Ring)
    left_inv x := by
      change (LinearMap.liftBaseChange _ _ ∘ₗ LinearMap.liftBaseChange _ _) x =
        LinearMap.id (R := T) x
      congr 1
      ext : 4
      refine Derivation.liftKaehlerDifferential_unique
        (R := R) (S := P.Ring) (M := T ⊗[S] P.CotangentSpace) _ _ ?_
      ext a
      have : (tensorKaehlerEquivOfFormallyEtale R P.Ring Q.Ring).symm
          ((D R Q.Ring) (f.toRingHom a)) = 1 ⊗ₜ D _ _ a :=
        tensorKaehlerEquivOfFormallyEtale_symm_D_algebraMap R P.Ring Q.Ring a
      simp [this]
    right_inv x := by
      change (LinearMap.liftBaseChange _ _ ∘ₗ LinearMap.liftBaseChange _ _) x =
        LinearMap.id (R := T) x
      congr 1
      ext a
      dsimp
      obtain ⟨x, hx⟩ := (tensorKaehlerEquivOfFormallyEtale R P.Ring _).surjective (D R Q.Ring a)
      simp only [one_smul, ← hx, LinearEquiv.symm_apply_apply]
      change (((CotangentSpace.map f).liftBaseChange T).restrictScalars Q.Ring ∘ₗ
        LinearMap.liftBaseChange _ _) x = ((TensorProduct.mk _ _ _ 1) ∘ₗ
          (tensorKaehlerEquivOfFormallyEtale R P.Ring Q.Ring).toLinearMap) x
      congr 1
      ext a
      simp; rfl }

/-- (Implementation)
If `J ≃ Q ⊗ₚ I` (e.g. when `T = Q ⊗ₚ S` and `P → Q` is flat), then `T ⊗ₛ I/I² ≃ J/J²`.
This is the inverse. -/
noncomputable
```

-- snippet 23
```lean
-- Mathlib.RingTheory.Etale.Basic.of_isLocalizationAway (L249-L252)
theorem of_isLocalizationAway (r : R) [IsLocalization.Away r A] : Etale R A where
  formallyEtale := Algebra.FormallyEtale.of_isLocalization (Submonoid.powers r)
finitePresentation := IsLocalization.Away.finitePresentation r
```

-- snippet 24
```lean
-- Mathlib.RingTheory.Etale.Basic.of_formallyUnramified_and_formallySmooth (L73-L76)
theorem of_formallyUnramified_and_formallySmooth [FormallyUnramified R A]
    [FormallySmooth R A] : FormallyEtale R A :=
FormallyEtale.iff_formallyUnramified_and_formallySmooth.mpr ⟨‹_›, ‹_›⟩
```

-- snippet 25
```lean
-- Mathlib.RingTheory.Etale.Field.iff_isSeparable (L158-L161)
theorem iff_isSeparable [EssFiniteType K L] :
    FormallyEtale K L ↔ Algebra.IsSeparable K L :=
⟨fun _ ↦ FormallyUnramified.isSeparable K L, fun _ ↦ of_isSeparable K L⟩
```

-- snippet 26
```lean
-- Mathlib.RingTheory.Etale.Basic.comp (L118-L122)
theorem comp [FormallyEtale R A] [FormallyEtale A B] :
    FormallyEtale R B :=
FormallyEtale.iff_formallyUnramified_and_formallySmooth.mpr
    ⟨FormallyUnramified.comp R A B, FormallySmooth.comp R A B⟩
```

-- snippet 27
```lean
-- Mathlib.RingTheory.Etale.Basic.iff_of_equiv (L108-L117)
theorem iff_of_equiv (e : A ≃ₐ[R] B) : FormallyEtale R A ↔ FormallyEtale R B :=
⟨fun _ ↦ of_equiv e, fun _ ↦ of_equiv e.symm⟩

end OfEquiv

section Comp

variable [Algebra A B] [IsScalarTower R A B]

variable (R A B) in
```

-- snippet 28
```lean
-- Mathlib.RingTheory.Etale.Basic.localization_base (L197-L201)
theorem localization_base [FormallyEtale R Sₘ] : FormallyEtale Rₘ Sₘ :=
FormallyEtale.iff_formallyUnramified_and_formallySmooth.mpr
    ⟨FormallyUnramified.localization_base M, FormallySmooth.localization_base M⟩

/-- The localization of a formally étale map is formally étale. -/
```

-- snippet 29
```lean
-- Mathlib.RingTheory.Etale.Field.iff_formallyUnramified_of_field (L173-L176)
lemma iff_formallyUnramified_of_field [EssFiniteType K A] :
    FormallyEtale K A ↔ FormallyUnramified K A :=
⟨fun _ ↦ inferInstance, fun _ ↦ .of_formallyUnramified_of_field K A⟩
```

-- snippet 30
```lean
-- Mathlib.RingTheory.Etale.Basic.localization_map (L202-L210)
theorem localization_map [FormallyEtale R S] : FormallyEtale Rₘ Sₘ := by
haveI : FormallyEtale S Sₘ := FormallyEtale.of_isLocalization (M.map (algebraMap R S))
  haveI : FormallyEtale R Sₘ := FormallyEtale.comp R S Sₘ
  exact FormallyEtale.localization_base M

end Localization

end FormallyEtale
```

-- snippet 31
```lean
-- Mathlib.RingTheory.Etale.Basic.iff_of_surjective (L142-L148)
lemma iff_of_surjective
    {R S : Type*} [CommRing R] [CommRing S]
    [Algebra R S] (h : Function.Surjective (algebraMap R S)) :
    Algebra.FormallyEtale R S ↔ IsIdempotentElem (RingHom.ker (algebraMap R S)) := by
rw [FormallyEtale.iff_formallyUnramified_and_formallySmooth, ← FormallySmooth.iff_of_surjective h,
    and_iff_right (FormallyUnramified.of_surjective (Algebra.ofId R S) h)]
```

-- snippet 32
```lean
-- Mathlib.RingTheory.Etale.Basic.iff_formallyUnramified_and_formallySmooth (L66-L69)
theorem iff_formallyUnramified_and_formallySmooth :
    FormallyEtale R A ↔ FormallyUnramified R A ∧ FormallySmooth R A :=
⟨fun _ ↦ ⟨inferInstance, inferInstance⟩, fun ⟨_, _⟩ ↦ ⟨inferInstance, inferInstance⟩⟩
```

-- snippet 33
```lean
-- Mathlib.RingTheory.Etale.Basic.formallyEtale_algebraMap (L274-L277)
lemma formallyEtale_algebraMap [Algebra R S] :
    (algebraMap R S).FormallyEtale ↔ Algebra.FormallyEtale R S := by
rw [FormallyEtale, toAlgebra_algebraMap]
```

-- snippet 34
```lean
-- Mathlib.RingTheory.Etale.Field.Algebra (L208-L223)
theorem Algebra.Etale.iff_exists_algEquiv_prod :
    Etale K A ↔
      ∃ (I : Type u) (_ : Finite I) (Ai : I → Type u) (_ : ∀ i, Field (Ai i))
        (_ : ∀ i, Algebra K (Ai i)) (_ : A ≃ₐ[K] Π i, Ai i),
        ∀ i, Module.Finite K (Ai i) ∧ Algebra.IsSeparable K (Ai i) := by
constructor
  · intro H
    obtain ⟨I, _, Ai, _, _, e, _⟩ := (FormallyEtale.iff_exists_algEquiv_prod K A).mp inferInstance
    have := FormallyUnramified.finite_of_free K A
    exact ⟨_, ‹_›, _, _, _, e, fun i ↦ ⟨.of_surjective ((LinearMap.proj i).comp e.toLinearMap)
      ((Function.surjective_eval i).comp e.surjective), inferInstance⟩⟩
  · intro ⟨I, _, Ai, _, _, e, H⟩
    choose h₁ h₂ using H
    have := Module.Finite.of_surjective e.symm.toLinearMap e.symm.surjective
    refine ⟨?_, FinitePresentation.of_finiteType.mp inferInstance⟩
    exact (FormallyEtale.iff_exists_algEquiv_prod K A).mpr ⟨_, inferInstance, _, _, _, e, h₂⟩
```

-- snippet 35
```lean
-- Mathlib.RingTheory.Etale.Basic.FormallyEtale (L270-L273)
def FormallyEtale (f : R →+* S) : Prop :=
letI := f.toAlgebra
  Algebra.FormallyEtale R S
```

-- snippet 36
```lean
-- Mathlib.RingTheory.Etale.Field.of_formallyUnramified_of_field (L163-L172)
lemma of_formallyUnramified_of_field [EssFiniteType K A] [FormallyUnramified K A] :
    FormallyEtale K A := by
have := FormallyUnramified.isReduced_of_field K A
  have : IsArtinianRing A := .of_finite K A
  have (I : MaximalSpectrum A) : FormallyEtale K (A ⧸ I.asIdeal) := by
    rw [FormallyEtale.iff_isSeparable, ← FormallyUnramified.iff_isSeparable]
    infer_instance
  exact .of_equiv ((IsArtinianRing.equivPi A).restrictScalars K).symm

variable {K A} in
```

-- snippet 37
```lean
-- Mathlib.RingTheory.Etale.Field.of_isSeparable_aux (L56-L97)
theorem of_isSeparable_aux [Algebra.IsSeparable K L] [EssFiniteType K L] :
    FormallyEtale K L := by
-- We already know that for field extensions
  -- IsSeparable + EssFiniteType => FormallyUnramified + Finite
  have := FormallyUnramified.of_isSeparable K L
  have := FormallyUnramified.finite_of_free (R := K) (S := L)
  -- We shall show that any `f : L → B/I` can be lifted to `L → B` if `I^2 = ⊥`
  refine FormallyEtale.iff_comp_bijective.mpr fun B _ _ I h ↦ ?_
  refine ⟨FormallyUnramified.iff_comp_injective_of_small.mp
    (FormallyUnramified.of_isSeparable K L) I h, ?_⟩
  intro f
  -- By separability and finiteness, we may assume `L = K(α)` with `p` the minpoly of `α`.
  let pb := Field.powerBasisOfFiniteOfSeparable K L
  -- Let `x : B` such that `f(α) = x` in `B / I`.
  obtain ⟨x, hx⟩ := Ideal.Quotient.mk_surjective (f pb.gen)
  have helper : ∀ x, IsScalarTower.toAlgHom K B (B ⧸ I) x = Ideal.Quotient.mk I x := fun _ ↦ rfl
  -- Then `p(x) = 0 mod I`, and the goal is to find some `ε ∈ I` such that
  -- `p(x + ε) = p(x) + ε p'(x) = 0`, and we will get our lift into `B`.
  have hx' : Ideal.Quotient.mk I (aeval x (minpoly K pb.gen)) = 0 := by
    rw [← helper, ← aeval_algHom_apply, helper, hx, aeval_algHom_apply, minpoly.aeval, map_zero]
  -- Since `p` is separable, `-p'(x)` is invertible in `B ⧸ I`,
  obtain ⟨u, hu⟩ : ∃ u, (aeval x) (derivative (minpoly K pb.gen)) * u + 1 ∈ I := by
    have := (isUnit_iff_ne_zero.mpr ((Algebra.IsSeparable.isSeparable K
      pb.gen).aeval_derivative_ne_zero (minpoly.aeval K _))).map f
    rw [← aeval_algHom_apply, ← hx, ← helper, aeval_algHom_apply, helper] at this
    obtain ⟨u, hu⟩ := Ideal.Quotient.mk_surjective (-this.unit⁻¹ : B ⧸ I)
    use u
    rw [← Ideal.Quotient.eq_zero_iff_mem, map_add, map_mul, map_one, hu, mul_neg,
      IsUnit.mul_val_inv, neg_add_cancel]
  -- And `ε = p(x)/(-p'(x))` works.
  use pb.liftEquiv.symm ⟨x + u * aeval x (minpoly K pb.gen), ?_⟩
  · apply pb.algHom_ext
    simp [hx, hx']
  · rw [← eval_map_algebraMap, Polynomial.eval_add_of_sq_eq_zero, derivative_map,
      ← one_mul (eval x _), eval_map_algebraMap, eval_map_algebraMap, ← mul_assoc, ← add_mul,
      ← Ideal.mem_bot, ← h, pow_two, add_comm]
    · exact Ideal.mul_mem_mul hu (Ideal.Quotient.eq_zero_iff_mem.mp hx')
    rw [← Ideal.mem_bot, ← h]
    apply Ideal.pow_mem_pow
    rw [← Ideal.Quotient.eq_zero_iff_mem, map_mul, hx', mul_zero]

open scoped IntermediateField in
```

-- snippet 38
```lean
-- Mathlib.RingTheory.Etale.Basic.of_isLocalization (L190-L193)
theorem of_isLocalization : FormallyEtale R Rₘ :=
FormallyEtale.iff_formallyUnramified_and_formallySmooth.mpr
    ⟨FormallyUnramified.of_isLocalization M, FormallySmooth.of_isLocalization M⟩
```

-- snippet 39
```lean
-- Mathlib.RingTheory.Etale.Basic.iff_restrictScalars (L129-L132)
lemma iff_restrictScalars [FormallyEtale R A] :
    Algebra.FormallyEtale R B ↔ Algebra.FormallyEtale A B :=
⟨fun _ ↦ .of_restrictScalars (R := R), fun _ ↦ .comp _ A _⟩
```

-- snippet 40
```lean
-- Mathlib.RingTheory.Etale.Field.of_isSeparable (L98-L157)
lemma of_isSeparable [Algebra.IsSeparable K L] : FormallyEtale K L := by
-- We shall show that any `f : L → B/I` can be lifted to `L → B` if `I^2 = ⊥`.
  refine FormallyEtale.iff_comp_bijective.mpr fun B _ _ I h ↦ ?_
  -- But we already know that there exists a unique lift for every finite subfield of `L`
  -- by `of_isSeparable_aux`, so we can glue them all together.
  refine ⟨FormallyUnramified.iff_comp_injective_of_small.mp
    (FormallyUnramified.of_isSeparable K L) I h, ?_⟩
  intro f
  have : ∀ k : L, ∃! g : K⟮k⟯ →ₐ[K] B,
      (Ideal.Quotient.mkₐ K I).comp g = f.comp (IsScalarTower.toAlgHom K _ L) := by
    intro k
    have := IsSeparable.of_algHom _ _ (IsScalarTower.toAlgHom K (K⟮k⟯) L)
    have := IntermediateField.adjoin.finiteDimensional
      (Algebra.IsSeparable.isSeparable K k).isIntegral
    have := FormallyEtale.of_isSeparable_aux K (K⟮k⟯)
    have := FormallyEtale.comp_bijective (R := K) (A := K⟮k⟯) I h
    exact this.existsUnique _
  choose g hg₁ hg₂ using this
  have hg₃ : ∀ x y (h : x ∈ K⟮y⟯), g y ⟨x, h⟩ = g x (IntermediateField.AdjoinSimple.gen K x) := by
    intro x y h
    have e : K⟮x⟯ ≤ K⟮y⟯ := by
      rw [IntermediateField.adjoin_le_iff]
      rintro _ rfl
      exact h
    rw [← hg₂ _ ((g _).comp (IntermediateField.inclusion e))]
    · rfl
    apply AlgHom.ext
    rw [← AlgHom.comp_assoc, hg₁, AlgHom.comp_assoc]
    simp
  have H : ∀ x y : L, ∃ α : L, x ∈ K⟮α⟯ ∧ y ∈ K⟮α⟯ := by
    intro x y
    have : FiniteDimensional K K⟮x, y⟯ := by
      apply IntermediateField.finiteDimensional_adjoin
      intro x _; exact (Algebra.IsSeparable.isSeparable K x).isIntegral
    have := IsSeparable.of_algHom _ _ (IsScalarTower.toAlgHom K (K⟮x, y⟯) L)
    obtain ⟨⟨α, hα⟩, e⟩ := Field.exists_primitive_element K K⟮x, y⟯
    apply_fun (IntermediateField.map (IntermediateField.val _)) at e
    rw [IntermediateField.adjoin_map, ← AlgHom.fieldRange_eq_map] at e
    simp only [IntermediateField.coe_val, Set.image_singleton,
      IntermediateField.fieldRange_val] at e
    have hx : x ∈ K⟮α⟯ := e ▸ IntermediateField.subset_adjoin K {x, y} (by simp)
    have hy : y ∈ K⟮α⟯ := e ▸ IntermediateField.subset_adjoin K {x, y} (by simp)
    exact ⟨α, hx, hy⟩
  refine ⟨⟨⟨⟨⟨fun x ↦ g x (IntermediateField.AdjoinSimple.gen K x), ?_⟩, ?_⟩, ?_, ?_⟩, ?_⟩, ?_⟩
  · change g 1 1 = 1; rw [map_one]
  · intro x y
    obtain ⟨α, hx, hy⟩ := H x y
    simp only [← hg₃ _ _ hx, ← hg₃ _ _ hy, ← map_mul, ← hg₃ _ _ (mul_mem hx hy)]
    rfl
  · change g 0 0 = 0; rw [map_zero]
  · intro x y
    obtain ⟨α, hx, hy⟩ := H x y
    simp only [← hg₃ _ _ hx, ← hg₃ _ _ hy, ← map_add, ← hg₃ _ _ (add_mem hx hy)]
    rfl
  · intro r
    change g _ (algebraMap K _ r) = _
    rw [AlgHom.commutes]
  · ext x
    simpa using AlgHom.congr_fun (hg₁ x) (IntermediateField.AdjoinSimple.gen K x)
```
[/INST]


[System] You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.Order.OmegaCompletePartialOrder).

[User]
Prove the following theorem. The retrieved context below may help.

```lean
theorem apply_mono {f g : α →𝒄 β} {x y : α} (h₁ : f ≤ g) (h₂ : x ≤ y) : f x ≤ g y
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.Chain (L71-L76)
def Chain (α : Type u) [Preorder α] :=
ℕ →o α

namespace Chain
variable [Preorder α] [Preorder β] [Preorder γ]
```

-- snippet 2
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.isChain_range (L95-L96)
lemma isChain_range : IsChain (· ≤ ·) (Set.range c) := Monotone.isChain_range (OrderHomClass.mono c)
```

-- snippet 3
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.directed (L97-L101)
lemma directed : Directed (· ≤ ·) c := directedOn_range.2 c.isChain_range.directedOn
/-- `map` function for `Chain` -/
-- Not `@[simps]`: we need `@[simps!]` to see through the type synonym `Chain β = ℕ →o β`,
-- but then we'd get the `FunLike` instance for `OrderHom` instead.
```

-- snippet 4
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.map (L102-L104)
def map : Chain β :=
f.comp c
```

-- snippet 5
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.mem_map (L109-L111)
theorem mem_map (x : α) : x ∈ c → f x ∈ Chain.map c f :=
fun ⟨i, h⟩ => ⟨i, h.symm ▸ rfl⟩
```

-- snippet 6
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.exists_of_mem_map (L112-L114)
theorem exists_of_mem_map {b : β} : b ∈ c.map f → ∃ a, a ∈ c ∧ f a = b :=
fun ⟨i, h⟩ => ⟨c i, ⟨i, rfl⟩, h.symm⟩
```

-- snippet 7
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.mem_map_iff (L116-L121)
theorem mem_map_iff {b : β} : b ∈ c.map f ↔ ∃ a, a ∈ c ∧ f a = b :=
⟨exists_of_mem_map _, fun h => by
    rcases h with ⟨w, h, h'⟩
    subst b
    apply mem_map c _ h⟩
```

-- snippet 8
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.map_id (L123-L125)
theorem map_id : c.map OrderHom.id = c :=
OrderHom.comp_id _
```

-- snippet 9
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.map_comp (L126-L128)
theorem map_comp : (c.map f).map g = c.map (g.comp f) :=
rfl
```

-- snippet 10
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.map_le_map (L130-L136)
theorem map_le_map {g : α →o β} (h : f ≤ g) : c.map f ≤ c.map g :=
fun i => by simp only [map_coe, Function.comp_apply]; exists i; apply h

/-- `OmegaCompletePartialOrder.Chain.zip` pairs up the elements of two chains
that have the same index. -/
-- Not `@[simps]`: we need `@[simps!]` to see through the type synonym `Chain β = ℕ →o β`,
-- but then we'd get the `FunLike` instance for `OrderHom` instead.
```

-- snippet 11
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.zip (L137-L139)
def zip (c₀ : Chain α) (c₁ : Chain β) : Chain (α × β) :=
OrderHom.prod c₀ c₁
```

-- snippet 12
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.pair (L143-L148)
def pair (a b : α) (hab : a ≤ b) : Chain α where
  toFun
    | 0 => a
    | _ => b
  monotone' _ _ _ := by aesop
```

-- snippet 13
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.le_ωSup_of_le (L192-L194)
theorem le_ωSup_of_le {c : Chain α} {x : α} (i : ℕ) (h : x ≤ c i) : x ≤ ωSup c :=
le_trans h (le_ωSup c _)
```

-- snippet 14
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.ωSup_total (L195-L203)
theorem ωSup_total {c : Chain α} {x : α} (h : ∀ i, c i ≤ x ∨ x ≤ c i) : ωSup c ≤ x ∨ x ≤ ωSup c :=
by_cases
    (fun (this : ∀ i, c i ≤ x) => Or.inl (ωSup_le _ _ this))
    (fun (this : ¬∀ i, c i ≤ x) =>
      have : ∃ i, ¬c i ≤ x := by simp only [not_forall] at this ⊢; assumption
      let ⟨i, hx⟩ := this
      have : x ≤ c i := (h i).resolve_left hx
      Or.inr <| le_ωSup_of_le _ this)
```

-- snippet 15
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.ωSup_le_ωSup_of_le (L205-L209)
theorem ωSup_le_ωSup_of_le {c₀ c₁ : Chain α} (h : c₀ ≤ c₁) : ωSup c₀ ≤ ωSup c₁ :=
(ωSup_le _ _) fun i => by
    obtain ⟨_, h⟩ := h i
    exact le_trans h (le_ωSup _ _)
```

<s>[SYSTEM_PROMPT]You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.Order.OmegaCompletePartialOrder).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]Prove the following theorem. The retrieved context below may help.

```lean
theorem apply_mono {f g : α →𝒄 β} {x y : α} (h₁ : f ≤ g) (h₂ : x ≤ y) : f x ≤ g y
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.Chain (L71-L76)
def Chain (α : Type u) [Preorder α] :=
ℕ →o α

namespace Chain
variable [Preorder α] [Preorder β] [Preorder γ]
```

-- snippet 2
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.isChain_range (L95-L96)
lemma isChain_range : IsChain (· ≤ ·) (Set.range c) := Monotone.isChain_range (OrderHomClass.mono c)
```

-- snippet 3
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.directed (L97-L101)
lemma directed : Directed (· ≤ ·) c := directedOn_range.2 c.isChain_range.directedOn
/-- `map` function for `Chain` -/
-- Not `@[simps]`: we need `@[simps!]` to see through the type synonym `Chain β = ℕ →o β`,
-- but then we'd get the `FunLike` instance for `OrderHom` instead.
```

-- snippet 4
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.map (L102-L104)
def map : Chain β :=
f.comp c
```

-- snippet 5
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.mem_map (L109-L111)
theorem mem_map (x : α) : x ∈ c → f x ∈ Chain.map c f :=
fun ⟨i, h⟩ => ⟨i, h.symm ▸ rfl⟩
```

-- snippet 6
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.exists_of_mem_map (L112-L114)
theorem exists_of_mem_map {b : β} : b ∈ c.map f → ∃ a, a ∈ c ∧ f a = b :=
fun ⟨i, h⟩ => ⟨c i, ⟨i, rfl⟩, h.symm⟩
```

-- snippet 7
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.mem_map_iff (L116-L121)
theorem mem_map_iff {b : β} : b ∈ c.map f ↔ ∃ a, a ∈ c ∧ f a = b :=
⟨exists_of_mem_map _, fun h => by
    rcases h with ⟨w, h, h'⟩
    subst b
    apply mem_map c _ h⟩
```

-- snippet 8
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.map_id (L123-L125)
theorem map_id : c.map OrderHom.id = c :=
OrderHom.comp_id _
```

-- snippet 9
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.map_comp (L126-L128)
theorem map_comp : (c.map f).map g = c.map (g.comp f) :=
rfl
```

-- snippet 10
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.map_le_map (L130-L136)
theorem map_le_map {g : α →o β} (h : f ≤ g) : c.map f ≤ c.map g :=
fun i => by simp only [map_coe, Function.comp_apply]; exists i; apply h

/-- `OmegaCompletePartialOrder.Chain.zip` pairs up the elements of two chains
that have the same index. -/
-- Not `@[simps]`: we need `@[simps!]` to see through the type synonym `Chain β = ℕ →o β`,
-- but then we'd get the `FunLike` instance for `OrderHom` instead.
```

-- snippet 11
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.zip (L137-L139)
def zip (c₀ : Chain α) (c₁ : Chain β) : Chain (α × β) :=
OrderHom.prod c₀ c₁
```

-- snippet 12
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.pair (L143-L148)
def pair (a b : α) (hab : a ≤ b) : Chain α where
  toFun
    | 0 => a
    | _ => b
  monotone' _ _ _ := by aesop
```

-- snippet 13
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.le_ωSup_of_le (L192-L194)
theorem le_ωSup_of_le {c : Chain α} {x : α} (i : ℕ) (h : x ≤ c i) : x ≤ ωSup c :=
le_trans h (le_ωSup c _)
```

-- snippet 14
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.ωSup_total (L195-L203)
theorem ωSup_total {c : Chain α} {x : α} (h : ∀ i, c i ≤ x ∨ x ≤ c i) : ωSup c ≤ x ∨ x ≤ ωSup c :=
by_cases
    (fun (this : ∀ i, c i ≤ x) => Or.inl (ωSup_le _ _ this))
    (fun (this : ¬∀ i, c i ≤ x) =>
      have : ∃ i, ¬c i ≤ x := by simp only [not_forall] at this ⊢; assumption
      let ⟨i, hx⟩ := this
      have : x ≤ c i := (h i).resolve_left hx
      Or.inr <| le_ωSup_of_le _ this)
```

-- snippet 15
```lean
-- Mathlib.Order.OmegaCompletePartialOrder.ωSup_le_ωSup_of_le (L205-L209)
theorem ωSup_le_ωSup_of_le {c₀ c₁ : Chain α} (h : c₀ ≤ c₁) : ωSup c₀ ≤ ωSup c₁ :=
(ωSup_le _ _) fun i => by
    obtain ⟨_, h⟩ := h i
    exact le_trans h (le_ωSup _ _)
```
[/INST]

mistral-common:Tekken v15 (Mistral chat template, [INST]/[SYSTEM_PROMPT])