Esempio n. 1
0
    def __init__(self, domain, codomain, data={}):
        """
        Initialize ``self``. Type ``QuiverRepHom?`` for more information.

        TESTS::

            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)
            sage: f = S.hom(M)
            sage: f.is_zero()
            True
            sage: maps2 = {2:[1, -1], 3:1}
            sage: g = S.hom(maps2, M)
            sage: x = M({2: (1, -1)})
            sage: y = M({3: (1,)})
            sage: h = S.hom([x, y], M)
            sage: g == h
            True
            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

        ::

            sage: Q = DiGraph({1:{2:['a']}}).path_semigroup()
            sage: H1 = Q.P(GF(3), 2).Hom(Q.S(GF(3), 2))
            sage: H2 = Q.P(GF(3), 2).Hom(Q.S(GF(3), 1))
            sage: H1.an_element() in H1   # indirect doctest
            True
        """
        # The data of a representation is held in the following private
        # variables:
        #
        # * _quiver
        #      The quiver of the representation.
        # * _base_ring
        #      The base ring of the representation.
        # * _domain
        #      The QuiverRep object that is the domain of the homomorphism.
        # * _codomain
        #      The QuiverRep object that is the codomain of the homomorphism.
        # * _vector
        #      A vector in some free module over the base ring of a length such
        #      that each coordinate corresponds to an entry in the matrix of a
        #      homomorphism attached to a vertex.
        #
        # The variable data can also be a vector of appropriate length.  When
        # this is the case it will be loaded directly into _vector and then
        # _assert_valid_hom is called.

        from sage.quivers.representation import QuiverRepElement, QuiverRep_with_path_basis

        self._domain = domain
        self._codomain = codomain
        self._quiver = domain._quiver
        self._base_ring = domain.base_ring()

        # Check that the quiver and base ring match
        if codomain._quiver != self._quiver:
            raise ValueError(
                "the quivers of the domain and codomain must be equal")
        if codomain.base_ring() != self._base_ring:
            raise ValueError(
                "the base ring of the domain and codomain must be equal")

        # Get the dimensions of the spaces
        mat_dims = {}
        domain_dims = {}
        codomain_dims = {}
        for v in self._quiver:
            domain_dims[v] = domain._spaces[v].dimension()
            codomain_dims[v] = codomain._spaces[v].dimension()
            mat_dims[v] = domain_dims[v] * codomain_dims[v]
        total_dim = sum(mat_dims.values())

        # Handle the case when data is a vector
        if data in self._base_ring**total_dim:
            self._vector = data
            self._assert_valid_hom()
            super(QuiverRepHom, self).__init__(domain.Hom(codomain))
            return

        # If data is not a dict, create one
        if isinstance(data, dict):
            maps_dict = data
        else:
            # If data is not a list create one, then create a dict from it
            if isinstance(data, list):
                im_list = data
            else:
                # If data is a QuiverRepHom, create a list from it
                if isinstance(data, QuiverRepHom):
                    f = data._domain.coerce_map_from(domain)
                    g = self._codomain.coerce_map_from(data._codomain)
                    im_list = [g(data(f(x))) for x in domain.gens()]

                # The only case left is that data is a QuiverRepElement
                else:
                    if not isinstance(data, QuiverRepElement):
                        raise TypeError("input data must be dictionary, list, "
                                        "QuiverRepElement or vector")
                    if not isinstance(domain, QuiverRep_with_path_basis):
                        raise TypeError(
                            "if data is a QuiverRepElement then domain "
                            "must be a QuiverRep_with_path_basis.")
                    if data not in codomain:
                        raise ValueError(
                            "if data is a QuiverRepElement then it must "
                            "be an element of codomain")
                    im_list = [
                        codomain.right_edge_action(data, p)
                        for v in domain._quiver for p in domain._bases[v]
                    ]

            # WARNING: This code assumes that the function QuiverRep.gens() returns
            # the generators ordered first by vertex and then by the order of the
            # gens() method of the space associated to that vertex.  In particular
            # this is the order that corresponds to how maps are represented via
            # matrices

            # Get the gens of the domain and check that im_list is the right length
            dom_gens = domain.gens()
            if len(im_list) != len(dom_gens):
                raise ValueError(
                    ("domain is dimension {} but only {} images"
                     " were supplied").format(len(dom_gens), len(im_list)))

            # Get the matrices of the maps
            start_index = 0
            maps_dict = {}
            for v in self._quiver:
                maps_dict[v] = []
                dim = domain._spaces[v].dimension()
                for i in range(start_index, start_index + dim):
                    if len(im_list[i].support()) != 0 and im_list[i].support(
                    ) != [v]:
                        # If the element doesn't have the correct support raise
                        # an error here, otherwise we might create a valid hom
                        # that does not map the generators to the supplied
                        # images
                        raise ValueError(
                            ("generator supported at vertex {} cannot"
                             " map to element with support {}").format(
                                 v, im_list[i].support()))
                    else:
                        # If the support works out add the images coordinates
                        # as a row of the matrix
                        maps_dict[v].append(codomain._spaces[v].coordinates(
                            im_list[i]._elems[v]))

                start_index += dim

        # Get the coordinates of the vector
        from sage.categories.map import is_Map
        vector = []
        for v in self._quiver:
            if v in maps_dict:
                if is_Map(maps_dict[v]):
                    try:
                        m = maps_dict[v].matrix()
                    except (AttributeError, ValueError):
                        gens_images = [
                            codomain._spaces[v].coordinate_vector(
                                maps_dict[v](x))
                            for x in domain._spaces[v].gens()
                        ]
                        m = Matrix(self._base_ring, domain_dims[v],
                                   codomain_dims[v], gens_images)
                else:
                    m = Matrix(self._base_ring, domain_dims[v],
                               codomain_dims[v], maps_dict[v])
            else:
                m = Matrix(self._base_ring, domain_dims[v], codomain_dims[v])
            for i in range(0, domain_dims[v]):
                vector += list(m[i])

        # Wrap as a vector, check it, and return
        self._vector = (self._base_ring**total_dim)(vector)
        self._assert_valid_hom()
        super(QuiverRepHom, self).__init__(domain.Hom(codomain))
Esempio n. 2
0
    def __init__(self, domain, codomain, data={}):
        """
        Initialize ``self``. Type ``QuiverRepHom?`` for more information.

        TESTS::

            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)
            sage: f = S.hom(M)
            sage: f.is_zero()
            True
            sage: maps2 = {2:[1, -1], 3:1}
            sage: g = S.hom(maps2, M)
            sage: x = M({2: (1, -1)})
            sage: y = M({3: (1,)})
            sage: h = S.hom([x, y], M)
            sage: g == h
            True
            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

        ::

            sage: Q = DiGraph({1:{2:['a']}}).path_semigroup()
            sage: H1 = Q.P(GF(3), 2).Hom(Q.S(GF(3), 2))
            sage: H2 = Q.P(GF(3), 2).Hom(Q.S(GF(3), 1))
            sage: H1.an_element() in H1   # indirect doctest
            True
        """
        # The data of a representation is held in the following private
        # variables:
        #
        # * _quiver
        #      The quiver of the representation.
        # * _base_ring
        #      The base ring of the representation.
        # * _domain
        #      The QuiverRep object that is the domain of the homomorphism.
        # * _codomain
        #      The QuiverRep object that is the codomain of the homomorphism.
        # * _vector
        #      A vector in some free module over the base ring of a length such
        #      that each coordinate corresponds to an entry in the matrix of a
        #      homomorphism attached to a vertex.
        #
        # The variable data can also be a vector of appropriate length.  When
        # this is the case it will be loaded directly into _vector and then
        # _assert_valid_hom is called.

        from sage.quivers.representation import QuiverRepElement, QuiverRep_with_path_basis

        self._domain = domain
        self._codomain = codomain
        self._quiver = domain._quiver
        self._base_ring = domain.base_ring()

        # Check that the quiver and base ring match
        if codomain._quiver != self._quiver:
            raise ValueError("the quivers of the domain and codomain must be equal")
        if codomain.base_ring() != self._base_ring:
            raise ValueError("the base ring of the domain and codomain must be equal")

        # Get the dimensions of the spaces
        mat_dims = {}
        domain_dims = {}
        codomain_dims = {}
        for v in self._quiver:
            domain_dims[v] = domain._spaces[v].dimension()
            codomain_dims[v] = codomain._spaces[v].dimension()
            mat_dims[v] = domain_dims[v]*codomain_dims[v]
        total_dim = sum(mat_dims.values())

        # Handle the case when data is a vector
        if data in self._base_ring**total_dim:
            self._vector = data
            self._assert_valid_hom()
            super(QuiverRepHom, self).__init__(domain.Hom(codomain))
            return

        # If data is not a dict, create one
        if isinstance(data, dict):
            maps_dict = data
        else:
            # If data is not a list create one, then create a dict from it
            if isinstance(data, list):
                im_list = data
            else:
                # If data is a QuiverRepHom, create a list from it
                if isinstance(data, QuiverRepHom):
                    f = data._domain.coerce_map_from(domain)
                    g = self._codomain.coerce_map_from(data._codomain)
                    im_list = [g(data(f(x))) for x in domain.gens()]

                # The only case left is that data is a QuiverRepElement
                else:
                    if not isinstance(data, QuiverRepElement):
                        raise TypeError("input data must be dictionary, list, "
                                        "QuiverRepElement or vector")
                    if not isinstance(domain, QuiverRep_with_path_basis):
                        raise TypeError("if data is a QuiverRepElement then domain "
                                        "must be a QuiverRep_with_path_basis.")
                    if data not in codomain:
                        raise ValueError("if data is a QuiverRepElement then it must "
                                         "be an element of codomain")
                    im_list = [codomain.right_edge_action(data, p) for v in domain._quiver for p in domain._bases[v]]

            # WARNING: This code assumes that the function QuiverRep.gens() returns
            # the generators ordered first by vertex and then by the order of the
            # gens() method of the space associated to that vertex.  In particular
            # this is the order that corresponds to how maps are represented via
            # matrices

            # Get the gens of the domain and check that im_list is the right length
            dom_gens = domain.gens()
            if len(im_list) != len(dom_gens):
                raise ValueError(("domain is dimension {} but only {} images"
                                  " were supplied").format(len(dom_gens), len(im_list)))

            # Get the matrices of the maps
            start_index = 0
            maps_dict = {}
            for v in self._quiver:
                maps_dict[v] = []
                dim = domain._spaces[v].dimension()
                for i in range(start_index, start_index + dim):
                    if len(im_list[i].support()) != 0 and im_list[i].support() != [v]:
                        # If the element doesn't have the correct support raise
                        # an error here, otherwise we might create a valid hom
                        # that does not map the generators to the supplied
                        # images
                        raise ValueError(("generator supported at vertex {} cannot"
                                          " map to element with support {}").format(
                                          v, im_list[i].support()))
                    else:
                        # If the support works out add the images coordinates
                        # as a row of the matrix
                        maps_dict[v].append(codomain._spaces[v].coordinates(im_list[i]._elems[v]))

                start_index += dim

        # Get the coordinates of the vector
        from sage.categories.map import is_Map
        vector = []
        for v in self._quiver:
            if v in maps_dict:
                if is_Map(maps_dict[v]):
                    if hasattr(maps_dict[v], 'matrix'):
                        m = maps_dict[v].matrix()
                    else:
                        gens_images = [codomain._spaces[v].coordinate_vector(maps_dict[v](x))
                                       for x in domain._spaces[v].gens()]
                        m = Matrix(self._base_ring, domain_dims[v], codomain_dims[v], gens_images)
                else:
                    m = Matrix(self._base_ring, domain_dims[v], codomain_dims[v], maps_dict[v])
            else:
                m = Matrix(self._base_ring, domain_dims[v], codomain_dims[v])
            for i in range(0, domain_dims[v]):
                vector += list(m[i])

        # Wrap as a vector, check it, and return
        self._vector = (self._base_ring**total_dim)(vector)
        self._assert_valid_hom()
        super(QuiverRepHom, self).__init__(domain.Hom(codomain))