Tensor products of free modules#
The class TensorFreeModule
implements tensor products of the type
where \(M\) is a free module of finite rank over a commutative ring \(R\) and \(M^*=\mathrm{Hom}_R(M,R)\) is the dual of \(M\). Note that \(T^{(1,0)}(M) = M\) and \(T^{(0,1)}(M) = M^*\).
Thanks to the canonical isomorphism \(M^{**} \simeq M\) (which holds since \(M\) is a free module of finite rank), \(T^{(k,l)}(M)\) can be identified with the set of tensors of type \((k,l)\) defined as multilinear maps
Accordingly, TensorFreeModule
is a Sage parent class, whose
element class is
FreeModuleTensor
.
\(T^{(k,l)}(M)\) is itself a free module over \(R\), of rank \(n^{k+l}\), \(n\)
being the rank of \(M\). Accordingly the class TensorFreeModule
inherits from the class
FiniteRankFreeModule
.
Todo
implement more general tensor products, i.e. tensor product of the type \(M_1\otimes\cdots\otimes M_n\), where the \(M_i\)’s are \(n\) free modules of finite rank over the same ring \(R\).
AUTHORS:
Eric Gourgoulhon, Michal Bejger (2014-2015): initial version
REFERENCES:
K. Conrad: Tensor products [Con2015]
Chap. 21 (Exer. 4) of R. Godement: Algebra [God1968]
Chap. 16 of S. Lang: Algebra [Lan2002]
- class sage.tensor.modules.tensor_free_module.TensorFreeModule(fmodule, tensor_type, name=None, latex_name=None, category=None)#
Bases:
sage.tensor.modules.finite_rank_free_module.FiniteRankFreeModule_abstract
Class for the free modules over a commutative ring \(R\) that are tensor products of a given free module \(M\) over \(R\) with itself and its dual \(M^*\):
\[T^{(k,l)}(M) = \underbrace{M\otimes\cdots\otimes M}_{k\ \; \mbox{times}} \otimes \underbrace{M^*\otimes\cdots\otimes M^*}_{l\ \; \mbox{times}}\]As recalled above, \(T^{(k,l)}(M)\) can be canonically identified with the set of tensors of type \((k,l)\) on \(M\).
This is a Sage parent class, whose element class is
FreeModuleTensor
.INPUT:
fmodule
– free module \(M\) of finite rank over a commutative ring \(R\), as an instance ofFiniteRankFreeModule
tensor_type
– pair(k, l)
withk
being the contravariant rank andl
the covariant rankname
– (default:None
) string; name given to the tensor modulelatex_name
– (default:None
) string; LaTeX symbol to denote the tensor module; if none is provided, it is set toname
EXAMPLES:
Set of tensors of type \((1,2)\) on a free \(\ZZ\)-module of rank 3:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: e = M.basis('e') sage: from sage.tensor.modules.tensor_free_module import TensorFreeModule sage: T = TensorFreeModule(M, (1,2)) ; T Free module of type-(1,2) tensors on the Rank-3 free module M over the Integer Ring
Instead of importing TensorFreeModule in the global name space, it is recommended to use the module’s method
tensor_module()
:sage: T = M.tensor_module(1,2) ; T Free module of type-(1,2) tensors on the Rank-3 free module M over the Integer Ring sage: latex(T) T^{(1, 2)}\left(M\right)
The module
M
itself is considered as the set of tensors of type \((1,0)\):sage: M is M.tensor_module(1,0) True
T
is a module (actually a free module) over \(\ZZ\):sage: T.category() Category of tensor products of finite dimensional modules over Integer Ring sage: T in Modules(ZZ) True sage: T.rank() 27 sage: T.base_ring() Integer Ring sage: T.base_module() Rank-3 free module M over the Integer Ring
T
is a parent object, whose elements are instances ofFreeModuleTensor
:sage: t = T.an_element() ; t Type-(1,2) tensor on the Rank-3 free module M over the Integer Ring sage: from sage.tensor.modules.free_module_tensor import FreeModuleTensor sage: isinstance(t, FreeModuleTensor) True sage: t in T True sage: T.is_parent_of(t) True
Elements can be constructed from
T
. In particular, 0 yields the zero element ofT
:sage: T(0) Type-(1,2) tensor zero on the Rank-3 free module M over the Integer Ring sage: T(0) is T.zero() True
while non-zero elements are constructed by providing their components in a given basis:
sage: e Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring sage: comp = [[[i-j+k for k in range(3)] for j in range(3)] for i in range(3)] sage: t = T(comp, basis=e, name='t') ; t Type-(1,2) tensor t on the Rank-3 free module M over the Integer Ring sage: t.comp(e)[:] [[[0, 1, 2], [-1, 0, 1], [-2, -1, 0]], [[1, 2, 3], [0, 1, 2], [-1, 0, 1]], [[2, 3, 4], [1, 2, 3], [0, 1, 2]]] sage: t.display(e) t = e_0⊗e^0⊗e^1 + 2 e_0⊗e^0⊗e^2 - e_0⊗e^1⊗e^0 + e_0⊗e^1⊗e^2 - 2 e_0⊗e^2⊗e^0 - e_0⊗e^2⊗e^1 + e_1⊗e^0⊗e^0 + 2 e_1⊗e^0⊗e^1 + 3 e_1⊗e^0⊗e^2 + e_1⊗e^1⊗e^1 + 2 e_1⊗e^1⊗e^2 - e_1⊗e^2⊗e^0 + e_1⊗e^2⊗e^2 + 2 e_2⊗e^0⊗e^0 + 3 e_2⊗e^0⊗e^1 + 4 e_2⊗e^0⊗e^2 + e_2⊗e^1⊗e^0 + 2 e_2⊗e^1⊗e^1 + 3 e_2⊗e^1⊗e^2 + e_2⊗e^2⊗e^1 + 2 e_2⊗e^2⊗e^2
An alternative is to construct the tensor from an empty list of components and to set the nonzero components afterwards:
sage: t = T([], name='t') sage: t.set_comp(e)[0,1,1] = -3 sage: t.set_comp(e)[2,0,1] = 4 sage: t.display(e) t = -3 e_0⊗e^1⊗e^1 + 4 e_2⊗e^0⊗e^1
See the documentation of
FreeModuleTensor
for the full list of arguments that can be provided to the __call__ operator. For instance, to construct a tensor symmetric with respect to the last two indices:sage: t = T([], name='t', sym=(1,2)) sage: t.set_comp(e)[0,1,1] = -3 sage: t.set_comp(e)[2,0,1] = 4 sage: t.display(e) # notice that t^2_{10} has be set equal to t^2_{01} by symmetry t = -3 e_0⊗e^1⊗e^1 + 4 e_2⊗e^0⊗e^1 + 4 e_2⊗e^1⊗e^0
The tensor modules over a given module \(M\) are unique:
sage: T is M.tensor_module(1,2) True
There is a coercion map from \(\Lambda^p(M^*)\), the set of alternating forms of degree \(p\), to \(T^{(0,p)}(M)\):
sage: L2 = M.dual_exterior_power(2) ; L2 2nd exterior power of the dual of the Rank-3 free module M over the Integer Ring sage: T02 = M.tensor_module(0,2) ; T02 Free module of type-(0,2) tensors on the Rank-3 free module M over the Integer Ring sage: T02.has_coerce_map_from(L2) True
Of course, for \(p\geq 2\), there is no coercion in the reverse direction, since not every tensor of type \((0,p)\) is alternating:
sage: L2.has_coerce_map_from(T02) False
The coercion map \(\Lambda^2(M^*)\rightarrow T^{(0,2)}(M)\) in action:
sage: a = M.alternating_form(2, name='a') ; a Alternating form a of degree 2 on the Rank-3 free module M over the Integer Ring sage: a[0,1], a[1,2] = 4, -3 sage: a.display(e) a = 4 e^0∧e^1 - 3 e^1∧e^2 sage: a.parent() is L2 True sage: ta = T02(a) ; ta Type-(0,2) tensor a on the Rank-3 free module M over the Integer Ring sage: ta.display(e) a = 4 e^0⊗e^1 - 4 e^1⊗e^0 - 3 e^1⊗e^2 + 3 e^2⊗e^1 sage: ta.symmetries() # the antisymmetry is of course preserved no symmetry; antisymmetry: (0, 1)
For the degree \(p=1\), we have the identity \(\Lambda^1(M^*) = T^{(0,1)}(M) = M^*\):
sage: M.dual_exterior_power(1) is M.tensor_module(0,1) True sage: M.tensor_module(0,1) is M.dual() True
There is a canonical identification between tensors of type \((1,1)\) and endomorphisms of module \(M\). Accordingly, coercion maps have been implemented between \(T^{(1,1)}(M)\) and \(\mathrm{End}(M)\) (the module of all endomorphisms of \(M\), see
FreeModuleHomset
):sage: T11 = M.tensor_module(1,1) ; T11 Free module of type-(1,1) tensors on the Rank-3 free module M over the Integer Ring sage: End(M) Set of Morphisms from Rank-3 free module M over the Integer Ring to Rank-3 free module M over the Integer Ring in Category of finite dimensional modules over Integer Ring sage: T11.has_coerce_map_from(End(M)) True sage: End(M).has_coerce_map_from(T11) True
The coercion map \(\mathrm{End}(M)\rightarrow T^{(1,1)}(M)\) in action:
sage: phi = End(M).an_element() ; phi Generic endomorphism of Rank-3 free module M over the Integer Ring sage: phi.matrix(e) [1 1 1] [1 1 1] [1 1 1] sage: tphi = T11(phi) ; tphi # image of phi by the coercion map Type-(1,1) tensor on the Rank-3 free module M over the Integer Ring sage: tphi[:] [1 1 1] [1 1 1] [1 1 1] sage: t = M.tensor((1,1)) sage: t[0,0], t[1,1], t[2,2] = -1,-2,-3 sage: t[:] [-1 0 0] [ 0 -2 0] [ 0 0 -3] sage: s = t + phi ; s # phi is coerced to a type-(1,1) tensor prior to the addition Type-(1,1) tensor on the Rank-3 free module M over the Integer Ring sage: s[:] [ 0 1 1] [ 1 -1 1] [ 1 1 -2]
The coercion map \(T^{(1,1)}(M) \rightarrow \mathrm{End}(M)\) in action:
sage: phi1 = End(M)(tphi) ; phi1 Generic endomorphism of Rank-3 free module M over the Integer Ring sage: phi1 == phi True sage: s = phi + t ; s # t is coerced to an endomorphism prior to the addition Generic endomorphism of Rank-3 free module M over the Integer Ring sage: s.matrix(e) [ 0 1 1] [ 1 -1 1] [ 1 1 -2]
There is a coercion \(\mathrm{GL}(M)\rightarrow T^{(1,1)}(M)\), i.e. from automorphisms of \(M\) to type-\((1,1)\) tensors on \(M\):
sage: GL = M.general_linear_group() ; GL General linear group of the Rank-3 free module M over the Integer Ring sage: T11.has_coerce_map_from(GL) True
The coercion map \(\mathrm{GL}(M)\rightarrow T^{(1,1)}(M)\) in action:
sage: a = GL.an_element() ; a Automorphism of the Rank-3 free module M over the Integer Ring sage: a.matrix(e) [ 1 0 0] [ 0 -1 0] [ 0 0 1] sage: ta = T11(a) ; ta Type-(1,1) tensor on the Rank-3 free module M over the Integer Ring sage: ta.display(e) e_0⊗e^0 - e_1⊗e^1 + e_2⊗e^2 sage: a.display(e) e_0⊗e^0 - e_1⊗e^1 + e_2⊗e^2
Of course, there is no coercion in the reverse direction, since not every type-\((1,1)\) tensor is invertible:
sage: GL.has_coerce_map_from(T11) False
- Element#
alias of
sage.tensor.modules.free_module_tensor.FreeModuleTensor
- base_module()#
Return the free module on which
self
is constructed.OUTPUT:
instance of
FiniteRankFreeModule
representing the free module on which the tensor module is defined.
EXAMPLES:
Base module of a type-\((1,2)\) tensor module:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: T = M.tensor_module(1,2) sage: T.base_module() Rank-3 free module M over the Integer Ring sage: T.base_module() is M True
- basis(symbol, latex_symbol=None, from_family=None, indices=None, latex_indices=None, symbol_dual=None, latex_symbol_dual=None)#
Return the standard basis of
self
corresponding to a basis of the base module.INPUT:
symbol
,indices
– passed to the base module’s methodbasis()
to select a basis of thebase_module()
ofself
, or to create it.other parameters – passed to
basis()
; when the basis does not exist yet, it will be created using these parameters.
EXAMPLES:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: T = M.tensor_module(1,1) sage: e_T = T.basis('e'); e_T Standard basis on the Free module of type-(1,1) tensors on the Rank-3 free module M over the Integer Ring induced by Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring sage: for a in e_T: a.display() e_0⊗e^0 e_0⊗e^1 e_0⊗e^2 e_1⊗e^0 e_1⊗e^1 e_1⊗e^2 e_2⊗e^0 e_2⊗e^1 e_2⊗e^2 sage: Sym2M = M.tensor_module(2, 0, sym=range(2)) sage: e_Sym2M = Sym2M.basis('e'); e_Sym2M Standard basis on the Free module of fully symmetric type-(2,0) tensors on the Rank-3 free module M over the Integer Ring induced by Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring sage: for a in e_Sym2M: a.display() e_0⊗e_0 e_0⊗e_1 + e_1⊗e_0 e_0⊗e_2 + e_2⊗e_0 e_1⊗e_1 e_1⊗e_2 + e_2⊗e_1 e_2⊗e_2 sage: M = FiniteRankFreeModule(ZZ, 2) sage: e = M.basis('e') sage: f = M.basis('f', from_family=(-e[1], e[0])) sage: for b in f: b.display() f_0 = -e_1 f_1 = e_0 sage: S = M.tensor_module(2, 0, sym=(0,1)) sage: fS = S.basis('f') sage: for b in fS: b.display() e_1⊗e_1 -e_0⊗e_1 - e_1⊗e_0 e_0⊗e_0 sage: for b in fS: b.display(f) f_0⊗f_0 f_0⊗f_1 + f_1⊗f_0 f_1⊗f_1
- tensor_factors()#
Return the tensor factors of this tensor module.
EXAMPLES:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: T = M.tensor_module(2, 3) sage: T.tensor_factors() [Rank-3 free module M over the Integer Ring, Rank-3 free module M over the Integer Ring, Dual of the Rank-3 free module M over the Integer Ring, Dual of the Rank-3 free module M over the Integer Ring, Dual of the Rank-3 free module M over the Integer Ring]
- tensor_type()#
Return the tensor type of
self
.OUTPUT:
pair \((k,l)\) such that
self
is the module tensor product \(T^{(k,l)}(M)\)
EXAMPLES:
sage: M = FiniteRankFreeModule(ZZ, 3) sage: T = M.tensor_module(1,2) sage: T.tensor_type() (1, 2)
- zero()#
Return the zero of
self
.EXAMPLES:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: e = M.basis('e') sage: T11 = M.tensor_module(1,1) sage: T11.zero() Type-(1,1) tensor zero on the Rank-3 free module M over the Integer Ring
The zero element is cached:
sage: T11.zero() is T11(0) True