Quiver Morphisms - Quivers

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

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

  - `domain` – `QuiverRep`, the domain of the homomorphism

  - `codomain` – `QuiverRep`, 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: `QuiverRepHom`

  EXAMPLES:

  Sage

      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)

  Python

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

  With no additional data this creates the zero map:

  Sage

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

  [Python]

      >>> from sage.all import *
      >>> f = S.hom(M)
      >>> 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

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

  Python

      >>> from sage.all import *
      >>> maps2 = {Integer(2):[Integer(1), -Integer(1)], Integer(3):Integer(1)}
      >>> g = S.hom(maps2, M)

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

  Sage

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

  [Python]

      >>> from sage.all import *
      >>> x = M({Integer(2): (Integer(1), -Integer(1))})
      >>> y = M({Integer(3): (Integer(1),)})
      >>> h = S.hom([x, y], M)
      >>> 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

      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

  Python

      >>> from sage.all import *
      >>> Proj = Q.P(GF(Integer(7)), Integer(3))
      >>> Simp = Q.S(GF(Integer(7)), Integer(3))
      >>> im = Simp({Integer(3): (Integer(1),)})
      >>> 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: `QuiverRepHom`; the map \(f^t : N^t \to M^t\)

    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

        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)

    Python

        >>> from sage.all import *
        >>> Q = DiGraph({Integer(1):{Integer(2):['a'], Integer(3):['b','c','d']}, Integer(2):{Integer(4):['e','f']}, Integer(3):{Integer(4):['g']}, Integer(5):{Integer(2):['h','i']}}).path_semigroup()
        >>> P1 = Q.P(QQ, Integer(4))
        >>> 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

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

    [Python]

        >>> from sage.all import *
        >>> Q.reverse().P(QQ, Integer(4))
        Representation with dimension vector (5, 2, 1, 1, 4)

  base_ring()

    Return the base ring of the representation in the codomain.

    OUTPUT: the base ring of the codomain

    EXAMPLES:

    Sage

        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

    Python

        >>> from sage.all import *
        >>> Q = DiGraph({Integer(1):{Integer(2):['a', 'b']}, Integer(2):{Integer(3):['c']}}).path_semigroup()
        >>> P = Q.P(QQ, Integer(1))
        >>> f = P.hom({Integer(1): Integer(1), Integer(2): Integer(1), Integer(3): Integer(1)}, P)
        >>> f.base_ring() is QQ
        True

  codomain()

    Return the codomain of the homomorphism.

    OUTPUT: `QuiverRep`; the codomain

    EXAMPLES:

    Sage

        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

    Python

        >>> from sage.all import *
        >>> Q = DiGraph({Integer(1):{Integer(2):['a', 'b']}, Integer(2):{Integer(3):['c']}}).path_semigroup()
        >>> spaces = {Integer(1): QQ**Integer(2), Integer(2): QQ**Integer(2), Integer(3):QQ**Integer(1)}
        >>> maps = {(Integer(1), Integer(2), 'a'): [[Integer(1), Integer(0)], [Integer(0), Integer(0)]], (Integer(1), Integer(2), 'b'): [[Integer(0), Integer(0)], [Integer(0), Integer(1)]], (Integer(2), Integer(3), 'c'): [[Integer(1)], [Integer(1)]]}
        >>> M = Q.representation(QQ, spaces, maps)
        >>> S = Q.representation(QQ)
        >>> g = S.hom(M)
        >>> 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

        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)

    Python

        >>> from sage.all import *
        >>> Q = DiGraph({Integer(1):{Integer(2):['a', 'b']}, Integer(2):{Integer(3):['c']}}).path_semigroup()
        >>> spaces = {Integer(1): QQ**Integer(2), Integer(2): QQ**Integer(2), Integer(3):QQ**Integer(1)}
        >>> maps = {(Integer(1), Integer(2), 'a'): [[Integer(1), Integer(0)], [Integer(0), Integer(0)]], (Integer(1), Integer(2), 'b'): [[Integer(0), Integer(0)], [Integer(0), Integer(1)]], (Integer(2), Integer(3), 'c'): [[Integer(1)], [Integer(1)]]}
        >>> M = Q.representation(QQ, spaces, maps)
        >>> spaces2 = {Integer(2): QQ**Integer(2), Integer(3): QQ**Integer(1)}
        >>> N = Q.representation(QQ, spaces2, {(Integer(2), Integer(3), 'c'): [[Integer(1)], [Integer(0)]]})
        >>> maps2 = {Integer(2):[[Integer(1), Integer(0)], [Integer(0), Integer(0)]], Integer(3):Integer(1)}
        >>> g = N.hom(maps2, M)
        >>> 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:

    - `maps` – `QuiverRepHom` or list of `QuiverRepHom`’s

    - `return_maps` – boolean (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: `QuiverRepHom` or tuple

    EXAMPLES:

    Sage

        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

    Python

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

  domain()

    Return the domain of the homomorphism.

    OUTPUT: `QuiverRep`; the domain

    EXAMPLES:

    Sage

        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

    Python

        >>> from sage.all import *
        >>> Q = DiGraph({Integer(1):{Integer(2):['a', 'b']}, Integer(2):{Integer(3):['c']}}).path_semigroup()
        >>> spaces = {Integer(1): QQ**Integer(2), Integer(2): QQ**Integer(2), Integer(3):QQ**Integer(1)}
        >>> maps = {(Integer(1), Integer(2), 'a'): [[Integer(1), Integer(0)], [Integer(0), Integer(0)]], (Integer(1), Integer(2), 'b'): [[Integer(0), Integer(0)], [Integer(0), Integer(1)]], (Integer(2), Integer(3), 'c'): [[Integer(1)], [Integer(1)]]}
        >>> M = Q.representation(QQ, spaces, maps)
        >>> S = Q.representation(QQ)
        >>> g = M.hom(S)
        >>> 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: the homomorphism associated to the given vertex

    EXAMPLES:

    Sage

        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

    Python

        >>> from sage.all import *
        >>> Q = DiGraph({Integer(1):{Integer(2):['a', 'b']}, Integer(2):{Integer(3):['c']}}).path_semigroup()
        >>> P = Q.P(QQ, Integer(1))
        >>> S = P/P.radical()
        >>> f = S.coerce_map_from(P)
        >>> f.get_map(Integer(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: the matrix representing the homomorphism associated to the given vertex

    EXAMPLES:

    Sage

        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]

    Python

        >>> from sage.all import *
        >>> Q = DiGraph({Integer(1):{Integer(2):['a', 'b']}, Integer(2):{Integer(3):['c']}}).path_semigroup()
        >>> I = Q.I(QQ, Integer(3))
        >>> M = I/I.radical()
        >>> f = M.coerce_map_from(I)
        >>> f.get_matrix(Integer(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

        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)

    Python

        >>> from sage.all import *
        >>> Q = DiGraph({Integer(1):{Integer(2):['a', 'b']}, Integer(2):{Integer(3):['c']}}).path_semigroup()
        >>> spaces = {Integer(1): QQ**Integer(2), Integer(2): QQ**Integer(2), Integer(3):QQ**Integer(1)}
        >>> maps = {(Integer(1), Integer(2), 'a'): [[Integer(1), Integer(0)], [Integer(0), Integer(0)]], (Integer(1), Integer(2), 'b'): [[Integer(0), Integer(0)], [Integer(0), Integer(1)]], (Integer(2), Integer(3), 'c'): [[Integer(1)], [Integer(1)]]}
        >>> M = Q.representation(QQ, spaces, maps)
        >>> spaces2 = {Integer(2): QQ**Integer(2), Integer(3): QQ**Integer(1)}
        >>> N = Q.representation(QQ, spaces2, {(Integer(2), Integer(3), 'c'): [[Integer(1)], [Integer(0)]]})
        >>> maps2 = {Integer(2):[[Integer(1), Integer(0)], [Integer(0), Integer(0)]], Integer(3):Integer(1)}
        >>> g = N.hom(maps2, M)
        >>> g.image().dimension_vector()
        (0, 1, 1)

  is_endomorphism()

    Test whether the homomorphism is an endomorphism.

    OUTPUT: boolean; `True` if the domain equals the codomain, `False` otherwise

    EXAMPLES:

    Sage

        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

    Python

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

  is_injective()

    Test whether the homomorphism is injective.

    OUTPUT: boolean; `True` if the homomorphism is injective, `False` otherwise

    EXAMPLES:

    Sage

        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

    Python

        >>> from sage.all import *
        >>> Q = DiGraph({Integer(1):{Integer(2):['a', 'b']}, Integer(2):{Integer(3):['c']}}).path_semigroup()
        >>> P = Q.P(QQ, Integer(1))
        >>> f = P.hom({Integer(1): Integer(1), Integer(2): Integer(1), Integer(3): Integer(1)}, P)
        >>> f.is_injective()
        True
        >>> g = P.hom(P)
        >>> g.is_injective()
        False

  is_isomorphism()

    Test whether the homomorphism is an isomorphism.

    OUTPUT: boolean; `True` if the homomorphism is bijective, `False` otherwise

    EXAMPLES:

    Sage

        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

    Python

        >>> from sage.all import *
        >>> Q = DiGraph({Integer(1):{Integer(2):['a', 'b']}, Integer(2):{Integer(3):['c']}}).path_semigroup()
        >>> P = Q.P(QQ, Integer(1))
        >>> f = P.hom({Integer(1): Integer(1), Integer(2): Integer(1), Integer(3): Integer(1)}, P)
        >>> f.is_isomorphism()
        True
        >>> g = P.hom(P)
        >>> g.is_isomorphism()
        False

  is_surjective()

    Test whether the homomorphism is surjective.

    OUTPUT: boolean; `True` if the homomorphism is surjective, `False` otherwise

    EXAMPLES:

    Sage

        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

    Python

        >>> from sage.all import *
        >>> Q = DiGraph({Integer(1):{Integer(2):['a', 'b']}, Integer(2):{Integer(3):['c']}}).path_semigroup()
        >>> P = Q.P(QQ, Integer(1))
        >>> f = P.hom({Integer(1): Integer(1), Integer(2): Integer(1), Integer(3): Integer(1)}, P)
        >>> f.is_surjective()
        True
        >>> g = P.hom(P)
        >>> g.is_surjective()
        False

  is_zero()

    Test whether the homomorphism is the zero homomorphism.

    OUTPUT: boolean; `True` if the homomorphism is zero, `False` otherwise

    EXAMPLES:

    Sage

        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

    Python

        >>> from sage.all import *
        >>> Q = DiGraph({Integer(1):{Integer(2):['a', 'b']}, Integer(2):{Integer(3):['c']}}).path_semigroup()
        >>> P = Q.P(QQ, Integer(1))
        >>> f = P.hom({Integer(1): Integer(1), Integer(2): Integer(1), Integer(3): Integer(1)}, P)
        >>> f.is_zero()
        False
        >>> g = P.hom(P)
        >>> g.is_zero()
        True

  iscalar_mult(scalar)

    Multiply `self` by `scalar` in place.

    EXAMPLES:

    Sage

        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

    Python

        >>> from sage.all import *
        >>> Q = DiGraph({Integer(1):{Integer(2):['a','b']}}).path_semigroup()
        >>> M = Q.P(QQ, Integer(1))
        >>> f = M.Hom(M).an_element()
        >>> x = M.an_element()
        >>> y = f(x)
        >>> f.iscalar_mult(Integer(6))
        >>> f(x) == Integer(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

        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)

    Python

        >>> from sage.all import *
        >>> Q = DiGraph({Integer(1):{Integer(2):['a', 'b']}, Integer(2):{Integer(3):['c']}}).path_semigroup()
        >>> spaces = {Integer(1): QQ**Integer(2), Integer(2): QQ**Integer(2), Integer(3):QQ**Integer(1)}
        >>> maps = {(Integer(1), Integer(2), 'a'): [[Integer(1), Integer(0)], [Integer(0), Integer(0)]], (Integer(1), Integer(2), 'b'): [[Integer(0), Integer(0)], [Integer(0), Integer(1)]], (Integer(2), Integer(3), 'c'): [[Integer(1)], [Integer(1)]]}
        >>> M = Q.representation(QQ, spaces, maps)
        >>> spaces2 = {Integer(2): QQ**Integer(2), Integer(3): QQ**Integer(1)}
        >>> N = Q.representation(QQ, spaces2, {(Integer(2), Integer(3), 'c'): [[Integer(1)], [Integer(0)]]})
        >>> maps2 = {Integer(2):[[Integer(1), Integer(0)], [Integer(0), Integer(0)]], Integer(3):Integer(1)}
        >>> g = N.hom(maps2, M)
        >>> 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:

    - `x` – `QuiverRepElement`

    OUTPUT: `QuiverRepElement`

    EXAMPLES:

    Sage

        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

    Python

        >>> from sage.all import *
        >>> Q = DiGraph({Integer(1):{Integer(2):['a','b']}, Integer(2):{Integer(3):['c','d']}}).path_semigroup()
        >>> P = Q.P(QQ, Integer(3))
        >>> S = P/P.radical()
        >>> proj = S.coerce_map_from(P)
        >>> x = S.an_element()
        >>> y = proj.lift(x)
        >>> proj(y) == x
        True
        >>> zero = S.hom(S, {})
        >>> 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: `QuiverRepHom`; the map \(Df : DN \to DM\)

    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

        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)

    Python

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

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

    Sage

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

    [Python]

        >>> from sage.all import *
        >>> f.is_surjective()
        True
        >>> g = f.linear_dual()
        >>> 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

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

    Python

        >>> from sage.all import *
        >>> g.quiver().path_semigroup() is Q.reverse()
        True

    The double dual of a map is the original representation:

    Sage

        sage: g.linear_dual() == f
        True

    [Python]

        >>> from sage.all import *
        >>> 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

        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

    Python

        >>> from sage.all import *
        >>> Q = DiGraph({Integer(1):{Integer(2):['a', 'b']}, Integer(2):{Integer(3):['c']}}).path_semigroup()
        >>> P = Q.P(QQ, Integer(1))
        >>> f = P.hom({Integer(1): Integer(1), Integer(2): Integer(1), Integer(3): Integer(1)}, P)
        >>> 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

        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)

    Python

        >>> from sage.all import *
        >>> Q = DiGraph({Integer(1):{Integer(2):['a', 'b']}, Integer(2):{Integer(3):['c']}}).path_semigroup()
        >>> P = Q.P(QQ, Integer(1))
        >>> S = P/P.radical()
        >>> f = S.coerce_map_from(P)
        >>> assert(f.rank() == Integer(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

        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

    Python

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