l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem image.map_id [HasImageMap (𝟙 f)] : image.map (𝟙 f) = 𝟙 (image f.hom) :=
  show (HasImageMap.imageMap (𝟙 f)).map = (imageMapId f).map by
    

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
f g : Arrow C
inst✝³ : HasImage f.hom
inst✝² : HasImage g.hom
sq : f ⟶ g
inst✝¹ : HasImageMap sq
inst✝ : HasImageMap (𝟙 f)
⊢ (HasImageMap.imageMap (𝟙 f)).map = (imageMapId f).map

Next tactic:
congr
@[simp]
theorem image.map_id [HasImageMap (𝟙 f)] : image.map (𝟙 f) = 𝟙 (image f.hom) :=
  show (HasImageMap.imageMap (𝟙 f)).map = (imageMapId f).map by
    congr; 

Proof state:
case e_self
C : Type u
inst✝⁴ : Category.{v, u} C
f g : Arrow C
inst✝³ : HasImage f.hom
inst✝² : HasImage g.hom
sq : f ⟶ g
inst✝¹ : HasImageMap sq
inst✝ : HasImageMap (𝟙 f)
⊢ HasImageMap.imageMap (𝟙 f) = imageMapId f

Next tactic:
simp only [eq_iff_true_of_subsingleton]
/-- Satisfying the inhabited linter -/
instance strongEpiMonoFactorisationInhabited {X Y : C} (f : X ⟶ Y) [StrongEpi f] :
    Inhabited (StrongEpiMonoFactorisation f) :=
  ⟨⟨⟨Y, 𝟙 Y, f, by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
X Y : C
f : X ⟶ Y
inst✝ : StrongEpi f
⊢ f ≫ 𝟙 Y = f

Next tactic:
simp
/-- A mono factorisation coming from a strong epi-mono factorisation always has the universal
    property of the image. -/
def StrongEpiMonoFactorisation.toMonoIsImage {X Y : C} {f : X ⟶ Y}
    (F : StrongEpiMonoFactorisation f) : IsImage F.toMonoFactorisation where
  lift G :=
    (CommSq.mk (show G.e ≫ G.m = F.e ≫ F.m by 

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : C
f : X ⟶ Y
F : StrongEpiMonoFactorisation f
G : MonoFactorisation f
⊢ G.e ≫ G.m = F.e ≫ F.m

Next tactic:
rw [F.toMonoFactorisation.fac, G.fac]
/-- If there is a single strong epi-mono factorisation of `f`, then every image factorisation is a
    strong epi-mono factorisation. -/
theorem strongEpi_of_strongEpiMonoFactorisation {X Y : C} {f : X ⟶ Y}
    (F : StrongEpiMonoFactorisation f) {F' : MonoFactorisation f} (hF' : IsImage F') :
    StrongEpi F'.e := by
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : C
f : X ⟶ Y
F : StrongEpiMonoFactorisation f
F' : MonoFactorisation f
hF' : IsImage F'
⊢ StrongEpi F'.e

Next tactic:
rw [← IsImage.e_isoExt_hom F.toMonoIsImage hF']
/-- If there is a single strong epi-mono factorisation of `f`, then every image factorisation is a
    strong epi-mono factorisation. -/
theorem strongEpi_of_strongEpiMonoFactorisation {X Y : C} {f : X ⟶ Y}
    (F : StrongEpiMonoFactorisation f) {F' : MonoFactorisation f} (hF' : IsImage F') :
    StrongEpi F'.e := by
  rw [← IsImage.e_isoExt_hom F.toMonoIsImage hF']
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : C
f : X ⟶ Y
F : StrongEpiMonoFactorisation f
F' : MonoFactorisation f
hF' : IsImage F'
⊢ StrongEpi (F.e ≫ (IsImage.isoExt (StrongEpiMonoFactorisation.toMonoIsImage F) hF').hom)

Next tactic:
apply strongEpi_comp
/-- A category with strong epi images has image maps. -/
instance (priority := 100) hasImageMapsOfHasStrongEpiImages [HasStrongEpiImages C] : HasImageMaps C
    where
  has_image_map {f} {g} st :=
    HasImageMap.mk
      { map :=
          (CommSq.mk
              (show
                (st.left ≫ factorThruImage g.hom) ≫ image.ι g.hom =
                  factorThruImage f.hom ≫ image.ι f.hom ≫ st.right
                by 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasImages C
inst✝ : HasStrongEpiImages C
f g : Arrow C
st : f ⟶ g
⊢ (st.left ≫ factorThruImage g.hom) ≫ image.ι g.hom = factorThruImage f.hom ≫ image.ι f.hom ≫ st.right

Next tactic:
simp
/-- If a category has images, equalizers and pullbacks, then images are automatically strong epi
    images. -/
instance (priority := 100) hasStrongEpiImages_of_hasPullbacks_of_hasEqualizers [HasPullbacks C]
    [HasEqualizers C] : HasStrongEpiImages C where
  strong_factorThruImage f :=
    StrongEpi.mk' fun {A} {B} h h_mono x y sq =>
      CommSq.HasLift.mk'
        { l :=
            image.lift
                { I := pullback h y
                  m := pullback.snd ≫ image.ι f
                  m_mono := mono_comp _ _
                  e := pullback.lift _ _ sq.w } ≫
              pullback.fst
          fac_left := by 

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : HasImages C
inst✝¹ : HasPullbacks C
inst✝ : HasEqualizers C
X✝ Y✝ : C
f : X✝ ⟶ Y✝
A B : C
h : A ⟶ B
h_mono : Mono h
x : X✝ ⟶ A
y : image f ⟶ B
sq : CommSq x (factorThruImage f) h y
⊢ factorThruImage f ≫
      image.lift
          (MonoFactorisation.mk (pullback h y) (pullback.snd ≫ image.ι f)
            (pullback.lift x (factorThruImage f) (_ : x ≫ h = factorThruImage f ≫ y))) ≫
        pullback.fst =
    x

Next tactic:
simp only [image.fac_lift_assoc, pullback.lift_fst]
/-- If a category has images, equalizers and pullbacks, then images are automatically strong epi
    images. -/
instance (priority := 100) hasStrongEpiImages_of_hasPullbacks_of_hasEqualizers [HasPullbacks C]
    [HasEqualizers C] : HasStrongEpiImages C where
  strong_factorThruImage f :=
    StrongEpi.mk' fun {A} {B} h h_mono x y sq =>
      CommSq.HasLift.mk'
        { l :=
            image.lift
                { I := pullback h y
                  m := pullback.snd ≫ image.ι f
                  m_mono := mono_comp _ _
                  e := pullback.lift _ _ sq.w } ≫
              pullback.fst
          fac_left := by simp only [image.fac_lift_assoc, pullback.lift_fst]
          fac_right := by
            

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : HasImages C
inst✝¹ : HasPullbacks C
inst✝ : HasEqualizers C
X✝ Y✝ : C
f : X✝ ⟶ Y✝
A B : C
h : A ⟶ B
h_mono : Mono h
x : X✝ ⟶ A
y : image f ⟶ B
sq : CommSq x (factorThruImage f) h y
⊢ (image.lift
          (MonoFactorisation.mk (pullback h y) (pullback.snd ≫ image.ι f)
            (pullback.lift x (factorThruImage f) (_ : x ≫ h = factorThruImage f ≫ y))) ≫
        pullback.fst) ≫
      h =
    y

Next tactic:
apply image.ext
/-- If a category has images, equalizers and pullbacks, then images are automatically strong epi
    images. -/
instance (priority := 100) hasStrongEpiImages_of_hasPullbacks_of_hasEqualizers [HasPullbacks C]
    [HasEqualizers C] : HasStrongEpiImages C where
  strong_factorThruImage f :=
    StrongEpi.mk' fun {A} {B} h h_mono x y sq =>
      CommSq.HasLift.mk'
        { l :=
            image.lift
                { I := pullback h y
                  m := pullback.snd ≫ image.ι f
                  m_mono := mono_comp _ _
                  e := pullback.lift _ _ sq.w } ≫
              pullback.fst
          fac_left := by simp only [image.fac_lift_assoc, pullback.lift_fst]
          fac_right := by
            apply image.ext
            

Proof state:
case w
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : HasImages C
inst✝¹ : HasPullbacks C
inst✝ : HasEqualizers C
X✝ Y✝ : C
f : X✝ ⟶ Y✝
A B : C
h : A ⟶ B
h_mono : Mono h
x : X✝ ⟶ A
y : image f ⟶ B
sq : CommSq x (factorThruImage f) h y
⊢ factorThruImage f ≫
      (image.lift
            (MonoFactorisation.mk (pullback h y) (pullback.snd ≫ image.ι f)
              (pullback.lift x (factorThruImage f) (_ : x ≫ h = factorThruImage f ≫ y))) ≫
          pullback.fst) ≫
        h =
    factorThruImage f ≫ y

Next tactic:
simp only [sq.w, Category.assoc, image.fac_lift_assoc, pullback.lift_fst_assoc]
@[simp]
theorem image.isoStrongEpiMono_hom_comp_ι {I' : C} (e : X ⟶ I') (m : I' ⟶ Y) (comm : e ≫ m = f)
    [StrongEpi e] [Mono m] : (image.isoStrongEpiMono e m comm).hom ≫ image.ι f = m := by
  

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : HasStrongEpiMonoFactorisations C
X Y : C
f : X ⟶ Y
I' : C
e : X ⟶ I'
m : I' ⟶ Y
comm : e ≫ m = f
inst✝¹ : StrongEpi e
inst✝ : Mono m
⊢ (isoStrongEpiMono e m comm).hom ≫ ι f = m

Next tactic:
dsimp [isoStrongEpiMono]
@[simp]
theorem image.isoStrongEpiMono_hom_comp_ι {I' : C} (e : X ⟶ I') (m : I' ⟶ Y) (comm : e ≫ m = f)
    [StrongEpi e] [Mono m] : (image.isoStrongEpiMono e m comm).hom ≫ image.ι f = m := by
  dsimp [isoStrongEpiMono]
  

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : HasStrongEpiMonoFactorisations C
X Y : C
f : X ⟶ Y
I' : C
e : X ⟶ I'
m : I' ⟶ Y
comm : e ≫ m = f
inst✝¹ : StrongEpi e
inst✝ : Mono m
⊢ IsImage.lift (StrongEpiMonoFactorisation.toMonoIsImage (StrongEpiMonoFactorisation.mk (MonoFactorisation.mk I' m e)))
        (Image.monoFactorisation f) ≫
      ι f =
    m

Next tactic:
apply IsImage.lift_fac
theorem hasStrongEpiMonoFactorisations_imp_of_isEquivalence (F : C ⥤ D) [IsEquivalence F]
    [h : HasStrongEpiMonoFactorisations C] : HasStrongEpiMonoFactorisations D :=
  ⟨fun {X} {Y} f => by
    

Proof state:
C : Type u_1
D : Type u_2
inst✝² : Category.{u_3, u_1} C
inst✝¹ : Category.{u_4, u_2} D
F : C ⥤ D
inst✝ : IsEquivalence F
h : HasStrongEpiMonoFactorisations C
X Y : D
f : X ⟶ Y
⊢ Nonempty (StrongEpiMonoFactorisation f)

Next tactic:
let em : StrongEpiMonoFactorisation (F.inv.map f) :=
      (HasStrongEpiMonoFactorisations.has_fac (F.inv.map f)).some
theorem hasStrongEpiMonoFactorisations_imp_of_isEquivalence (F : C ⥤ D) [IsEquivalence F]
    [h : HasStrongEpiMonoFactorisations C] : HasStrongEpiMonoFactorisations D :=
  ⟨fun {X} {Y} f => by
    let em : StrongEpiMonoFactorisation (F.inv.map f) :=
      (HasStrongEpiMonoFactorisations.has_fac (F.inv.map f)).some
    

Proof state:
C : Type u_1
D : Type u_2
inst✝² : Category.{u_3, u_1} C
inst✝¹ : Category.{u_4, u_2} D
F : C ⥤ D
inst✝ : IsEquivalence F
h : HasStrongEpiMonoFactorisations C
X Y : D
f : X ⟶ Y
em : StrongEpiMonoFactorisation ((inv F).map f) :=
  Nonempty.some (_ : Nonempty (StrongEpiMonoFactorisation ((inv F).map f)))
⊢ Nonempty (StrongEpiMonoFactorisation f)

Next tactic:
haveI : Mono (F.map em.m ≫ F.asEquivalence.counitIso.hom.app Y) := mono_comp _ _
theorem hasStrongEpiMonoFactorisations_imp_of_isEquivalence (F : C ⥤ D) [IsEquivalence F]
    [h : HasStrongEpiMonoFactorisations C] : HasStrongEpiMonoFactorisations D :=
  ⟨fun {X} {Y} f => by
    let em : StrongEpiMonoFactorisation (F.inv.map f) :=
      (HasStrongEpiMonoFactorisations.has_fac (F.inv.map f)).some
    haveI : Mono (F.map em.m ≫ F.asEquivalence.counitIso.hom.app Y) := mono_comp _ _
    

Proof state:
C : Type u_1
D : Type u_2
inst✝² : Category.{u_3, u_1} C
inst✝¹ : Category.{u_4, u_2} D
F : C ⥤ D
inst✝ : IsEquivalence F
h : HasStrongEpiMonoFactorisations C
X Y : D
f : X ⟶ Y
em : StrongEpiMonoFactorisation ((inv F).map f) :=
  Nonempty.some (_ : Nonempty (StrongEpiMonoFactorisation ((inv F).map f)))
this : Mono (F.map em.m ≫ (asEquivalence F).counitIso.hom.app Y)
⊢ Nonempty (StrongEpiMonoFactorisation f)

Next tactic:
haveI : StrongEpi (F.asEquivalence.counitIso.inv.app X ≫ F.map em.e) := strongEpi_comp _ _
theorem hasStrongEpiMonoFactorisations_imp_of_isEquivalence (F : C ⥤ D) [IsEquivalence F]
    [h : HasStrongEpiMonoFactorisations C] : HasStrongEpiMonoFactorisations D :=
  ⟨fun {X} {Y} f => by
    let em : StrongEpiMonoFactorisation (F.inv.map f) :=
      (HasStrongEpiMonoFactorisations.has_fac (F.inv.map f)).some
    haveI : Mono (F.map em.m ≫ F.asEquivalence.counitIso.hom.app Y) := mono_comp _ _
    haveI : StrongEpi (F.asEquivalence.counitIso.inv.app X ≫ F.map em.e) := strongEpi_comp _ _
    

Proof state:
C : Type u_1
D : Type u_2
inst✝² : Category.{u_3, u_1} C
inst✝¹ : Category.{u_4, u_2} D
F : C ⥤ D
inst✝ : IsEquivalence F
h : HasStrongEpiMonoFactorisations C
X Y : D
f : X ⟶ Y
em : StrongEpiMonoFactorisation ((inv F).map f) :=
  Nonempty.some (_ : Nonempty (StrongEpiMonoFactorisation ((inv F).map f)))
this✝ : Mono (F.map em.m ≫ (asEquivalence F).counitIso.hom.app Y)
this : StrongEpi ((asEquivalence F).counitIso.inv.app X ≫ F.map em.e)
⊢ Nonempty (StrongEpiMonoFactorisation f)

Next tactic:
exact
      Nonempty.intro
        { I := F.obj em.I
          e := F.asEquivalence.counitIso.inv.app X ≫ F.map em.e
          m := F.map em.m ≫ F.asEquivalence.counitIso.hom.app Y
          fac := by
            simpa only [Category.assoc, ← F.map_comp_assoc, em.fac, IsEquivalence.fun_inv_map,
              Iso.inv_hom_id_app, Iso.inv_hom_id_app_assoc] using Category.comp_id _ }
theorem hasStrongEpiMonoFactorisations_imp_of_isEquivalence (F : C ⥤ D) [IsEquivalence F]
    [h : HasStrongEpiMonoFactorisations C] : HasStrongEpiMonoFactorisations D :=
  ⟨fun {X} {Y} f => by
    let em : StrongEpiMonoFactorisation (F.inv.map f) :=
      (HasStrongEpiMonoFactorisations.has_fac (F.inv.map f)).some
    haveI : Mono (F.map em.m ≫ F.asEquivalence.counitIso.hom.app Y) := mono_comp _ _
    haveI : StrongEpi (F.asEquivalence.counitIso.inv.app X ≫ F.map em.e) := strongEpi_comp _ _
    exact
      Nonempty.intro
        { I := F.obj em.I
          e := F.asEquivalence.counitIso.inv.app X ≫ F.map em.e
          m := F.map em.m ≫ F.asEquivalence.counitIso.hom.app Y
          fac := by
            

Proof state:
C : Type u_1
D : Type u_2
inst✝² : Category.{u_3, u_1} C
inst✝¹ : Category.{u_4, u_2} D
F : C ⥤ D
inst✝ : IsEquivalence F
h : HasStrongEpiMonoFactorisations C
X Y : D
f : X ⟶ Y
em : StrongEpiMonoFactorisation ((inv F).map f) :=
  Nonempty.some (_ : Nonempty (StrongEpiMonoFactorisation ((inv F).map f)))
this✝ : Mono (F.map em.m ≫ (asEquivalence F).counitIso.hom.app Y)
this : StrongEpi ((asEquivalence F).counitIso.inv.app X ≫ F.map em.e)
⊢ ((asEquivalence F).counitIso.inv.app X ≫ F.map em.e) ≫ F.map em.m ≫ (asEquivalence F).counitIso.hom.app Y = f

Next tactic:
simpa only [Category.assoc, ← F.map_comp_assoc, em.fac, IsEquivalence.fun_inv_map,
              Iso.inv_hom_id_app, Iso.inv_hom_id_app_assoc] using Category.comp_id _
/-- If `f₁ f₂ : A →ₐ[R] B` are two lifts of the same `A →ₐ[R] B ⧸ I`,
  we may define a map `f₁ - f₂ : A →ₗ[R] I`. -/
def diffToIdealOfQuotientCompEq (f₁ f₂ : A →ₐ[R] B)
    (e : (Ideal.Quotient.mkₐ R I).comp f₁ = (Ideal.Quotient.mkₐ R I).comp f₂) : A →ₗ[R] I :=
  LinearMap.codRestrict (I.restrictScalars _) (f₁.toLinearMap - f₂.toLinearMap) (by
    

Proof state:
R : Type u
A : Type v
B : Type w
inst✝⁴ : CommSemiring R
inst✝³ : CommSemiring A
inst✝² : CommRing B
inst✝¹ : Algebra R A
inst✝ : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
f₁ f₂ : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f₁ = AlgHom.comp (Ideal.Quotient.mkₐ R I) f₂
⊢ ∀ (c : A), (AlgHom.toLinearMap f₁ - AlgHom.toLinearMap f₂) c ∈ Submodule.restrictScalars R I

Next tactic:
intro x
/-- If `f₁ f₂ : A →ₐ[R] B` are two lifts of the same `A →ₐ[R] B ⧸ I`,
  we may define a map `f₁ - f₂ : A →ₗ[R] I`. -/
def diffToIdealOfQuotientCompEq (f₁ f₂ : A →ₐ[R] B)
    (e : (Ideal.Quotient.mkₐ R I).comp f₁ = (Ideal.Quotient.mkₐ R I).comp f₂) : A →ₗ[R] I :=
  LinearMap.codRestrict (I.restrictScalars _) (f₁.toLinearMap - f₂.toLinearMap) (by
    intro x
    

Proof state:
R : Type u
A : Type v
B : Type w
inst✝⁴ : CommSemiring R
inst✝³ : CommSemiring A
inst✝² : CommRing B
inst✝¹ : Algebra R A
inst✝ : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
f₁ f₂ : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f₁ = AlgHom.comp (Ideal.Quotient.mkₐ R I) f₂
x : A
⊢ (AlgHom.toLinearMap f₁ - AlgHom.toLinearMap f₂) x ∈ Submodule.restrictScalars R I

Next tactic:
change f₁ x - f₂ x ∈ I
/-- If `f₁ f₂ : A →ₐ[R] B` are two lifts of the same `A →ₐ[R] B ⧸ I`,
  we may define a map `f₁ - f₂ : A →ₗ[R] I`. -/
def diffToIdealOfQuotientCompEq (f₁ f₂ : A →ₐ[R] B)
    (e : (Ideal.Quotient.mkₐ R I).comp f₁ = (Ideal.Quotient.mkₐ R I).comp f₂) : A →ₗ[R] I :=
  LinearMap.codRestrict (I.restrictScalars _) (f₁.toLinearMap - f₂.toLinearMap) (by
    intro x
    change f₁ x - f₂ x ∈ I
    

Proof state:
R : Type u
A : Type v
B : Type w
inst✝⁴ : CommSemiring R
inst✝³ : CommSemiring A
inst✝² : CommRing B
inst✝¹ : Algebra R A
inst✝ : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
f₁ f₂ : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f₁ = AlgHom.comp (Ideal.Quotient.mkₐ R I) f₂
x : A
⊢ f₁ x - f₂ x ∈ I

Next tactic:
rw [← Ideal.Quotient.eq, ← Ideal.Quotient.mkₐ_eq_mk R, ← AlgHom.comp_apply, e]
/-- If `f₁ f₂ : A →ₐ[R] B` are two lifts of the same `A →ₐ[R] B ⧸ I`,
  we may define a map `f₁ - f₂ : A →ₗ[R] I`. -/
def diffToIdealOfQuotientCompEq (f₁ f₂ : A →ₐ[R] B)
    (e : (Ideal.Quotient.mkₐ R I).comp f₁ = (Ideal.Quotient.mkₐ R I).comp f₂) : A →ₗ[R] I :=
  LinearMap.codRestrict (I.restrictScalars _) (f₁.toLinearMap - f₂.toLinearMap) (by
    intro x
    change f₁ x - f₂ x ∈ I
    rw [← Ideal.Quotient.eq, ← Ideal.Quotient.mkₐ_eq_mk R, ← AlgHom.comp_apply, e]
    

Proof state:
R : Type u
A : Type v
B : Type w
inst✝⁴ : CommSemiring R
inst✝³ : CommSemiring A
inst✝² : CommRing B
inst✝¹ : Algebra R A
inst✝ : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
f₁ f₂ : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f₁ = AlgHom.comp (Ideal.Quotient.mkₐ R I) f₂
x : A
⊢ (AlgHom.comp (Ideal.Quotient.mkₐ R I) f₂) x = (Ideal.Quotient.mkₐ R I) (f₂ x)

Next tactic:
rfl
/-- Given a tower of algebras `R → A → B`, and a square-zero `I : Ideal B`, each lift `A →ₐ[R] B`
of the canonical map `A →ₐ[R] B ⧸ I` corresponds to an `R`-derivation from `A` to `I`. -/
def derivationToSquareZeroOfLift (f : A →ₐ[R] B)
    (e : (Ideal.Quotient.mkₐ R I).comp f = IsScalarTower.toAlgHom R A (B ⧸ I)) :
    Derivation R A I := by
  

Proof state:
R : Type u
A : Type v
B : Type w
inst✝⁶ : CommSemiring R
inst✝⁵ : CommSemiring A
inst✝⁴ : CommRing B
inst✝³ : Algebra R A
inst✝² : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
inst✝¹ : Algebra A B
inst✝ : IsScalarTower R A B
f : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = IsScalarTower.toAlgHom R A (B ⧸ I)
⊢ Derivation R A ↥I

Next tactic:
refine'
    { diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) _ with
      map_one_eq_zero' := _
      leibniz' := _ }
/-- Given a tower of algebras `R → A → B`, and a square-zero `I : Ideal B`, each lift `A →ₐ[R] B`
of the canonical map `A →ₐ[R] B ⧸ I` corresponds to an `R`-derivation from `A` to `I`. -/
def derivationToSquareZeroOfLift (f : A →ₐ[R] B)
    (e : (Ideal.Quotient.mkₐ R I).comp f = IsScalarTower.toAlgHom R A (B ⧸ I)) :
    Derivation R A I := by
  refine'
    { diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) _ with
      map_one_eq_zero' := _
      leibniz' := _ }
  · 

Proof state:
case refine'_1
R : Type u
A : Type v
B : Type w
inst✝⁶ : CommSemiring R
inst✝⁵ : CommSemiring A
inst✝⁴ : CommRing B
inst✝³ : Algebra R A
inst✝² : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
inst✝¹ : Algebra A B
inst✝ : IsScalarTower R A B
f : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = IsScalarTower.toAlgHom R A (B ⧸ I)
⊢ AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B)

Next tactic:
rw [e]
/-- Given a tower of algebras `R → A → B`, and a square-zero `I : Ideal B`, each lift `A →ₐ[R] B`
of the canonical map `A →ₐ[R] B ⧸ I` corresponds to an `R`-derivation from `A` to `I`. -/
def derivationToSquareZeroOfLift (f : A →ₐ[R] B)
    (e : (Ideal.Quotient.mkₐ R I).comp f = IsScalarTower.toAlgHom R A (B ⧸ I)) :
    Derivation R A I := by
  refine'
    { diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) _ with
      map_one_eq_zero' := _
      leibniz' := _ }
  · rw [e]; 

Proof state:
case refine'_1
R : Type u
A : Type v
B : Type w
inst✝⁶ : CommSemiring R
inst✝⁵ : CommSemiring A
inst✝⁴ : CommRing B
inst✝³ : Algebra R A
inst✝² : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
inst✝¹ : Algebra A B
inst✝ : IsScalarTower R A B
f : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = IsScalarTower.toAlgHom R A (B ⧸ I)
⊢ IsScalarTower.toAlgHom R A (B ⧸ I) = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B)

Next tactic:
ext
/-- Given a tower of algebras `R → A → B`, and a square-zero `I : Ideal B`, each lift `A →ₐ[R] B`
of the canonical map `A →ₐ[R] B ⧸ I` corresponds to an `R`-derivation from `A` to `I`. -/
def derivationToSquareZeroOfLift (f : A →ₐ[R] B)
    (e : (Ideal.Quotient.mkₐ R I).comp f = IsScalarTower.toAlgHom R A (B ⧸ I)) :
    Derivation R A I := by
  refine'
    { diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) _ with
      map_one_eq_zero' := _
      leibniz' := _ }
  · rw [e]; ext; 

Proof state:
case refine'_1.H
R : Type u
A : Type v
B : Type w
inst✝⁶ : CommSemiring R
inst✝⁵ : CommSemiring A
inst✝⁴ : CommRing B
inst✝³ : Algebra R A
inst✝² : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
inst✝¹ : Algebra A B
inst✝ : IsScalarTower R A B
f : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = IsScalarTower.toAlgHom R A (B ⧸ I)
x✝ : A
⊢ (IsScalarTower.toAlgHom R A (B ⧸ I)) x✝ = (AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B)) x✝

Next tactic:
rfl
/-- Given a tower of algebras `R → A → B`, and a square-zero `I : Ideal B`, each lift `A →ₐ[R] B`
of the canonical map `A →ₐ[R] B ⧸ I` corresponds to an `R`-derivation from `A` to `I`. -/
def derivationToSquareZeroOfLift (f : A →ₐ[R] B)
    (e : (Ideal.Quotient.mkₐ R I).comp f = IsScalarTower.toAlgHom R A (B ⧸ I)) :
    Derivation R A I := by
  refine'
    { diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) _ with
      map_one_eq_zero' := _
      leibniz' := _ }
  · rw [e]; ext; rfl
  · 

Proof state:
case refine'_2
R : Type u
A : Type v
B : Type w
inst✝⁶ : CommSemiring R
inst✝⁵ : CommSemiring A
inst✝⁴ : CommRing B
inst✝³ : Algebra R A
inst✝² : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
inst✝¹ : Algebra A B
inst✝ : IsScalarTower R A B
f : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = IsScalarTower.toAlgHom R A (B ⧸ I)
src✝ : A →ₗ[R] ↥I :=
  diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
    (_ : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))
⊢ { toAddHom := src✝.toAddHom,
        map_smul' :=
          (_ :
            ∀ (r : R) (x : A), AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }
      1 =
    0

Next tactic:
ext
/-- Given a tower of algebras `R → A → B`, and a square-zero `I : Ideal B`, each lift `A →ₐ[R] B`
of the canonical map `A →ₐ[R] B ⧸ I` corresponds to an `R`-derivation from `A` to `I`. -/
def derivationToSquareZeroOfLift (f : A →ₐ[R] B)
    (e : (Ideal.Quotient.mkₐ R I).comp f = IsScalarTower.toAlgHom R A (B ⧸ I)) :
    Derivation R A I := by
  refine'
    { diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) _ with
      map_one_eq_zero' := _
      leibniz' := _ }
  · rw [e]; ext; rfl
  · ext; 

Proof state:
case refine'_2.a
R : Type u
A : Type v
B : Type w
inst✝⁶ : CommSemiring R
inst✝⁵ : CommSemiring A
inst✝⁴ : CommRing B
inst✝³ : Algebra R A
inst✝² : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
inst✝¹ : Algebra A B
inst✝ : IsScalarTower R A B
f : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = IsScalarTower.toAlgHom R A (B ⧸ I)
src✝ : A →ₗ[R] ↥I :=
  diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
    (_ : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))
⊢ ↑({ toAddHom := src✝.toAddHom,
          map_smul' :=
            (_ :
              ∀ (r : R) (x : A), AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }
        1) =
    ↑0

Next tactic:
change f 1 - algebraMap A B 1 = 0
/-- Given a tower of algebras `R → A → B`, and a square-zero `I : Ideal B`, each lift `A →ₐ[R] B`
of the canonical map `A →ₐ[R] B ⧸ I` corresponds to an `R`-derivation from `A` to `I`. -/
def derivationToSquareZeroOfLift (f : A →ₐ[R] B)
    (e : (Ideal.Quotient.mkₐ R I).comp f = IsScalarTower.toAlgHom R A (B ⧸ I)) :
    Derivation R A I := by
  refine'
    { diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) _ with
      map_one_eq_zero' := _
      leibniz' := _ }
  · rw [e]; ext; rfl
  · ext; change f 1 - algebraMap A B 1 = 0; 

Proof state:
case refine'_2.a
R : Type u
A : Type v
B : Type w
inst✝⁶ : CommSemiring R
inst✝⁵ : CommSemiring A
inst✝⁴ : CommRing B
inst✝³ : Algebra R A
inst✝² : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
inst✝¹ : Algebra A B
inst✝ : IsScalarTower R A B
f : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = IsScalarTower.toAlgHom R A (B ⧸ I)
src✝ : A →ₗ[R] ↥I :=
  diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
    (_ : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))
⊢ f 1 - (algebraMap A B) 1 = 0

Next tactic:
rw [map_one, map_one, sub_self]