diff --git a/src/sage/algebras/schur_algebra.py b/src/sage/algebras/schur_algebra.py index ba606ded999..b716db0ce94 100644 --- a/src/sage/algebras/schur_algebra.py +++ b/src/sage/algebras/schur_algebra.py @@ -454,6 +454,19 @@ def _repr_(self): msg += " over {}" return msg.format(self._r, self._n, self.base_ring()) + def construction(self): + """ + Return ``None``. + + There is no functorial construction for ``self``. + + EXAMPLES:: + + sage: T = SchurTensorModule(QQ, 2, 3) + sage: T.construction() + """ + return None + def _monomial_product(self, xi, v): """ Result of acting by the basis element ``xi`` of the corresponding @@ -581,11 +594,11 @@ def GL_irreducible_character(n, mu, KK): A = M._schur SGA = M._sga - #make ST the superstandard tableau of shape mu + # make ST the superstandard tableau of shape mu from sage.combinat.tableau import from_shape_and_word ST = from_shape_and_word(mu, list(range(1, r + 1)), convention='English') - #make ell the reading word of the highest weight tableau of shape mu + # make ell the reading word of the highest weight tableau of shape mu ell = [i + 1 for i, l in enumerate(mu) for dummy in range(l)] e = M.basis()[tuple(ell)] # the element e_l @@ -607,17 +620,17 @@ def GL_irreducible_character(n, mu, KK): y = A.basis()[schur_rep] * e # M.action_by_Schur_alg(A.basis()[schur_rep], e) carter_lusztig.append(y.to_vector()) - #Therefore, we now have carter_lusztig as a list giving the basis - #of `V_\mu` + # Therefore, we now have carter_lusztig as a list giving the basis + # of `V_\mu` - #We want to think of expressing this character as a sum of monomial - #symmetric functions. + # We want to think of expressing this character as a sum of monomial + # symmetric functions. - #We will determine a basis element for each m_\lambda in the - #character, and we want to keep track of them by \lambda. + # We will determine a basis element for each m_\lambda in the + # character, and we want to keep track of them by \lambda. - #That means that we only want to pick out the basis elements above for - #those semistandard words whose content is a partition. + # That means that we only want to pick out the basis elements above for + # those semistandard words whose content is a partition. contents = Partitions(r, max_length=n).list() # all partitions of r, length at most n @@ -648,15 +661,15 @@ def GL_irreducible_character(n, mu, KK): except ValueError: pass - #There is an inner product on the Carter-Lusztig module V_\mu; its - #maximal submodule is exactly the kernel of the inner product. + # There is an inner product on the Carter-Lusztig module V_\mu; its + # maximal submodule is exactly the kernel of the inner product. - #Now, for each possible partition content, we look at the graded piece of - #that degree, and we record how these elements pair with each of the - #elements of carter_lusztig. + # Now, for each possible partition content, we look at the graded piece of + # that degree, and we record how these elements pair with each of the + # elements of carter_lusztig. - #The kernel of this pairing is the part of this graded piece which is - #not in the irreducible module for \mu. + # The kernel of this pairing is the part of this graded piece which is + # not in the irreducible module for \mu. length = len(carter_lusztig) diff --git a/src/sage/categories/modules.py b/src/sage/categories/modules.py index d37b4812209..21ee46b24f1 100644 --- a/src/sage/categories/modules.py +++ b/src/sage/categories/modules.py @@ -12,6 +12,7 @@ # ***************************************************************************** from sage.misc.cachefunc import cached_method +from sage.misc.abstract_method import abstract_method from sage.misc.lazy_import import LazyImport from sage.categories.category_with_axiom import CategoryWithAxiom_over_base_ring from sage.categories.morphism import SetMorphism @@ -19,7 +20,7 @@ from sage.categories.homset import Hom from .category import Category from .category_types import Category_module -from sage.categories.tensor import TensorProductsCategory, tensor +from sage.categories.tensor import TensorProductsCategory, TensorProductFunctor, tensor from .dual import DualObjectsCategory from sage.categories.cartesian_product import CartesianProductsCategory from sage.categories.sets_cat import Sets @@ -891,3 +892,55 @@ def extra_super_categories(self): [Category of modules over Integer Ring] """ return [self.base_category()] + + class ParentMethods: + """ + Implement operations on tensor products of modules. + """ + def construction(self): + """ + Return the construction of ``self``. + + EXAMPLES:: + + sage: A = algebras.Free(QQ,2) + sage: T = A.tensor(A) + sage: T.construction() + (The tensor functorial construction, + (Free Algebra on 2 generators (None0, None1) over Rational Field, + Free Algebra on 2 generators (None0, None1) over Rational Field)) + """ + try: + factors = self.tensor_factors() + except (TypeError, NotImplementedError): + from sage.misc.superseded import deprecation + deprecation(34393, "implementations of Modules().TensorProducts() now must define the method tensor_factors") + return None + return (TensorProductFunctor(), + factors) + + @abstract_method(optional=True) + def tensor_factors(self): + """ + Return the tensor factors of this tensor product. + + EXAMPLES:: + + sage: F = CombinatorialFreeModule(ZZ, [1,2]) + sage: F.rename("F") + sage: G = CombinatorialFreeModule(ZZ, [3,4]) + sage: G.rename("G") + sage: T = tensor([F, G]); T + F # G + sage: T.tensor_factors() + (F, G) + + TESTS:: + + sage: M = CombinatorialFreeModule(ZZ, ((1, 1), (1, 2), (2, 1), (2, 2)), + ....: category=ModulesWithBasis(ZZ).FiniteDimensional().TensorProducts()) + sage: M.construction() + doctest:warning... + DeprecationWarning: implementations of Modules().TensorProducts() now must define the method tensor_factors + See https://trac.sagemath.org/34393 for details. + """ diff --git a/src/sage/combinat/free_module.py b/src/sage/combinat/free_module.py index f11f9b81499..d6042d6facc 100644 --- a/src/sage/combinat/free_module.py +++ b/src/sage/combinat/free_module.py @@ -1183,8 +1183,8 @@ class CombinatorialFreeModule_Tensor(CombinatorialFreeModule): We construct two free modules, assign them short names, and construct their tensor product:: - sage: F = CombinatorialFreeModule(ZZ, [1,2]); F.__custom_name = "F" - sage: G = CombinatorialFreeModule(ZZ, [3,4]); G.__custom_name = "G" + sage: F = CombinatorialFreeModule(ZZ, [1,2]); F.rename("F") + sage: G = CombinatorialFreeModule(ZZ, [3,4]); G.rename("G") sage: T = tensor([F, G]); T F # G @@ -1330,6 +1330,23 @@ def _repr_(self): return symb.join("%s" % module for module in self._sets) # TODO: make this overridable by setting _name + def tensor_factors(self): + """ + Return the tensor factors of this tensor product. + + EXAMPLES:: + + sage: F = CombinatorialFreeModule(ZZ, [1,2]) + sage: F.rename("F") + sage: G = CombinatorialFreeModule(ZZ, [3,4]) + sage: G.rename("G") + sage: T = tensor([F, G]); T + F # G + sage: T.tensor_factors() + (F, G) + """ + return self._sets + def _ascii_art_(self, term): """ TESTS:: @@ -1454,8 +1471,8 @@ def tensor_constructor(self, modules): EXAMPLES:: - sage: F = CombinatorialFreeModule(ZZ, [1,2]); F.__custom_name = "F" - sage: G = CombinatorialFreeModule(ZZ, [3,4]); G.__custom_name = "G" + sage: F = CombinatorialFreeModule(ZZ, [1,2]); F.rename("F") + sage: G = CombinatorialFreeModule(ZZ, [3,4]); G.rename("G") sage: H = CombinatorialFreeModule(ZZ, [5,6]); H.rename("H") sage: f = F.monomial(1) + 2 * F.monomial(2) @@ -1494,8 +1511,8 @@ def _tensor_of_elements(self, elements): EXAMPLES:: - sage: F = CombinatorialFreeModule(ZZ, [1,2]); F.__custom_name = "F" - sage: G = CombinatorialFreeModule(ZZ, [3,4]); G.__custom_name = "G" + sage: F = CombinatorialFreeModule(ZZ, [1,2]); F.rename("F") + sage: G = CombinatorialFreeModule(ZZ, [3,4]); G.rename("G") sage: H = CombinatorialFreeModule(ZZ, [5,6]); H.rename("H") sage: f = F.monomial(1) + 2 * F.monomial(2) @@ -1629,9 +1646,9 @@ class CombinatorialFreeModule_CartesianProduct(CombinatorialFreeModule): We construct two free modules, assign them short names, and construct their Cartesian product:: - sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.__custom_name = "F" - sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.__custom_name = "G" - sage: H = CombinatorialFreeModule(ZZ, [4,7]); H.__custom_name = "H" + sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.rename("F") + sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.rename("G") + sage: H = CombinatorialFreeModule(ZZ, [4,7]); H.rename("H") sage: S = cartesian_product([F, G]) sage: S F (+) G @@ -1703,7 +1720,7 @@ def _repr_(self): sage: F = CombinatorialFreeModule(ZZ, [2,4,5]) sage: CP = cartesian_product([F, F]); CP # indirect doctest Free module generated by {2, 4, 5} over Integer Ring (+) Free module generated by {2, 4, 5} over Integer Ring - sage: F.__custom_name = "F"; CP + sage: F.rename("F"); CP F (+) F """ from sage.categories.cartesian_product import cartesian_product @@ -1723,8 +1740,8 @@ def cartesian_embedding(self, i): EXAMPLES:: - sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.__custom_name = "F" - sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.__custom_name = "G" + sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.rename("F") + sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.rename("G") sage: S = cartesian_product([F, G]) sage: phi = S.cartesian_embedding(0) sage: phi(F.monomial(4) + 2 * F.monomial(5)) @@ -1757,8 +1774,8 @@ def cartesian_projection(self, i): EXAMPLES:: - sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.__custom_name = "F" - sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.__custom_name = "G" + sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.rename("F") + sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.rename("G") sage: S = cartesian_product([F, G]) sage: x = S.monomial((0,4)) + 2 * S.monomial((0,5)) + 3 * S.monomial((1,6)) sage: S.cartesian_projection(0)(x) @@ -1787,8 +1804,8 @@ def _cartesian_product_of_elements(self, elements): EXAMPLES:: - sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.__custom_name = "F" - sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.__custom_name = "G" + sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.rename("F") + sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.rename("G") sage: S = cartesian_product([F, G]) sage: f = F.monomial(4) + 2 * F.monomial(5) sage: g = 2*G.monomial(4) + G.monomial(6) @@ -1826,12 +1843,11 @@ def cartesian_factors(self): EXAMPLES:: - sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.__custom_name = "F" - sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.__custom_name = "G" + sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.rename("F") + sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.rename("G") sage: S = cartesian_product([F, G]) sage: S.cartesian_factors() (F, G) - """ return self._sets