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

File trac_11553-matrix-morphisms-additions-v2.patch, 9.0 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 7e5bfd1845c700fa852b4a7435f8a287f7dd91a2
    # Parent  c69e9a23607fa9326561439023c6b37448b1c7b4
    11553: matrix morphisms,  additional methods
    
    diff --git a/sage/modules/matrix_morphism.py b/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::
     
    568691        raise NotImplementedError, "this method must be overridden in the extension class"
    569692
    570693    def rank(self):
    571         """
     694        r"""
     695        Returns the rank of the matrix representing this morphism.
     696
    572697        EXAMPLES::
    573698       
    574699            sage: V = ZZ^2; phi = V.hom(V.basis())
     
    580705        """
    581706        return self.matrix().rank()
    582707
     708    def nullity(self):
     709        r"""
     710        Returns the nullity of the matrix representing this morphism.
     711
     712        EXAMPLES::
     713
     714            sage: V = ZZ^2; phi = V.hom(V.basis())
     715            sage: phi.nullity()
     716            0
     717            sage: V = ZZ^2; phi = V.hom([V.0, V.0])
     718            sage: phi.nullity()
     719            1
     720        """
     721        return self.matrix().left_nullity()
     722
    583723    def restrict_domain(self, sub):
    584724        """
    585725        Restrict this matrix morphism to a subspace sub of the domain. The
     
    8711011        #   reverse inclusion of below is trivially true
    8721012        return self.codomain().is_submodule(self.image())
    8731013
     1014    def is_bijective(self):
     1015        r"""
     1016        Tell whether ``self`` is bijective.
     1017
     1018        EXAMPLES:
     1019
     1020        Two morphisms that are obviously not bijective, simply on
     1021        considerations of the dimensions.  However, each fullfills
     1022        half of the requirements to be a bijection.  ::
     1023
     1024            sage: V1 = QQ^2
     1025            sage: V2 = QQ^3
     1026            sage: m = matrix(QQ, [[1,2],[3,4],[5,6]])
     1027            sage: phi = V1.hom(m, V2)
     1028            sage: phi.is_injective()
     1029            True
     1030            sage: phi.is_bijective()
     1031            False
     1032            sage: rho = V2.hom(m.transpose(), V1)
     1033            sage: rho.is_surjective()
     1034            True
     1035            sage: rho.is_bijective()
     1036            False
     1037
     1038        We construct a simple bijection between two one-dimensional
     1039        vector spaces.  ::
     1040
     1041            sage: V1 = QQ^3
     1042            sage: V2 = QQ^2
     1043            sage: phi = V1.hom(matrix(QQ, [[1, 2, 3], [4, 5, 6]]), V2)
     1044            sage: x = vector(QQ, [1, -1, 4])
     1045            sage: y = phi(x); y
     1046            (18, 22)
     1047            sage: rho = phi.restrict_domain(V1.span([x]))
     1048            sage: zeta = rho.restrict_codomain(V2.span([y]))
     1049            sage: zeta.is_bijective()
     1050            True
     1051
     1052        AUTHOR:
     1053
     1054        - Rob Beezer (2011-06-28)
     1055        """
     1056        return self.is_injective() and self.is_surjective()
     1057
     1058    def is_identity(self):
     1059        r"""
     1060        Determines if this morphism is the identity or not.
     1061
     1062        EXAMPLES:
     1063
     1064        A homomorphism that cannot possibly be the identity
     1065        due to an unequal domain and codomain.  ::
     1066
     1067            sage: V = QQ^3
     1068            sage: W = QQ^2
     1069            sage: m = matrix(QQ, [[1, 2], [3, 4], [5, 6]])
     1070            sage: phi = V.hom(m, W)
     1071            sage: phi.is_identity()
     1072            False
     1073
     1074        A bijection, but not the identity. ::
     1075
     1076            sage: V = QQ^3
     1077            sage: n = matrix(QQ, [[3, 1, -8], [5, -4, 6], [1, 1, -5]])
     1078            sage: phi = V.hom(n, V)
     1079            sage: phi.is_bijective()
     1080            True
     1081            sage: phi.is_identity()
     1082            False
     1083
     1084        A restriction that is the identity.  ::
     1085
     1086            sage: V = QQ^3
     1087            sage: p = matrix(QQ, [[1, 0, 0], [5, 8, 3], [0, 0, 1]])
     1088            sage: phi = V.hom(p, V)
     1089            sage: rho = phi.restrict(V.span([V.0, V.2]))
     1090            sage: rho.is_identity()
     1091            True
     1092
     1093        TEST::
     1094
     1095            sage: V = QQ^10
     1096            sage: H = Hom(V, V)
     1097            sage: id = H.identity()
     1098            sage: id.is_identity()
     1099            True
     1100
     1101        AUTHOR:
     1102
     1103        - Rob Beezer (2011-06-28)
     1104        """
     1105        import sage.matrix.constructor
     1106        if self.domain() != self.codomain():
     1107            return False
     1108        R = self.base_ring()
     1109        n = self.domain().dimension()
     1110        if self.matrix() != sage.matrix.constructor.identity_matrix(R, n):
     1111            return False
     1112        return True
     1113
    8741114    def _repr_(self):
    8751115        """
    8761116        Return string representation of this morphism (this gets overloaded in the derived class).