File: Mathlib/RingTheory/IsTensorProduct.lean

full_name: IsTensorProduct
code: /-- Given a bilinear map `f : M₁ →ₗ[R] M₂ →ₗ[R] M`, `IsTensorProduct f` means that
`M` is the tensor product of `M₁` and `M₂` via `f`.
This is defined by requiring the lift `M₁ ⊗[R] M₂ → M` to be bijective.
-/
def IsTensorProduct : Prop 
goal: Prop

full_name: TensorProduct.isTensorProduct
code: theorem TensorProduct.isTensorProduct : IsTensorProduct (TensorProduct.mk R M N) 
goal: IsTensorProduct (TensorProduct.mk R M N)

full_name: IsTensorProduct.equiv_apply
code: /-- If `M` is the tensor product of `M₁` and `M₂`, it is linearly equivalent to `M₁ ⊗[R] M₂`. -/
@[simps! apply]
noncomputable def IsTensorProduct.equiv (h : IsTensorProduct f) : M₁ ⊗[R] M₂ ≃ₗ[R] M 
goal: ∀ (a : M₁ ⊗[R] M₂), h.equiv a = (TensorProduct.lift f) a

full_name: IsTensorProduct.equiv
code: /-- If `M` is the tensor product of `M₁` and `M₂`, it is linearly equivalent to `M₁ ⊗[R] M₂`. -/
@[simps! apply]
noncomputable def IsTensorProduct.equiv (h : IsTensorProduct f) : M₁ ⊗[R] M₂ ≃ₗ[R] M 
goal: M₁ ⊗[R] M₂ ≃ₗ[R] M

full_name: IsTensorProduct.equiv_toLinearMap
code: @[simp]
theorem IsTensorProduct.equiv_toLinearMap (h : IsTensorProduct f) :
    h.equiv.toLinearMap = TensorProduct.lift f 
goal: ↑h.equiv = TensorProduct.lift f

full_name: IsTensorProduct.equiv_symm_apply
code: @[simp]
theorem IsTensorProduct.equiv_symm_apply (h : IsTensorProduct f) (x₁ : M₁) (x₂ : M₂) :
    h.equiv.symm (f x₁ x₂) = x₁ ⊗ₜ x₂ 
goal: h.equiv.symm ((f x₁) x₂) = x₁ ⊗ₜ[R] x₂

full_name: IsTensorProduct.lift
code: /-- If `M` is the tensor product of `M₁` and `M₂`, we may lift a bilinear map `M₁ →ₗ[R] M₂ →ₗ[R] M'`
to a `M →ₗ[R] M'`. -/
noncomputable def IsTensorProduct.lift (h : IsTensorProduct f) (f' : M₁ →ₗ[R] M₂ →ₗ[R] M') :
    M →ₗ[R] M' 
goal: M →ₗ[R] M'

full_name: IsTensorProduct.lift_eq
code: theorem IsTensorProduct.lift_eq (h : IsTensorProduct f) (f' : M₁ →ₗ[R] M₂ →ₗ[R] M') (x₁ : M₁)
    (x₂ : M₂) : h.lift f' (f x₁ x₂) = f' x₁ x₂ 
goal: (h.lift f') ((f x₁) x₂) = (f' x₁) x₂

full_name: IsTensorProduct.map
code: /-- The tensor product of a pair of linear maps between modules. -/
noncomputable def IsTensorProduct.map (hf : IsTensorProduct f) (hg : IsTensorProduct g)
    (i₁ : M₁ →ₗ[R] N₁) (i₂ : M₂ →ₗ[R] N₂) : M →ₗ[R] N 
goal: M →ₗ[R] N

full_name: IsTensorProduct.map_eq
code: theorem IsTensorProduct.map_eq (hf : IsTensorProduct f) (hg : IsTensorProduct g) (i₁ : M₁ →ₗ[R] N₁)
    (i₂ : M₂ →ₗ[R] N₂) (x₁ : M₁) (x₂ : M₂) : hf.map hg i₁ i₂ (f x₁ x₂) = g (i₁ x₁) (i₂ x₂) 
goal: (hf.map hg i₁ i₂) ((f x₁) x₂) = (g (i₁ x₁)) (i₂ x₂)

full_name: IsTensorProduct.inductionOn
code: theorem IsTensorProduct.inductionOn (h : IsTensorProduct f) {C : M → Prop} (m : M) (h0 : C 0)
    (htmul : ∀ x y, C (f x y)) (hadd : ∀ x y, C x → C y → C (x + y)) : C m 
goal: C m

full_name: IsBaseChange
code: /-- Given an `R`-algebra `S` and an `R`-module `M`, an `S`-module `N` together with a map
`f : M →ₗ[R] N` is the base change of `M` to `S` if the map `S × M → N, (s, m) ↦ s • f m` is the
tensor product. -/
def IsBaseChange : Prop 
goal: Prop

full_name: IsBaseChange.lift
code: /-- Suppose `f : M →ₗ[R] N` is the base change of `M` along `R → S`. Then any `R`-linear map from
`M` to an `S`-module factors through `f`. -/
noncomputable nonrec def IsBaseChange.lift (g : M →ₗ[R] Q) : N →ₗ[S] Q 
goal: N →ₗ[S] Q

full_name: IsBaseChange.lift_eq
code: nonrec theorem IsBaseChange.lift_eq (g : M →ₗ[R] Q) (x : M) : h.lift g (f x) = g x 
goal: (h.lift g) (f x) = g x

full_name: IsBaseChange.lift_comp
code: theorem IsBaseChange.lift_comp (g : M →ₗ[R] Q) : ((h.lift g).restrictScalars R).comp f = g 
goal: ↑R (h.lift g) ∘ₗ f = g

full_name: IsBaseChange.inductionOn
code: @[elab_as_elim]
nonrec theorem IsBaseChange.inductionOn (x : N) (P : N → Prop) (h₁ : P 0) (h₂ : ∀ m : M, P (f m))
    (h₃ : ∀ (s : S) (n), P n → P (s • n)) (h₄ : ∀ n₁ n₂, P n₁ → P n₂ → P (n₁ + n₂)) : P x 
goal: P x

full_name: IsBaseChange.algHom_ext
code: theorem IsBaseChange.algHom_ext (g₁ g₂ : N →ₗ[S] Q) (e : ∀ x, g₁ (f x) = g₂ (f x)) : g₁ = g₂ 
goal: g₁ = g₂

full_name: IsBaseChange.algHom_ext'
code: theorem IsBaseChange.algHom_ext' [Module R Q] [IsScalarTower R S Q] (g₁ g₂ : N →ₗ[S] Q)
    (e : (g₁.restrictScalars R).comp f = (g₂.restrictScalars R).comp f) : g₁ = g₂ 
goal: g₁ = g₂

full_name: TensorProduct.isBaseChange
code: theorem TensorProduct.isBaseChange : IsBaseChange S (TensorProduct.mk R S M 1) 
goal: IsBaseChange S ((TensorProduct.mk R S M) 1)

full_name: IsBaseChange.equiv
code: /-- The base change of `M` along `R → S` is linearly equivalent to `S ⊗[R] M`. -/
noncomputable nonrec def IsBaseChange.equiv : S ⊗[R] M ≃ₗ[S] N 
goal: S ⊗[R] M ≃ₗ[S] N

full_name: IsBaseChange.equiv_tmul
code: theorem IsBaseChange.equiv_tmul (s : S) (m : M) : h.equiv (s ⊗ₜ m) = s • f m 
goal: h.equiv (s ⊗ₜ[R] m) = s • f m

full_name: IsBaseChange.equiv_symm_apply
code: theorem IsBaseChange.equiv_symm_apply (m : M) : h.equiv.symm (f m) = 1 ⊗ₜ m 
goal: h.equiv.symm (f m) = 1 ⊗ₜ[R] m

full_name: IsBaseChange.of_lift_unique
code: theorem IsBaseChange.of_lift_unique
    (h : ∀ (Q : Type max v₁ v₂ v₃) [AddCommMonoid Q],
      ∀ [Module R Q] [Module S Q], ∀ [IsScalarTower R S Q],
        ∀ g : M →ₗ[R] Q, ∃! g' : N →ₗ[S] Q, (g'.restrictScalars R).comp f = g) :
    IsBaseChange S f 
goal: IsBaseChange S f

full_name: IsBaseChange.iff_lift_unique
code: theorem IsBaseChange.iff_lift_unique :
    IsBaseChange S f ↔
      ∀ (Q : Type max v₁ v₂ v₃) [AddCommMonoid Q],
        ∀ [Module R Q] [Module S Q],
          ∀ [IsScalarTower R S Q],
            ∀ g : M →ₗ[R] Q, ∃! g' : N →ₗ[S] Q, (g'.restrictScalars R).comp f = g 
goal: IsBaseChange S f ↔
  ∀ (Q : Type (max v₁ v₂ v₃)) [inst : AddCommMonoid Q] [inst_1 : Module R Q] [inst_2 : Module S Q]
    [inst_3 : IsScalarTower R S Q] (g : M →ₗ[R] Q), ∃! g', ↑R g' ∘ₗ f = g

full_name: IsBaseChange.ofEquiv
code: theorem IsBaseChange.ofEquiv (e : M ≃ₗ[R] N) : IsBaseChange R e.toLinearMap 
goal: IsBaseChange R ↑e

full_name: IsBaseChange.comp
code: theorem IsBaseChange.comp {f : M →ₗ[R] N} (hf : IsBaseChange S f) {g : N →ₗ[S] O}
    (hg : IsBaseChange T g) : IsBaseChange T ((g.restrictScalars R).comp f) 
goal: IsBaseChange T (↑R g ∘ₗ f)

full_name: Algebra.isPushout_iff
code: /-- A type-class stating that the following diagram of scalar towers
R  →  S
↓     ↓
R' →  S'
is a pushout diagram (i.e. `S' = S ⊗[R] R'`)
-/
@[mk_iff]
class Algebra.IsPushout : Prop where
  out : IsBaseChange S (toAlgHom R R' S').toLinearMap
goal: Algebra.IsPushout R S R' S' ↔ IsBaseChange S (IsScalarTower.toAlgHom R R' S').toLinearMap

full_name: Algebra.IsPushout
code: /-- A type-class stating that the following diagram of scalar towers
R  →  S
↓     ↓
R' →  S'
is a pushout diagram (i.e. `S' = S ⊗[R] R'`)
-/
@[mk_iff]
class Algebra.IsPushout : Prop where
  out : IsBaseChange S (toAlgHom R R' S').toLinearMap
goal: Prop

full_name: Algebra.IsPushout.out
code: /-- A type-class stating that the following diagram of scalar towers
R  →  S
↓     ↓
R' →  S'
is a pushout diagram (i.e. `S' = S ⊗[R] R'`)
-/
@[mk_iff]
class Algebra.IsPushout : Prop where
  out : IsBaseChange S (toAlgHom R R' S').toLinearMap
goal: IsBaseChange S (IsScalarTower.toAlgHom R R' S').toLinearMap

full_name: Algebra.IsPushout.symm
code: @[symm]
theorem Algebra.IsPushout.symm (h : Algebra.IsPushout R S R' S') : Algebra.IsPushout R R' S S' 
goal: Algebra.IsPushout R R' S S'

full_name: Algebra.IsPushout.comm
code: theorem Algebra.IsPushout.comm : Algebra.IsPushout R S R' S' ↔ Algebra.IsPushout R R' S S' 
goal: Algebra.IsPushout R S R' S' ↔ Algebra.IsPushout R R' S S'

full_name: TensorProduct.isPushout
code: instance TensorProduct.isPushout {R S T : Type*} [CommRing R] [CommRing S] [CommRing T]
    [Algebra R S] [Algebra R T] : Algebra.IsPushout R S T (TensorProduct R S T) 
goal: Algebra.IsPushout R S T (S ⊗[R] T)

full_name: TensorProduct.isPushout'
code: instance TensorProduct.isPushout' {R S T : Type*} [CommRing R] [CommRing S] [CommRing T]
    [Algebra R S] [Algebra R T] : Algebra.IsPushout R T S (TensorProduct R S T) 
goal: Algebra.IsPushout R T S (S ⊗[R] T)

full_name: Algebra.pushoutDesc
code: /-- If `S' = S ⊗[R] R'`, then any pair of `R`-algebra homomorphisms `f : S → A` and `g : R' → A`
such that `f x` and `g y` commutes for all `x, y` descends to a (unique) homomorphism `S' → A`.
-/
@[simps! (config := .lemmasOnly) apply]
noncomputable def Algebra.pushoutDesc [H : Algebra.IsPushout R S R' S'] {A : Type*} [Semiring A]
    [Algebra R A] (f : S →ₐ[R] A) (g : R' →ₐ[R] A) (hf : ∀ x y, f x * g y = g y * f x) :
    S' →ₐ[R] A 
goal: S' →ₐ[R] A

full_name: Algebra.pushoutDesc_apply
code: /-- If `S' = S ⊗[R] R'`, then any pair of `R`-algebra homomorphisms `f : S → A` and `g : R' → A`
such that `f x` and `g y` commutes for all `x, y` descends to a (unique) homomorphism `S' → A`.
-/
@[simps! (config := .lemmasOnly) apply]
noncomputable def Algebra.pushoutDesc [H : Algebra.IsPushout R S R' S'] {A : Type*} [Semiring A]
    [Algebra R A] (f : S →ₐ[R] A) (g : R' →ₐ[R] A) (hf : ∀ x y, f x * g y = g y * f x) :
    S' →ₐ[R] A 
goal: (Algebra.pushoutDesc S' f g hf) a = (⋯.lift g.toLinearMap) a

full_name: Algebra.pushoutDesc_left
code: @[simp]
theorem Algebra.pushoutDesc_left [H : Algebra.IsPushout R S R' S'] {A : Type*} [Semiring A]
    [Algebra R A] (f : S →ₐ[R] A) (g : R' →ₐ[R] A) (H) (x : S) :
    Algebra.pushoutDesc S' f g H (algebraMap S S' x) = f x 
goal: ∀ (H_1 : ∀ (x : S) (y : R'), f x * g y = g y * f x) (x : S),
  (Algebra.pushoutDesc S' f g H_1) ((algebraMap S S') x) = f x

full_name: Algebra.lift_algHom_comp_left
code: theorem Algebra.lift_algHom_comp_left [Algebra.IsPushout R S R' S'] {A : Type*} [Semiring A]
    [Algebra R A] (f : S →ₐ[R] A) (g : R' →ₐ[R] A) (H) :
    (Algebra.pushoutDesc S' f g H).comp (toAlgHom R S S') = f 
goal: (Algebra.pushoutDesc S' f g H).comp (IsScalarTower.toAlgHom R S S') = f

full_name: Algebra.pushoutDesc_right
code: @[simp]
theorem Algebra.pushoutDesc_right [H : Algebra.IsPushout R S R' S'] {A : Type*} [Semiring A]
    [Algebra R A] (f : S →ₐ[R] A) (g : R' →ₐ[R] A) (H) (x : R') :
    Algebra.pushoutDesc S' f g H (algebraMap R' S' x) = g x 
goal: ∀ (H_1 : ∀ (x : S) (y : R'), f x * g y = g y * f x) (x : R'),
  (Algebra.pushoutDesc S' f g H_1) ((algebraMap R' S') x) = g x

full_name: Algebra.lift_algHom_comp_right
code: theorem Algebra.lift_algHom_comp_right [Algebra.IsPushout R S R' S'] {A : Type*} [Semiring A]
    [Algebra R A] (f : S →ₐ[R] A) (g : R' →ₐ[R] A) (H) :
    (Algebra.pushoutDesc S' f g H).comp (toAlgHom R R' S') = g 
goal: (Algebra.pushoutDesc S' f g H).comp (IsScalarTower.toAlgHom R R' S') = g

full_name: Algebra.IsPushout.algHom_ext
code: @[ext]
theorem Algebra.IsPushout.algHom_ext [H : Algebra.IsPushout R S R' S'] {A : Type*} [Semiring A]
    [Algebra R A] {f g : S' →ₐ[R] A} (h₁ : f.comp (toAlgHom R R' S') = g.comp (toAlgHom R R' S'))
    (h₂ : f.comp (toAlgHom R S S') = g.comp (toAlgHom R S S')) : f = g 
goal: f = g