@@ -38,10 +38,11 @@ class :class:`~sage.modules.free_module.FreeModule_generic`
3838AUTHORS:
3939
4040- Eric Gourgoulhon, Michal Bejger (2014-2015): initial version
41- - Travis Scrimshaw (2016): category set to Modules(ring).FiniteDimensional()
41+ - Travis Scrimshaw (2016): category set to `` Modules(ring).FiniteDimensional()``
4242 (:trac:`20770`)
4343- Michael Jung (2019): improve treatment of the zero element
4444- Eric Gourgoulhon (2021): unicode symbols for tensor and exterior products
45+ - Matthias Koeppe (2022): ``FiniteRankFreeModule_abstract``, symmetric powers
4546
4647REFERENCES:
4748
@@ -519,16 +520,19 @@ class :class:`~sage.modules.free_module.FreeModule_generic`
519520 [2, 0, -5]
520521
521522"""
522- #******************************************************************************
523- # Copyright (C) 2015-2021 Eric Gourgoulhon <[email protected] > 524- # Copyright (C) 2015 Michal Bejger <[email protected] > 525- # Copyright (C) 2016 Travis Scrimshaw <[email protected] > 523+ # ******************************************************************************
524+ # Copyright (C) 2014-2021 Eric Gourgoulhon <[email protected] > 525+ # 2014-2016 Travis Scrimshaw <[email protected] > 526+ # 2015 Michal Bejger <[email protected] > 527+ # 2016 Frédéric Chapoton
528+ # 2020 Michael Jung
529+ # 2020-2022 Matthias Koeppe
526530#
527531# Distributed under the terms of the GNU General Public License (GPL)
528532# as published by the Free Software Foundation; either version 2 of
529533# the License, or (at your option) any later version.
530534# https://www.gnu.org/licenses/
531- #******************************************************************************
535+ # ******************************************************************************
532536from __future__ import annotations
533537
534538from typing import Generator , Optional
@@ -645,13 +649,70 @@ def tensor_product(self, *others):
645649 sage: M.tensor_module(1,1).tensor_product(M.tensor_module(1,2))
646650 Free module of type-(2,3) tensors on the 2-dimensional vector space over the Rational Field
647651
652+ sage: Sym2M = M.tensor_module(2, 0, sym=range(2)); Sym2M
653+ Free module of fully symmetric type-(2,0) tensors on the 2-dimensional vector space over the Rational Field
654+ sage: Sym01x23M = Sym2M.tensor_product(Sym2M); Sym01x23M
655+ Free module of type-(4,0) tensors on the 2-dimensional vector space over the Rational Field,
656+ with symmetry on the index positions (0, 1), with symmetry on the index positions (2, 3)
657+ sage: Sym01x23M._index_maps
658+ ((0, 1), (2, 3))
659+
660+ sage: N = M.tensor_module(3, 3, sym=[1, 2], antisym=[3, 4]); N
661+ Free module of type-(3,3) tensors on the 2-dimensional vector space over the Rational Field,
662+ with symmetry on the index positions (1, 2),
663+ with antisymmetry on the index positions (3, 4)
664+ sage: NxN = N.tensor_product(N); NxN
665+ Free module of type-(6,6) tensors on the 2-dimensional vector space over the Rational Field,
666+ with symmetry on the index positions (1, 2), with symmetry on the index positions (4, 5),
667+ with antisymmetry on the index positions (6, 7), with antisymmetry on the index positions (9, 10)
668+ sage: NxN._index_maps
669+ ((0, 1, 2, 6, 7, 8), (3, 4, 5, 9, 10, 11))
648670 """
649671 from sage .modules .free_module_element import vector
672+ from .comp import CompFullySym , CompFullyAntiSym , CompWithSym
673+
650674 base_module = self .base_module ()
651675 if not all (module .base_module () == base_module for module in others ):
652676 raise NotImplementedError ('all factors must be tensor modules over the same base module' )
653- tensor_type = sum (vector (module .tensor_type ()) for module in [self ] + list (others ))
654- return base_module .tensor_module (* tensor_type )
677+ factors = [self ] + list (others )
678+ result_tensor_type = sum (vector (factor .tensor_type ()) for factor in factors )
679+ index_maps = []
680+ running_indices = vector ([0 , result_tensor_type [0 ]])
681+ result_sym = []
682+ result_antisym = []
683+ for factor in factors :
684+ tensor_type = factor .tensor_type ()
685+ index_map = tuple (i + running_indices [0 ] for i in range (tensor_type [0 ]))
686+ index_map += tuple (i + running_indices [1 ] for i in range (tensor_type [1 ]))
687+ index_maps .append (index_map )
688+
689+ if tensor_type [0 ] + tensor_type [1 ] > 1 :
690+ basis_sym = factor ._basis_sym ()
691+ all_indices = tuple (range (tensor_type [0 ] + tensor_type [1 ]))
692+ if isinstance (basis_sym , CompFullySym ):
693+ sym = [all_indices ]
694+ antisym = []
695+ elif isinstance (basis_sym , CompFullyAntiSym ):
696+ sym = []
697+ antisym = [all_indices ]
698+ elif isinstance (basis_sym , CompWithSym ):
699+ sym = basis_sym ._sym
700+ antisym = basis_sym ._antisym
701+ else :
702+ sym = antisym = []
703+
704+ def map_isym (isym ):
705+ return tuple (index_map [i ] for i in isym )
706+
707+ result_sym .extend (tuple (index_map [i ] for i in isym ) for isym in sym )
708+ result_antisym .extend (tuple (index_map [i ] for i in isym ) for isym in antisym )
709+
710+ running_indices += vector (tensor_type )
711+
712+ result = base_module .tensor_module (* result_tensor_type ,
713+ sym = result_sym , antisym = result_antisym )
714+ result ._index_maps = tuple (index_maps )
715+ return result
655716
656717 def rank (self ) -> int :
657718 r"""
@@ -760,7 +821,7 @@ def is_submodule(self, other):
760821 EXAMPLES::
761822
762823 sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
763- sage: N = FiniteRankFreeModule(ZZ, 4, name='M ')
824+ sage: N = FiniteRankFreeModule(ZZ, 4, name='N ')
764825 sage: M.is_submodule(M)
765826 True
766827 sage: M.is_submodule(N)
0 commit comments