Ticket #8071: trac_8071-matrix-kernels-trivially.patch

File trac_8071-matrix-kernels-trivially.patch, 18.5 KB (added by rbeezer, 11 years ago)
  • sage/matrix/matrix2.pyx

    # HG changeset patch
    # User Rob Beezer <beezer@ups.edu>
    # Date 1264571203 28800
    # Node ID 9d78f89061fc59a0bb1eb79718f097725df7deba
    # Parent  4498ef979fc42b03037970223b0873b07d63b96b
    Trac 8071: right kernels in trivial cases
    
    diff -r 4498ef979fc4 -r 9d78f89061fc sage/matrix/matrix2.pyx
    a b  
    20652065        """
    20662066        return self.ncols() - self.rank()
    20672067
     2068    ######################################
     2069    # Kernel Helper Functions
     2070    ######################################
     2071
     2072    def _right_kernel_trivial(self):
     2073        r"""
     2074        Computes the right kernel of matrices with zero rows or zero columns (or both).
     2075
     2076        OUTPUT:
     2077        For a matrix with zero columns, the returned kernel
     2078        has degree zero and thus dimension zero.  For a matrix with
     2079        zero rows the degree is the number of columns and the
     2080        dimension is full (the number of columns).
     2081
     2082        If the base ring is a field the result is a
     2083        :meth:`sage.modules.free_module.VectorSpace`,
     2084        otherwise the result is a
     2085        :meth:`sage.modules.free_module.FreeModule`.
     2086
     2087        TESTS:
     2088
     2089        Three rows, zero columns, over a field. ::
     2090
     2091            sage: m = matrix(QQ, [[],[],[]])
     2092            sage: m._right_kernel_trivial()
     2093            Vector space of degree 0 and dimension 0 over Rational Field
     2094            Basis matrix:
     2095            []
     2096
     2097        Zero rows, three columns, over a field. ::
     2098
     2099            sage: m = matrix(QQ, [[],[],[]]).transpose()
     2100            sage: m._right_kernel_trivial()
     2101            Vector space of dimension 3 over Rational Field
     2102
     2103        Three rows, zero columns, over a principal ideal domain. ::
     2104
     2105            sage: m = matrix(ZZ, [[],[],[]])
     2106            sage: m._right_kernel_trivial()
     2107            Free module of degree 0 and rank 0 over Integer Ring
     2108            Echelon basis matrix:
     2109            []
     2110
     2111        Zero rows, three columns, over a  principal ideal domain. ::
     2112
     2113            sage: m = matrix(ZZ, [[],[],[]]).transpose()
     2114            sage: m._right_kernel_trivial()
     2115            Ambient free module of rank 3 over the principal ideal domain Integer Ring
     2116
     2117        Three rows, zero columns, over an integral domain.
     2118        If modules over integral domains ever allow creation of
     2119        zero submodules, this test will fail to raise an error.
     2120        This is a response to Trac #8071. ::
     2121
     2122            sage: m = matrix(ZZ['x'], [[],[],[]])
     2123            sage: m._right_kernel_trivial()
     2124            Traceback (most recent call last):
     2125            ...
     2126            NotImplementedError: Cannot create kernel over Univariate Polynomial Ring in x over Integer Ring
     2127
     2128        Zero rows, three columns, over an integral domain.
     2129        Creating a full free module as a return value is
     2130        not problematic. ::
     2131
     2132            sage: m = matrix(ZZ['x'], [[],[],[]]).transpose()
     2133            sage: m._right_kernel_trivial()
     2134            Ambient free module of rank 3 over the integral domain Univariate Polynomial Ring in x over Integer Ring
     2135
     2136        Three rows, zero columns, over a generic ring.
     2137        If modules over generic rings ever allow creation of
     2138        zero submodules, this test will fail to raise an error.
     2139        This is a response to Trac #8071. ::
     2140
     2141            sage: m = matrix(Integers(6), [[],[],[]])
     2142            sage: m._right_kernel_trivial()
     2143            Traceback (most recent call last):
     2144            ...
     2145            NotImplementedError: Cannot create kernel over Ring of integers modulo 6
     2146
     2147        Zero rows, three columns, over a generic ring.
     2148        Creating a full free module as a return value is
     2149        not problematic. ::
     2150
     2151            sage: m = matrix(Integers(6), [[],[],[]]).transpose()
     2152            sage: m._right_kernel_trivial()
     2153            Ambient free module of rank 3 over Ring of integers modulo 6
     2154        """
     2155        if self._ncols != 0 and self._nrows != 0:
     2156            raise ValueError('The right kernel is not automatically trivial for %s' % self )
     2157        R = self._base_ring
     2158        if self._ncols == 0:    # from a degree-0 space
     2159            V = sage.modules.free_module.FreeModule(R, self._ncols)
     2160            try:
     2161                Z = V.zero_submodule()
     2162            except AttributeError:
     2163                raise NotImplementedError('Cannot create kernel over %s' % R)
     2164            self.cache('right_kernel', Z)
     2165            return Z
     2166        elif self._nrows == 0:  # to a degree-0 space
     2167            Z = sage.modules.free_module.FreeModule(R, self._ncols)
     2168            self.cache('right_kernel', Z)
     2169            return Z
     2170
    20682171    def kernel(self, *args, **kwds):
    20692172        r"""
    20702173        Return the (left) kernel of this matrix, as a vector space. This is
     
    21902293        Return the right kernel of this matrix, as a vector space. This is
    21912294        the space of vectors x such that self\*x=0.  A left kernel can be found
    21922295        with self.left_kernel() or just self.kernel().
    2193            
     2296
    21942297        INPUT: all additional arguments to the kernel function are passed
    21952298        directly onto the echelon call.
    2196        
     2299
    21972300        By convention if self has 0 columns, the kernel is of dimension 0,
    21982301        whereas the kernel is whole domain if self has 0 rows.
    2199        
     2302
    22002303        ALGORITHM:
    2201        
     2304
    22022305        Elementary row operations do not change the right kernel, since they
    22032306        are left multiplication by an invertible matrix, so we
    22042307        instead compute the kernel of the row echelon form. When the base ring
     
    22662369            Basis matrix:
    22672370            [      1  4/13*zeta12^2 - 1/13      0 -2/13*zeta12^2 + 7/13]
    22682371            [      0                     0      1                     0]
    2269        
    2270         A nontrivial right kernel over a complicated base field.
    2271        
    2272         ::
    2273        
     2372
     2373        A nontrivial right kernel over a complicated base field. ::
     2374
    22742375            sage: K = FractionField(PolynomialRing(QQ, 2, 'x'))
    22752376            sage: M = MatrixSpace(K, 2)([[K.1, K.0], [K.1, K.0]])
    22762377            sage: M
     
    22852386        in matrix_integer_dense class.  Timing on a 64-bit 3 GHz dual-core machine is about
    22862387        3 seconds to setup and about 1 second for the kernel() call.  Timings that are one
    22872388        or two orders of magnitude larger indicate problems with reaching specialized
    2288         derived classes.
    2289 
    2290         ::
     2389        derived classes. ::
    22912390
    22922391            sage: entries = [[1/(i+j+1) for i in srange(500)] for j in srange(500)]
    22932392            sage: a = matrix(QQ, entries)
     
    22982397
    22992398        Right kernel of a matrix defined over a principal ideal domain which is
    23002399        not ZZ or a field. This invokes the general Smith normal form routine,
    2301         rather than echelon form which is less suitable in this case.
    2302 
    2303         ::
     2400        rather than echelon form which is less suitable in this case. ::
    23042401
    23052402            sage: L.<w> = NumberField(x^2 - x + 2)
    23062403            sage: OL = L.ring_of_integers()
     
    23102407            Echelon basis matrix:
    23112408            [    -1 -w + 1]
    23122409
     2410        With zero columns the right kernel has dimension 0. ::
     2411
     2412            sage: M = matrix(QQ, [[],[],[]])
     2413            sage: M.right_kernel()
     2414            Vector space of degree 0 and dimension 0 over Rational Field
     2415            Basis matrix:
     2416            []
     2417
     2418        With zero rows, the whole domain is the kernel, so the
     2419        dimension is the number of columns. ::
     2420
     2421            sage: M = matrix(QQ, [[],[],[]]).transpose()
     2422            sage: M.right_kernel()
     2423            Vector space of dimension 3 over Rational Field
    23132424        """
    23142425        K = self.fetch('right_kernel')
    23152426        if not K is None:
    23162427            return K
    23172428
     2429        # First: obvious and easy kernels, for matrices over any ring
     2430        if self._ncols == 0 or self._nrows == 0:
     2431            return self._right_kernel_trivial()
     2432
    23182433        R = self._base_ring
    23192434
    2320         if self._ncols == 0:    # from a degree-0 space
    2321             V = sage.modules.free_module.VectorSpace(R, self._ncols)
    2322             Z = V.zero_subspace()
    2323             self.cache('right_kernel', Z)
    2324             return Z
    2325         elif self._nrows == 0:  # to a degree-0 space
    2326             Z = sage.modules.free_module.VectorSpace(R, self._ncols)
    2327             self.cache('right_kernel', Z)
    2328             return Z
    2329 
    23302435        if is_IntegerRing(R):
    23312436            Z = self.right_kernel(*args, **kwds)
    23322437            self.cache('right_kernel', Z)
  • sage/matrix/matrix_integer_dense.pyx

    diff -r 4498ef979fc4 -r 9d78f89061fc sage/matrix/matrix_integer_dense.pyx
    a b  
    23612361                return A
    23622362        else:
    23632363            raise ValueError, "unknown algorithm '%s'"%algorithm
    2364            
     2364
    23652365    def right_kernel(self, algorithm='default', LLL=False, proof=None, echelonize=True):
    23662366        r"""
    2367         Return the right kernel of this matrix, as a module over the
    2368         integers. This is the saturated ZZ-module spanned by all the column
    2369         vectors v such that self\*v = 0.
    2370        
    2371         INPUT:
    2372        
    2373        
     2367        Return the right kernel of a matrix over the integers.
     2368
     2369        INPUT:
     2370
    23742371        -  ``algorithm`` - see the docs for ``self.kernel_matrix``
    2375        
     2372
    23762373        -  ``LLL`` - bool (default: False); if True the basis
    23772374           is an LLL reduced basis; otherwise, it is an echelon basis.
    2378        
     2375
    23792376        -  ``proof`` - None (default: proof.linear_algebra());
    23802377           if False, impacts how determinants are computed.
    2381        
    2382        
    2383         By convention if self has 0 columns, the right kernel is of dimension 0,
    2384         whereas the right kernel is the whole domain if self has 0 rows.
    2385        
    2386         EXAMPLES::
    2387        
     2378
     2379        OUTPUT:
     2380        A module over the integers is returned. This is the
     2381        saturated ZZ-module spanned by all the column
     2382        vectors ``v`` such that ``self*v = 0``.
     2383
     2384        EXAMPLES::
     2385
    23882386            sage: M = MatrixSpace(ZZ,2,4)(range(8))
    23892387            sage: M.right_kernel()
    23902388            Free module of degree 4 and rank 2 over Integer Ring
    23912389            Echelon basis matrix:
    23922390            [ 1  0 -3  2]
    23932391            [ 0  1 -2  1]
    2394         """
    2395         if self._ncols == 0:    # from a 0 space
    2396             M = sage.modules.free_module.FreeModule(ZZ, self._ncols)
    2397             return M.zero_submodule()
    2398         elif self._nrows == 0:  # to a 0 space
    2399             return sage.modules.free_module.FreeModule(ZZ, self._ncols)
     2392
     2393        With zero columns the right kernel has dimension 0. ::
     2394
     2395            sage: M = matrix(ZZ, [[],[],[]])
     2396            sage: M.right_kernel()
     2397            Free module of degree 0 and rank 0 over Integer Ring
     2398            Echelon basis matrix:
     2399            []
     2400
     2401        With zero rows, the whole domain is the kernel, so the
     2402        dimension is the number of columns. ::
     2403
     2404            sage: M = matrix(ZZ, [[],[],[]]).transpose()
     2405            sage: M.right_kernel()
     2406            Ambient free module of rank 3 over the principal ideal domain Integer Ring
     2407        """
     2408        if self._ncols == 0 or self._nrows == 0:
     2409            return self._right_kernel_trivial()
    24002410
    24012411        X = self._right_kernel_matrix(algorithm=algorithm, LLL=LLL, proof=proof)
    24022412        if not LLL and echelonize:
  • sage/matrix/matrix_integer_sparse.pyx

    diff -r 4498ef979fc4 -r 9d78f89061fc sage/matrix/matrix_integer_sparse.pyx
    a b  
    374374            proof -- None (default: proof.linear_algebra()); if False,
    375375                   impacts how determinants are computed.
    376376
    377         By convention if self has 0 rows, the kernel is of dimension
    378         0, whereas the kernel is the whole domain if self has 0 columns.
     377        EXAMPLES::
    379378
    380         EXAMPLES:
    381379            sage: M = MatrixSpace(ZZ,2,4,sparse=True)(range(8))
    382380            sage: M.right_kernel()
    383381            Free module of degree 4 and rank 2 over Integer Ring
    384382            Echelon basis matrix:
    385383            [ 1  0 -3  2]
    386384            [ 0  1 -2  1]
     385
     386        With zero columns the right kernel has dimension 0. ::
     387
     388            sage: M = matrix(ZZ, [[],[],[]],sparse=True)
     389            sage: M.right_kernel()
     390            Free module of degree 0 and rank 0 over Integer Ring
     391            Echelon basis matrix:
     392            []
     393
     394        With zero rows, the whole domain is the kernel, so the
     395        dimension is the number of columns. ::
     396
     397            sage: M = matrix(ZZ, [[],[],[]],sparse=True).transpose()
     398            sage: M.right_kernel()
     399            Ambient free module of rank 3 over the principal ideal domain Integer Ring
    387400        """
    388401        return self.dense_matrix().right_kernel(algorithm, LLL, proof, echelonize)
    389402
  • sage/matrix/matrix_mod2_dense.pyx

    diff -r 4498ef979fc4 -r 9d78f89061fc sage/matrix/matrix_mod2_dense.pyx
    a b  
    17041704        return r
    17051705
    17061706    def right_kernel(self, algorithm='pluq'):
    1707         """
     1707        r"""
    17081708        Return the right kernel of this matrix, as a vector
    17091709        space. This is the space of vectors x such that ``self*x=0``.
    17101710        A left kernel can be found with :meth:`left_kernel()` or just
    17111711        :meth:`kernel`.
    1712            
    1713         INPUT: 
    1714        
     1712
     1713        INPUT:
     1714
    17151715        - ``algorithm`` - either "pluq" or "generic"
    1716        
    1717         By convention if self has 0 columns, the kernel is of dimension 0,
    1718         whereas the kernel is whole domain if self has 0 rows.
    1719        
     1716
    17201717        .. note::
    17211718
    17221719           Preference is given to left kernels in that the generic method
    17231720           name :meth:`kernel` returns a left kernel.  However most computations
    17241721           of kernels are implemented as right kernels.
    1725        
     1722
    17261723        EXAMPLES:
    1727        
     1724
    17281725        A trivial right kernel::
    1729        
     1726
    17301727            sage: A = MatrixSpace(GF(2), 2)([1,0,0,1])
    17311728            sage: A.right_kernel()
    17321729            Vector space of degree 2 and dimension 0 over Finite Field of size 2
    17331730            Basis matrix:
    17341731            []
    1735        
     1732
    17361733        Right kernel of a zero matrix::
    1737        
     1734
    17381735            sage: A = MatrixSpace(GF(2), 2)(0)
    17391736            sage: A.right_kernel()
    17401737            Vector space of degree 2 and dimension 2 over Finite Field of size 2
    17411738            Basis matrix:
    17421739            [1 0]
    17431740            [0 1]
    1744        
     1741
    17451742        Right kernel of a non-square matrix::
    1746        
     1743
    17471744            sage: A = MatrixSpace(GF(2),2,3)(range(6))
    17481745            sage: A.right_kernel()
    17491746            Vector space of degree 3 and dimension 1 over Finite Field of size 2
    17501747            Basis matrix:
    17511748            [1 0 1]
    1752        
     1749
    17531750        A non-trivial kernel computation::
    17541751
    17551752            sage: A = random_matrix(GF(2),1000,1010)
     
    17571754            Vector space of degree 1010 and dimension 10 over Finite Field of size 2
    17581755            Basis matrix:
    17591756            10 x 1010 dense matrix over Finite Field of size 2
     1757
     1758        With zero columns the right kernel has dimension 0. ::
     1759
     1760            sage: M = matrix(GF(2), [[],[],[]],sparse=True)
     1761            sage: M.right_kernel()
     1762            Vector space of degree 0 and dimension 0 over Finite Field of size 2
     1763            Basis matrix:
     1764            []
     1765
     1766        With zero rows, the whole domain is the kernel, so the
     1767        dimension is the number of columns. ::
     1768
     1769            sage: M = matrix(GF(2), [[],[],[]],sparse=True).transpose()
     1770            sage: M.right_kernel()
     1771            Vector space of dimension 3 over Finite Field of size 2
    17601772        """
    17611773        if algorithm == 'generic':
    17621774            return matrix_dense.Matrix_dense.right_kernel(self)
    17631775        if algorithm != 'pluq':
    17641776            raise ValueError("Algorithm '%s' is unknown."%algorithm)
    17651777
    1766         cdef Matrix_mod2_dense M
    17671778        K = self.fetch('right_kernel')
    17681779        if not K is None:
    17691780            return K
    17701781
    1771         R = self._base_ring
    1772         if self._ncols == 0:    # from a degree-0 space
    1773             V = VectorSpace(R, self._ncols)
    1774             Z = V.zero_subspace()
    1775             self.cache('right_kernel', Z)
    1776             return Z
    1777         elif self._nrows == 0:  # to a degree-0 space
    1778             Z = VectorSpace(R, self._ncols)
    1779             self.cache('right_kernel', Z)
    1780             return Z
     1782        if self._ncols == 0 or self._nrows == 0:
     1783            return self._right_kernel_trivial()
    17811784
     1785        cdef Matrix_mod2_dense M
    17821786        cdef mzd_t *A = mzd_copy(NULL, self._entries)
    17831787        cdef mzd_t *k = mzd_kernel_left_pluq(A, 0) # well, we don't
    17841788                                                   # agree on the name
     
    17931797        else:
    17941798            basis = []
    17951799
     1800        R = self._base_ring
    17961801        V = R**self._ncols
    17971802        W = V.submodule(basis, check=False, already_echelonized=True)
    17981803        self.cache('right_kernel', W)
  • sage/matrix/matrix_rational_dense.pyx

    diff -r 4498ef979fc4 -r 9d78f89061fc sage/matrix/matrix_rational_dense.pyx
    a b  
    12051205        mpq_clear(s)
    12061206        mpq_clear(pr)
    12071207        return _pr
    1208        
     1208
    12091209    def right_kernel(self, algorithm='padic', **kwds):
    1210         """
     1210        r"""
    12111211        Return the right kernel of this matrix, as a vector space over QQ.
    12121212        For a left kernel use self.left_kernel() or just self.kernel().
    1213        
     1213
    12141214        INPUT:
    1215        
     1215
    12161216        -  ``algorithm`` - 'padic' (or 'default'): use IML's
    12171217           p-adic nullspace algorithm
    1218        
     1218
    12191219        -  ``anything else`` - passed on to the generic
    12201220           echelon-form based algorithm.
    1221        
     1221
    12221222        -  ``**kwds`` - passed onto to echelon form algorithm
    12231223           in the echelon case.
    12241224
     
    12321232                Basis matrix:
    12331233                [   1    0   -2  3/2]
    12341234                [   0    1    1 -1/2]
    1235        
     1235
    12361236            A trivial right kernel, plus left kernel (via superclass)::
    12371237
    12381238                sage: M=Matrix(QQ,[[1/2,3],[0,1],[1,1]])
     
    12441244                Vector space of degree 3 and dimension 1 over Rational Field
    12451245                Basis matrix:
    12461246                [   1 -5/2 -1/2]
    1247 
    1248 
    12491247        """
    12501248        K = self.fetch('right_kernel')
    12511249        if not K is None:
     
    12581256            V = K.column_space()
    12591257            self.cache('right_kernel', V)
    12601258            return V
     1259        elif self._nrows == 0 or self._ncols == 0:
     1260            return self._right_kernel_trivial()
    12611261        else:
    12621262            return matrix_dense.Matrix_dense.right_kernel(self, algorithm, **kwds)
    12631263