Path: blob/master/src/sage/modules/free_module_homspace.py
8815 views
r"""1Homspaces between free modules23EXAMPLES: We create `\mathrm{End}(\ZZ^2)` and compute a4basis.56::78sage: M = FreeModule(IntegerRing(),2)9sage: E = End(M)10sage: B = E.basis()11sage: len(B)12413sage: B[0]14Free module morphism defined by the matrix15[1 0]16[0 0]17Domain: Ambient free module of rank 2 over the principal ideal domain ...18Codomain: Ambient free module of rank 2 over the principal ideal domain ...1920We create `\mathrm{Hom}(\ZZ^3, \ZZ^2)` and21compute a basis.2223::2425sage: V3 = FreeModule(IntegerRing(),3)26sage: V2 = FreeModule(IntegerRing(),2)27sage: H = Hom(V3,V2)28sage: H29Set of Morphisms from Ambient free module of rank 330over the principal ideal domain Integer Ring to31Ambient free module of rank 232over the principal ideal domain Integer Ring33in Category of modules with basis over Integer Ring34sage: B = H.basis()35sage: len(B)36637sage: B[0]38Free module morphism defined by the matrix39[1 0]40[0 0]41[0 0]...4243TESTS::4445sage: H = Hom(QQ^2, QQ^1)46sage: loads(dumps(H)) == H47True4849See trac 5886::5051sage: V = (ZZ^2).span_of_basis([[1,2],[3,4]])52sage: V.hom([V.0, V.1])53Free module morphism defined by the matrix54[1 0]55[0 1]...5657"""5859#*****************************************************************************60# Copyright (C) 2005 William Stein <[email protected]>61#62# Distributed under the terms of the GNU General Public License (GPL)63#64# This code is distributed in the hope that it will be useful,65# but WITHOUT ANY WARRANTY; without even the implied warranty66# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.67#68# See the GNU General Public License for more details; the full text69# is available at:70#71# http://www.gnu.org/licenses/72#*****************************************************************************7374import sage.categories.homset75import sage.matrix.all as matrix76import free_module_morphism77from inspect import isfunction78from sage.misc.cachefunc import cached_method798081def is_FreeModuleHomspace(x):82r"""83Return ``True`` if ``x`` is a free module homspace.8485EXAMPLES:8687Notice that every vector space is a free module, but when we construct88a set of morphisms between two vector spaces, it is a89``VectorSpaceHomspace``, which qualifies as a ``FreeModuleHomspace``,90since the former is special case of the latter.9192sage: H = Hom(ZZ^3, ZZ^2)93sage: type(H)94<class 'sage.modules.free_module_homspace.FreeModuleHomspace_with_category'>95sage: sage.modules.free_module_homspace.is_FreeModuleHomspace(H)96True9798sage: K = Hom(QQ^3, ZZ^2)99sage: type(K)100<class 'sage.modules.free_module_homspace.FreeModuleHomspace_with_category'>101sage: sage.modules.free_module_homspace.is_FreeModuleHomspace(K)102True103104sage: L = Hom(ZZ^3, QQ^2)105sage: type(L)106<class 'sage.modules.free_module_homspace.FreeModuleHomspace_with_category'>107sage: sage.modules.free_module_homspace.is_FreeModuleHomspace(L)108True109110sage: P = Hom(QQ^3, QQ^2)111sage: type(P)112<class 'sage.modules.vector_space_homspace.VectorSpaceHomspace_with_category'>113sage: sage.modules.free_module_homspace.is_FreeModuleHomspace(P)114True115116sage: sage.modules.free_module_homspace.is_FreeModuleHomspace('junk')117False118"""119return isinstance(x, FreeModuleHomspace)120121class FreeModuleHomspace(sage.categories.homset.HomsetWithBase):122def __call__(self, A, check=True):123r"""124INPUT:125126- A -- either a matrix or a list/tuple of images of generators,127or a function returning elements of the codomain for elements128of the domain.129- check -- bool (default: True)130131If A is a matrix, then it is the matrix of this linear132transformation, with respect to the basis for the domain and133codomain. Thus the identity matrix always defines the134identity morphism.135136EXAMPLES::137138sage: V = (ZZ^3).span_of_basis([[1,1,0],[1,0,2]])139sage: H = V.Hom(V); H140Set of Morphisms from ...141sage: H([V.0,V.1]) # indirect doctest142Free module morphism defined by the matrix143[1 0]144[0 1]...145sage: phi = H([V.1,V.0]); phi146Free module morphism defined by the matrix147[0 1]148[1 0]...149sage: phi(V.1) == V.0150True151sage: phi(V.0) == V.1152True153154The following tests against a bug that was fixed in trac155ticket #9944. The method ``zero()`` calls this hom space with156a function, not with a matrix, and that case had previously157not been taken care of::158159sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ)160sage: V.Hom(V).zero() # indirect doctest161Free module morphism defined by the matrix162[0 0 0]163[0 0 0]164[0 0 0]165Domain: Free module of degree 3 and rank 3 over Integer Ring166Echelon ...167Codomain: Free module of degree 3 and rank 3 over Integer Ring168Echelon ...169170"""171if not sage.matrix.matrix.is_Matrix(A):172# Compute the matrix of the morphism that sends the173# generators of the domain to the elements of A.174C = self.codomain()175if isfunction(A):176try:177v = [C(A(g)) for g in self.domain().gens()]178A = matrix.matrix([C.coordinates(a) for a in v])179except TypeError, msg:180# Let us hope that FreeModuleMorphism knows to handle that case181pass182else:183try:184v = [C(a) for a in A]185A = matrix.matrix([C.coordinates(a) for a in v])186except TypeError, msg:187# Let us hope that FreeModuleMorphism knows to handle that case188pass189return free_module_morphism.FreeModuleMorphism(self, A)190191@cached_method192def zero(self):193"""194EXAMPLES::195196sage: E = ZZ^2197sage: F = ZZ^3198sage: H = Hom(E, F)199sage: f = H.zero()200sage: f201Free module morphism defined by the matrix202[0 0 0]203[0 0 0]204Domain: Ambient free module of rank 2 over the principal ideal domain Integer Ring205Codomain: Ambient free module of rank 3 over the principal ideal domain Integer Ring206sage: f(E.an_element())207(0, 0, 0)208sage: f(E.an_element()) == F.zero()209True210211TESTS:212213We check that ``H.zero()`` is picklable::214215sage: loads(dumps(f.parent().zero()))216Free module morphism defined by the matrix217[0 0 0]218[0 0 0]219Domain: Ambient free module of rank 2 over the principal ideal domain Integer Ring220Codomain: Ambient free module of rank 3 over the principal ideal domain Integer Ring221"""222return self(lambda x: self.codomain().zero())223224def _matrix_space(self):225"""226Return underlying matrix space that contains the matrices that define227the homomorphisms in this free module homspace.228229OUTPUT:230231- matrix space232233EXAMPLES::234235sage: H = Hom(QQ^3, QQ^2)236sage: H._matrix_space()237Full MatrixSpace of 3 by 2 dense matrices over Rational Field238"""239try:240return self.__matrix_space241except AttributeError:242R = self.domain().base_ring()243M = matrix.MatrixSpace(R, self.domain().rank(), self.codomain().rank())244self.__matrix_space = M245return M246247def basis(self):248"""249Return a basis for this space of free module homomorphisms.250251OUTPUT:252253- tuple254255EXAMPLES::256257sage: H = Hom(ZZ^2, ZZ^1)258sage: H.basis()259(Free module morphism defined by the matrix260[1]261[0]262Domain: Ambient free module of rank 2 over the principal ideal domain ...263Codomain: Ambient free module of rank 1 over the principal ideal domain ..., Free module morphism defined by the matrix264[0]265[1]266Domain: Ambient free module of rank 2 over the principal ideal domain ...267Codomain: Ambient free module of rank 1 over the principal ideal domain ...)268"""269try:270return self.__basis271except AttributeError:272M = self._matrix_space()273B = M.basis()274self.__basis = tuple([self(x) for x in B])275return self.__basis276277def identity(self):278r"""279Return identity morphism in an endomorphism ring.280281EXAMPLE::282283sage: V=FreeModule(ZZ,5)284sage: H=V.Hom(V)285sage: H.identity()286Free module morphism defined by the matrix287[1 0 0 0 0]288[0 1 0 0 0]289[0 0 1 0 0]290[0 0 0 1 0]291[0 0 0 0 1]292Domain: Ambient free module of rank 5 over the principal ideal domain ...293Codomain: Ambient free module of rank 5 over the principal ideal domain ...294"""295if self.is_endomorphism_set():296return self(matrix.identity_matrix(self.base_ring(),self.domain().rank()))297else:298raise TypeError, "Identity map only defined for endomorphisms. Try natural_map() instead."299300301302