File: Mathlib/LinearAlgebra/TensorProduct/RightExactness.lean

full_name: le_comap_range_lTensor
code: lemma le_comap_range_lTensor (q : Q) :
    LinearMap.range g ≤ (LinearMap.range (lTensor Q g)).comap (TensorProduct.mk R Q P q) 
goal: LinearMap.range g ≤ Submodule.comap ((TensorProduct.mk R Q P) q) (LinearMap.range (LinearMap.lTensor Q g))

full_name: le_comap_range_rTensor
code: lemma le_comap_range_rTensor (q : Q) :
    LinearMap.range g ≤ (LinearMap.range (rTensor Q g)).comap
      ((TensorProduct.mk R P Q).flip q) 
goal: LinearMap.range g ≤ Submodule.comap ((TensorProduct.mk R P Q).flip q) (LinearMap.range (LinearMap.rTensor Q g))

full_name: LinearMap.lTensor_surjective
code: /-- If `g` is surjective, then `lTensor Q g` is surjective -/
theorem LinearMap.lTensor_surjective (hg : Function.Surjective g) :
    Function.Surjective (lTensor Q g) 
goal: Function.Surjective ⇑(LinearMap.lTensor Q g)

full_name: LinearMap.lTensor_range
code: theorem LinearMap.lTensor_range :
    range (lTensor Q g) =
      range (lTensor Q (Submodule.subtype (range g))) 
goal: LinearMap.range (LinearMap.lTensor Q g) = LinearMap.range (LinearMap.lTensor Q (LinearMap.range g).subtype)

full_name: LinearMap.rTensor_surjective
code: /-- If `g` is surjective, then `rTensor Q g` is surjective -/
theorem LinearMap.rTensor_surjective (hg : Function.Surjective g) :
    Function.Surjective (rTensor Q g) 
goal: Function.Surjective ⇑(LinearMap.rTensor Q g)

full_name: LinearMap.rTensor_range
code: theorem LinearMap.rTensor_range :
    range (rTensor Q g) =
      range (rTensor Q (Submodule.subtype (range g))) 
goal: LinearMap.range (LinearMap.rTensor Q g) = LinearMap.range (LinearMap.rTensor Q (LinearMap.range g).subtype)

full_name: lTensor.toFun
code: /-- The direct map in `lTensor.equiv` -/
noncomputable def lTensor.toFun :
    Q ⊗[R] N ⧸ LinearMap.range (lTensor Q f) →ₗ[R] Q ⊗[R] P 
goal: TensorProduct R Q N ⧸ LinearMap.range (LinearMap.lTensor Q f) →ₗ[R] TensorProduct R Q P

full_name: lTensor.inverse_of_rightInverse
code: /-- The inverse map in `lTensor.equiv_of_rightInverse` (computably, given a right inverse)-/
noncomputable def lTensor.inverse_of_rightInverse {h : P → N} (hgh : Function.RightInverse h g) :
    Q ⊗[R] P →ₗ[R] Q ⊗[R] N ⧸ LinearMap.range (lTensor Q f) 
goal: TensorProduct R Q P →ₗ[R] TensorProduct R Q N ⧸ LinearMap.range (LinearMap.lTensor Q f)

full_name: lTensor.inverse_of_rightInverse_apply
code: lemma lTensor.inverse_of_rightInverse_apply
    {h : P → N} (hgh : Function.RightInverse h g) (y : Q ⊗[R] N) :
    (lTensor.inverse_of_rightInverse Q hfg hgh) ((lTensor Q g) y) =
      Submodule.Quotient.mk (p := (LinearMap.range (lTensor Q f))) y 
goal: (lTensor.inverse_of_rightInverse Q hfg hgh) ((LinearMap.lTensor Q g) y) = Submodule.Quotient.mk y

full_name: lTensor.inverse_of_rightInverse_comp_lTensor
code: lemma lTensor.inverse_of_rightInverse_comp_lTensor
    {h : P → N} (hgh : Function.RightInverse h g) :
    (lTensor.inverse_of_rightInverse Q hfg hgh).comp (lTensor Q g) =
      Submodule.mkQ (p := LinearMap.range (lTensor Q f)) 
goal: lTensor.inverse_of_rightInverse Q hfg hgh ∘ₗ LinearMap.lTensor Q g = (LinearMap.range (LinearMap.lTensor Q f)).mkQ

full_name: lTensor.inverse
code: /-- The inverse map in `lTensor.equiv` -/
noncomputable
def lTensor.inverse :
    Q ⊗[R] P →ₗ[R] Q ⊗[R] N ⧸ LinearMap.range (lTensor Q f) 
goal: TensorProduct R Q P →ₗ[R] TensorProduct R Q N ⧸ LinearMap.range (LinearMap.lTensor Q f)

full_name: lTensor.inverse_apply
code: lemma lTensor.inverse_apply (y : Q ⊗[R] N) :
    (lTensor.inverse Q hfg hg) ((lTensor Q g) y) =
      Submodule.Quotient.mk (p := (LinearMap.range (lTensor Q f))) y 
goal: (lTensor.inverse Q hfg hg) ((LinearMap.lTensor Q g) y) = Submodule.Quotient.mk y

full_name: lTensor.inverse_comp_lTensor
code: lemma lTensor.inverse_comp_lTensor :
    (lTensor.inverse Q hfg hg).comp (lTensor Q g) =
      Submodule.mkQ (p := LinearMap.range (lTensor Q f)) 
goal: lTensor.inverse Q hfg hg ∘ₗ LinearMap.lTensor Q g = (LinearMap.range (LinearMap.lTensor Q f)).mkQ

full_name: lTensor.linearEquiv_of_rightInverse
code: /-- For a surjective `f : N →ₗ[R] P`,
  the natural equivalence between `Q ⊗ N ⧸ (image of ker f)` to `Q ⊗ P`
  (computably, given a right inverse) -/
noncomputable
def lTensor.linearEquiv_of_rightInverse {h : P → N} (hgh : Function.RightInverse h g) :
    ((Q ⊗[R] N) ⧸ (LinearMap.range (lTensor Q f))) ≃ₗ[R] (Q ⊗[R] P) 
goal: (TensorProduct R Q N ⧸ LinearMap.range (LinearMap.lTensor Q f)) ≃ₗ[R] TensorProduct R Q P

full_name: lTensor.equiv
code: /-- For a surjective `f : N →ₗ[R] P`,
  the natural equivalence between `Q ⊗ N ⧸ (image of ker f)` to `Q ⊗ P` -/
noncomputable def lTensor.equiv :
    ((Q ⊗[R] N) ⧸ (LinearMap.range (lTensor Q f))) ≃ₗ[R] (Q ⊗[R] P) 
goal: (TensorProduct R Q N ⧸ LinearMap.range (LinearMap.lTensor Q f)) ≃ₗ[R] TensorProduct R Q P

full_name: lTensor_exact
code: /-- Tensoring an exact pair on the left gives an exact pair -/
theorem lTensor_exact : Exact (lTensor Q f) (lTensor Q g) 
goal: Function.Exact ⇑(LinearMap.lTensor Q f) ⇑(LinearMap.lTensor Q g)

full_name: lTensor_mkQ
code: /-- Right-exactness of tensor product -/
lemma lTensor_mkQ (N : Submodule R M) :
    ker (lTensor Q (N.mkQ)) = range (lTensor Q N.subtype) 
goal: LinearMap.ker (LinearMap.lTensor Q N.mkQ) = LinearMap.range (LinearMap.lTensor Q N.subtype)

full_name: rTensor.toFun
code: /-- The direct map in `rTensor.equiv` -/
noncomputable def rTensor.toFun :
    N ⊗[R] Q ⧸ range (rTensor Q f) →ₗ[R] P ⊗[R] Q 
goal: TensorProduct R N Q ⧸ LinearMap.range (LinearMap.rTensor Q f) →ₗ[R] TensorProduct R P Q

full_name: rTensor.inverse_of_rightInverse
code: /-- The inverse map in `rTensor.equiv_of_rightInverse` (computably, given a right inverse) -/
noncomputable def rTensor.inverse_of_rightInverse {h : P → N} (hgh : Function.RightInverse h g) :
    P ⊗[R] Q →ₗ[R] N ⊗[R] Q ⧸ LinearMap.range (rTensor Q f) 
goal: TensorProduct R P Q →ₗ[R] TensorProduct R N Q ⧸ LinearMap.range (LinearMap.rTensor Q f)

full_name: rTensor.inverse_of_rightInverse_apply
code: lemma rTensor.inverse_of_rightInverse_apply
    {h : P → N} (hgh : Function.RightInverse h g) (y : N ⊗[R] Q) :
    (rTensor.inverse_of_rightInverse Q hfg hgh) ((rTensor Q g) y) =
      Submodule.Quotient.mk (p := LinearMap.range (rTensor Q f)) y 
goal: (rTensor.inverse_of_rightInverse Q hfg hgh) ((LinearMap.rTensor Q g) y) = Submodule.Quotient.mk y

full_name: rTensor.inverse_of_rightInverse_comp_rTensor
code: lemma rTensor.inverse_of_rightInverse_comp_rTensor
    {h : P → N} (hgh : Function.RightInverse h g) :
    (rTensor.inverse_of_rightInverse Q hfg hgh).comp (rTensor Q g) =
      Submodule.mkQ (p := LinearMap.range (rTensor Q f)) 
goal: rTensor.inverse_of_rightInverse Q hfg hgh ∘ₗ LinearMap.rTensor Q g = (LinearMap.range (LinearMap.rTensor Q f)).mkQ

full_name: rTensor.inverse
code: /-- The inverse map in `rTensor.equiv` -/
noncomputable
def rTensor.inverse :
    P ⊗[R] Q →ₗ[R] N ⊗[R] Q ⧸ LinearMap.range (rTensor Q f) 
goal: TensorProduct R P Q →ₗ[R] TensorProduct R N Q ⧸ LinearMap.range (LinearMap.rTensor Q f)

full_name: rTensor.inverse_apply
code: lemma rTensor.inverse_apply (y : N ⊗[R] Q) :
    (rTensor.inverse Q hfg hg) ((rTensor Q g) y) =
      Submodule.Quotient.mk (p := LinearMap.range (rTensor Q f)) y 
goal: (rTensor.inverse Q hfg hg) ((LinearMap.rTensor Q g) y) = Submodule.Quotient.mk y

full_name: rTensor.inverse_comp_rTensor
code: lemma rTensor.inverse_comp_rTensor :
    (rTensor.inverse Q hfg hg).comp (rTensor Q g) =
      Submodule.mkQ (p := LinearMap.range (rTensor Q f)) 
goal: rTensor.inverse Q hfg hg ∘ₗ LinearMap.rTensor Q g = (LinearMap.range (LinearMap.rTensor Q f)).mkQ

full_name: rTensor.linearEquiv_of_rightInverse
code: /-- For a surjective `f : N →ₗ[R] P`,
  the natural equivalence between `N ⊗[R] Q ⧸ (range (rTensor Q f))` and `P ⊗[R] Q`
  (computably, given a right inverse) -/
noncomputable
def rTensor.linearEquiv_of_rightInverse {h : P → N} (hgh : Function.RightInverse h g) :
    ((N ⊗[R] Q) ⧸ (range (rTensor Q f))) ≃ₗ[R] (P ⊗[R] Q) 
goal: (TensorProduct R N Q ⧸ LinearMap.range (LinearMap.rTensor Q f)) ≃ₗ[R] TensorProduct R P Q

full_name: rTensor.equiv
code: /-- For a surjective `f : N →ₗ[R] P`,
  the natural equivalence between `N ⊗[R] Q ⧸ (range (rTensor Q f))` and `P ⊗[R] Q` -/
noncomputable def rTensor.equiv :
    ((N ⊗[R] Q) ⧸ (LinearMap.range (rTensor Q f))) ≃ₗ[R] (P ⊗[R] Q) 
goal: (TensorProduct R N Q ⧸ LinearMap.range (LinearMap.rTensor Q f)) ≃ₗ[R] TensorProduct R P Q

full_name: rTensor_exact
code: /-- Tensoring an exact pair on the right gives an exact pair -/
theorem rTensor_exact : Exact (rTensor Q f) (rTensor Q g) 
goal: Function.Exact ⇑(LinearMap.rTensor Q f) ⇑(LinearMap.rTensor Q g)

full_name: rTensor_mkQ
code: /-- Right-exactness of tensor product (`rTensor`) -/
lemma rTensor_mkQ (N : Submodule R M) :
    ker (rTensor Q (N.mkQ)) = range (rTensor Q N.subtype) 
goal: LinearMap.ker (LinearMap.rTensor Q N.mkQ) = LinearMap.range (LinearMap.rTensor Q N.subtype)

full_name: TensorProduct.map_surjective
code: theorem TensorProduct.map_surjective : Function.Surjective (TensorProduct.map g g') 
goal: Function.Surjective ⇑(TensorProduct.map g g')

full_name: TensorProduct.map_ker
code: /-- Kernel of a product map (right-exactness of tensor product) -/
theorem TensorProduct.map_ker :
    ker (TensorProduct.map g g') = range (lTensor N f') ⊔ range (rTensor N' f) 
goal: LinearMap.ker (TensorProduct.map g g') =
  LinearMap.range (LinearMap.lTensor N f') ⊔ LinearMap.range (LinearMap.rTensor N' f)

full_name: TensorProduct.mk_surjective
code: theorem TensorProduct.mk_surjective (S) [Semiring S] [Algebra R S]
    (h : Surjective (algebraMap R S)) :
    Surjective (TensorProduct.mk R S M 1) 
goal: Function.Surjective ⇑((TensorProduct.mk R S M) 1)

full_name: quotTensorEquivQuotSMul
code: /-- Left tensoring a module with a quotient of the ring is the same as
quotienting that module by the corresponding submodule. -/
noncomputable def quotTensorEquivQuotSMul (I : Ideal R) :
    (R ⧸ I) ⊗[R] M ≃ₗ[R] M ⧸ (I • ⊤ : Submodule R M) 
goal: TensorProduct R (R ⧸ I) M ≃ₗ[R] M ⧸ I • ⊤

full_name: tensorQuotEquivQuotSMul
code: /-- Right tensoring a module with a quotient of the ring is the same as
quotienting that module by the corresponding submodule. -/
noncomputable def tensorQuotEquivQuotSMul (I : Ideal R) :
    M ⊗[R] (R ⧸ I) ≃ₗ[R] M ⧸ (I • ⊤ : Submodule R M) 
goal: TensorProduct R M (R ⧸ I) ≃ₗ[R] M ⧸ I • ⊤

full_name: quotTensorEquivQuotSMul_mk_tmul
code: @[simp]
lemma quotTensorEquivQuotSMul_mk_tmul (I : Ideal R) (r : R) (x : M) :
    quotTensorEquivQuotSMul M I (Ideal.Quotient.mk I r ⊗ₜ[R] x) =
      Submodule.Quotient.mk (r • x) 
goal: (quotTensorEquivQuotSMul M I) ((Ideal.Quotient.mk I) r ⊗ₜ[R] x) = Submodule.Quotient.mk (r • x)

full_name: quotTensorEquivQuotSMul_comp_mkQ_rTensor
code: lemma quotTensorEquivQuotSMul_comp_mkQ_rTensor (I : Ideal R) :
    quotTensorEquivQuotSMul M I ∘ₗ I.mkQ.rTensor M =
      (I • ⊤ : Submodule R M).mkQ ∘ₗ TensorProduct.lid R M 
goal: ↑(quotTensorEquivQuotSMul M I) ∘ₗ LinearMap.rTensor M (Submodule.mkQ I) = (I • ⊤).mkQ ∘ₗ ↑(TensorProduct.lid R M)

full_name: quotTensorEquivQuotSMul_symm_mk
code: @[simp]
lemma quotTensorEquivQuotSMul_symm_mk (I : Ideal R) (x : M) :
    (quotTensorEquivQuotSMul M I).symm (Submodule.Quotient.mk x) = 1 ⊗ₜ[R] x 
goal: (quotTensorEquivQuotSMul M I).symm (Submodule.Quotient.mk x) = 1 ⊗ₜ[R] x

full_name: quotTensorEquivQuotSMul_symm_comp_mkQ
code: lemma quotTensorEquivQuotSMul_symm_comp_mkQ (I : Ideal R) :
    (quotTensorEquivQuotSMul M I).symm ∘ₗ (I • ⊤ : Submodule R M).mkQ =
      TensorProduct.mk R (R ⧸ I) M 1 
goal: ↑(quotTensorEquivQuotSMul M I).symm ∘ₗ (I • ⊤).mkQ = (TensorProduct.mk R (R ⧸ I) M) 1

full_name: quotTensorEquivQuotSMul_comp_mk
code: lemma quotTensorEquivQuotSMul_comp_mk (I : Ideal R) :
    quotTensorEquivQuotSMul M I ∘ₗ TensorProduct.mk R (R ⧸ I) M 1 =
      Submodule.mkQ (I • ⊤) 
goal: ↑(quotTensorEquivQuotSMul M I) ∘ₗ (TensorProduct.mk R (R ⧸ I) M) 1 = (I • ⊤).mkQ

full_name: tensorQuotEquivQuotSMul_tmul_mk
code: @[simp]
lemma tensorQuotEquivQuotSMul_tmul_mk (I : Ideal R) (x : M) (r : R) :
    tensorQuotEquivQuotSMul M I (x ⊗ₜ[R] Ideal.Quotient.mk I r) =
      Submodule.Quotient.mk (r • x) 
goal: (tensorQuotEquivQuotSMul M I) (x ⊗ₜ[R] (Ideal.Quotient.mk I) r) = Submodule.Quotient.mk (r • x)

full_name: tensorQuotEquivQuotSMul_comp_mkQ_lTensor
code: lemma tensorQuotEquivQuotSMul_comp_mkQ_lTensor (I : Ideal R) :
    tensorQuotEquivQuotSMul M I ∘ₗ I.mkQ.lTensor M =
      (I • ⊤ : Submodule R M).mkQ ∘ₗ TensorProduct.rid R M 
goal: ↑(tensorQuotEquivQuotSMul M I) ∘ₗ LinearMap.lTensor M (Submodule.mkQ I) = (I • ⊤).mkQ ∘ₗ ↑(TensorProduct.rid R M)

full_name: tensorQuotEquivQuotSMul_symm_mk
code: @[simp]
lemma tensorQuotEquivQuotSMul_symm_mk (I : Ideal R) (x : M) :
    (tensorQuotEquivQuotSMul M I).symm (Submodule.Quotient.mk x) = x ⊗ₜ[R] 1 
goal: (tensorQuotEquivQuotSMul M I).symm (Submodule.Quotient.mk x) = x ⊗ₜ[R] 1

full_name: tensorQuotEquivQuotSMul_symm_comp_mkQ
code: lemma tensorQuotEquivQuotSMul_symm_comp_mkQ (I : Ideal R) :
    (tensorQuotEquivQuotSMul M I).symm ∘ₗ (I • ⊤ : Submodule R M).mkQ =
      (TensorProduct.mk R M (R ⧸ I)).flip 1 
goal: ↑(tensorQuotEquivQuotSMul M I).symm ∘ₗ (I • ⊤).mkQ = (TensorProduct.mk R M (R ⧸ I)).flip 1

full_name: tensorQuotEquivQuotSMul_comp_mk
code: lemma tensorQuotEquivQuotSMul_comp_mk (I : Ideal R) :
    tensorQuotEquivQuotSMul M I ∘ₗ (TensorProduct.mk R M (R ⧸ I)).flip 1 =
      Submodule.mkQ (I • ⊤) 
goal: ↑(tensorQuotEquivQuotSMul M I) ∘ₗ (TensorProduct.mk R M (R ⧸ I)).flip 1 = (I • ⊤).mkQ

full_name: Ideal.map_includeLeft_eq
code: /-- The ideal of `A ⊗[R] B` generated by `I` is the image of `I ⊗[R] B` -/
lemma Ideal.map_includeLeft_eq (I : Ideal A) :
    (I.map (Algebra.TensorProduct.includeLeft : A →ₐ[R] A ⊗[R] B)).restrictScalars R
      = LinearMap.range (LinearMap.rTensor B (Submodule.subtype (I.restrictScalars R))) 
goal: Submodule.restrictScalars R (Ideal.map Algebra.TensorProduct.includeLeft I) =
  LinearMap.range (LinearMap.rTensor B (Submodule.restrictScalars R I).subtype)

full_name: Ideal.map_includeRight_eq
code: /-- The ideal of `A ⊗[R] B` generated by `I` is the image of `A ⊗[R] I` -/
lemma Ideal.map_includeRight_eq (I : Ideal B) :
    (I.map (Algebra.TensorProduct.includeRight : B →ₐ[R] A ⊗[R] B)).restrictScalars R
      = LinearMap.range (LinearMap.lTensor A (Submodule.subtype (I.restrictScalars R))) 
goal: Submodule.restrictScalars R (Ideal.map Algebra.TensorProduct.includeRight I) =
  LinearMap.range (LinearMap.lTensor A (Submodule.restrictScalars R I).subtype)

full_name: Algebra.TensorProduct.lTensor_ker
code: /-- 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) 
goal: RingHom.ker (Algebra.TensorProduct.map (AlgHom.id R A) g) = Ideal.map Algebra.TensorProduct.includeRight (RingHom.ker g)

full_name: Algebra.TensorProduct.rTensor_ker
code: /-- 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) 
goal: RingHom.ker (Algebra.TensorProduct.map f (AlgHom.id R C)) = Ideal.map Algebra.TensorProduct.includeLeft (RingHom.ker f)

full_name: Algebra.TensorProduct.map_ker
code: /-- 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) 
goal: RingHom.ker (Algebra.TensorProduct.map f g) =
  Ideal.map Algebra.TensorProduct.includeLeft (RingHom.ker f) ⊔
    Ideal.map Algebra.TensorProduct.includeRight (RingHom.ker g)