Quiver Morphisms#

class sage.quivers.morphism.QuiverRepHom(domain, codomain, data={})#

Bases: CallMorphism

A homomorphism of quiver representations (of one and the same quiver) is given by specifying, for each vertex of the quiver, a homomorphism of the spaces assigned to this vertex such that these homomorphisms commute with the edge maps. The domain and codomain of the homomorphism are required to be representations of the same quiver over the same base ring.

INPUT:

  • domainQuiverRep, the domain of the homomorphism

  • codomainQuiverRep, the codomain of the homomorphism

  • data - dict, list, or QuiverRepElement (default: empty dict), with the following meaning:

    • list: data can be a list of images for the generators of the domain. “Generators” means the output of the gens() method. An error will be generated if the map so defined is not equivariant with respect to the action of the quiver.

    • dictionary: data can be a dictionary associating to each vertex of the quiver either a homomorphism with domain and codomain the spaces associated to this vertex in the domain and codomain modules respectively, or a matrix defining such a homomorphism, or an object that sage can construct such a matrix from. Not all vertices must be specified, unspecified vertices are assigned the zero map, and keys not corresponding to vertices of the quiver are ignored. An error will be generated if these maps do not commute with the edge maps of the domain and codomain.

    • QuiverRepElement: if the domain is a QuiverRep_with_path_basis then data can be a single QuiverRepElement belonging to the codomain. The map is then defined by sending each path, p, in the basis to data*p. If data is not an element of the codomain or the domain is not a QuiverRep_with_path_basis then an error will be generated.

    • QuiverRepHom: the input can also be a map \(f : D \to C\) such that there is a coercion from the domain of self to D and from C to the codomain of self. The composition of these maps is the result.

OUTPUT:

EXAMPLES:

sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
sage: M = Q.representation(QQ, spaces, maps)
sage: spaces2 = {2: QQ^1, 3: QQ^1}
sage: S = Q.representation(QQ, spaces2)

With no additional data this creates the zero map:

sage: f = S.hom(M)
sage: f.is_zero()
True

We must specify maps at the vertices to get a nonzero homomorphism. Note that if the dimensions of the spaces assigned to the domain and codomain of a vertex are equal then Sage will construct the identity matrix from 1:

sage: maps2 = {2:[1, -1], 3:1}
sage: g = S.hom(maps2, M)

Here we create the same map by specifying images for the generators:

sage: x = M({2: (1, -1)})
sage: y = M({3: (1,)})
sage: h = S.hom([x, y], M)
sage: g == h
True

If the domain is a module of type QuiverRep_with_path_basis (for example, the indecomposable projectives) we can create maps by specifying a single image:

sage: Proj = Q.P(GF(7), 3)
sage: Simp = Q.S(GF(7), 3)
sage: im = Simp({3: (1,)})
sage: Proj.hom(im, Simp).is_surjective()
True
algebraic_dual()#

Compute the algebraic dual \(f^t : N^t \to M^t\) of self = \(f : M \to N\) where \((-)^t = Hom_Q(-, kQ)\).

OUTPUT:

Note

If \(e\) is an edge of the quiver \(Q\) and \(g\) is an element of \(Hom_Q(N, kQ)\) then we let \((ge)(m) = eg(m)\). This gives \(Hom_Q(N, kQ)\) its structure as a module over the opposite quiver Q.reverse(). The map \(Hom_Q(N, kQ) \to Hom_Q(M, kQ)\) returned sends \(g\) to \(gf\).

EXAMPLES:

sage: Q = DiGraph({1:{2:['a'], 3:['b','c','d']}, 2:{4:['e','f']}, 3:{4:['g']}, 5:{2:['h','i']}}).path_semigroup()
sage: P1 = Q.P(QQ, 4)
sage: P1.algebraic_dual()
Representation with dimension vector (5, 2, 1, 1, 4)

The algebraic dual of an indecomposable projective is the indecomposable projective of the same vertex in the opposite quiver.

sage: Q.reverse().P(QQ, 4)
Representation with dimension vector (5, 2, 1, 1, 4)
base_ring()#

Return the base ring of the representation in the codomain.

OUTPUT:

  • ring, the base ring of the codomain

EXAMPLES:

sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
sage: P = Q.P(QQ, 1)
sage: f = P.hom({1: 1, 2: 1, 3: 1}, P)
sage: f.base_ring() is QQ
True
codomain()#

Return the codomain of the homomorphism.

OUTPUT:

  • QuiverRep, the codomain

EXAMPLES:

sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
sage: M = Q.representation(QQ, spaces, maps)
sage: S = Q.representation(QQ)
sage: g = S.hom(M)
sage: g.codomain() is M
True
cokernel()#

Return the cokernel of self.

OUTPUT:

  • QuiverRep, the cokernel

Note

To get the factor map of the codomain, D, onto the cokernel, C, use C.coerce_map_from(D).

EXAMPLES:

sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
sage: M = Q.representation(QQ, spaces, maps)
sage: spaces2 = {2: QQ^2, 3: QQ^1}
sage: N = Q.representation(QQ, spaces2, {(2, 3, 'c'): [[1], [0]]})
sage: maps2 = {2:[[1, 0], [0, 0]], 3:1}
sage: g = N.hom(maps2, M)
sage: g.cokernel().dimension_vector()
(2, 1, 0)
direct_sum(maps, return_maps=False, pinch=None)#

Return the direct sum of self with the maps in the list maps.

INPUT:

  • mapsQuiverRepHom or list of QuiverRepHom’s

  • return_maps – bool (default: False). If False, then the return value is a QuiverRepHom which is the direct sum of self with the QuiverRepHoms in maps. If True, then the return value is a tuple of length either 3 or 5. The first entry of the tuple is the QuiverRepHom giving the direct sum. If pinch is either None or 'codomain' then the next two entries in the tuple are lists giving respectively the inclusion and the projection maps for the factors of the direct sum. Summands are ordered as given in maps with self as the zeroth summand. If pinch is either None or 'domain' then the next two entries in the tuple are the inclusion and projection maps for the codomain. Thus if pinch is None then the tuple will have length 5. If pinch is either 'domain' or 'codomain' then the tuple will have length 3.

  • pinch – string or None (default: None). If this is equal to 'domain', then the domains of self and the given maps must be equal. The direct sum of \(f: A \to B\) and \(g: A \to C\) returned is then the map \(A \to B \oplus C\) defined by sending \(x\) to \((f(x), g(x))\). If pinch equals 'codomain', then the codomains of self and the given maps must be equal. The direct sum of \(f: A \to C\) and \(g: B \to C\) returned is then the map \(A \oplus B \to C\) defined by sending \((x, y)\) to \(f(x) + g(y)\). Finally, if pinch is anything other than 'domain' or 'codomain', then the direct sum of \(f: A \to B\) and \(g: C \to D\) returned is the map \(A \oplus C \to B \oplus D\) defined by sending \((x, y)\) to \((f(x), g(y))\).

OUTPUT:

EXAMPLES:

sage: Q = DiGraph({1:{2:['a', 'b']}}).path_semigroup()
sage: P1 = Q.P(GF(3), 1)
sage: P2 = Q.P(GF(3), 2)
sage: S1 = P1/P1.radical()
sage: S2 = P2/P2.radical()
sage: pi1 = S1.coerce_map_from(P1)
sage: pi2 = S2.coerce_map_from(P2)
sage: f = pi1.direct_sum(pi2)
sage: f.domain().dimension_vector() == Q.free_module(GF(3)).dimension_vector()
True
sage: f.is_surjective()
True
sage: id = P1.Hom(P1).identity()
sage: g = pi1.direct_sum(id, pinch='domain')
sage: g.is_surjective()
False
domain()#

Return the domain of the homomorphism.

OUTPUT:

  • QuiverRep, the domain

EXAMPLES:

sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
sage: M = Q.representation(QQ, spaces, maps)
sage: S = Q.representation(QQ)
sage: g = M.hom(S)
sage: g.domain() is M
True
get_map(vertex)#

Return the homomorphism at the given vertex vertex.

INPUT:

  • vertex – integer, a vertex of the quiver

OUTPUT:

  • homomorphism, the homomorphism associated to the given vertex

EXAMPLES:

sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
sage: P = Q.P(QQ, 1)
sage: S = P/P.radical()
sage: f = S.coerce_map_from(P)
sage: f.get_map(1).is_bijective()
True
get_matrix(vertex)#

Return the matrix of the homomorphism attached to vertex vertex.

INPUT:

  • vertex – integer, a vertex of the quiver

OUTPUT:

  • matrix, the matrix representing the homomorphism associated to the given vertex

EXAMPLES:

sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
sage: I = Q.I(QQ, 3)
sage: M = I/I.radical()
sage: f = M.coerce_map_from(I)
sage: f.get_matrix(1)
[1 0]
[0 1]
image()#

Return the image of self.

OUTPUT:

  • QuiverRep, the image

Note

To get the inclusion map of the image, I, into the codomain, C, use C.coerce_map_from(I).

EXAMPLES:

sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
sage: M = Q.representation(QQ, spaces, maps)
sage: spaces2 = {2: QQ^2, 3: QQ^1}
sage: N = Q.representation(QQ, spaces2, {(2, 3, 'c'): [[1], [0]]})
sage: maps2 = {2:[[1, 0], [0, 0]], 3:1}
sage: g = N.hom(maps2, M)
sage: g.image().dimension_vector()
(0, 1, 1)
is_endomorphism()#

Test whether the homomorphism is an endomorphism.

OUTPUT:

  • bool, True if the domain equals the codomain, False otherwise

EXAMPLES:

sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
sage: P = Q.P(QQ, 1)
sage: f = P.hom({1: 1, 2: 1, 3: 1}, P)
sage: f.is_endomorphism()
True
sage: S = P/P.radical()
sage: g = S.coerce_map_from(P)
sage: g.is_endomorphism()
False
is_injective()#

Test whether the homomorphism is injective.

OUTPUT:

  • bool, True if the homomorphism is injective, False otherwise

EXAMPLES:

sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
sage: P = Q.P(QQ, 1)
sage: f = P.hom({1: 1, 2: 1, 3: 1}, P)
sage: f.is_injective()
True
sage: g = P.hom(P)
sage: g.is_injective()
False
is_isomorphism()#

Test whether the homomorphism is an isomorphism.

OUTPUT:

  • bool, True if the homomorphism is bijective, False otherwise

EXAMPLES:

sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
sage: P = Q.P(QQ, 1)
sage: f = P.hom({1: 1, 2: 1, 3: 1}, P)
sage: f.is_isomorphism()
True
sage: g = P.hom(P)
sage: g.is_isomorphism()
False
is_surjective()#

Test whether the homomorphism is surjective.

OUTPUT:

  • bool, True if the homomorphism is surjective, False otherwise

EXAMPLES:

sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
sage: P = Q.P(QQ, 1)
sage: f = P.hom({1: 1, 2: 1, 3: 1}, P)
sage: f.is_surjective()
True
sage: g = P.hom(P)
sage: g.is_surjective()
False
is_zero()#

Test whether the homomorphism is the zero homomorphism.

OUTPUT:

  • bool, True if the homomorphism is zero, False otherwise

EXAMPLES:

sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
sage: P = Q.P(QQ, 1)
sage: f = P.hom({1: 1, 2: 1, 3: 1}, P)
sage: f.is_zero()
False
sage: g = P.hom(P)
sage: g.is_zero()
True
iscalar_mult(scalar)#

Multiply self by scalar in place.

EXAMPLES:

sage: Q = DiGraph({1:{2:['a','b']}}).path_semigroup()
sage: M = Q.P(QQ, 1)
sage: f = M.Hom(M).an_element()
sage: x = M.an_element()
sage: y = f(x)
sage: f.iscalar_mult(6)
sage: f(x) == 6*y
True
kernel()#

Return the kernel of self.

OUTPUT:

  • QuiverRep, the kernel

Note

To get the inclusion map of the kernel, K, into the domain, D, use D.coerce_map_from(K).

EXAMPLES:

sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
sage: M = Q.representation(QQ, spaces, maps)
sage: spaces2 = {2: QQ^2, 3: QQ^1}
sage: N = Q.representation(QQ, spaces2, {(2, 3, 'c'): [[1], [0]]})
sage: maps2 = {2:[[1, 0], [0, 0]], 3:1}
sage: g = N.hom(maps2, M)
sage: g.kernel().dimension_vector()
(0, 1, 0)
lift(x)#

Given an element \(x\) of the image, return an element of the domain that maps onto it under self.

INPUT:

  • xQuiverRepElement

OUTPUT:

  • QuiverRepElement

EXAMPLES:

sage: Q = DiGraph({1:{2:['a','b']}, 2:{3:['c','d']}}).path_semigroup()
sage: P = Q.P(QQ, 3)
sage: S = P/P.radical()
sage: proj = S.coerce_map_from(P)
sage: x = S.an_element()
sage: y = proj.lift(x)
sage: proj(y) == x
True
sage: zero = S.hom(S, {})
sage: zero.lift(x)
Traceback (most recent call last):
...
ValueError: element is not in the image
linear_dual()#

Compute the linear dual \(Df : DN \to DM\) of self = \(f : M \to N\) where \(D(-) = Hom_k(-, k)\).

OUTPUT:

Note

If \(e\) is an edge of the quiver \(Q\) and \(g\) is an element of \(Hom_k(N, k)\) then we let \((ga)(m) = g(ma)\). This gives \(Hom_k(N, k)\) its structure as a module over the opposite quiver Q.reverse(). The map \(Hom_k(N, k) \to Hom_k(M, k)\) returned sends \(g\) to \(gf\).

EXAMPLES:

sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
sage: P = Q.P(QQ, 1)
sage: S = P/P.radical()
sage: f = S.coerce_map_from(P)

The dual of a surjective map is injective and vice versa:

sage: f.is_surjective()
True
sage: g = f.linear_dual()
sage: g.is_injective()
True

The dual of a right module is a left module for the same quiver, Sage represents this as a right module for the opposite quiver:

sage: g.quiver().path_semigroup() is Q.reverse()
True

The double dual of a map is the original representation:

sage: g.linear_dual() == f
True
quiver()#

Return the quiver of the representations in the domain/codomain.

OUTPUT:

  • DiGraph, the quiver of the representations in the domain and codomain

EXAMPLES:

sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
sage: P = Q.P(QQ, 1)
sage: f = P.hom({1: 1, 2: 1, 3: 1}, P)
sage: f.quiver() is Q.quiver()
True
rank()#

Return the rank of the homomorphism self (as a \(k\)-linear map).

OUTPUT:

  • integer, the rank

EXAMPLES:

sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
sage: P = Q.P(QQ, 1)
sage: S = P/P.radical()
sage: f = S.coerce_map_from(P)
sage: assert(f.rank() == 1)
scalar_mult(scalar)#

Return the result of the scalar multiplication scalar * self, where scalar is an element of the base ring \(k\).

EXAMPLES:

sage: Q = DiGraph({1:{2:['a','b']}}).path_semigroup()
sage: M = Q.P(QQ, 1)
sage: f = M.Hom(M).an_element()
sage: x = M.an_element()
sage: g = f.scalar_mult(6)
sage: g(x) == 6*f(x)
True