Skip to content

Commit

Permalink
Trac #30180: Category Modules should provide a parent method module_m…
Browse files Browse the repository at this point in the history
…orphism compatible with ModulesWithBasis.module_morphism

Because there is no distinguished basis, it would only support the
option `function` of `ModulesWithBasis.module_morphism`:

{{{
        def module_morphism(self, on_basis=None, matrix=None,
function=None,
                            diagonal=None, triangular=None,
unitriangular=False,
                            **keywords):
            r"""
            Construct a module morphism from ``self`` to ``codomain``.

            Let ``self`` be a module `X` with a basis indexed by `I`.
            This constructs a morphism `f: X \to Y` by linearity from
            a map `I \to Y` which is to be its restriction to the
            basis `(x_i)_{i \in I}` of `X`. Some variants are possible
            too.

            INPUT:

            - ``self`` -- a parent `X` in ``ModulesWithBasis(R)`` with
              basis `x=(x_i)_{i\in I}`.

            Exactly one of the four following options must be
            specified in order to define the morphism:

            - ``on_basis`` -- a function `f` from `I` to `Y`
            - ``diagonal`` -- a function `d` from `I` to `R`
*KEEP*      - ``function`` -- a function `f` from `X` to `Y`
            - ``matrix``   -- a matrix of size `\dim Y \times \dim X`
              (if the keyword ``side`` is set to ``'left'``) or
              `\dim Y \times \dim X` (if this keyword is ``'right'``)

            Further options include:

*KEEP*      - ``codomain`` -- the codomain `Y` of the morphism (default:
              ``f.codomain()`` if it's defined; otherwise it must be
specified)

*KEEP*      - ``category`` -- a category or ``None`` (default: `None``)

            - ``zero`` -- the zero of the codomain (default:
``codomain.zero()``);
              can be used (with care) to define affine maps.
              Only meaningful with ``on_basis``.

            - ``position`` -- a non-negative integer specifying which
              positional argument is used as the input of the function
`f`
              (default: 0); this is currently only used with
``on_basis``.

            - ``triangular`` --  (default: ``None``) ``"upper"`` or
              ``"lower"`` or ``None``:

              * ``"upper"`` - if the
                :meth:`~ModulesWithBasis.ElementMethods.leading_support`
                of the image of the basis vector `x_i` is `i`, or

              * ``"lower"`` - if the
:meth:`~ModulesWithBasis.ElementMethods.trailing_support`
                of the image of the basis vector `x_i` is `i`.

            - ``unitriangular`` -- (default: ``False``) a boolean.
              Only meaningful for a triangular morphism.
              As a shorthand, one may use ``unitriangular="lower"``
              for ``triangular="lower", unitriangular=True``.

            - ``side`` -- "left" or "right" (default: "left")
              Only meaningful for a morphism built from a matrix.

}}}

URL: https://trac.sagemath.org/30180
Reported by: mkoeppe
Ticket author(s): Matthias Koeppe
Reviewer(s): Eric Gourgoulhon
  • Loading branch information
Release Manager committed Jul 28, 2020
2 parents abd54ac + e2fc5d5 commit 7be09f6
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 1 deletion.
37 changes: 37 additions & 0 deletions src/sage/categories/modules.py
Expand Up @@ -15,7 +15,9 @@
from sage.misc.cachefunc import cached_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
from sage.categories.homsets import HomsetsCategory
from sage.categories.homset import Hom
from .category import Category
from .category_types import Category_module
from sage.categories.tensor import TensorProductsCategory, tensor
Expand Down Expand Up @@ -570,6 +572,41 @@ def tensor_square(self):
"""
return tensor([self, self])

def module_morphism(self, *, function, category=None, codomain, **keywords):
r"""
Construct a module morphism from ``self`` to ``codomain``.
Let ``self`` be a module `X` over a ring `R`.
This constructs a morphism `f: X \to Y`.
INPUT:
- ``self`` -- a parent `X` in ``Modules(R)``.
- ``function`` -- a function `f` from `X` to `Y`
- ``codomain`` -- the codomain `Y` of the morphism (default:
``f.codomain()`` if it's defined; otherwise it must be specified)
- ``category`` -- a category or ``None`` (default: ``None``)
EXAMPLES::
sage: V = FiniteRankFreeModule(QQ, 2)
sage: e = V.basis('e'); e
Basis (e_0,e_1) on the 2-dimensional vector space over the Rational Field
sage: neg = V.module_morphism(function=operator.neg, codomain=V); neg
Generic endomorphism of 2-dimensional vector space over the Rational Field
sage: neg(e[0])
Element -e_0 of the 2-dimensional vector space over the Rational Field
"""
# Make sure that we only create a module morphism, even if
# domain and codomain have more structure
if category is None:
category = Modules(self.base_ring())
return SetMorphism(Hom(self, codomain, category), function)

class ElementMethods:
pass

Expand Down
2 changes: 1 addition & 1 deletion src/sage/categories/modules_with_basis.py
Expand Up @@ -255,7 +255,7 @@ def module_morphism(self, on_basis=None, matrix=None, function=None,
- ``codomain`` -- the codomain `Y` of the morphism (default:
``f.codomain()`` if it's defined; otherwise it must be specified)
- ``category`` -- a category or ``None`` (default: `None``)
- ``category`` -- a category or ``None`` (default: ``None``)
- ``zero`` -- the zero of the codomain (default: ``codomain.zero()``);
can be used (with care) to define affine maps.
Expand Down

0 comments on commit 7be09f6

Please sign in to comment.