# Base class for maps¶

Base class for maps

class sage.categories.map.FormalCompositeMap

Bases: sage.categories.map.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.

EXAMPLE:

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

first()

The first map in the formal composition, where the composition is x|--> second(first(x)).

EXAMPLE:

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).first() is g
True

is_injective()

Tell whether self is injective.

It raises NotImplementedError if it can’t be determined.

EXAMPLE:

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)


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()),phi1,phi2)
sage: c1.is_injective()
True


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

sage: psi1 = V2.hom(Matrix([[1,2],[3,4],[5,6]]),V1)
sage: c2 = FormalCompositeMap(Hom(V1,V1,phi2.category_for()),phi2,psi1)
sage: c2.is_injective()
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)
sage: c3 = FormalCompositeMap(Hom(V2,QQ^1,phi2.category_for()),psi2,psi1)
sage: c3.is_injective()
False

is_surjective()

Tell whether self is surjective.

It raises NotImplementedError if it can’t be determined.

EXAMPLE:

sage: from sage.categories.map import FormalCompositeMap
sage: V3 = QQ^3
sage: V2 = QQ^2
sage: V1 = QQ^1


If both maps are surjective, the composition is surjective:

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


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

sage: FormalCompositeMap(Hom(V3,V1,phi32.category_for()),phi32,V2.hom(Matrix([[0],[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()),V2.hom(Matrix([[0],[0]]),V1),V1.hom(Matrix([[1]]),V1)).is_surjective()
False


Otherwise, surjectivity of the composition can not be determined:

sage: FormalCompositeMap(Hom(V2, V1, phi32.category_for()),
...     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.

second()

The second map in the formal composition, where the composition is x|–> second(first(x)).

EXAMPLE:

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).second() is f
True

class sage.categories.map.Map

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

category_for()

Returns 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 hom sets in Category of rings
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 commutative algebras over Rational Field
sage: f.category()
Join of Category of hom sets in Category of modules over Rational Field and Category of hom sets in Category of rings


FIXME: find a better name for this method

codomain()

Return the codomain of self.

EXAMPLE:

sage: from sage.categories.map import Map
sage: f = Map(Hom(QQ, ZZ, Rings()))
sage: f.codomain()
Integer Ring
sage: R.<x,y> = QQ[]
sage: phi = R.hom([x+y,x-y],R)
sage: phi.codomain()
Multivariate Polynomial Ring in x, y over Rational Field

domain()

Return the domain of self.

EXAMPLE:

sage: from sage.categories.map import Map
sage: f = Map(Hom(QQ, ZZ, Rings()))
sage: f.domain()
Rational Field
sage: R.<x,y> = QQ[]
sage: phi = R.hom([x+y,x-y],R)
sage: phi.domain()
Multivariate Polynomial Ring in x, y over Rational Field

extend_codomain(new_codomain)

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

extend_domain(new_domain)

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: 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

is_injective()

Tells whether the map is injective (not implemented in the base class).

TEST:

sage: from sage.categories.map import Map
sage: f = Map(Hom(QQ, ZZ, Rings()))
sage: f.is_injective()
Traceback (most recent call last):
...
NotImplementedError: <type 'sage.categories.map.Map'>

is_surjective()

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

TEST:

sage: from sage.categories.map import Map
sage: f = Map(Hom(QQ, ZZ, Rings()))
sage: f.is_surjective()
Traceback (most recent call last):
...
NotImplementedError: <type 'sage.categories.map.Map'>

post_compose(left)

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 right 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

pre_compose(right)

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

section()

Return a section of self.

NOTE:

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

TEST:

sage: R.<x,y> = QQ[]
sage: f = R.hom([x+y,x-y],R)
sage: print f.section()
None

sage: f = QQ.coerce_map_from(ZZ); f
Natural morphism:
From: Integer Ring
To:   Rational Field
sage: ff = f.section(); ff
Generic map:
From: Rational Field
To:   Integer Ring
sage: ff(4/2)
2
sage: parent(ff(4/2)) is ZZ
True
sage: ff(1/2)
Traceback (most recent call last):
...
TypeError: no conversion of this rational to integer

class sage.categories.map.Section

Bases: sage.categories.map.Map

A formal section of a map.

NOTE:

Call methods are not implemented for the base class Section.

EXAMPLE:

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: <type 'sage.categories.map.Section'>

sage.categories.map.is_Map(x)

Auxiliary function: Is the argument a map?

EXAMPLE:

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)
True

sage.categories.map.unpickle_map(_class, parent, _dict, _slots)

Auxiliary function for unpickling a map.

TEST:

sage: R.<x,y> = QQ[]
sage: f = R.hom([x+y,x-y],R)
sage: f == loads(dumps(f))  # indirect doctest
True


#### Previous topic

Specific category classes

Homsets