Base class for maps

AUTHORS:

class sage.categories.map.FormalCompositeMap[source]

Bases: Map

Formal composite maps.

A formal composite map is formed by two maps, so that the codomain of the first map is contained in the domain of the second map.

Note

When calling a composite with additional arguments, these arguments are only passed to the second underlying map.

EXAMPLES:

sage: R.<x> = QQ[]
sage: S.<a> = QQ[]
sage: from sage.categories.morphism import SetMorphism
sage: f = SetMorphism(Hom(R, S, Rings()), lambda p: p[0]*a^p.degree())
sage: g = S.hom([2*x])
sage: f*g
Composite map:
  From: Univariate Polynomial Ring in a over Rational Field
  To:   Univariate Polynomial Ring in a over Rational Field
  Defn:   Ring morphism:
          From: Univariate Polynomial Ring in a over Rational Field
          To:   Univariate Polynomial Ring in x over Rational Field
          Defn: a |--> 2*x
        then
          Generic morphism:
          From: Univariate Polynomial Ring in x over Rational Field
          To:   Univariate Polynomial Ring in a over Rational Field
sage: g*f
Composite map:
  From: Univariate Polynomial Ring in x over Rational Field
  To:   Univariate Polynomial Ring in x over Rational Field
  Defn:   Generic morphism:
          From: Univariate Polynomial Ring in x over Rational Field
          To:   Univariate Polynomial Ring in a over Rational Field
        then
          Ring morphism:
          From: Univariate Polynomial Ring in a over Rational Field
          To:   Univariate Polynomial Ring in x over Rational Field
          Defn: a |--> 2*x
sage: (f*g)(2*a^2+5)
5*a^2
sage: (g*f)(2*x^2+5)
20*x^2
>>> from sage.all import *
>>> R = QQ['x']; (x,) = R._first_ngens(1)
>>> S = QQ['a']; (a,) = S._first_ngens(1)
>>> from sage.categories.morphism import SetMorphism
>>> f = SetMorphism(Hom(R, S, Rings()), lambda p: p[Integer(0)]*a**p.degree())
>>> g = S.hom([Integer(2)*x])
>>> f*g
Composite map:
  From: Univariate Polynomial Ring in a over Rational Field
  To:   Univariate Polynomial Ring in a over Rational Field
  Defn:   Ring morphism:
          From: Univariate Polynomial Ring in a over Rational Field
          To:   Univariate Polynomial Ring in x over Rational Field
          Defn: a |--> 2*x
        then
          Generic morphism:
          From: Univariate Polynomial Ring in x over Rational Field
          To:   Univariate Polynomial Ring in a over Rational Field
>>> g*f
Composite map:
  From: Univariate Polynomial Ring in x over Rational Field
  To:   Univariate Polynomial Ring in x over Rational Field
  Defn:   Generic morphism:
          From: Univariate Polynomial Ring in x over Rational Field
          To:   Univariate Polynomial Ring in a over Rational Field
        then
          Ring morphism:
          From: Univariate Polynomial Ring in a over Rational Field
          To:   Univariate Polynomial Ring in x over Rational Field
          Defn: a |--> 2*x
>>> (f*g)(Integer(2)*a**Integer(2)+Integer(5))
5*a^2
>>> (g*f)(Integer(2)*x**Integer(2)+Integer(5))
20*x^2
domains()[source]

Iterate over the domains of the factors of this map.

(This is useful in particular to check for loops in coercion maps.)

See also

Map.domains()

EXAMPLES:

sage: f = QQ.coerce_map_from(ZZ)
sage: g = MatrixSpace(QQ, 2, 2).coerce_map_from(QQ)                         # needs sage.modules
sage: list((g * f).domains())                                               # needs sage.modules
[Integer Ring, Rational Field]
>>> from sage.all import *
>>> f = QQ.coerce_map_from(ZZ)
>>> g = MatrixSpace(QQ, Integer(2), Integer(2)).coerce_map_from(QQ)                         # needs sage.modules
>>> list((g * f).domains())                                               # needs sage.modules
[Integer Ring, Rational Field]
first()[source]

Return the first map in the formal composition.

If self represents \(f_n \circ f_{n-1} \circ \cdots \circ f_1 \circ f_0\), then self.first() returns \(f_0\). We have self == self.then() * self.first().

EXAMPLES:

sage: R.<x> = QQ[]
sage: S.<a> = QQ[]
sage: from sage.categories.morphism import SetMorphism
sage: f = SetMorphism(Hom(R, S, Rings()), lambda p: p[0]*a^p.degree())
sage: g = S.hom([2*x])
sage: fg = f * g
sage: fg.first() == g
True
sage: fg == fg.then() * fg.first()
True
>>> from sage.all import *
>>> R = QQ['x']; (x,) = R._first_ngens(1)
>>> S = QQ['a']; (a,) = S._first_ngens(1)
>>> from sage.categories.morphism import SetMorphism
>>> f = SetMorphism(Hom(R, S, Rings()), lambda p: p[Integer(0)]*a**p.degree())
>>> g = S.hom([Integer(2)*x])
>>> fg = f * g
>>> fg.first() == g
True
>>> fg == fg.then() * fg.first()
True
is_injective()[source]

Tell whether self is injective.

It raises NotImplementedError if it cannot be determined.

EXAMPLES:

sage: # needs sage.modules
sage: V1 = QQ^2
sage: V2 = QQ^3
sage: phi1 = (QQ^1).hom(Matrix([[1, 1]]), V1)
sage: phi2 = V1.hom(Matrix([[1, 2, 3], [4, 5, 6]]), V2)
>>> from sage.all import *
>>> # needs sage.modules
>>> V1 = QQ**Integer(2)
>>> V2 = QQ**Integer(3)
>>> phi1 = (QQ**Integer(1)).hom(Matrix([[Integer(1), Integer(1)]]), V1)
>>> phi2 = V1.hom(Matrix([[Integer(1), Integer(2), Integer(3)], [Integer(4), Integer(5), Integer(6)]]), V2)

If both constituents are injective, the composition is injective:

sage: from sage.categories.map import FormalCompositeMap
sage: c1 = FormalCompositeMap(Hom(QQ^1, V2, phi1.category_for()),           # needs sage.modules
....:                         phi1, phi2)
sage: c1.is_injective()                                                     # needs sage.modules
True
>>> from sage.all import *
>>> from sage.categories.map import FormalCompositeMap
>>> c1 = FormalCompositeMap(Hom(QQ**Integer(1), V2, phi1.category_for()),           # needs sage.modules
...                         phi1, phi2)
>>> c1.is_injective()                                                     # needs sage.modules
True

If it cannot be determined whether the composition is injective, an error is raised:

sage: psi1 = V2.hom(Matrix([[1, 2], [3, 4], [5, 6]]), V1)                   # needs sage.modules
sage: c2 = FormalCompositeMap(Hom(V1, V1, phi2.category_for()),             # needs sage.modules
....:                         phi2, psi1)
sage: c2.is_injective()                                                     # needs sage.modules
Traceback (most recent call last):
...
NotImplementedError: not enough information to deduce injectivity
>>> from sage.all import *
>>> psi1 = V2.hom(Matrix([[Integer(1), Integer(2)], [Integer(3), Integer(4)], [Integer(5), Integer(6)]]), V1)                   # needs sage.modules
>>> c2 = FormalCompositeMap(Hom(V1, V1, phi2.category_for()),             # needs sage.modules
...                         phi2, psi1)
>>> c2.is_injective()                                                     # needs sage.modules
Traceback (most recent call last):
...
NotImplementedError: not enough information to deduce injectivity

If the first map is surjective and the second map is not injective, then the composition is not injective:

sage: psi2 = V1.hom([[1], [1]], QQ^1)                                       # needs sage.modules
sage: c3 = FormalCompositeMap(Hom(V2, QQ^1, phi2.category_for()),           # needs sage.modules
....:                         psi2, psi1)
sage: c3.is_injective()                                                     # needs sage.modules
False
>>> from sage.all import *
>>> psi2 = V1.hom([[Integer(1)], [Integer(1)]], QQ**Integer(1))                                       # needs sage.modules
>>> c3 = FormalCompositeMap(Hom(V2, QQ**Integer(1), phi2.category_for()),           # needs sage.modules
...                         psi2, psi1)
>>> c3.is_injective()                                                     # needs sage.modules
False
is_surjective()[source]

Tell whether self is surjective.

It raises NotImplementedError if it cannot be determined.

EXAMPLES:

sage: from sage.categories.map import FormalCompositeMap
sage: V3 = QQ^3                                                             # needs sage.modules
sage: V2 = QQ^2                                                             # needs sage.modules
sage: V1 = QQ^1                                                             # needs sage.modules
>>> from sage.all import *
>>> from sage.categories.map import FormalCompositeMap
>>> V3 = QQ**Integer(3)                                                             # needs sage.modules
>>> V2 = QQ**Integer(2)                                                             # needs sage.modules
>>> V1 = QQ**Integer(1)                                                             # needs sage.modules

If both maps are surjective, the composition is surjective:

sage: # needs sage.modules
sage: phi32 = V3.hom(Matrix([[1, 2], [3, 4], [5, 6]]), V2)
sage: phi21 = V2.hom(Matrix([[1], [1]]), V1)
sage: c_phi = FormalCompositeMap(Hom(V3, V1, phi32.category_for()),
....:                            phi32, phi21)
sage: c_phi.is_surjective()
True
>>> from sage.all import *
>>> # needs sage.modules
>>> phi32 = V3.hom(Matrix([[Integer(1), Integer(2)], [Integer(3), Integer(4)], [Integer(5), Integer(6)]]), V2)
>>> phi21 = V2.hom(Matrix([[Integer(1)], [Integer(1)]]), V1)
>>> c_phi = FormalCompositeMap(Hom(V3, V1, phi32.category_for()),
...                            phi32, phi21)
>>> c_phi.is_surjective()
True

If the second map is not surjective, the composition is not surjective:

sage: FormalCompositeMap(Hom(V3, V1, phi32.category_for()),                 # needs sage.modules
....:                    phi32,
....:                    V2.hom(Matrix([[0], [0]]), V1)).is_surjective()
False
>>> from sage.all import *
>>> FormalCompositeMap(Hom(V3, V1, phi32.category_for()),                 # needs sage.modules
...                    phi32,
...                    V2.hom(Matrix([[Integer(0)], [Integer(0)]]), V1)).is_surjective()
False

If the second map is an isomorphism and the first map is not surjective, then the composition is not surjective:

sage: FormalCompositeMap(Hom(V2, V1, phi32.category_for()),                 # needs sage.modules
....:                    V2.hom(Matrix([[0], [0]]), V1),
....:                    V1.hom(Matrix([[1]]), V1)).is_surjective()
False
>>> from sage.all import *
>>> FormalCompositeMap(Hom(V2, V1, phi32.category_for()),                 # needs sage.modules
...                    V2.hom(Matrix([[Integer(0)], [Integer(0)]]), V1),
...                    V1.hom(Matrix([[Integer(1)]]), V1)).is_surjective()
False

Otherwise, surjectivity of the composition cannot be determined:

sage: FormalCompositeMap(Hom(V2, V1, phi32.category_for()),                 # needs sage.modules
....:     V2.hom(Matrix([[1, 1], [1, 1]]), V2),
....:     V2.hom(Matrix([[1], [1]]), V1)).is_surjective()
Traceback (most recent call last):
...
NotImplementedError: not enough information to deduce surjectivity
>>> from sage.all import *
>>> FormalCompositeMap(Hom(V2, V1, phi32.category_for()),                 # needs sage.modules
...     V2.hom(Matrix([[Integer(1), Integer(1)], [Integer(1), Integer(1)]]), V2),
...     V2.hom(Matrix([[Integer(1)], [Integer(1)]]), V1)).is_surjective()
Traceback (most recent call last):
...
NotImplementedError: not enough information to deduce surjectivity
section()[source]

Compute a section map from sections of the factors of self if they have been implemented.

EXAMPLES:

sage: P.<x> = QQ[]
sage: incl = P.coerce_map_from(ZZ)
sage: sect = incl.section(); sect
Composite map:
  From: Univariate Polynomial Ring in x over Rational Field
  To:   Integer Ring
  Defn:   Generic map:
          From: Univariate Polynomial Ring in x over Rational Field
          To:   Rational Field
        then
          Generic map:
          From: Rational Field
          To:   Integer Ring
sage: p = x + 5; q = x + 2
sage: sect(p-q)
3
>>> from sage.all import *
>>> P = QQ['x']; (x,) = P._first_ngens(1)
>>> incl = P.coerce_map_from(ZZ)
>>> sect = incl.section(); sect
Composite map:
  From: Univariate Polynomial Ring in x over Rational Field
  To:   Integer Ring
  Defn:   Generic map:
          From: Univariate Polynomial Ring in x over Rational Field
          To:   Rational Field
        then
          Generic map:
          From: Rational Field
          To:   Integer Ring
>>> p = x + Integer(5); q = x + Integer(2)
>>> sect(p-q)
3

the following example has been attached to _integer_() of sage.rings.polynomial.polynomial_element.Polynomial before (see comment there):

sage: k = GF(47)
sage: R.<x> = PolynomialRing(k)
sage: R.coerce_map_from(ZZ).section()
Composite map:
  From: Univariate Polynomial Ring in x over Finite Field of size 47
  To:   Integer Ring
  Defn:   Generic map:
          From: Univariate Polynomial Ring in x over Finite Field of size 47
          To:   Finite Field of size 47
        then
          Lifting map:
          From: Finite Field of size 47
          To:   Integer Ring
sage: ZZ(R(45))                 # indirect doctest
45
sage: ZZ(3*x + 45)              # indirect doctest
Traceback (most recent call last):
...
TypeError: 3*x + 45 is not a constant polynomial
>>> from sage.all import *
>>> k = GF(Integer(47))
>>> R = PolynomialRing(k, names=('x',)); (x,) = R._first_ngens(1)
>>> R.coerce_map_from(ZZ).section()
Composite map:
  From: Univariate Polynomial Ring in x over Finite Field of size 47
  To:   Integer Ring
  Defn:   Generic map:
          From: Univariate Polynomial Ring in x over Finite Field of size 47
          To:   Finite Field of size 47
        then
          Lifting map:
          From: Finite Field of size 47
          To:   Integer Ring
>>> ZZ(R(Integer(45)))                 # indirect doctest
45
>>> ZZ(Integer(3)*x + Integer(45))              # indirect doctest
Traceback (most recent call last):
...
TypeError: 3*x + 45 is not a constant polynomial
then()[source]

Return the tail of the list of maps.

If self represents \(f_n \circ f_{n-1} \circ \cdots \circ f_1 \circ f_0\), then self.first() returns \(f_n \circ f_{n-1} \circ \cdots \circ f_1\). We have self == self.then() * self.first().

EXAMPLES:

sage: R.<x> = QQ[]
sage: S.<a> = QQ[]
sage: from sage.categories.morphism import SetMorphism
sage: f = SetMorphism(Hom(R, S, Rings()), lambda p: p[0]*a^p.degree())
sage: g = S.hom([2*x])
sage: (f*g).then() == f
True

sage: f = QQ.coerce_map_from(ZZ)
sage: f = f.extend_domain(ZZ).extend_codomain(QQ)
sage: f.then()
Composite map:
From: Integer Ring
To:   Rational Field
Defn:   Natural morphism:
From: Integer Ring
To:   Rational Field
then
Identity endomorphism of Rational Field
>>> from sage.all import *
>>> R = QQ['x']; (x,) = R._first_ngens(1)
>>> S = QQ['a']; (a,) = S._first_ngens(1)
>>> from sage.categories.morphism import SetMorphism
>>> f = SetMorphism(Hom(R, S, Rings()), lambda p: p[Integer(0)]*a**p.degree())
>>> g = S.hom([Integer(2)*x])
>>> (f*g).then() == f
True

>>> f = QQ.coerce_map_from(ZZ)
>>> f = f.extend_domain(ZZ).extend_codomain(QQ)
>>> f.then()
Composite map:
From: Integer Ring
To:   Rational Field
Defn:   Natural morphism:
From: Integer Ring
To:   Rational Field
then
Identity endomorphism of Rational Field
class sage.categories.map.Map[source]

Bases: Element

Basic class for all maps.

Note

The call method is of course not implemented in this base class. This must be done in the sub classes, by overloading _call_ and possibly also _call_with_args.

EXAMPLES:

Usually, instances of this class will not be constructed directly, but for example like this:

sage: from sage.categories.morphism import SetMorphism
sage: X.<x> = ZZ[]
sage: Y = ZZ
sage: phi = SetMorphism(Hom(X, Y, Rings()), lambda p: p[0])
sage: phi(x^2+2*x-1)
-1
sage: R.<x,y> = QQ[]
sage: f = R.hom([x+y, x-y], R)
sage: f(x^2+2*x-1)
x^2 + 2*x*y + y^2 + 2*x + 2*y - 1
>>> from sage.all import *
>>> from sage.categories.morphism import SetMorphism
>>> X = ZZ['x']; (x,) = X._first_ngens(1)
>>> Y = ZZ
>>> phi = SetMorphism(Hom(X, Y, Rings()), lambda p: p[Integer(0)])
>>> phi(x**Integer(2)+Integer(2)*x-Integer(1))
-1
>>> R = QQ['x, y']; (x, y,) = R._first_ngens(2)
>>> f = R.hom([x+y, x-y], R)
>>> f(x**Integer(2)+Integer(2)*x-Integer(1))
x^2 + 2*x*y + y^2 + 2*x + 2*y - 1
category_for()[source]

Return the category self is a morphism for.

Note

This is different from the category of maps to which this map belongs as an object.

EXAMPLES:

sage: from sage.categories.morphism import SetMorphism
sage: X.<x> = ZZ[]
sage: Y = ZZ
sage: phi = SetMorphism(Hom(X, Y, Rings()), lambda p: p[0])
sage: phi.category_for()
Category of rings
sage: phi.category()
Category of homsets of unital magmas and additive unital additive magmas
sage: R.<x,y> = QQ[]
sage: f = R.hom([x+y, x-y], R)
sage: f.category_for()
Join of Category of unique factorization domains
 and Category of algebras with basis over
  (number fields and quotient fields and metric spaces)
 and Category of commutative algebras over
  (number fields and quotient fields and metric spaces)
 and Category of infinite sets
sage: f.category()
Category of endsets of unital magmas
 and right modules over (number fields and quotient fields and metric spaces)
 and left modules over (number fields and quotient fields and metric spaces)
>>> from sage.all import *
>>> from sage.categories.morphism import SetMorphism
>>> X = ZZ['x']; (x,) = X._first_ngens(1)
>>> Y = ZZ
>>> phi = SetMorphism(Hom(X, Y, Rings()), lambda p: p[Integer(0)])
>>> phi.category_for()
Category of rings
>>> phi.category()
Category of homsets of unital magmas and additive unital additive magmas
>>> R = QQ['x, y']; (x, y,) = R._first_ngens(2)
>>> f = R.hom([x+y, x-y], R)
>>> f.category_for()
Join of Category of unique factorization domains
 and Category of algebras with basis over
  (number fields and quotient fields and metric spaces)
 and Category of commutative algebras over
  (number fields and quotient fields and metric spaces)
 and Category of infinite sets
>>> f.category()
Category of endsets of unital magmas
 and right modules over (number fields and quotient fields and metric spaces)
 and left modules over (number fields and quotient fields and metric spaces)

FIXME: find a better name for this method

codomain[source]
domain[source]
domains()[source]

Iterate over the domains of the factors of a (composite) map.

This default implementation simply yields the domain of this map.

EXAMPLES:

sage: list(QQ.coerce_map_from(ZZ).domains())
[Integer Ring]
>>> from sage.all import *
>>> list(QQ.coerce_map_from(ZZ).domains())
[Integer Ring]
extend_codomain(new_codomain)[source]

INPUT:

  • self – a member of Hom(X, Y)

  • new_codomain – an object Z such that there is a canonical coercion \(\phi\) in Hom(Y, Z)

OUTPUT:

An element of Hom(X, Z) obtained by composing self with \(\phi\). If no canonical \(\phi\) exists, a TypeError is raised.

EXAMPLES:

sage: mor = QQ.coerce_map_from(ZZ)
sage: mor.extend_codomain(RDF)
Composite map:
  From: Integer Ring
  To:   Real Double Field
  Defn:   Natural morphism:
          From: Integer Ring
          To:   Rational Field
        then
          Native morphism:
          From: Rational Field
          To:   Real Double Field
sage: mor.extend_codomain(GF(7))
Traceback (most recent call last):
...
TypeError: No coercion from Rational Field to Finite Field of size 7
>>> from sage.all import *
>>> mor = QQ.coerce_map_from(ZZ)
>>> mor.extend_codomain(RDF)
Composite map:
  From: Integer Ring
  To:   Real Double Field
  Defn:   Natural morphism:
          From: Integer Ring
          To:   Rational Field
        then
          Native morphism:
          From: Rational Field
          To:   Real Double Field
>>> mor.extend_codomain(GF(Integer(7)))
Traceback (most recent call last):
...
TypeError: No coercion from Rational Field to Finite Field of size 7
extend_domain(new_domain)[source]

INPUT:

  • self – a member of Hom(Y, Z)

  • new_codomain – an object X such that there is a canonical coercion \(\phi\) in Hom(X, Y)

OUTPUT:

An element of Hom(X, Z) obtained by composing self with \(\phi\). If no canonical \(\phi\) exists, a TypeError is raised.

EXAMPLES:

sage: # needs sage.rings.complex_double
sage: mor = CDF.coerce_map_from(RDF)
sage: mor.extend_domain(QQ)
Composite map:
  From: Rational Field
  To:   Complex Double Field
  Defn:   Native morphism:
          From: Rational Field
          To:   Real Double Field
        then
          Native morphism:
          From: Real Double Field
          To:   Complex Double Field
sage: mor.extend_domain(ZZ['x'])
Traceback (most recent call last):
...
TypeError: No coercion from Univariate Polynomial Ring in x over Integer Ring
to Real Double Field
>>> from sage.all import *
>>> # needs sage.rings.complex_double
>>> mor = CDF.coerce_map_from(RDF)
>>> mor.extend_domain(QQ)
Composite map:
  From: Rational Field
  To:   Complex Double Field
  Defn:   Native morphism:
          From: Rational Field
          To:   Real Double Field
        then
          Native morphism:
          From: Real Double Field
          To:   Complex Double Field
>>> mor.extend_domain(ZZ['x'])
Traceback (most recent call last):
...
TypeError: No coercion from Univariate Polynomial Ring in x over Integer Ring
to Real Double Field
is_surjective()[source]

Tell whether the map is surjective (not implemented in the base class).

parent()[source]

Return the homset containing this map.

Note

The method _make_weak_references(), that is used for the maps found by the coercion system, needs to remove the usual strong reference from the coercion map to the homset containing it. As long as the user keeps strong references to domain and codomain of the map, we will be able to reconstruct the homset. However, a strong reference to the coercion map does not prevent the domain from garbage collection!

EXAMPLES:

sage: Q = QuadraticField(-5)                                                # needs sage.rings.number_field
sage: phi = CDF._internal_convert_map_from(Q)                               # needs sage.rings.number_field
sage: print(phi.parent())                                                   # needs sage.rings.number_field
Set of field embeddings
 from Number Field in a with defining polynomial x^2 + 5
      with a = 2.236067977499790?*I
   to Complex Double Field
>>> from sage.all import *
>>> Q = QuadraticField(-Integer(5))                                                # needs sage.rings.number_field
>>> phi = CDF._internal_convert_map_from(Q)                               # needs sage.rings.number_field
>>> print(phi.parent())                                                   # needs sage.rings.number_field
Set of field embeddings
 from Number Field in a with defining polynomial x^2 + 5
      with a = 2.236067977499790?*I
   to Complex Double Field

We now demonstrate that the reference to the coercion map \(\phi\) does not prevent \(Q\) from being garbage collected:

sage: import gc
sage: del Q                                                                 # needs sage.rings.number_field
sage: _ = gc.collect()
sage: phi.parent()                                                          # needs sage.rings.number_field
Traceback (most recent call last):
...
ValueError: This map is in an invalid state,
the domain has been garbage collected
>>> from sage.all import *
>>> import gc
>>> del Q                                                                 # needs sage.rings.number_field
>>> _ = gc.collect()
>>> phi.parent()                                                          # needs sage.rings.number_field
Traceback (most recent call last):
...
ValueError: This map is in an invalid state,
the domain has been garbage collected

You can still obtain copies of the maps used by the coercion system with strong references:

sage: # needs sage.rings.number_field
sage: Q = QuadraticField(-5)
sage: phi = CDF.convert_map_from(Q)
sage: print(phi.parent())
Set of field embeddings
 from Number Field in a with defining polynomial x^2 + 5
      with a = 2.236067977499790?*I
   to Complex Double Field
sage: import gc
sage: del Q
sage: _ = gc.collect()
sage: phi.parent()
Set of field embeddings
 from Number Field in a with defining polynomial x^2 + 5
      with a = 2.236067977499790?*I
   to Complex Double Field
>>> from sage.all import *
>>> # needs sage.rings.number_field
>>> Q = QuadraticField(-Integer(5))
>>> phi = CDF.convert_map_from(Q)
>>> print(phi.parent())
Set of field embeddings
 from Number Field in a with defining polynomial x^2 + 5
      with a = 2.236067977499790?*I
   to Complex Double Field
>>> import gc
>>> del Q
>>> _ = gc.collect()
>>> phi.parent()
Set of field embeddings
 from Number Field in a with defining polynomial x^2 + 5
      with a = 2.236067977499790?*I
   to Complex Double Field
post_compose(left)[source]

INPUT:

  • self – a Map in some Hom(X, Y, category_right)

  • left – a Map in some Hom(Y, Z, category_left)

Returns the composition of self followed by left as a morphism in Hom(X, Z, category) where category is the meet of category_left and category_right.

Caveat: see the current restrictions on Category.meet()

EXAMPLES:

sage: from sage.categories.morphism import SetMorphism
sage: X.<x> = ZZ[]
sage: Y = ZZ
sage: Z = QQ
sage: phi_xy = SetMorphism(Hom(X, Y, Rings()), lambda p: p[0])
sage: phi_yz = SetMorphism(Hom(Y, Z, Monoids()), lambda y: QQ(y**2))
sage: phi_xz = phi_xy.post_compose(phi_yz); phi_xz
Composite map:
  From: Univariate Polynomial Ring in x over Integer Ring
  To:   Rational Field
  Defn:   Generic morphism:
          From: Univariate Polynomial Ring in x over Integer Ring
          To:   Integer Ring
        then
          Generic morphism:
          From: Integer Ring
          To:   Rational Field
sage: phi_xz.category_for()
Category of monoids
>>> from sage.all import *
>>> from sage.categories.morphism import SetMorphism
>>> X = ZZ['x']; (x,) = X._first_ngens(1)
>>> Y = ZZ
>>> Z = QQ
>>> phi_xy = SetMorphism(Hom(X, Y, Rings()), lambda p: p[Integer(0)])
>>> phi_yz = SetMorphism(Hom(Y, Z, Monoids()), lambda y: QQ(y**Integer(2)))
>>> phi_xz = phi_xy.post_compose(phi_yz); phi_xz
Composite map:
  From: Univariate Polynomial Ring in x over Integer Ring
  To:   Rational Field
  Defn:   Generic morphism:
          From: Univariate Polynomial Ring in x over Integer Ring
          To:   Integer Ring
        then
          Generic morphism:
          From: Integer Ring
          To:   Rational Field
>>> phi_xz.category_for()
Category of monoids
pre_compose(right)[source]

INPUT:

  • self – a Map in some Hom(Y, Z, category_left)

  • left – a Map in some Hom(X, Y, category_right)

Returns the composition of right followed by self as a morphism in Hom(X, Z, category) where category is the meet of category_left and category_right.

EXAMPLES:

sage: from sage.categories.morphism import SetMorphism
sage: X.<x> = ZZ[]
sage: Y = ZZ
sage: Z = QQ
sage: phi_xy = SetMorphism(Hom(X, Y, Rings()), lambda p: p[0])
sage: phi_yz = SetMorphism(Hom(Y, Z, Monoids()), lambda y: QQ(y**2))
sage: phi_xz = phi_yz.pre_compose(phi_xy); phi_xz
Composite map:
  From: Univariate Polynomial Ring in x over Integer Ring
  To:   Rational Field
  Defn:   Generic morphism:
          From: Univariate Polynomial Ring in x over Integer Ring
          To:   Integer Ring
        then
          Generic morphism:
          From: Integer Ring
          To:   Rational Field
sage: phi_xz.category_for()
Category of monoids
>>> from sage.all import *
>>> from sage.categories.morphism import SetMorphism
>>> X = ZZ['x']; (x,) = X._first_ngens(1)
>>> Y = ZZ
>>> Z = QQ
>>> phi_xy = SetMorphism(Hom(X, Y, Rings()), lambda p: p[Integer(0)])
>>> phi_yz = SetMorphism(Hom(Y, Z, Monoids()), lambda y: QQ(y**Integer(2)))
>>> phi_xz = phi_yz.pre_compose(phi_xy); phi_xz
Composite map:
  From: Univariate Polynomial Ring in x over Integer Ring
  To:   Rational Field
  Defn:   Generic morphism:
          From: Univariate Polynomial Ring in x over Integer Ring
          To:   Integer Ring
        then
          Generic morphism:
          From: Integer Ring
          To:   Rational Field
>>> phi_xz.category_for()
Category of monoids
section()[source]

Return a section of self.

Note

By default, it returns None. You may override it in subclasses.

class sage.categories.map.Section[source]

Bases: Map

A formal section of a map.

Note

Call methods are not implemented for the base class Section.

EXAMPLES:

sage: from sage.categories.map import Section
sage: R.<x,y> = ZZ[]
sage: S.<a,b> = QQ[]
sage: f = R.hom([a+b, a-b])
sage: sf = Section(f); sf
Section map:
  From: Multivariate Polynomial Ring in a, b over Rational Field
  To:   Multivariate Polynomial Ring in x, y over Integer Ring
sage: sf(a)
Traceback (most recent call last):
...
NotImplementedError: <class 'sage.categories.map.Section'>
>>> from sage.all import *
>>> from sage.categories.map import Section
>>> R = ZZ['x, y']; (x, y,) = R._first_ngens(2)
>>> S = QQ['a, b']; (a, b,) = S._first_ngens(2)
>>> f = R.hom([a+b, a-b])
>>> sf = Section(f); sf
Section map:
  From: Multivariate Polynomial Ring in a, b over Rational Field
  To:   Multivariate Polynomial Ring in x, y over Integer Ring
>>> sf(a)
Traceback (most recent call last):
...
NotImplementedError: <class 'sage.categories.map.Section'>
inverse()[source]

Return inverse of self.

sage.categories.map.is_Map(x)[source]

Auxiliary function: Is the argument a map?

EXAMPLES:

sage: R.<x,y> = QQ[]
sage: f = R.hom([x+y, x-y], R)
sage: from sage.categories.map import is_Map
sage: is_Map(f)
doctest:warning...
DeprecationWarning: The function is_Map is deprecated; use 'isinstance(..., Map)' instead.
See https://github.com/sagemath/sage/issues/38103 for details.
True
>>> from sage.all import *
>>> R = QQ['x, y']; (x, y,) = R._first_ngens(2)
>>> f = R.hom([x+y, x-y], R)
>>> from sage.categories.map import is_Map
>>> is_Map(f)
doctest:warning...
DeprecationWarning: The function is_Map is deprecated; use 'isinstance(..., Map)' instead.
See https://github.com/sagemath/sage/issues/38103 for details.
True
sage.categories.map.unpickle_map(_class, parent, _dict, _slots)[source]

Auxiliary function for unpickling a map.