Morphisms - Category Framework

Skip to content
Back to top
View this page
Edit this page

# Morphisms

This module defines the base classes of morphisms between objects of a given category.

EXAMPLES:

Typically, a morphism is defined by the images of the generators of the domain.

Sage

    sage: X.<a, b> = ZZ[]
    sage: Y.<c> = ZZ[]
    sage: X.hom([c, c^2])
    Ring morphism:
      From: Multivariate Polynomial Ring in a, b over Integer Ring
      To:   Univariate Polynomial Ring in c over Integer Ring
      Defn: a |--> c
            b |--> c^2

Python

    >>> from sage.all import *
    >>> X = ZZ['a, b']; (a, b,) = X._first_ngens(2)
    >>> Y = ZZ['c']; (c,) = Y._first_ngens(1)
    >>> X.hom([c, c**Integer(2)])
    Ring morphism:
      From: Multivariate Polynomial Ring in a, b over Integer Ring
      To:   Univariate Polynomial Ring in c over Integer Ring
      Defn: a |--> c
            b |--> c^2

AUTHORS:

- William Stein (2005): initial version

- David Joyner (2005-12-17): added examples

- Robert Bradshaw (2007-06-25): Pyrexification

class sage.categories.morphism.CallMorphism

  Bases: `Morphism`

class sage.categories.morphism.FormalCoercionMorphism

  Bases: `Morphism`

class sage.categories.morphism.IdentityMorphism

  Bases: `Morphism`

  is_identity()

    Return `True` if this morphism is the identity morphism.

    EXAMPLES:

    Sage

        sage: E = End(Partitions(5))                                                # needs sage.combinat
        sage: E.identity().is_identity()                                            # needs sage.combinat
        True

    Python

        >>> from sage.all import *
        >>> E = End(Partitions(Integer(5)))                                                # needs sage.combinat
        >>> E.identity().is_identity()                                            # needs sage.combinat
        True

    Check that Issue #15478 is fixed:

    Sage

        sage: # needs sage.rings.finite_rings
        sage: K.<z> = GF(4)
        sage: phi = End(K)([z^2])
        sage: R.<t> = K[]
        sage: psi = End(R)(phi)
        sage: psi.is_identity()
        False

    [Python]

        >>> from sage.all import *
        >>> # needs sage.rings.finite_rings
        >>> K = GF(Integer(4), names=('z',)); (z,) = K._first_ngens(1)
        >>> phi = End(K)([z**Integer(2)])
        >>> R = K['t']; (t,) = R._first_ngens(1)
        >>> psi = End(R)(phi)
        >>> psi.is_identity()
        False

  is_injective()

    Return whether this morphism is injective.

    EXAMPLES:

    Sage

        sage: Hom(ZZ, ZZ).identity().is_injective()
        True

    Python

        >>> from sage.all import *
        >>> Hom(ZZ, ZZ).identity().is_injective()
        True

  is_surjective()

    Return whether this morphism is surjective.

    EXAMPLES:

    Sage

        sage: Hom(ZZ, ZZ).identity().is_surjective()
        True

    Python

        >>> from sage.all import *
        >>> Hom(ZZ, ZZ).identity().is_surjective()
        True

  section()

    Return a section of this morphism.

    EXAMPLES:

    Sage

        sage: T = Hom(ZZ, ZZ).identity()
        sage: T.section() is T
        True

    Python

        >>> from sage.all import *
        >>> T = Hom(ZZ, ZZ).identity()
        >>> T.section() is T
        True

class sage.categories.morphism.Morphism

  Bases: `Map`

  category()

    Return the category of the parent of this morphism.

    EXAMPLES:

    Sage

        sage: R.<t> = ZZ[]
        sage: f = R.hom([t**2])
        sage: f.category()
        Category of endsets of unital magmas and right modules over
         (Dedekind domains and euclidean domains
          and noetherian rings
          and infinite enumerated sets and metric spaces)
         and left modules over
         (Dedekind domains and euclidean domains
          and noetherian rings
          and infinite enumerated sets and metric spaces)

        sage: # needs sage.rings.number_field
        sage: K = CyclotomicField(12)
        sage: L = CyclotomicField(132)
        sage: phi = L._internal_coerce_map_from(K)
        sage: phi.category()
        Category of homsets of number fields

    Python

        >>> from sage.all import *
        >>> R = ZZ['t']; (t,) = R._first_ngens(1)
        >>> f = R.hom([t**Integer(2)])
        >>> f.category()
        Category of endsets of unital magmas and right modules over
         (Dedekind domains and euclidean domains
          and noetherian rings
          and infinite enumerated sets and metric spaces)
         and left modules over
         (Dedekind domains and euclidean domains
          and noetherian rings
          and infinite enumerated sets and metric spaces)

        >>> # needs sage.rings.number_field
        >>> K = CyclotomicField(Integer(12))
        >>> L = CyclotomicField(Integer(132))
        >>> phi = L._internal_coerce_map_from(K)
        >>> phi.category()
        Category of homsets of number fields

  is_endomorphism()

    Return `True` if this morphism is an endomorphism.

    EXAMPLES:

    Sage

        sage: R.<t> = ZZ[]
        sage: f = R.hom([t])
        sage: f.is_endomorphism()
        True

        sage: # needs sage.rings.number_field
        sage: K = CyclotomicField(12)
        sage: L = CyclotomicField(132)
        sage: phi = L._internal_coerce_map_from(K)
        sage: phi.is_endomorphism()
        False

    Python

        >>> from sage.all import *
        >>> R = ZZ['t']; (t,) = R._first_ngens(1)
        >>> f = R.hom([t])
        >>> f.is_endomorphism()
        True

        >>> # needs sage.rings.number_field
        >>> K = CyclotomicField(Integer(12))
        >>> L = CyclotomicField(Integer(132))
        >>> phi = L._internal_coerce_map_from(K)
        >>> phi.is_endomorphism()
        False

  is_identity()

    Return `True` if this morphism is the identity morphism.

    Note

    Implemented only when the domain has a method gens()

    EXAMPLES:

    Sage

        sage: R.<t> = ZZ[]
        sage: f = R.hom([t])
        sage: f.is_identity()
        True
        sage: g = R.hom([t + 1])
        sage: g.is_identity()
        False

    Python

        >>> from sage.all import *
        >>> R = ZZ['t']; (t,) = R._first_ngens(1)
        >>> f = R.hom([t])
        >>> f.is_identity()
        True
        >>> g = R.hom([t + Integer(1)])
        >>> g.is_identity()
        False

    A morphism between two different spaces cannot be the identity:

    Sage

        sage: R2.<t2> = QQ[]
        sage: h = R.hom([t2])
        sage: h.is_identity()
        False

    [Python]

        >>> from sage.all import *
        >>> R2 = QQ['t2']; (t2,) = R2._first_ngens(1)
        >>> h = R.hom([t2])
        >>> h.is_identity()
        False

  pushforward(I)
  register_as_coercion()

    Register this morphism as a coercion to Sage’s coercion model (see `sage.structure.coerce`).

    EXAMPLES:

    By default, adding polynomials over different variables triggers an error:

    Sage

        sage: X.<x> = ZZ[]
        sage: Y.<y> = ZZ[]
        sage: x^2 + y
        Traceback (most recent call last):
        ...
        TypeError: unsupported operand parent(s) for +:
        'Univariate Polynomial Ring in x over Integer Ring' and
        'Univariate Polynomial Ring in y over Integer Ring'

    Python

        >>> from sage.all import *
        >>> X = ZZ['x']; (x,) = X._first_ngens(1)
        >>> Y = ZZ['y']; (y,) = Y._first_ngens(1)
        >>> x**Integer(2) + y
        Traceback (most recent call last):
        ...
        TypeError: unsupported operand parent(s) for +:
        'Univariate Polynomial Ring in x over Integer Ring' and
        'Univariate Polynomial Ring in y over Integer Ring'

    Let us declare a coercion from \(\ZZ[x]\) to \(\ZZ[z]\):

    Sage

        sage: Z.<z> = ZZ[]
        sage: phi = Hom(X, Z)(z)
        sage: phi(x^2+1)
        z^2 + 1
        sage: phi.register_as_coercion()

    [Python]

        >>> from sage.all import *
        >>> Z = ZZ['z']; (z,) = Z._first_ngens(1)
        >>> phi = Hom(X, Z)(z)
        >>> phi(x**Integer(2)+Integer(1))
        z^2 + 1
        >>> phi.register_as_coercion()

    Now we can add elements from \(\ZZ[x]\) and \(\ZZ[z]\), because the elements of the former are allowed to be implicitly coerced into the later:

    Sage

        sage: x^2 + z
        z^2 + z

    Python

        >>> from sage.all import *
        >>> x**Integer(2) + z
        z^2 + z

    Caveat: the registration of the coercion must be done before any other coercion is registered or discovered:

    Sage

        sage: phi = Hom(X, Z)(z^2)
        sage: phi.register_as_coercion()
        Traceback (most recent call last):
        ...
        AssertionError: coercion from Univariate Polynomial Ring in x over Integer Ring
        to Univariate Polynomial Ring in z over Integer Ring
        already registered or discovered

    [Python]

        >>> from sage.all import *
        >>> phi = Hom(X, Z)(z**Integer(2))
        >>> phi.register_as_coercion()
        Traceback (most recent call last):
        ...
        AssertionError: coercion from Univariate Polynomial Ring in x over Integer Ring
        to Univariate Polynomial Ring in z over Integer Ring
        already registered or discovered

  register_as_conversion()

    Register this morphism as a conversion to Sage’s coercion model.

    (see `sage.structure.coerce`).

    EXAMPLES:

    Let us declare a conversion from the symmetric group to \(\ZZ\) through the sign map:

    Sage

        sage: # needs sage.groups
        sage: S = SymmetricGroup(4)
        sage: phi = Hom(S, ZZ)(lambda x: ZZ(x.sign()))
        sage: x = S.an_element(); x
        (2,3,4)
        sage: phi(x)
        1
        sage: phi.register_as_conversion()
        sage: ZZ(x)
        1

    Python

        >>> from sage.all import *
        >>> # needs sage.groups
        >>> S = SymmetricGroup(Integer(4))
        >>> phi = Hom(S, ZZ)(lambda x: ZZ(x.sign()))
        >>> x = S.an_element(); x
        (2,3,4)
        >>> phi(x)
        1
        >>> phi.register_as_conversion()
        >>> ZZ(x)
        1

class sage.categories.morphism.SetIsomorphism

  Bases: `SetMorphism`

  An isomorphism of sets.

  INPUT:

  - `parent` – a Homset

  - `function` – a Python function that takes elements of the domain as input and returns elements of the codomain

  EXAMPLES:

  Sage

      sage: f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()),
      ....:                                             operator.__neg__); f
      Generic endomorphism of Integer Ring
      sage: f._set_inverse(f)
      sage: ~f is f
      True

  Python

      >>> from sage.all import *
      >>> f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()),
      ...                                             operator.__neg__); f
      Generic endomorphism of Integer Ring
      >>> f._set_inverse(f)
      >>> ~f is f
      True

  is_injective()

    Return whether this morphism is injective.

    EXAMPLES:

    Sage

        sage: f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()),
        ....:                                             operator.__neg__)
        sage: f.is_injective()
        True

    Python

        >>> from sage.all import *
        >>> f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()),
        ...                                             operator.__neg__)
        >>> f.is_injective()
        True

  is_surjective()

    Return whether this morphism is surjective.

    EXAMPLES:

    Sage

        sage: f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()),
        ....:                                             operator.__neg__)
        sage: f.is_surjective()
        True

    Python

        >>> from sage.all import *
        >>> f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()),
        ...                                             operator.__neg__)
        >>> f.is_surjective()
        True

  section()

    Return a section of this morphism.

    EXAMPLES:

    Sage

        sage: f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()),
        ....:                                             operator.__neg__)
        sage: f._set_inverse(f)
        sage: f.section() is f
        True

    Python

        >>> from sage.all import *
        >>> f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()),
        ...                                             operator.__neg__)
        >>> f._set_inverse(f)
        >>> f.section() is f
        True

class sage.categories.morphism.SetMorphism

  Bases: `Morphism`

  INPUT:

  - `parent` – a Homset

  - `function` – a Python function that takes elements of the domain as input and returns elements of the codomain

  EXAMPLES:

  Sage

      sage: from sage.categories.morphism import SetMorphism
      sage: f = SetMorphism(Hom(QQ, ZZ, Sets()), numerator)
      sage: f.parent()
      Set of Morphisms from Rational Field to Integer Ring in Category of sets
      sage: f.domain()
      Rational Field
      sage: f.codomain()
      Integer Ring
      sage: TestSuite(f).run()

  Python

      >>> from sage.all import *
      >>> from sage.categories.morphism import SetMorphism
      >>> f = SetMorphism(Hom(QQ, ZZ, Sets()), numerator)
      >>> f.parent()
      Set of Morphisms from Rational Field to Integer Ring in Category of sets
      >>> f.domain()
      Rational Field
      >>> f.codomain()
      Integer Ring
      >>> TestSuite(f).run()

sage.categories.morphism.is_Morphism(x)