Ticket #11556: trac_11556-linear-transformations.patch

File trac_11556-linear-transformations.patch, 20.9 KB (added by rbeezer, 10 years ago)

Safe-keeping patch

  • sage/modules/free_module.py

    # HG changeset patch
    # User Rob Beezer <beezer@ups.edu>
    # Date 1309408493 25200
    # Node ID 5047759cbe846382dc13630dd4a2742007ad7bfc
    # Parent  4ad86990d7215498658440de04560aa028dcdeeb
    11556: linear transformations from free module morphisms
    
    diff --git a/sage/modules/free_module.py b/sage/modules/free_module.py
    a b  
    604604
    605605    # FIXME: what's the level of generality of FreeModuleHomspace?
    606606    # Should there be a category for free modules accepting it as hom space?
     607    # See similar method for FreeModule_generic_field class
    607608    def _Hom_(self, Y, category):
    608609        from free_module_homspace import FreeModuleHomspace
    609610        return FreeModuleHomspace(self, Y, category)
     
    28962897            raise TypeError, "The base_field (=%s) must be a field"%base_field
    28972898        FreeModule_generic_pid.__init__(self, base_ring, dimension, degree, sparse=sparse)
    28982899
     2900    def _Hom_(self, Y, category):
     2901        r"""
     2902        Returns a homspace whose morphisms have this vector space as domain.
     2903
     2904        This is called by the general methods such as
     2905        :meth:`sage.structure.parent.Parent.Hom` and
     2906        :meth:`sage.structure.parent_base.ParentWithBase.Hom`.
     2907
     2908        INPUT:
     2909
     2910        - ``Y`` - a free module (or vector space) that will
     2911          be the codomain of the morphisms in returned homspace
     2912        - ``category`` - the category for the homspace
     2913
     2914        OUTPUT:
     2915
     2916        If ``Y`` is a free module over a field, in other words, a vector space,
     2917        then this returns a space of homomorphisms between vector spaces,
     2918        in other words a space of linear transformations.
     2919
     2920        If ``Y`` is a free module that is not a vector space, then
     2921        the returned space contains homomorphisms between free modules.
     2922
     2923        EXAMPLES::
     2924
     2925            sage: V = QQ^2
     2926            sage: W = QQ^3
     2927            sage: H = V._Hom_(W, category=None)
     2928            sage: type(H)
     2929            <class 'sage.modules.vector_space_homspace.VectorSpaceHomspace_with_category'>
     2930            sage: H
     2931            Set of Morphisms (Linear Transformations) from Vector space of dimension 2 over Rational Field to Vector space of dimension 3 over Rational Field
     2932
     2933            sage: V = QQ^2
     2934            sage: W = ZZ^3
     2935            sage: H = V._Hom_(W, category=None)
     2936            sage: type(H)
     2937            <class 'sage.modules.free_module_homspace.FreeModuleHomspace_with_category'>
     2938            sage: H
     2939            Set of Morphisms from Vector space of dimension 2 over Rational Field to Ambient free module of rank 3 over the principal ideal domain Integer Ring in Category of vector spaces over Rational Field
     2940        """
     2941        if Y.base_ring().is_field():
     2942            import vector_space_homspace
     2943            return vector_space_homspace.VectorSpaceHomspace(self, Y, category)
     2944        import free_module_homspace
     2945        return free_module_homspace.FreeModuleHomspace(self, Y, category)
     2946
    28992947    def scale(self, other):
    29002948        """
    29012949        Return the product of self by the number other, which is the module
  • sage/modules/free_module_homspace.py

    diff --git a/sage/modules/free_module_homspace.py b/sage/modules/free_module_homspace.py
    a b  
    7979from matrix_morphism import MatrixMorphism
    8080
    8181def is_FreeModuleHomspace(x):
    82     """
    83     Return True if x is a Free module homspace.
     82    r"""
     83    Return ``True`` if ``x`` is a free module homspace.
    8484
    85     EXAMPLES::
     85    EXAMPLES:
    8686
    87         sage: H = Hom(QQ^3, QQ^2)
     87    Notice that every vector space is a field, but when we construct a set of
     88    morphisms between two vector spaces, it is a ``VectorSpaceHomspace``,
     89    which qualifies as a ``FreeModuleHomspace``, since the former is
     90    special case of the latter.
     91
     92        sage: H = Hom(ZZ^3, ZZ^2)
     93        sage: type(H)
     94        <class 'sage.modules.free_module_homspace.FreeModuleHomspace_with_category'>
    8895        sage: sage.modules.free_module_homspace.is_FreeModuleHomspace(H)
    8996        True
    90         sage: sage.modules.free_module_homspace.is_FreeModuleHomspace(2)
     97
     98        sage: K = Hom(QQ^3, ZZ^2)
     99        sage: type(K)
     100        <class 'sage.modules.free_module_homspace.FreeModuleHomspace_with_category'>
     101        sage: sage.modules.free_module_homspace.is_FreeModuleHomspace(K)
     102        True
     103
     104        sage: L = Hom(ZZ^3, QQ^2)
     105        sage: type(L)
     106        <class 'sage.modules.free_module_homspace.FreeModuleHomspace_with_category'>
     107        sage: sage.modules.free_module_homspace.is_FreeModuleHomspace(L)
     108        True
     109
     110        sage: P = Hom(QQ^3, QQ^2)
     111        sage: type(P)
     112        <class 'sage.modules.vector_space_homspace.VectorSpaceHomspace_with_category'>
     113        sage: sage.modules.free_module_homspace.is_FreeModuleHomspace(P)
     114        True
     115
     116        sage: sage.modules.free_module_homspace.is_FreeModuleHomspace('junk')
    91117        False
    92118    """
    93119    return isinstance(x, FreeModuleHomspace)
    94120
    95121class FreeModuleHomspace(sage.categories.homset.HomsetWithBase):
    96122    def __call__(self, A, check=True):
    97         """
     123        r"""
    98124        INPUT:
    99125
    100126        - A -- either a matrix or a list/tuple of images of generators,
     
    109135
    110136        EXAMPLES::
    111137
    112             sage: V = (QQ^3).span_of_basis([[1,1,0],[1,0,2]])
     138            sage: V = (ZZ^3).span_of_basis([[1,1,0],[1,0,2]])
    113139            sage: H = V.Hom(V); H
    114140            Set of Morphisms from ...
    115141            sage: H([V.0,V.1])                    # indirect doctest
  • new file sage/modules/vector_space_homspace.py

    diff --git a/sage/modules/vector_space_homspace.py b/sage/modules/vector_space_homspace.py
    new file mode 100644
    - +  
     1r"""
     2Space of Morphisms of Vector Spaces (Linear Transformations)
     3
     4AUTHOR:
     5
     6    - Rob Beezer: (2011-06-29)
     7
     8A :class:`VectorSpaceHomspace` object represents the set of all
     9possible homomorphisms from one vector space to another.
     10These mappings are usually known as linear transformations.
     11
     12To actually construct and use linear transformations, consult
     13the documentation for vector space morphisms at
     14:module:`sage.modules.vector_space_morphisms`.
     15Also, this is an extremely thin veneer on free module homspaces
     16and free module morphisms, objects which might also be useful, and
     17places where much of the documentation resides.
     18
     19EXAMPLES:
     20
     21Creation and basic examination is simple. ::
     22
     23    sage: V = QQ^3
     24    sage: W = QQ^2
     25    sage: H = Hom(V, W)
     26    sage: H
     27    Set of Morphisms (Linear Transformations) from Vector space of dimension 3 over Rational Field to Vector space of dimension 2 over Rational Field
     28    sage: H.domain()
     29    Vector space of dimension 3 over Rational Field
     30    sage: H.codomain()
     31    Vector space of dimension 2 over Rational Field
     32
     33Homspaces have a few useful properties.  A basis is provided by
     34a list of matrix representations, where these matrix representatives
     35are relative to the bases of the domain and codomain.  ::
     36
     37    sage: K = Hom(GF(3)^2, GF(3)^2)
     38    sage: B = K.basis()
     39    sage: for f in B:
     40    ...     print f, "\n"
     41    Linear transformation represented by the matrix:
     42    (acting on vectors at the left of the matrix)
     43    [1 0]
     44    [0 0]
     45    Domain: Vector space of dimension 2 over Finite Field of size 3
     46    Codomain: Vector space of dimension 2 over Finite Field of size 3
     47    <BLANKLINE>
     48    Linear transformation represented by the matrix:
     49    (acting on vectors at the left of the matrix)
     50    [0 1]
     51    [0 0]
     52    Domain: Vector space of dimension 2 over Finite Field of size 3
     53    Codomain: Vector space of dimension 2 over Finite Field of size 3
     54    <BLANKLINE>
     55    Linear transformation represented by the matrix:
     56    (acting on vectors at the left of the matrix)
     57    [0 0]
     58    [1 0]
     59    Domain: Vector space of dimension 2 over Finite Field of size 3
     60    Codomain: Vector space of dimension 2 over Finite Field of size 3
     61    <BLANKLINE>
     62    Linear transformation represented by the matrix:
     63    (acting on vectors at the left of the matrix)
     64    [0 0]
     65    [0 1]
     66    Domain: Vector space of dimension 2 over Finite Field of size 3
     67    Codomain: Vector space of dimension 2 over Finite Field of size 3
     68    <BLANKLINE>
     69
     70The zero and identity mappings are properties of the space.
     71The identity mapping will only be available if the domain and codomain
     72allow for endomorphisms.  ::
     73
     74    sage: H = Hom(QQ^3, QQ^3)
     75    sage: g = H.zero()
     76    sage: g([1, 1/2, -3])
     77    (0, 0, 0)
     78    sage: f = H.identity()
     79    sage: f([1, 1/2, -3])
     80    (1, 1/2, -3)
     81
     82The homspace may be used with various representations of a
     83morphism in the space to create the morphism.  We demonstrate
     84three ways to create the same linear transformation between
     85two two-dimensional subspaces of `QQ^3`.  The "V.n" notation
     86is a shortcut to the generators of each vector space, better
     87known as the basis elements.  Note thst the matrix representations
     88are relative to the bases, which are purposely fixed as input
     89("user bases").  ::
     90
     91    sage: U = QQ^3
     92    sage: V = U.subspace_with_basis([U.0+U.1, U.1-U.2])
     93    sage: W = U.subspace_with_basis([U.0, U.1+U.2])
     94    sage: H = Hom(V, W)
     95
     96First, with a matrix.  Note that the matrix representation
     97acts by matrix multiplication with the vector on the left. ::
     98
     99    sage: m = matrix(QQ, [[1, 2], [3, 4]])
     100    sage: f1 = H(m)
     101    sage: f1
     102    Linear transformation represented by the matrix:
     103    (acting on vectors at the left of the matrix)
     104    [1 2]
     105    [3 4]
     106    Domain: Vector space of degree 3 and dimension 2 over Rational Field
     107    User basis matrix:
     108    [ 1  1  0]
     109    [ 0  1 -1]
     110    Codomain: Vector space of degree 3 and dimension 2 over Rational Field
     111    User basis matrix:
     112    [1 0 0]
     113    [0 1 1]
     114    sage: f1([3,1,2])
     115    (-3, -2, -2)
     116
     117Second, with a list of images of the domain's basis elements.  ::
     118
     119    sage: img = [1*(U.0) + 2*(U.1+U.2), 3*U.0 + 4*(U.1+U.2)]
     120    sage: f2 = H(img)
     121    sage: f2
     122    Linear transformation represented by the matrix:
     123    (acting on vectors at the left of the matrix)
     124    [1 2]
     125    [3 4]
     126    Domain: Vector space of degree 3 and dimension 2 over Rational Field
     127    User basis matrix:
     128    [ 1  1  0]
     129    [ 0  1 -1]
     130    Codomain: Vector space of degree 3 and dimension 2 over Rational Field
     131    User basis matrix:
     132    [1 0 0]
     133    [0 1 1]
     134    sage: f2([3,1,2])
     135    (-3, -2, -2)
     136
     137Third, with a function between the domain and codomain.  ::
     138
     139    sage: g = lambda x: vector(QQ, [-2*x[0]+3*x[1], -2*x[0]+4*x[1], -2*x[0]+4*x[1]])
     140    sage: f3 = H(g)
     141    sage: f3
     142    Linear transformation represented by the matrix:
     143    (acting on vectors at the left of the matrix)
     144    [1 2]
     145    [3 4]
     146    Domain: Vector space of degree 3 and dimension 2 over Rational Field
     147    User basis matrix:
     148    [ 1  1  0]
     149    [ 0  1 -1]
     150    Codomain: Vector space of degree 3 and dimension 2 over Rational Field
     151    User basis matrix:
     152    [1 0 0]
     153    [0 1 1]
     154    sage: f3([3,1,2])
     155    (-3, -2, -2)
     156
     157TESTS::
     158
     159    sage: V = QQ^2
     160    sage: W = QQ^3
     161    sage: H = Hom(QQ^2, QQ^3)
     162    sage: loads(dumps(H))
     163    Set of Morphisms (Linear Transformations) from Vector space of dimension 2 over Rational Field to Vector space of dimension 3 over Rational Field
     164    sage: loads(dumps(H)) == H
     165    True
     166"""
     167
     168####################################################################################
     169#       Copyright (C) 2011 Rob Beezer <beezer@ups.edu>
     170#
     171#  Distributed under the terms of the GNU General Public License (GPL)
     172#
     173#    This code is distributed in the hope that it will be useful,
     174#    but WITHOUT ANY WARRANTY; without even the implied warranty of
     175#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     176#    General Public License for more details.
     177#
     178#  The full text of the GPL is available at:
     179#
     180#                  http://www.gnu.org/licenses/
     181####################################################################################
     182
     183import inspect
     184import sage.matrix.all as matrix
     185import sage.modules.free_module_homspace
     186import vector_space_morphism
     187
     188# This module initially overrides just the minimum functionality necessary
     189# from  sage.modules.free_module_homspace.FreeModuleHomSpace.
     190# If additional methods here override the free module homspace methods,
     191# consider adjusting the free module doctests, since many are written with
     192# examples that are actually vector spaces and not so many use "pure" modules
     193# for the examples.
     194
     195
     196def is_VectorSpaceHomspace(x):
     197    r"""
     198    Return ``True`` if ``x`` is a vector space homspace.
     199
     200    EXAMPLES:
     201
     202    To be a vector space morphism, the domain and codomain must both be
     203    vector spaces, in other words, modules over fields.  If either
     204    set is just a module, then the ``Hom()`` constructor will build a
     205    space of free module morphisms.  ::
     206
     207        sage: H = Hom(QQ^3, QQ^2)
     208        sage: type(H)
     209        <class 'sage.modules.vector_space_homspace.VectorSpaceHomspace_with_category'>
     210        sage: sage.modules.vector_space_homspace.is_VectorSpaceHomspace(H)
     211        True
     212
     213        sage: K = Hom(QQ^3, ZZ^2)
     214        sage: type(K)
     215        <class 'sage.modules.free_module_homspace.FreeModuleHomspace_with_category'>
     216        sage: sage.modules.vector_space_homspace.is_VectorSpaceHomspace(K)
     217        False
     218
     219        sage: L = Hom(ZZ^3, QQ^2)
     220        sage: type(L)
     221        <class 'sage.modules.free_module_homspace.FreeModuleHomspace_with_category'>
     222        sage: sage.modules.vector_space_homspace.is_VectorSpaceHomspace(L)
     223        False
     224
     225        sage: sage.modules.vector_space_homspace.is_VectorSpaceHomspace('junk')
     226        False
     227    """
     228    return isinstance(x, VectorSpaceHomspace)
     229
     230
     231class VectorSpaceHomspace(sage.modules.free_module_homspace.FreeModuleHomspace):
     232
     233    def __call__(self, A, check=True):
     234        r"""
     235        INPUT:
     236
     237        - ``A`` - one of several possible inputs representing
     238          a morphism from this vector space homspace.
     239          - a matrix representation relative to the bases of the vector spaces
     240          - a list or tuple containing images of the domain's basis vectors
     241          - a function from the domain to the codomain
     242        - ``check`` (default: True) - ``True`` or ``False``, required for
     243          compatibility with calls from
     244          :meth:`sage.structure.parent_gens.ParentWithGens.hom`.
     245
     246        EXAMPLES::
     247
     248            sage: V = (QQ^3).span_of_basis([[1,1,0],[1,0,2]])
     249            sage: H = V.Hom(V); H
     250            Set of Morphisms from ...
     251            sage: H([V.0,V.1])                    # indirect doctest
     252            Free module morphism defined by the matrix
     253            [1 0]
     254            [0 1]...
     255            sage: phi = H([V.1,V.0]); phi
     256            Free module morphism defined by the matrix
     257            [0 1]
     258            [1 0]...
     259            sage: phi(V.1) == V.0
     260            True
     261            sage: phi(V.0) == V.1
     262            True
     263        """
     264        if not matrix.is_Matrix(A):
     265            # Compute the matrix of the morphism that sends the
     266            # generators of the domain to the elements of A.
     267            C = self.codomain()
     268            if inspect.isfunction(A):
     269                try:
     270                    v = [C(A(g)) for g in self.domain().gens()]
     271                    A = matrix.matrix([C.coordinates(a) for a in v])
     272                except TypeError, msg:
     273                    # Let us hope that FreeModuleMorphism knows to handle that case
     274                    pass
     275            else:
     276                try:
     277                    v = [C(a) for a in A]
     278                    A = matrix.matrix([C.coordinates(a) for a in v])
     279                except TypeError, msg:
     280                    # Let us hope that FreeModuleMorphism knows to handle that case
     281                    pass
     282        return vector_space_morphism.VectorSpaceMorphism(self, A, side='left')
     283
     284
     285    def _repr_(self):
     286        r"""
     287        Text representation of a space of vector space morphisms.
     288
     289        EXAMPLE::
     290
     291            sage: H = Hom(QQ^2, QQ^3)
     292            sage: H._repr_()
     293            'Set of Morphisms (Linear Transformations) from Vector space of dimension 2 over Rational Field to Vector space of dimension 3 over Rational Field'
     294        """
     295        msg = 'Set of Morphisms (Linear Transformations) from {0} to {1}'
     296        return msg.format(self.domain(), self.codomain())
     297 No newline at end of file
  • new file sage/modules/vector_space_morphism.py

    diff --git a/sage/modules/vector_space_morphism.py b/sage/modules/vector_space_morphism.py
    new file mode 100644
    - +  
     1"""
     2Vector Space Morphisms (aka Linear Transformations)
     3
     4AUTHORS:
     5
     6    - Rob Beezer: (2011-06-29)
     7
     8TESTS::
     9
     10    sage: V = QQ^2; f = V.hom([V.1,-2*V.0])
     11    sage: loads(dumps(f))
     12    Free module morphism defined by the matrix
     13    [ 0  1]
     14    [-2  0]
     15    Domain: Ambient free module of rank 2 over the principal ideal domain ...
     16    Codomain: Ambient free module of rank 2 over the principal ideal domain ...
     17    sage: loads(dumps(f)) == f
     18    True
     19"""
     20
     21####################################################################################
     22#       Copyright (C) 2011 Rob Beezer <beezer@ups.edu>
     23#
     24#  Distributed under the terms of the GNU General Public License (GPL)
     25#
     26#    This code is distributed in the hope that it will be useful,
     27#    but WITHOUT ANY WARRANTY; without even the implied warranty of
     28#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     29#    General Public License for more details.
     30#
     31#  The full text of the GPL is available at:
     32#
     33#                  http://www.gnu.org/licenses/
     34####################################################################################
     35
     36
     37import sage.modules.matrix_morphism as matrix_morphism
     38import sage.modules.free_module_morphism as free_module_morphism
     39import vector_space_homspace
     40
     41def is_VectorSpaceMorphism(x):
     42    r"""
     43    Returns ``True`` if ``x`` is a vector space morphism (a linear transformation).
     44
     45    INPUT:
     46
     47    ``x`` - anything
     48
     49    OUTPUT:
     50
     51    ``True`` only if ``x`` is an instance of a vector space morphism,
     52    which are also known as linear transformations.
     53
     54    EXAMPLES::
     55
     56        sage: V = QQ^2; f = V.hom([V.1,-2*V.0])
     57        sage: sage.modules.vector_space_morphism.is_VectorSpaceMorphism(f)
     58        True
     59        sage: sage.modules.vector_space_morphism.is_VectorSpaceMorphism('junk')
     60        False
     61    """
     62    return isinstance(x, VectorSpaceMorphism)
     63
     64
     65
     66
     67class VectorSpaceMorphism(free_module_morphism.FreeModuleMorphism):
     68
     69    def __init__(self, homspace, A, side=None):
     70        r"""
     71        Create a linear transformation, a morphism between vector spaces.
     72
     73        INPUT:
     74
     75        -  ``homspace`` - a homspace (of vector spaces) to serve
     76            as a parent for the linear transformation
     77        -  ``A`` - matrix representing the linear transformation
     78        - ``side`` - default: 'left' - values are 'left' and 'right',
     79            and indicates side of the matrix where the argument is placed
     80            when the matrix is used to effect the linear transformation.
     81
     82        EXAMPLES::
     83
     84            sage: V = QQ^3; W = span([[1,2,3],[-1,2,5/3]], QQ)
     85            sage: phi = V.hom(matrix(QQ,3,[1..9]))
     86            sage: type(phi)
     87            <class 'sage.modules.free_module_morphism.FreeModuleMorphism'>
     88        """
     89        if not vector_space_homspace.is_VectorSpaceHomspace(homspace):
     90            raise TypeError, 'homspace must be a vector space hom space, not {0}'.format(homspace)
     91        msg = 'domain of linear transformation must be a field, not {0}'
     92        if not homspace.domain().base_ring().is_field():
     93            raise TypeError(msg.format(homspace.domain().base_ring()))
     94        if not homspace.codomain().base_ring().is_field():
     95            raise TypeError(('co'+msg).format(homspace.codomain().base_ring()))
     96        if isinstance(A, matrix_morphism.MatrixMorphism):
     97            A = A.matrix()
     98            side = 'left'
     99        if side == None:
     100            side = 'left'
     101        if not side in ['left', 'right']:
     102            raise ValueError("side must be 'left' or 'right', not {0}".format(side))
     103        # now have a vector space homspace, a matrix and a side
     104        # so can build the morphism
     105        #
     106        # to work on an argument on the right, we just carry the transpose
     107        # this should be totally cosmetic - input here, output elsewhere
     108        # otherwise we will not reference _side, nor make it available
     109        self._side = side
     110        if side == 'right':
     111            A = A.transpose()
     112        A = homspace._matrix_space()(A)
     113        free_module_morphism.FreeModuleMorphism.__init__(self, homspace, A)
     114
     115
     116
     117    def _latex_(self):
     118        pass
     119
     120    def _repr_(self):
     121        r"""
     122        """
     123        mat = self.matrix()
     124        if self._side == 'right':
     125            mat = mat.transpose()
     126        msg = ("Linear transformation represented by the matrix:\n",
     127               "(acting on vectors at the {0} of the matrix)\n{1}\n",
     128               "Domain: {2}\n",
     129               "Codomain: {3}")
     130        return ''.join(msg).format(self._side, mat, self.domain(), self.codomain())
     131
     132
     133
     134
     135
     136
     137
     138
     139
     140
     141
     142
     143
     144
     145
     146
     147
     148
     149