Zulip Chat Archive

Stream: Is there code for X?

Topic: tensorproduct with endomorphisms


Johan Commelin (Feb 24 2024 at 05:51):

I would be interested in knowing if we have constructions that allow to golf this.
Certainly, the first two decls should be generalized to the case of linear maps between two modules, instead of just endomorphisms. But that's orthogonal to my question.

import Mathlib

namespace LinearMap

variable (R A M : Type*) [CommRing R] [CommRing A] [Algebra R A] [AddCommGroup M] [Module R M]

open Module
open scoped TensorProduct

noncomputable
def TensorProductEndₗ' : A [R] (End R M) →ₗ[R] End A (A [R] M) :=
  TensorProduct.lift <|
  { toFun := fun a  a  baseChangeHom R A M M
    map_add' := by simp only [add_smul, forall_true_iff]
    map_smul' := by simp only [smul_assoc, RingHom.id_apply, forall_true_iff] }

noncomputable
def TensorProductEndₗ : A [R] (End R M) →ₗ[A] End A (A [R] M) :=
  { TensorProductEndₗ' R A M with
    map_smul' := by
      intros a f
      show TensorProductEndₗ' R A M (a  f) = a  TensorProductEndₗ' R A M f
      unfold TensorProductEndₗ'
      induction f using TensorProduct.induction_on with
      | zero => simp only [smul_zero, LinearMap.map_zero]
      | tmul b f =>
          simp only [TensorProduct.smul_tmul', TensorProduct.lift.tmul]
          dsimp only [coe_mk, AddHom.coe_mk, smul_apply, baseChangeHom_apply]
          rw [smul_assoc]
      | add f g hf hg => simp only [smul_add, LinearMap.map_add, hf, hg] }

noncomputable
def TensorProductEnd : A [R] (End R M) →ₐ[A] End A (A [R] M) :=
  Algebra.TensorProduct.algHomOfLinearMapTensorProduct
    (TensorProductEndₗ R A M)
    (fun a b f g  by
      simp only [TensorProductEndₗ, TensorProductEndₗ', coe_mk, TensorProduct.lift.tmul',
        AddHom.coe_mk, mul_eq_comp, baseChangeHom_apply, smul_apply, baseChange_comp]
      apply LinearMap.ext
      intro x
      simp only [LinearMap.comp_apply, smul_apply, map_smul, mul_comm a b, mul_smul])
    (by
      simp only [TensorProductEndₗ, TensorProductEndₗ', coe_mk, TensorProduct.lift.tmul',
        AddHom.coe_mk, one_smul, baseChangeHom_apply]
      apply LinearMap.ext
      intro x
      erw [baseChange_eq_ltensor, lTensor_id, LinearMap.id_apply])

end LinearMap

Eric Wieser (Feb 24 2024 at 08:48):

I think you can merge the first two by using TensorProduct.AlgebraTensorModule.lift

Antoine Chambert-Loir (Feb 24 2024 at 10:40):

I don't think you can go much shorter, because it is really about the definition of a base change functor in various categories. Basically , one applies the universal property of the tensor product, and sone hypotheses have to be checked — they could have been checked elsewhere.

Oliver Nash (Feb 24 2024 at 11:00):

The key here is indeed docs#TensorProduct.AlgebraTensorModule.lift as @Eric Wieser suggests:

import Mathlib

namespace LinearMap

variable (R A M : Type*) [CommRing R] [CommRing A] [Algebra R A] [AddCommGroup M] [Module R M]

open Module
open scoped TensorProduct

noncomputable
def TensorProductEndₗ : A [R] (End R M) →ₗ[A] End A (A [R] M) :=
  TensorProduct.AlgebraTensorModule.lift <|
  { toFun := fun a  a  baseChangeHom R A M M
    map_add' := by simp only [add_smul, forall_true_iff]
    map_smul' := by simp only [smul_assoc, RingHom.id_apply, forall_true_iff] }

Eric Wieser (Feb 24 2024 at 11:10):

I would guess that linear map already exists too

Eric Wieser (Feb 24 2024 at 11:10):

(as the general form that SMul is a linear map)

Johan Commelin (Feb 24 2024 at 11:56):

I searched for it, but didn't find it. SMulOneHom isn't the right thing...

Oliver Nash (Feb 24 2024 at 12:03):

(Likewise I couldn't find it.)

Johan Commelin (Feb 24 2024 at 12:04):

But thanks for the pointer to TensorProduct.AlgebraTensorModule.lift!

Eric Wieser (Feb 24 2024 at 12:44):

It will be something like Module.toLinearMap

Junyan Xu (Feb 24 2024 at 12:54):

docs#LinearMap.toSpanSingleton (see also docs#LinearMap.ringLmapEquivSelf)

Eric Wieser (Feb 24 2024 at 13:25):

docs#Algebra.lsmul should give the last result, along with docs#Algebra.TensorProduct.lift

Johan Commelin (Feb 24 2024 at 13:26):

Which result?

Eric Wieser (Feb 24 2024 at 16:51):

Now that I'm at a computer, here's my spelling of all of them:

import Mathlib

namespace LinearMap

variable (R A M N : Type*) [CommRing R] [CommRing A] [Algebra R A] [AddCommGroup M] [AddCommGroup N] [Module R M] [Module R N]

open Module
open scoped TensorProduct

-- these should be in mathlib
@[simp]
theorem baseChange_id : LinearMap.baseChange A (.id : M →ₗ[R] M) = .id := by simp [baseChange]

/-- On endomorphisms, `LinearMap.baseChangeHom` is an `AlgHom`. -/
@[simps!]
noncomputable
def _root_.Module.End.baseChangeHom : End R M →ₐ[R] End A (A [R] M) :=
  .ofLinearMap (LinearMap.baseChangeHom _ _ _ _) (baseChange_id _ _ _) (fun f g => baseChange_comp g f)


-- These are maybe more contrived
noncomputable
def TensorProductEndₗ : A [R] (M →ₗ[R] N) →ₗ[A] (A [R] M) →ₗ[A] (A [R] N):=
  TensorProduct.AlgebraTensorModule.lift <|
    (Algebra.lsmul A A _).toLinearMap.flip (baseChangeHom R A M N)

noncomputable
def TensorProductEnd : A [R] (End R M) →ₐ[A] End A (A [R] M) :=
  Algebra.TensorProduct.lift (Algebra.ofId _ _) (Module.End.baseChangeHom _ _ _) (fun _ _=> Algebra.commute_algebraMap_left _ _)

end LinearMap

Eric Wieser (Feb 24 2024 at 16:52):

Probably we should have AlgHom.baseChange that handles the lift (.ofId _ _) ?_ sorry pattern

Eric Wieser (Feb 24 2024 at 16:59):

#10928 adds the first two results

Johan Commelin (Feb 24 2024 at 17:54):

Thanks!


Last updated: May 02 2025 at 03:31 UTC