l3lab/ntp-mathlib huggingface dataset:
/-- If `g` is surjective, then the kernel of `(id A) ⊗ g` is generated by the kernel of `g` -/
lemma Algebra.TensorProduct.lTensor_ker (hg : Function.Surjective g) :
    RingHom.ker (map (AlgHom.id R A) g) =
      (RingHom.ker g).map (Algebra.TensorProduct.includeRight : C →ₐ[R] A ⊗[R] C) := by
  

Proof state:
R✝ : Type u_1
inst✝¹³ : CommSemiring R✝
A✝ : Type u_2
B✝ : Type u_3
inst✝¹² : Semiring A✝
inst✝¹¹ : Semiring B✝
inst✝¹⁰ : Algebra R✝ A✝
inst✝⁹ : Algebra R✝ B✝
R : Type u_4
inst✝⁸ : CommRing R
A : Type u_5
B : Type u_6
C : Type u_7
D : Type u_8
inst✝⁷ : Ring A
inst✝⁶ : Ring B
inst✝⁵ : Ring C
inst✝⁴ : Ring D
inst✝³ : Algebra R A
inst✝² : Algebra R B
inst✝¹ : Algebra R C
inst✝ : Algebra R D
f : A →ₐ[R] B
g : C →ₐ[R] D
hg : Function.Surjective ⇑g
⊢ RingHom.ker (map (AlgHom.id R A) g) = Ideal.map includeRight (RingHom.ker g)

Next tactic:
rw [← Submodule.restrictScalars_inj R]
/-- If `g` is surjective, then the kernel of `(id A) ⊗ g` is generated by the kernel of `g` -/
lemma Algebra.TensorProduct.lTensor_ker (hg : Function.Surjective g) :
    RingHom.ker (map (AlgHom.id R A) g) =
      (RingHom.ker g).map (Algebra.TensorProduct.includeRight : C →ₐ[R] A ⊗[R] C) := by
  rw [← Submodule.restrictScalars_inj R]
  

Proof state:
R✝ : Type u_1
inst✝¹³ : CommSemiring R✝
A✝ : Type u_2
B✝ : Type u_3
inst✝¹² : Semiring A✝
inst✝¹¹ : Semiring B✝
inst✝¹⁰ : Algebra R✝ A✝
inst✝⁹ : Algebra R✝ B✝
R : Type u_4
inst✝⁸ : CommRing R
A : Type u_5
B : Type u_6
C : Type u_7
D : Type u_8
inst✝⁷ : Ring A
inst✝⁶ : Ring B
inst✝⁵ : Ring C
inst✝⁴ : Ring D
inst✝³ : Algebra R A
inst✝² : Algebra R B
inst✝¹ : Algebra R C
inst✝ : Algebra R D
f : A →ₐ[R] B
g : C →ₐ[R] D
hg : Function.Surjective ⇑g
⊢ Submodule.restrictScalars R (RingHom.ker (map (AlgHom.id R A) g)) =
    Submodule.restrictScalars R (Ideal.map includeRight (RingHom.ker g))

Next tactic:
have : (RingHom.ker (map (AlgHom.id R A) g)).restrictScalars R =
    LinearMap.ker (LinearMap.lTensor A (AlgHom.toLinearMap g)) := rfl
/-- If `g` is surjective, then the kernel of `(id A) ⊗ g` is generated by the kernel of `g` -/
lemma Algebra.TensorProduct.lTensor_ker (hg : Function.Surjective g) :
    RingHom.ker (map (AlgHom.id R A) g) =
      (RingHom.ker g).map (Algebra.TensorProduct.includeRight : C →ₐ[R] A ⊗[R] C) := by
  rw [← Submodule.restrictScalars_inj R]
  have : (RingHom.ker (map (AlgHom.id R A) g)).restrictScalars R =
    LinearMap.ker (LinearMap.lTensor A (AlgHom.toLinearMap g)) := rfl
  

Proof state:
R✝ : Type u_1
inst✝¹³ : CommSemiring R✝
A✝ : Type u_2
B✝ : Type u_3
inst✝¹² : Semiring A✝
inst✝¹¹ : Semiring B✝
inst✝¹⁰ : Algebra R✝ A✝
inst✝⁹ : Algebra R✝ B✝
R : Type u_4
inst✝⁸ : CommRing R
A : Type u_5
B : Type u_6
C : Type u_7
D : Type u_8
inst✝⁷ : Ring A
inst✝⁶ : Ring B
inst✝⁵ : Ring C
inst✝⁴ : Ring D
inst✝³ : Algebra R A
inst✝² : Algebra R B
inst✝¹ : Algebra R C
inst✝ : Algebra R D
f : A →ₐ[R] B
g : C →ₐ[R] D
hg : Function.Surjective ⇑g
this :
  Submodule.restrictScalars R (RingHom.ker (map (AlgHom.id R A) g)) =
    LinearMap.ker (LinearMap.lTensor A (AlgHom.toLinearMap g))
⊢ Submodule.restrictScalars R (RingHom.ker (map (AlgHom.id R A) g)) =
    Submodule.restrictScalars R (Ideal.map includeRight (RingHom.ker g))

Next tactic:
rw [this, Ideal.map_includeRight_eq]
/-- If `g` is surjective, then the kernel of `(id A) ⊗ g` is generated by the kernel of `g` -/
lemma Algebra.TensorProduct.lTensor_ker (hg : Function.Surjective g) :
    RingHom.ker (map (AlgHom.id R A) g) =
      (RingHom.ker g).map (Algebra.TensorProduct.includeRight : C →ₐ[R] A ⊗[R] C) := by
  rw [← Submodule.restrictScalars_inj R]
  have : (RingHom.ker (map (AlgHom.id R A) g)).restrictScalars R =
    LinearMap.ker (LinearMap.lTensor A (AlgHom.toLinearMap g)) := rfl
  rw [this, Ideal.map_includeRight_eq]
  

Proof state:
R✝ : Type u_1
inst✝¹³ : CommSemiring R✝
A✝ : Type u_2
B✝ : Type u_3
inst✝¹² : Semiring A✝
inst✝¹¹ : Semiring B✝
inst✝¹⁰ : Algebra R✝ A✝
inst✝⁹ : Algebra R✝ B✝
R : Type u_4
inst✝⁸ : CommRing R
A : Type u_5
B : Type u_6
C : Type u_7
D : Type u_8
inst✝⁷ : Ring A
inst✝⁶ : Ring B
inst✝⁵ : Ring C
inst✝⁴ : Ring D
inst✝³ : Algebra R A
inst✝² : Algebra R B
inst✝¹ : Algebra R C
inst✝ : Algebra R D
f : A →ₐ[R] B
g : C →ₐ[R] D
hg : Function.Surjective ⇑g
this :
  Submodule.restrictScalars R (RingHom.ker (map (AlgHom.id R A) g)) =
    LinearMap.ker (LinearMap.lTensor A (AlgHom.toLinearMap g))
⊢ LinearMap.ker (LinearMap.lTensor A (AlgHom.toLinearMap g)) =
    LinearMap.range (LinearMap.lTensor A (Submodule.subtype (Submodule.restrictScalars R (RingHom.ker g))))

Next tactic:
rw [(lTensor_exact A g.toLinearMap.exact_subtype_ker_map hg).linearMap_ker_eq]
/-- If `g` is surjective, then the kernel of `(id A) ⊗ g` is generated by the kernel of `g` -/
lemma Algebra.TensorProduct.lTensor_ker (hg : Function.Surjective g) :
    RingHom.ker (map (AlgHom.id R A) g) =
      (RingHom.ker g).map (Algebra.TensorProduct.includeRight : C →ₐ[R] A ⊗[R] C) := by
  rw [← Submodule.restrictScalars_inj R]
  have : (RingHom.ker (map (AlgHom.id R A) g)).restrictScalars R =
    LinearMap.ker (LinearMap.lTensor A (AlgHom.toLinearMap g)) := rfl
  rw [this, Ideal.map_includeRight_eq]
  rw [(lTensor_exact A g.toLinearMap.exact_subtype_ker_map hg).linearMap_ker_eq]
  

Proof state:
R✝ : Type u_1
inst✝¹³ : CommSemiring R✝
A✝ : Type u_2
B✝ : Type u_3
inst✝¹² : Semiring A✝
inst✝¹¹ : Semiring B✝
inst✝¹⁰ : Algebra R✝ A✝
inst✝⁹ : Algebra R✝ B✝
R : Type u_4
inst✝⁸ : CommRing R
A : Type u_5
B : Type u_6
C : Type u_7
D : Type u_8
inst✝⁷ : Ring A
inst✝⁶ : Ring B
inst✝⁵ : Ring C
inst✝⁴ : Ring D
inst✝³ : Algebra R A
inst✝² : Algebra R B
inst✝¹ : Algebra R C
inst✝ : Algebra R D
f : A →ₐ[R] B
g : C →ₐ[R] D
hg : Function.Surjective ⇑g
this :
  Submodule.restrictScalars R (RingHom.ker (map (AlgHom.id R A) g)) =
    LinearMap.ker (LinearMap.lTensor A (AlgHom.toLinearMap g))
⊢ LinearMap.range (LinearMap.lTensor A (Submodule.subtype (LinearMap.ker (AlgHom.toLinearMap g)))) =
    LinearMap.range (LinearMap.lTensor A (Submodule.subtype (Submodule.restrictScalars R (RingHom.ker g))))

Next tactic:
rfl
/-- If `f` is surjective, then the kernel of `f ⊗ (id B)` is generated by the kernel of `f` -/
lemma Algebra.TensorProduct.rTensor_ker (hf : Function.Surjective f) :
    RingHom.ker (map f (AlgHom.id R C)) =
      (RingHom.ker f).map (Algebra.TensorProduct.includeLeft : A →ₐ[R] A ⊗[R] C) := by
  

Proof state:
R✝ : Type u_1
inst✝¹³ : CommSemiring R✝
A✝ : Type u_2
B✝ : Type u_3
inst✝¹² : Semiring A✝
inst✝¹¹ : Semiring B✝
inst✝¹⁰ : Algebra R✝ A✝
inst✝⁹ : Algebra R✝ B✝
R : Type u_4
inst✝⁸ : CommRing R
A : Type u_5
B : Type u_6
C : Type u_7
D : Type u_8
inst✝⁷ : Ring A
inst✝⁶ : Ring B
inst✝⁵ : Ring C
inst✝⁴ : Ring D
inst✝³ : Algebra R A
inst✝² : Algebra R B
inst✝¹ : Algebra R C
inst✝ : Algebra R D
f : A →ₐ[R] B
g : C →ₐ[R] D
hf : Function.Surjective ⇑f
⊢ RingHom.ker (map f (AlgHom.id R C)) = Ideal.map includeLeft (RingHom.ker f)

Next tactic:
rw [← Submodule.restrictScalars_inj R]
/-- If `f` is surjective, then the kernel of `f ⊗ (id B)` is generated by the kernel of `f` -/
lemma Algebra.TensorProduct.rTensor_ker (hf : Function.Surjective f) :
    RingHom.ker (map f (AlgHom.id R C)) =
      (RingHom.ker f).map (Algebra.TensorProduct.includeLeft : A →ₐ[R] A ⊗[R] C) := by
  rw [← Submodule.restrictScalars_inj R]
  

Proof state:
R✝ : Type u_1
inst✝¹³ : CommSemiring R✝
A✝ : Type u_2
B✝ : Type u_3
inst✝¹² : Semiring A✝
inst✝¹¹ : Semiring B✝
inst✝¹⁰ : Algebra R✝ A✝
inst✝⁹ : Algebra R✝ B✝
R : Type u_4
inst✝⁸ : CommRing R
A : Type u_5
B : Type u_6
C : Type u_7
D : Type u_8
inst✝⁷ : Ring A
inst✝⁶ : Ring B
inst✝⁵ : Ring C
inst✝⁴ : Ring D
inst✝³ : Algebra R A
inst✝² : Algebra R B
inst✝¹ : Algebra R C
inst✝ : Algebra R D
f : A →ₐ[R] B
g : C →ₐ[R] D
hf : Function.Surjective ⇑f
⊢ Submodule.restrictScalars R (RingHom.ker (map f (AlgHom.id R C))) =
    Submodule.restrictScalars R (Ideal.map includeLeft (RingHom.ker f))

Next tactic:
have : (RingHom.ker (map f (AlgHom.id R C))).restrictScalars R =
    LinearMap.ker (LinearMap.rTensor C (AlgHom.toLinearMap f)) := rfl
/-- If `f` is surjective, then the kernel of `f ⊗ (id B)` is generated by the kernel of `f` -/
lemma Algebra.TensorProduct.rTensor_ker (hf : Function.Surjective f) :
    RingHom.ker (map f (AlgHom.id R C)) =
      (RingHom.ker f).map (Algebra.TensorProduct.includeLeft : A →ₐ[R] A ⊗[R] C) := by
  rw [← Submodule.restrictScalars_inj R]
  have : (RingHom.ker (map f (AlgHom.id R C))).restrictScalars R =
    LinearMap.ker (LinearMap.rTensor C (AlgHom.toLinearMap f)) := rfl
  

Proof state:
R✝ : Type u_1
inst✝¹³ : CommSemiring R✝
A✝ : Type u_2
B✝ : Type u_3
inst✝¹² : Semiring A✝
inst✝¹¹ : Semiring B✝
inst✝¹⁰ : Algebra R✝ A✝
inst✝⁹ : Algebra R✝ B✝
R : Type u_4
inst✝⁸ : CommRing R
A : Type u_5
B : Type u_6
C : Type u_7
D : Type u_8
inst✝⁷ : Ring A
inst✝⁶ : Ring B
inst✝⁵ : Ring C
inst✝⁴ : Ring D
inst✝³ : Algebra R A
inst✝² : Algebra R B
inst✝¹ : Algebra R C
inst✝ : Algebra R D
f : A →ₐ[R] B
g : C →ₐ[R] D
hf : Function.Surjective ⇑f
this :
  Submodule.restrictScalars R (RingHom.ker (map f (AlgHom.id R C))) =
    LinearMap.ker (LinearMap.rTensor C (AlgHom.toLinearMap f))
⊢ Submodule.restrictScalars R (RingHom.ker (map f (AlgHom.id R C))) =
    Submodule.restrictScalars R (Ideal.map includeLeft (RingHom.ker f))

Next tactic:
rw [this, Ideal.map_includeLeft_eq]
/-- If `f` is surjective, then the kernel of `f ⊗ (id B)` is generated by the kernel of `f` -/
lemma Algebra.TensorProduct.rTensor_ker (hf : Function.Surjective f) :
    RingHom.ker (map f (AlgHom.id R C)) =
      (RingHom.ker f).map (Algebra.TensorProduct.includeLeft : A →ₐ[R] A ⊗[R] C) := by
  rw [← Submodule.restrictScalars_inj R]
  have : (RingHom.ker (map f (AlgHom.id R C))).restrictScalars R =
    LinearMap.ker (LinearMap.rTensor C (AlgHom.toLinearMap f)) := rfl
  rw [this, Ideal.map_includeLeft_eq]
  

Proof state:
R✝ : Type u_1
inst✝¹³ : CommSemiring R✝
A✝ : Type u_2
B✝ : Type u_3
inst✝¹² : Semiring A✝
inst✝¹¹ : Semiring B✝
inst✝¹⁰ : Algebra R✝ A✝
inst✝⁹ : Algebra R✝ B✝
R : Type u_4
inst✝⁸ : CommRing R
A : Type u_5
B : Type u_6
C : Type u_7
D : Type u_8
inst✝⁷ : Ring A
inst✝⁶ : Ring B
inst✝⁵ : Ring C
inst✝⁴ : Ring D
inst✝³ : Algebra R A
inst✝² : Algebra R B
inst✝¹ : Algebra R C
inst✝ : Algebra R D
f : A →ₐ[R] B
g : C →ₐ[R] D
hf : Function.Surjective ⇑f
this :
  Submodule.restrictScalars R (RingHom.ker (map f (AlgHom.id R C))) =
    LinearMap.ker (LinearMap.rTensor C (AlgHom.toLinearMap f))
⊢ LinearMap.ker (LinearMap.rTensor C (AlgHom.toLinearMap f)) =
    LinearMap.range (LinearMap.rTensor C (Submodule.subtype (Submodule.restrictScalars R (RingHom.ker f))))

Next tactic:
rw [(rTensor_exact C f.toLinearMap.exact_subtype_ker_map hf).linearMap_ker_eq]
/-- If `f` is surjective, then the kernel of `f ⊗ (id B)` is generated by the kernel of `f` -/
lemma Algebra.TensorProduct.rTensor_ker (hf : Function.Surjective f) :
    RingHom.ker (map f (AlgHom.id R C)) =
      (RingHom.ker f).map (Algebra.TensorProduct.includeLeft : A →ₐ[R] A ⊗[R] C) := by
  rw [← Submodule.restrictScalars_inj R]
  have : (RingHom.ker (map f (AlgHom.id R C))).restrictScalars R =
    LinearMap.ker (LinearMap.rTensor C (AlgHom.toLinearMap f)) := rfl
  rw [this, Ideal.map_includeLeft_eq]
  rw [(rTensor_exact C f.toLinearMap.exact_subtype_ker_map hf).linearMap_ker_eq]
  

Proof state:
R✝ : Type u_1
inst✝¹³ : CommSemiring R✝
A✝ : Type u_2
B✝ : Type u_3
inst✝¹² : Semiring A✝
inst✝¹¹ : Semiring B✝
inst✝¹⁰ : Algebra R✝ A✝
inst✝⁹ : Algebra R✝ B✝
R : Type u_4
inst✝⁸ : CommRing R
A : Type u_5
B : Type u_6
C : Type u_7
D : Type u_8
inst✝⁷ : Ring A
inst✝⁶ : Ring B
inst✝⁵ : Ring C
inst✝⁴ : Ring D
inst✝³ : Algebra R A
inst✝² : Algebra R B
inst✝¹ : Algebra R C
inst✝ : Algebra R D
f : A →ₐ[R] B
g : C →ₐ[R] D
hf : Function.Surjective ⇑f
this :
  Submodule.restrictScalars R (RingHom.ker (map f (AlgHom.id R C))) =
    LinearMap.ker (LinearMap.rTensor C (AlgHom.toLinearMap f))
⊢ LinearMap.range (LinearMap.rTensor C (Submodule.subtype (LinearMap.ker (AlgHom.toLinearMap f)))) =
    LinearMap.range (LinearMap.rTensor C (Submodule.subtype (Submodule.restrictScalars R (RingHom.ker f))))

Next tactic:
rfl
/-- If `f` and `g` are surjective morphisms of algebras, then
  the kernel of `Algebra.TensorProduct.map f g` is generated by the kernels of `f` and `g` -/
theorem Algebra.TensorProduct.map_ker (hf : Function.Surjective f) (hg : Function.Surjective g) :
    RingHom.ker (map f g) =
      (RingHom.ker f).map (Algebra.TensorProduct.includeLeft : A →ₐ[R] A ⊗[R] C) ⊔
        (RingHom.ker g).map (Algebra.TensorProduct.includeRight : C →ₐ[R] A ⊗[R] C) := by
  -- rewrite map f g as the composition of two maps
  

Proof state:
R✝ : Type u_1
inst✝¹³ : CommSemiring R✝
A✝ : Type u_2
B✝ : Type u_3
inst✝¹² : Semiring A✝
inst✝¹¹ : Semiring B✝
inst✝¹⁰ : Algebra R✝ A✝
inst✝⁹ : Algebra R✝ B✝
R : Type u_4
inst✝⁸ : CommRing R
A : Type u_5
B : Type u_6
C : Type u_7
D : Type u_8
inst✝⁷ : Ring A
inst✝⁶ : Ring B
inst✝⁵ : Ring C
inst✝⁴ : Ring D
inst✝³ : Algebra R A
inst✝² : Algebra R B
inst✝¹ : Algebra R C
inst✝ : Algebra R D
f : A →ₐ[R] B
g : C →ₐ[R] D
hf : Function.Surjective ⇑f
hg : Function.Surjective ⇑g
⊢ RingHom.ker (map f g) = Ideal.map includeLeft (RingHom.ker f) ⊔ Ideal.map includeRight (RingHom.ker g)

Next tactic:
have : map f g = (map f (AlgHom.id R D)).comp (map (AlgHom.id R A) g) := ext rfl rfl
/-- If `f` and `g` are surjective morphisms of algebras, then
  the kernel of `Algebra.TensorProduct.map f g` is generated by the kernels of `f` and `g` -/
theorem Algebra.TensorProduct.map_ker (hf : Function.Surjective f) (hg : Function.Surjective g) :
    RingHom.ker (map f g) =
      (RingHom.ker f).map (Algebra.TensorProduct.includeLeft : A →ₐ[R] A ⊗[R] C) ⊔
        (RingHom.ker g).map (Algebra.TensorProduct.includeRight : C →ₐ[R] A ⊗[R] C) := by
  -- rewrite map f g as the composition of two maps
  have : map f g = (map f (AlgHom.id R D)).comp (map (AlgHom.id R A) g) := ext rfl rfl
  

Proof state:
R✝ : Type u_1
inst✝¹³ : CommSemiring R✝
A✝ : Type u_2
B✝ : Type u_3
inst✝¹² : Semiring A✝
inst✝¹¹ : Semiring B✝
inst✝¹⁰ : Algebra R✝ A✝
inst✝⁹ : Algebra R✝ B✝
R : Type u_4
inst✝⁸ : CommRing R
A : Type u_5
B : Type u_6
C : Type u_7
D : Type u_8
inst✝⁷ : Ring A
inst✝⁶ : Ring B
inst✝⁵ : Ring C
inst✝⁴ : Ring D
inst✝³ : Algebra R A
inst✝² : Algebra R B
inst✝¹ : Algebra R C
inst✝ : Algebra R D
f : A →ₐ[R] B
g : C →ₐ[R] D
hf : Function.Surjective ⇑f
hg : Function.Surjective ⇑g
this : map f g = AlgHom.comp (map f (AlgHom.id R D)) (map (AlgHom.id R A) g)
⊢ RingHom.ker (map f g) = Ideal.map includeLeft (RingHom.ker f) ⊔ Ideal.map includeRight (RingHom.ker g)

Next tactic:
rw [this]
/-- If `f` and `g` are surjective morphisms of algebras, then
  the kernel of `Algebra.TensorProduct.map f g` is generated by the kernels of `f` and `g` -/
theorem Algebra.TensorProduct.map_ker (hf : Function.Surjective f) (hg : Function.Surjective g) :
    RingHom.ker (map f g) =
      (RingHom.ker f).map (Algebra.TensorProduct.includeLeft : A →ₐ[R] A ⊗[R] C) ⊔
        (RingHom.ker g).map (Algebra.TensorProduct.includeRight : C →ₐ[R] A ⊗[R] C) := by
  -- rewrite map f g as the composition of two maps
  have : map f g = (map f (AlgHom.id R D)).comp (map (AlgHom.id R A) g) := ext rfl rfl
  rw [this]
  -- this needs some rewriting to RingHom
  

Proof state:
R✝ : Type u_1
inst✝¹³ : CommSemiring R✝
A✝ : Type u_2
B✝ : Type u_3
inst✝¹² : Semiring A✝
inst✝¹¹ : Semiring B✝
inst✝¹⁰ : Algebra R✝ A✝
inst✝⁹ : Algebra R✝ B✝
R : Type u_4
inst✝⁸ : CommRing R
A : Type u_5
B : Type u_6
C : Type u_7
D : Type u_8
inst✝⁷ : Ring A
inst✝⁶ : Ring B
inst✝⁵ : Ring C
inst✝⁴ : Ring D
inst✝³ : Algebra R A
inst✝² : Algebra R B
inst✝¹ : Algebra R C
inst✝ : Algebra R D
f : A →ₐ[R] B
g : C →ₐ[R] D
hf : Function.Surjective ⇑f
hg : Function.Surjective ⇑g
this : map f g = AlgHom.comp (map f (AlgHom.id R D)) (map (AlgHom.id R A) g)
⊢ RingHom.ker (AlgHom.comp (map f (AlgHom.id R D)) (map (AlgHom.id R A) g)) =
    Ideal.map includeLeft (RingHom.ker f) ⊔ Ideal.map includeRight (RingHom.ker g)

Next tactic:
simp only [AlgHom.coe_ker, AlgHom.comp_toRingHom]
/-- If `f` and `g` are surjective morphisms of algebras, then
  the kernel of `Algebra.TensorProduct.map f g` is generated by the kernels of `f` and `g` -/
theorem Algebra.TensorProduct.map_ker (hf : Function.Surjective f) (hg : Function.Surjective g) :
    RingHom.ker (map f g) =
      (RingHom.ker f).map (Algebra.TensorProduct.includeLeft : A →ₐ[R] A ⊗[R] C) ⊔
        (RingHom.ker g).map (Algebra.TensorProduct.includeRight : C →ₐ[R] A ⊗[R] C) := by
  -- rewrite map f g as the composition of two maps
  have : map f g = (map f (AlgHom.id R D)).comp (map (AlgHom.id R A) g) := ext rfl rfl
  rw [this]
  -- this needs some rewriting to RingHom
  simp only [AlgHom.coe_ker, AlgHom.comp_toRingHom]
  

Proof state:
R✝ : Type u_1
inst✝¹³ : CommSemiring R✝
A✝ : Type u_2
B✝ : Type u_3
inst✝¹² : Semiring A✝
inst✝¹¹ : Semiring B✝
inst✝¹⁰ : Algebra R✝ A✝
inst✝⁹ : Algebra R✝ B✝
R : Type u_4
inst✝⁸ : CommRing R
A : Type u_5
B : Type u_6
C : Type u_7
D : Type u_8
inst✝⁷ : Ring A
inst✝⁶ : Ring B
inst✝⁵ : Ring C
inst✝⁴ : Ring D
inst✝³ : Algebra R A
inst✝² : Algebra R B
inst✝¹ : Algebra R C
inst✝ : Algebra R D
f : A →ₐ[R] B
g : C →ₐ[R] D
hf : Function.Surjective ⇑f
hg : Function.Surjective ⇑g
this : map f g = AlgHom.comp (map f (AlgHom.id R D)) (map (AlgHom.id R A) g)
⊢ RingHom.ker (RingHom.comp ↑(map f (AlgHom.id R D)) ↑(map (AlgHom.id R A) g)) =
    Ideal.map includeLeft (RingHom.ker ↑f) ⊔ Ideal.map includeRight (RingHom.ker ↑g)

Next tactic:
rw [← RingHom.comap_ker]
/-- If `f` and `g` are surjective morphisms of algebras, then
  the kernel of `Algebra.TensorProduct.map f g` is generated by the kernels of `f` and `g` -/
theorem Algebra.TensorProduct.map_ker (hf : Function.Surjective f) (hg : Function.Surjective g) :
    RingHom.ker (map f g) =
      (RingHom.ker f).map (Algebra.TensorProduct.includeLeft : A →ₐ[R] A ⊗[R] C) ⊔
        (RingHom.ker g).map (Algebra.TensorProduct.includeRight : C →ₐ[R] A ⊗[R] C) := by
  -- rewrite map f g as the composition of two maps
  have : map f g = (map f (AlgHom.id R D)).comp (map (AlgHom.id R A) g) := ext rfl rfl
  rw [this]
  -- this needs some rewriting to RingHom
  simp only [AlgHom.coe_ker, AlgHom.comp_toRingHom]
  rw [← RingHom.comap_ker]
  

Proof state:
R✝ : Type u_1
inst✝¹³ : CommSemiring R✝
A✝ : Type u_2
B✝ : Type u_3
inst✝¹² : Semiring A✝
inst✝¹¹ : Semiring B✝
inst✝¹⁰ : Algebra R✝ A✝
inst✝⁹ : Algebra R✝ B✝
R : Type u_4
inst✝⁸ : CommRing R
A : Type u_5
B : Type u_6
C : Type u_7
D : Type u_8
inst✝⁷ : Ring A
inst✝⁶ : Ring B
inst✝⁵ : Ring C
inst✝⁴ : Ring D
inst✝³ : Algebra R A
inst✝² : Algebra R B
inst✝¹ : Algebra R C
inst✝ : Algebra R D
f : A →ₐ[R] B
g : C →ₐ[R] D
hf : Function.Surjective ⇑f
hg : Function.Surjective ⇑g
this : map f g = AlgHom.comp (map f (AlgHom.id R D)) (map (AlgHom.id R A) g)
⊢ Ideal.comap (↑(map (AlgHom.id R A) g)) (RingHom.ker ↑(map f (AlgHom.id R D))) =
    Ideal.map includeLeft (RingHom.ker ↑f) ⊔ Ideal.map includeRight (RingHom.ker ↑g)

Next tactic:
simp only [← AlgHom.coe_ker]
/-- If `f` and `g` are surjective morphisms of algebras, then
  the kernel of `Algebra.TensorProduct.map f g` is generated by the kernels of `f` and `g` -/
theorem Algebra.TensorProduct.map_ker (hf : Function.Surjective f) (hg : Function.Surjective g) :
    RingHom.ker (map f g) =
      (RingHom.ker f).map (Algebra.TensorProduct.includeLeft : A →ₐ[R] A ⊗[R] C) ⊔
        (RingHom.ker g).map (Algebra.TensorProduct.includeRight : C →ₐ[R] A ⊗[R] C) := by
  -- rewrite map f g as the composition of two maps
  have : map f g = (map f (AlgHom.id R D)).comp (map (AlgHom.id R A) g) := ext rfl rfl
  rw [this]
  -- this needs some rewriting to RingHom
  simp only [AlgHom.coe_ker, AlgHom.comp_toRingHom]
  rw [← RingHom.comap_ker]
  simp only [← AlgHom.coe_ker]
  -- apply one step of exactness
  

Proof state:
R✝ : Type u_1
inst✝¹³ : CommSemiring R✝
A✝ : Type u_2
B✝ : Type u_3
inst✝¹² : Semiring A✝
inst✝¹¹ : Semiring B✝
inst✝¹⁰ : Algebra R✝ A✝
inst✝⁹ : Algebra R✝ B✝
R : Type u_4
inst✝⁸ : CommRing R
A : Type u_5
B : Type u_6
C : Type u_7
D : Type u_8
inst✝⁷ : Ring A
inst✝⁶ : Ring B
inst✝⁵ : Ring C
inst✝⁴ : Ring D
inst✝³ : Algebra R A
inst✝² : Algebra R B
inst✝¹ : Algebra R C
inst✝ : Algebra R D
f : A →ₐ[R] B
g : C →ₐ[R] D
hf : Function.Surjective ⇑f
hg : Function.Surjective ⇑g
this : map f g = AlgHom.comp (map f (AlgHom.id R D)) (map (AlgHom.id R A) g)
⊢ Ideal.comap (↑(map (AlgHom.id R A) g)) (RingHom.ker (map f (AlgHom.id R D))) =
    Ideal.map includeLeft (RingHom.ker f) ⊔ Ideal.map includeRight (RingHom.ker g)

Next tactic:
rw [← Algebra.TensorProduct.lTensor_ker _ hg, RingHom.ker_eq_comap_bot (map (AlgHom.id R A) g)]
/-- If `f` and `g` are surjective morphisms of algebras, then
  the kernel of `Algebra.TensorProduct.map f g` is generated by the kernels of `f` and `g` -/
theorem Algebra.TensorProduct.map_ker (hf : Function.Surjective f) (hg : Function.Surjective g) :
    RingHom.ker (map f g) =
      (RingHom.ker f).map (Algebra.TensorProduct.includeLeft : A →ₐ[R] A ⊗[R] C) ⊔
        (RingHom.ker g).map (Algebra.TensorProduct.includeRight : C →ₐ[R] A ⊗[R] C) := by
  -- rewrite map f g as the composition of two maps
  have : map f g = (map f (AlgHom.id R D)).comp (map (AlgHom.id R A) g) := ext rfl rfl
  rw [this]
  -- this needs some rewriting to RingHom
  simp only [AlgHom.coe_ker, AlgHom.comp_toRingHom]
  rw [← RingHom.comap_ker]
  simp only [← AlgHom.coe_ker]
  -- apply one step of exactness
  rw [← Algebra.TensorProduct.lTensor_ker _ hg, RingHom.ker_eq_comap_bot (map (AlgHom.id R A) g)]
  

Proof state:
R✝ : Type u_1
inst✝¹³ : CommSemiring R✝
A✝ : Type u_2
B✝ : Type u_3
inst✝¹² : Semiring A✝
inst✝¹¹ : Semiring B✝
inst✝¹⁰ : Algebra R✝ A✝
inst✝⁹ : Algebra R✝ B✝
R : Type u_4
inst✝⁸ : CommRing R
A : Type u_5
B : Type u_6
C : Type u_7
D : Type u_8
inst✝⁷ : Ring A
inst✝⁶ : Ring B
inst✝⁵ : Ring C
inst✝⁴ : Ring D
inst✝³ : Algebra R A
inst✝² : Algebra R B
inst✝¹ : Algebra R C
inst✝ : Algebra R D
f : A →ₐ[R] B
g : C →ₐ[R] D
hf : Function.Surjective ⇑f
hg : Function.Surjective ⇑g
this : map f g = AlgHom.comp (map f (AlgHom.id R D)) (map (AlgHom.id R A) g)
⊢ Ideal.comap (↑(map (AlgHom.id R A) g)) (RingHom.ker (map f (AlgHom.id R D))) =
    Ideal.map includeLeft (RingHom.ker f) ⊔ Ideal.comap (map (AlgHom.id R A) g) ⊥

Next tactic:
rw [← Ideal.comap_map_of_surjective _ (lTensor.surjective A hg)]
/-- If `f` and `g` are surjective morphisms of algebras, then
  the kernel of `Algebra.TensorProduct.map f g` is generated by the kernels of `f` and `g` -/
theorem Algebra.TensorProduct.map_ker (hf : Function.Surjective f) (hg : Function.Surjective g) :
    RingHom.ker (map f g) =
      (RingHom.ker f).map (Algebra.TensorProduct.includeLeft : A →ₐ[R] A ⊗[R] C) ⊔
        (RingHom.ker g).map (Algebra.TensorProduct.includeRight : C →ₐ[R] A ⊗[R] C) := by
  -- rewrite map f g as the composition of two maps
  have : map f g = (map f (AlgHom.id R D)).comp (map (AlgHom.id R A) g) := ext rfl rfl
  rw [this]
  -- this needs some rewriting to RingHom
  simp only [AlgHom.coe_ker, AlgHom.comp_toRingHom]
  rw [← RingHom.comap_ker]
  simp only [← AlgHom.coe_ker]
  -- apply one step of exactness
  rw [← Algebra.TensorProduct.lTensor_ker _ hg, RingHom.ker_eq_comap_bot (map (AlgHom.id R A) g)]
  rw [← Ideal.comap_map_of_surjective _ (lTensor.surjective A hg)]
  -- apply the other step of exactness
  

Proof state:
R✝ : Type u_1
inst✝¹³ : CommSemiring R✝
A✝ : Type u_2
B✝ : Type u_3
inst✝¹² : Semiring A✝
inst✝¹¹ : Semiring B✝
inst✝¹⁰ : Algebra R✝ A✝
inst✝⁹ : Algebra R✝ B✝
R : Type u_4
inst✝⁸ : CommRing R
A : Type u_5
B : Type u_6
C : Type u_7
D : Type u_8
inst✝⁷ : Ring A
inst✝⁶ : Ring B
inst✝⁵ : Ring C
inst✝⁴ : Ring D
inst✝³ : Algebra R A
inst✝² : Algebra R B
inst✝¹ : Algebra R C
inst✝ : Algebra R D
f : A →ₐ[R] B
g : C →ₐ[R] D
hf : Function.Surjective ⇑f
hg : Function.Surjective ⇑g
this : map f g = AlgHom.comp (map f (AlgHom.id R D)) (map (AlgHom.id R A) g)
⊢ Ideal.comap (↑(map (AlgHom.id R A) g)) (RingHom.ker (map f (AlgHom.id R D))) =
    Ideal.comap (map (AlgHom.id R A) g) (Ideal.map (map (AlgHom.id R A) g) (Ideal.map includeLeft (RingHom.ker f)))

Next tactic:
rw [Algebra.TensorProduct.rTensor_ker _ hf]