Ticket #11553: trac_11553-matrix-morphisms-additions.patch

File trac_11553-matrix-morphisms-additions.patch, 8.1 KB (added by rbeezer, 10 years ago)
  • sage/modules/matrix_morphism.py

    # HG changeset patch
    # User Rob Beezer <beezer@ups.edu>
    # Date 1309303921 25200
    # Node ID a0440ab5e935ee3b3031d695b589b085aa61203a
    # Parent  5bdcfb304ad9a5f12c702e641b63b7289ba28a11
    11553: matrix morphisms,  additional methods
    
    diff -r 5bdcfb304ad9 -r a0440ab5e935 sage/modules/matrix_morphism.py
    a b  
    192192        except TypeError:
    193193            raise ZeroDivisionError, "matrix morphism not invertible"
    194194
     195    def inverse(self):
     196        r"""
     197        Returns the inverse of this matrix morphism, if the inverse exists.
     198
     199        Raises a ``ZeroDivisionError`` if the inverse does not exist.
     200
     201        EXAMPLES:
     202
     203        An invertible morphism created as a restriction of
     204        a non-invertible morphism, and which has an unequal
     205        domain and codomain.  ::
     206
     207            sage: V = QQ^4
     208            sage: W = QQ^3
     209            sage: m = matrix(QQ, [[2, 0, 3], [-6, 1, 4], [1, 2, -4], [1, 0, 1]])
     210            sage: phi = V.hom(m, W)
     211            sage: rho = phi.restrict_domain(V.span([V.0, V.3]))
     212            sage: zeta = rho.restrict_codomain(W.span([W.0, W.2]))
     213            sage: x = vector(QQ, [2, 0, 0, -7])
     214            sage: y = zeta(x); y
     215            (-3, 0, -1)
     216            sage: inv = zeta.inverse(); inv
     217            Free module morphism defined by the matrix
     218            [-1  3]
     219            [ 1 -2]
     220            Domain: Vector space of degree 3 and dimension 2 over Rational Field
     221            Basis ...
     222            Codomain: Vector space of degree 4 and dimension 2 over Rational Field
     223            Basis ...
     224            sage: inv(y) == x
     225            True
     226
     227        An example of an invertible morphism between modules,
     228        (rather than between vector spaces).  ::
     229
     230            sage: M = ZZ^4
     231            sage: p = matrix(ZZ, [[ 0, -1,  1, -2],
     232            ...                   [ 1, -3,  2, -3],
     233            ...                   [ 0,  4, -3,  4],
     234            ...                   [-2,  8, -4,  3]])
     235            sage: phi = M.hom(p, M)
     236            sage: x = vector(ZZ, [1, -3, 5, -2])
     237            sage: y = phi(x); y
     238            (1, 12, -12, 21)
     239            sage: rho = phi.inverse(); rho
     240            Free module morphism defined by the matrix
     241            [ -5   3  -1   1]
     242            [ -9   4  -3   2]
     243            [-20   8  -7   4]
     244            [ -6   2  -2   1]
     245            Domain: Ambient free module of rank 4 over the principal ideal domain ...
     246            Codomain: Ambient free module of rank 4 over the principal ideal domain ...
     247            sage: rho(y) == x
     248            True
     249
     250        A non-invertible morphism, despite having an appropriate
     251        domain and codomain.  ::
     252
     253            sage: V = QQ^2
     254            sage: m = matrix(QQ, [[1, 2], [20, 40]])
     255            sage: phi = V.hom(m, V)
     256            sage: phi.is_bijective()
     257            False
     258            sage: phi.inverse()
     259            Traceback (most recent call last):
     260            ...
     261            ZeroDivisionError: matrix morphism not invertible
     262
     263        The matrix representation of this morphism is invertible
     264        over the rationals, but not over the integers, thus the
     265        morphism is not invertible as a map between modules.
     266        It is easy to notice from the definition that every
     267        vector of the image will have a second entry that
     268        is an even integer.  ::
     269
     270            sage: V = ZZ^2
     271            sage: q = matrix(ZZ, [[1, 2], [3, 4]])
     272            sage: phi = V.hom(q, V)
     273            sage: phi.matrix().change_ring(QQ).inverse()
     274            [  -2    1]
     275            [ 3/2 -1/2]
     276            sage: phi.is_bijective()
     277            False
     278            sage: phi.image()
     279            Free module of degree 2 and rank 2 over Integer Ring
     280            Echelon basis matrix:
     281            [1 0]
     282            [0 2]
     283            sage: phi.lift(vector(ZZ, [1, 1]))
     284            Traceback (most recent call last):
     285            ...
     286            ValueError: element is not in the image
     287            sage: phi.inverse()
     288            Traceback (most recent call last):
     289            ...
     290            ZeroDivisionError: matrix morphism not invertible
     291
     292        The unary invert operator (~, tilde, "wiggle") is synonymous
     293        with the ``inverse()`` method (and a lot easier to type).  ::
     294
     295            sage: V = QQ^2
     296            sage: r = matrix(QQ, [[4, 3], [-2, 5]])
     297            sage: phi = V.hom(r, V)
     298            sage: rho = phi.inverse()
     299            sage: zeta = ~phi
     300            sage: rho == zeta
     301            True
     302
     303        TESTS::
     304
     305            sage: V = QQ^2
     306            sage: W = QQ^3
     307            sage: U = W.span([W.0, W.1])
     308            sage: m = matrix(QQ, [[2, 1], [3, 4]])
     309            sage: phi = V.hom(m, U)
     310            sage: inv = phi.inverse()
     311            sage: (inv*phi).is_identity()
     312            True
     313            sage: (phi*inv).is_identity()
     314            True
     315        """
     316        return self.__invert__()
     317
    195318    def __rmul__(self, left):
    196319        """
    197320        EXAMPLES::
     
    853976        """
    854977        return self.image() == self.codomain()
    855978
     979    def is_bijective(self):
     980        r"""
     981        Tell whether ``self`` is bijective.
     982
     983        EXAMPLES:
     984
     985        Two morphisms that are obviously not bijective, simply on
     986        considerations of the dimensions.  However, each fullfills
     987        half of the requirements to be a bijection.  ::
     988
     989            sage: V1 = QQ^2
     990            sage: V2 = QQ^3
     991            sage: m = matrix(QQ, [[1,2],[3,4],[5,6]])
     992            sage: phi = V1.hom(m, V2)
     993            sage: phi.is_injective()
     994            True
     995            sage: phi.is_bijective()
     996            False
     997            sage: rho = V2.hom(m.transpose(), V1)
     998            sage: rho.is_surjective()
     999            True
     1000            sage: rho.is_bijective()
     1001            False
     1002
     1003        We construct a simple bijection between two one-dimensional
     1004        vector spaces.  ::
     1005
     1006            sage: V1 = QQ^3
     1007            sage: V2 = QQ^2
     1008            sage: phi = V1.hom(matrix(QQ, [[1, 2, 3], [4, 5, 6]]), V2)
     1009            sage: x = vector(QQ, [1, -1, 4])
     1010            sage: y = phi(x); y
     1011            (18, 22)
     1012            sage: rho = phi.restrict_domain(V1.span([x]))
     1013            sage: zeta = rho.restrict_codomain(V2.span([y]))
     1014            sage: zeta.is_bijective()
     1015            True
     1016
     1017        AUTHOR:
     1018
     1019        - Rob Beezer (2011-06-28)
     1020        """
     1021        return self.is_injective() and self.is_surjective()
     1022
     1023    def is_identity(self):
     1024        r"""
     1025        Determines if this morphism is the identity or not.
     1026
     1027        EXAMPLES:
     1028
     1029        A homomorphism that cannot possibly be the identity
     1030        due to an unequal domain and codomain.  ::
     1031
     1032            sage: V = QQ^3
     1033            sage: W = QQ^2
     1034            sage: m = matrix(QQ, [[1, 2], [3, 4], [5, 6]])
     1035            sage: phi = V.hom(m, W)
     1036            sage: phi.is_identity()
     1037            False
     1038
     1039        A bijection, but not the identity. ::
     1040
     1041            sage: V = QQ^3
     1042            sage: n = matrix(QQ, [[3, 1, -8], [5, -4, 6], [1, 1, -5]])
     1043            sage: phi = V.hom(n, V)
     1044            sage: phi.is_bijective()
     1045            True
     1046            sage: phi.is_identity()
     1047            False
     1048
     1049        A restriction that is the identity.  ::
     1050
     1051            sage: V = QQ^3
     1052            sage: p = matrix(QQ, [[1, 0, 0], [5, 8, 3], [0, 0, 1]])
     1053            sage: phi = V.hom(p, V)
     1054            sage: rho = phi.restrict(V.span([V.0, V.2]))
     1055            sage: rho.is_identity()
     1056            True
     1057
     1058        TEST::
     1059
     1060            sage: V = QQ^10
     1061            sage: H = Hom(V, V)
     1062            sage: id = H.identity()
     1063            sage: id.is_identity()
     1064            True
     1065
     1066        AUTHOR:
     1067
     1068        - Rob Beezer (2011-06-28)
     1069        """
     1070        import sage.matrix.constructor
     1071        if self.domain() != self.codomain():
     1072            return False
     1073        R = self.base_ring()
     1074        n = self.domain().dimension()
     1075        if self.matrix() != sage.matrix.constructor.identity_matrix(R, n):
     1076            return False
     1077        return True
     1078
    8561079    def _repr_(self):
    8571080        """
    8581081        Return string representation of this morphism (this gets overloaded in the derived class).