Matrix Spaces¶

You can create any space $$\text{Mat}_{n\times m}(R)$$ of either dense or sparse matrices with given number of rows and columns over any commutative or noncommutative ring.

EXAMPLES:

sage: MS = MatrixSpace(QQ,6,6,sparse=True); MS
Full MatrixSpace of 6 by 6 sparse matrices over Rational Field
sage: MS.base_ring()
Rational Field
sage: MS = MatrixSpace(ZZ,3,5,sparse=False); MS
Full MatrixSpace of 3 by 5 dense matrices over Integer Ring


TESTS:

sage: matrix(RR,2,2,sparse=True)
[0.000000000000000 0.000000000000000]
[0.000000000000000 0.000000000000000]
sage: matrix(GF(11),2,2,sparse=True)
[0 0]
[0 0]

class sage.matrix.matrix_space.MatrixSpace(base_ring, nrows, ncols=None, sparse=False)

The space of all nrows x ncols matrices over base_ring.

INPUT:

• base_ring - a ring
• nrows - int, the number of rows
• ncols - (default nrows) int, the number of columns
• sparse - (default false) whether or not matrices are given a sparse representation

EXAMPLES:

sage: MatrixSpace(ZZ,10,5)
Full MatrixSpace of 10 by 5 dense matrices over Integer Ring
sage: MatrixSpace(ZZ,10,5).category()
Category of modules over euclidean domains

sage: MatrixSpace(ZZ,10,2^31)
...                                                                  # 32-bit
ValueError: number of rows and columns must be less than 2^31 (on a 32-bit computer -- use a 64-bit computer for matrices with up to 2^63-1 rows and columns)           # 32-bit
Full MatrixSpace of 10 by 2147483648 dense matrices over Integer Ring   # 64-bit
sage: MatrixSpace(ZZ,2^31,10)
...                                                                  # 32-bit
ValueError: number of rows and columns must be less than 2^31 (on a 32-bit computer -- use a 64-bit computer for matrices with up to 2^63-1 rows and columns)           # 32-bit
Full MatrixSpace of 2147483648 by 10 dense matrices over Integer Ring   # 64-bit
sage: MatrixSpace(ZZ,10,10).category()
Category of algebras over euclidean domains
sage: MatrixSpace(QQ,10).category()
Category of algebras over quotient fields

base_extend(R)

Return base extension of this matrix space to R.

INPUT:

• R - ring

OUTPUT: a matrix space

EXAMPLES:

sage: Mat(ZZ,3,5).base_extend(QQ)
Full MatrixSpace of 3 by 5 dense matrices over Rational Field
sage: Mat(QQ,3,5).base_extend(GF(7))
Traceback (most recent call last):
...
TypeError: no base extension defined

basis()

Returns a basis for this matrix space.

Warning

This will of course compute every generator of this matrix space. So for large matrices, this could take a long time, waste a massive amount of memory (for dense matrices), and is likely not very useful. Don’t use this on large matrix spaces.

EXAMPLES:

sage: Mat(ZZ,2,2).basis()
[
[1 0]  [0 1]  [0 0]  [0 0]
[0 0], [0 0], [1 0], [0 1]
]

cached_method(f, name=None, key=None)

A decorator for cached methods.

EXAMPLES:

In the following examples, one can see how a cached method works in application. Below, we demonstrate what is done behind the scenes:

sage: class C:
....:     @cached_method
....:     def __hash__(self):
....:         print "compute hash"
....:         return int(5)
....:     @cached_method
....:     def f(self, x):
....:         print "computing cached method"
....:         return x*2
sage: c = C()
sage: type(C.__hash__)
<type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'>
sage: hash(c)
compute hash
5


When calling a cached method for the second time with the same arguments, the value is gotten from the cache, so that a new computation is not needed:

sage: hash(c)
5
sage: c.f(4)
computing cached method
8
sage: c.f(4) is c.f(4)
True


Different instances have distinct caches:

sage: d = C()
sage: d.f(4) is c.f(4)
computing cached method
False
sage: d.f.clear_cache()
sage: c.f(4)
8
sage: d.f(4)
computing cached method
8


Using cached methods for the hash and other special methods was implemented in trac ticket #12601, by means of CachedSpecialMethod. We show that it is used behind the scenes:

sage: cached_method(c.__hash__)
<sage.misc.cachefunc.CachedSpecialMethod object at ...>
sage: cached_method(c.f)
<sage.misc.cachefunc.CachedMethod object at ...>

change_ring(R)

Return matrix space over R with otherwise same parameters as self.

INPUT:

• R - ring

OUTPUT: a matrix space

EXAMPLES:

sage: Mat(QQ,3,5).change_ring(GF(7))
Full MatrixSpace of 3 by 5 dense matrices over Finite Field of size 7

column_space()

Return the module spanned by all columns of matrices in this matrix space. This is a free module of rank the number of columns. It will be sparse or dense as this matrix space is sparse or dense.

EXAMPLES:

sage: M = Mat(GF(9,'a'),20,5,sparse=True); M.column_space()
Sparse vector space of dimension 20 over Finite Field in a of size 3^2

construction()

EXAMPLES:

sage: A = matrix(ZZ, 2, [1..4], sparse=True)
sage: A.parent().construction()
(MatrixFunctor, Integer Ring)
sage: A.parent().construction()[0](QQ['x'])
Full MatrixSpace of 2 by 2 sparse matrices over Univariate Polynomial Ring in x over Rational Field
sage: parent(A/2)
Full MatrixSpace of 2 by 2 sparse matrices over Rational Field

dimension()

Returns (m rows) * (n cols) of self as Integer

EXAMPLES:

sage: MS = MatrixSpace(ZZ,4,6)
sage: u = MS.dimension()
sage: u - 24 == 0
True

dims()

Returns (m row, n col) representation of self dimension

EXAMPLES:

sage: MS = MatrixSpace(ZZ,4,6)
sage: MS.dims()
(4, 6)

full_category_initialisation()

Make full use of the category framework.

Note

It turns out that it causes a massive speed regression in computations with elliptic curves, if a full initialisation of the category framework of matrix spaces happens at initialisation: The elliptic curves code treats matrix spaces as containers, not as objects of a category. Therefore, making full use of the category framework is now provided by a separate method (see trac ticket #11900).

EXAMPLES:

sage: MS = MatrixSpace(QQ,8)
sage: TestSuite(MS).run()
sage: type(MS)
<class 'sage.matrix.matrix_space.MatrixSpace_with_category'>
sage: MS.full_category_initialisation()
doctest:...: DeprecationWarning: the full_category_initialization
method does nothing, as a matrix space now has its category
systematically fully initialized
See http://trac.sagemath.org/15801 for details.

gen(n)

Return the n-th generator of this matrix space.

This doesn’t compute all basis matrices, so it is reasonably intelligent.

EXAMPLES:

sage: M = Mat(GF(7),10000,5); M.ngens()
50000
sage: a = M.10
sage: a[:4]
[0 0 0 0 0]
[0 0 0 0 0]
[1 0 0 0 0]
[0 0 0 0 0]

get_action_impl(S, op, self_on_left)

x.__init__(...) initializes x; see help(type(x)) for signature

identity_matrix()

Returns the identity matrix in self.

self must be a space of square matrices. The returned matrix is immutable. Please use copy if you want a modified copy.

EXAMPLES:

sage: MS1 = MatrixSpace(ZZ,4)
sage: MS2 = MatrixSpace(QQ,3,4)
sage: I = MS1.identity_matrix()
sage: I
[1 0 0 0]
[0 1 0 0]
[0 0 1 0]
[0 0 0 1]
sage: Er = MS2.identity_matrix()
Traceback (most recent call last):
...
TypeError: self must be a space of square matrices


TESTS:

sage: MS1.one()[1,2] = 3
Traceback (most recent call last):
...
ValueError: matrix is immutable; please change a copy instead (i.e., use copy(M) to change a copy of M).

is_dense()

Returns True if matrices in self are dense and False otherwise.

EXAMPLES:

sage: Mat(RDF,2,3).is_sparse()
False
sage: Mat(RR,123456,22,sparse=True).is_sparse()
True

is_finite()

EXAMPLES:

sage: MatrixSpace(GF(101), 10000).is_finite()
True
sage: MatrixSpace(QQ, 2).is_finite()
False

is_sparse()

Returns True if matrices in self are sparse and False otherwise.

EXAMPLES:

sage: Mat(GF(2011),10000).is_sparse()
False
sage: Mat(GF(2011),10000,sparse=True).is_sparse()
True

matrix(x=0, coerce=True, copy=True)

Create a matrix in self.

INPUT:

• x – (default: 0) data to construct a new matrix from. Can be one of the following:
• 0, corresponding to the zero matrix;
• 1, corresponding to the identity_matrix;
• a matrix, whose dimensions must match self and whose base ring must be convertible to the base ring of self;
• a list of entries corresponding to all elements of the new matrix;
• a list of rows with each row given as an iterable;
• coerce – (default: True) whether to coerce x into self;
• copy – (default: True) whether to copy x during construction (makes a difference only if x is a matrix in self).

OUTPUT:

• a matrix in self.

EXAMPLES:

sage: M = MatrixSpace(ZZ, 2)
sage: M.matrix([[1,0],[0,-1]])
[ 1  0]
[ 0 -1]
sage: M.matrix([1,0,0,-1])
[ 1  0]
[ 0 -1]
sage: M.matrix([1,2,3,4])
[1 2]
[3 4]


Note that the last “flip” cannot be performed if x is a matrix, no matter what is rows (it used to be possible but was fixed by Trac 10793):

sage: projection = matrix(ZZ,[[1,0,0],[0,1,0]])
sage: projection
[1 0 0]
[0 1 0]
sage: projection.parent()
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring
sage: M = MatrixSpace(ZZ, 3 , 2)
sage: M
Full MatrixSpace of 3 by 2 dense matrices over Integer Ring
sage: M(projection)
Traceback (most recent call last):
...
ValueError: a matrix from
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring
cannot be converted to a matrix in
Full MatrixSpace of 3 by 2 dense matrices over Integer Ring!


If you really want to make from a matrix another matrix of different dimensions, use either transpose method or explicit conversion to a list:

sage: M(projection.list())
[1 0]
[0 0]
[1 0]


TESTS:

The following corner cases were problematic while working on #10628:

sage: MS = MatrixSpace(ZZ,2,1)
sage: MS([[1],[2]])
[1]
[2]
sage: MS = MatrixSpace(CC,2,1)
sage: F = NumberField(x^2+1, name='x')
sage: MS([F(1),F(0)])
[ 1.00000000000000]
[0.000000000000000]


Trac ticket #10628 allowed to provide the data be lists of matrices, but trac ticket #13012 prohibited it:

sage: MS = MatrixSpace(ZZ,4,2)
sage: MS0 = MatrixSpace(ZZ,2)
sage: MS.matrix([MS0([1,2,3,4]), MS0([5,6,7,8])])
Traceback (most recent call last):
...
TypeError: cannot construct an element of
Full MatrixSpace of 4 by 2 dense matrices over Integer Ring
from [[1 2]
[3 4], [5 6]
[7 8]]!


A mixed list of matrices and vectors is prohibited as well:

sage: MS.matrix( [MS0([1,2,3,4])] + list(MS0([5,6,7,8])) )
Traceback (most recent call last):
...
TypeError: cannot construct an element of
Full MatrixSpace of 4 by 2 dense matrices over Integer Ring
from [[1 2]
[3 4], (5, 6), (7, 8)]!


Check that trac ticket #13302 is fixed:

sage: MatrixSpace(Qp(3),1,1)([Qp(3).zero()])
[0]
sage: MatrixSpace(Qp(3),1,1)([Qp(3)(4/3)])
[3^-1 + 1 + O(3^19)]

matrix_space(nrows=None, ncols=None, sparse=False)

Return the matrix space with given number of rows, columns and sparcity over the same base ring as self, and defaults the same as self.

EXAMPLES:

sage: M = Mat(GF(7),100,200)
sage: M.matrix_space(5000)
Full MatrixSpace of 5000 by 200 dense matrices over Finite Field of size 7
sage: M.matrix_space(ncols=5000)
Full MatrixSpace of 100 by 5000 dense matrices over Finite Field of size 7
sage: M.matrix_space(sparse=True)
Full MatrixSpace of 100 by 200 sparse matrices over Finite Field of size 7

ncols()

Return the number of columns of matrices in this space.

EXAMPLES:

sage: M = Mat(ZZ['x'],200000,500000,sparse=True)
sage: M.ncols()
500000

ngens()

Return the number of generators of this matrix space, which is the number of entries in the matrices in this space.

EXAMPLES:

sage: M = Mat(GF(7),100,200); M.ngens()
20000

nrows()

Return the number of rows of matrices in this space.

EXAMPLES:

sage: M = Mat(ZZ,200000,500000)
sage: M.nrows()
200000

one()

Returns the identity matrix in self.

self must be a space of square matrices. The returned matrix is immutable. Please use copy if you want a modified copy.

EXAMPLES:

sage: MS1 = MatrixSpace(ZZ,4)
sage: MS2 = MatrixSpace(QQ,3,4)
sage: I = MS1.identity_matrix()
sage: I
[1 0 0 0]
[0 1 0 0]
[0 0 1 0]
[0 0 0 1]
sage: Er = MS2.identity_matrix()
Traceback (most recent call last):
...
TypeError: self must be a space of square matrices


TESTS:

sage: MS1.one()[1,2] = 3
Traceback (most recent call last):
...
ValueError: matrix is immutable; please change a copy instead (i.e., use copy(M) to change a copy of M).

random_element(density=None, *args, **kwds)

Returns a random element from this matrix space.

INPUT:

• density - float or None (default: None); rough measure of the proportion of nonzero entries in the random matrix; if set to None, all entries of the matrix are randomized, allowing for any element of the underlying ring, but if set to a float, a proportion of entries is selected and randomized to non-zero elements of the ring
• *args, **kwds - remaining parameters, which may be passed to the random_element function of the base ring. (“may be”, since this function calls the randomize function on the zero matrix, which need not call the random_element function of the base ring at all in general.)

OUTPUT:

• Matrix

Note

This method will randomize a proportion of roughly density entries in a newly allocated zero matrix.

By default, if the user sets the value of density explicitly, this method will enforce that these entries are set to non-zero values. However, if the test for equality with zero in the base ring is too expensive, the user can override this behaviour by passing the argument nonzero=False to this method.

Otherwise, if the user does not set the value of density, the default value is taken to be 1, and the option nonzero=False is passed to the randomize method.

EXAMPLES:

sage: Mat(ZZ,2,5).random_element()
[ -8   2   0   0   1]
[ -1   2   1 -95  -1]
sage: Mat(QQ,2,5).random_element(density=0.5)
[ 2  0  0  0  1]
[ 0  0  0 -1  0]
sage: Mat(QQ,3,sparse=True).random_element()
[  -1   -1   -1]
[  -3 -1/3   -1]
[   0   -1    1]
sage: Mat(GF(9,'a'),3,sparse=True).random_element()
[    a   2*a     1]
[    2     1 a + 2]
[  2*a     2     2]

row_space()

Return the module spanned by all rows of matrices in this matrix space. This is a free module of rank the number of rows. It will be sparse or dense as this matrix space is sparse or dense.

EXAMPLES:

sage: M = Mat(ZZ,20,5,sparse=False); M.row_space()
Ambient free module of rank 5 over the principal ideal domain Integer Ring

zero()

Returns the zero matrix in self.

self must be a space of square matrices. The returned matrix is immutable. Please use copy if you want a modified copy.

EXAMPLES:

sage: z = MatrixSpace(GF(7),2,4).zero_matrix(); z
[0 0 0 0]
[0 0 0 0]
sage: z.is_mutable()
False


TESTS:

sage: MM = MatrixSpace(RDF,1,1,sparse=False); mat = MM.zero_matrix()
sage: copy(mat)
[0.0]
sage: MM = MatrixSpace(RDF,0,0,sparse=False); mat = MM.zero_matrix()
sage: copy(mat)
[]
sage: mat.is_mutable()
False
sage: MM.zero().is_mutable()
False

zero_matrix()

Returns the zero matrix in self.

self must be a space of square matrices. The returned matrix is immutable. Please use copy if you want a modified copy.

EXAMPLES:

sage: z = MatrixSpace(GF(7),2,4).zero_matrix(); z
[0 0 0 0]
[0 0 0 0]
sage: z.is_mutable()
False


TESTS:

sage: MM = MatrixSpace(RDF,1,1,sparse=False); mat = MM.zero_matrix()
sage: copy(mat)
[0.0]
sage: MM = MatrixSpace(RDF,0,0,sparse=False); mat = MM.zero_matrix()
sage: copy(mat)
[]
sage: mat.is_mutable()
False
sage: MM.zero().is_mutable()
False

sage.matrix.matrix_space.dict_to_list(entries, nrows, ncols)

Given a dictionary of coordinate tuples, return the list given by reading off the nrows*ncols matrix in row order.

EXAMPLES:

sage: from sage.matrix.matrix_space import dict_to_list
sage: d = {}
sage: d[(0,0)] = 1
sage: d[(1,1)] = 2
sage: dict_to_list(d, 2, 2)
[1, 0, 0, 2]
sage: dict_to_list(d, 2, 3)
[1, 0, 0, 0, 2, 0]

sage.matrix.matrix_space.is_MatrixSpace(x)

Returns True if self is an instance of MatrixSpace returns false if self is not an instance of MatrixSpace

EXAMPLES:

sage: from sage.matrix.matrix_space import is_MatrixSpace
sage: MS = MatrixSpace(QQ,2)
sage: A = MS.random_element()
sage: is_MatrixSpace(MS)
True
sage: is_MatrixSpace(A)
False
sage: is_MatrixSpace(5)
False

sage.matrix.matrix_space.list_to_dict(entries, nrows, ncols, rows=True)

Given a list of entries, create a dictionary whose keys are coordinate tuples and values are the entries.

EXAMPLES:

sage: from sage.matrix.matrix_space import list_to_dict
sage: d = list_to_dict([1,2,3,4],2,2)
sage: d[(0,1)]
2
sage: d = list_to_dict([1,2,3,4],2,2,rows=False)
sage: d[(0,1)]
3

sage.matrix.matrix_space.test_trivial_matrices_inverse(ring, sparse=True, checkrank=True)

Tests inversion, determinant and is_invertible for trivial matrices.

This function is a helper to check that the inversion of trivial matrices (of size 0x0, nx0, 0xn or 1x1) is handled consistently by the various implementation of matrices. The coherency is checked through a bunch of assertions. If an inconsistency is found, an AssertionError is raised which should make clear what is the problem.

INPUT:

• ring - a ring
• sparse - a boolean
• checkrank - a boolean

OUTPUT:

• nothing if everything is correct, otherwise raise an AssertionError
The methods determinant, is_invertible, rank and inverse are checked for
• the 0x0 empty identity matrix
• the 0x3 and 3x0 matrices
• the 1x1 null matrix [0]
• the 1x1 identity matrix [1]

If checkrank is False then the rank is not checked. This is used the check matrix over ring where echelon form is not implemented.

TODO: must be adapted to category check framework when ready (see trac #5274).

TESTS:

sage: from sage.matrix.matrix_space import test_trivial_matrices_inverse as tinv
sage: tinv(ZZ, sparse=True)
sage: tinv(ZZ, sparse=False)
sage: tinv(QQ, sparse=True)
sage: tinv(QQ, sparse=False)
sage: tinv(GF(11), sparse=True)
sage: tinv(GF(11), sparse=False)
sage: tinv(GF(2), sparse=True)
sage: tinv(GF(2), sparse=False)
sage: tinv(SR, sparse=True)
sage: tinv(SR, sparse=False)
sage: tinv(RDF, sparse=True)
sage: tinv(RDF, sparse=False)
sage: tinv(CDF, sparse=True)
sage: tinv(CDF, sparse=False)
sage: tinv(CyclotomicField(7), sparse=True)
sage: tinv(CyclotomicField(7), sparse=False)
sage: tinv(QQ['x,y'], sparse=True)
sage: tinv(QQ['x,y'], sparse=False)


Previous topic

Matrices and Spaces of Matrices

Next topic

Matrix Constructor