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
- class sage.matrix.matrix_space.MatrixSpace(base_ring, nrows, ncols, sparse, implementation)#
Bases:
UniqueRepresentation
,Parent
The space of matrices of given size and base ring
EXAMPLES:
Some examples of square 2 by 2 rational matrices:
sage: MS = MatrixSpace(QQ, 2) sage: MS.dimension() 4 sage: MS.dims() (2, 2) sage: B = MS.basis() sage: list(B) [ [1 0] [0 1] [0 0] [0 0] [0 0], [0 0], [1 0], [0 1] ] sage: B[0,0] [1 0] [0 0] sage: B[0,1] [0 1] [0 0] sage: B[1,0] [0 0] [1 0] sage: B[1,1] [0 0] [0 1] sage: A = MS.matrix([1,2,3,4]) sage: A [1 2] [3 4]
The above matrix
A
can be multiplied by a 2 by 3 integer matrix:sage: MS2 = MatrixSpace(ZZ, 2, 3) sage: B = MS2.matrix([1,2,3,4,5,6]) sage: A * B [ 9 12 15] [19 26 33]
Check categories:
sage: MatrixSpace(ZZ,10,5) Full MatrixSpace of 10 by 5 dense matrices over Integer Ring sage: MatrixSpace(ZZ,10,5).category() Category of infinite enumerated finite dimensional modules with basis over (euclidean domains and infinite enumerated sets and metric spaces) sage: MatrixSpace(ZZ,10,10).category() Category of infinite enumerated finite dimensional algebras with basis over (euclidean domains and infinite enumerated sets and metric spaces) sage: MatrixSpace(QQ,10).category() Category of infinite finite dimensional algebras with basis over (number fields and quotient fields and metric spaces)
- 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()#
Return a basis for this matrix space.
Warning
This will of course compute every generator of this matrix space. So for large dimensions, 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: list(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, do_pickle=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__) <class '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 ...>
The parameter
do_pickle
can be used if the contents of the cache should be stored in a pickle of the cached method. This can be dangerous with special methods such as__hash__
:sage: class C: ....: @cached_method(do_pickle=True) ....: def __hash__(self): ....: return id(self) sage: import __main__ sage: __main__.C = C sage: c = C() sage: hash(c) # random output sage: d = loads(dumps(c)) sage: hash(d) == hash(c) True
However, the contents of a method’s cache are not pickled unless
do_pickle
is set:sage: class C: ....: @cached_method ....: def __hash__(self): ....: return id(self) sage: __main__.C = C sage: c = C() sage: hash(c) # random output sage: d = loads(dumps(c)) sage: hash(d) == hash(c) False
- cardinality()#
Return the number of elements in
self
.EXAMPLES:
sage: MatrixSpace(GF(3), 2, 3).cardinality() 729 sage: MatrixSpace(ZZ, 2).cardinality() +Infinity sage: MatrixSpace(ZZ, 0, 3).cardinality() 1
- 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
- characteristic()#
Return the characteristic.
EXAMPLES:
sage: MatrixSpace(ZZ, 2).characteristic() 0 sage: MatrixSpace(GF(9), 0).characteristic() 3
- 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
- diagonal_matrix(entries)#
Create a diagonal matrix in
self
using the specified elementsINPUT:
entries
– the elements to use as the diagonal entries
self
must be a space of square matrices. The length ofentries
must be less than or equal to the matrix dimensions. If the length ofentries
is less than the matrix dimensions,entries
is padded with zeroes at the end.EXAMPLES:
sage: MS1 = MatrixSpace(ZZ,4) sage: MS2 = MatrixSpace(QQ,3,4) sage: I = MS1.diagonal_matrix([1, 2, 3, 4]) sage: I [1 0 0 0] [0 2 0 0] [0 0 3 0] [0 0 0 4] sage: MS2.diagonal_matrix([1, 2]) Traceback (most recent call last): ... TypeError: diagonal matrix must be square sage: MS1.diagonal_matrix([1, 2, 3, 4, 5]) Traceback (most recent call last): ... ValueError: number of diagonal matrix entries (5) exceeds the matrix size (4) sage: MS1.diagonal_matrix([1/2, 2, 3, 4]) Traceback (most recent call last): ... TypeError: no conversion of this rational to integer
Check different implementations:
sage: M1 = MatrixSpace(ZZ, 2, implementation='flint') sage: M2 = MatrixSpace(ZZ, 2, implementation='generic') sage: type(M1.diagonal_matrix([1, 2])) <class 'sage.matrix.matrix_integer_dense.Matrix_integer_dense'> sage: type(M2.diagonal_matrix([1, 2])) <class 'sage.matrix.matrix_generic_dense.Matrix_generic_dense'>
- dimension()#
Return (m rows) * (n cols) of
self
asInteger
.EXAMPLES:
sage: MS = MatrixSpace(ZZ,4,6) sage: u = MS.dimension() sage: u - 24 == 0 True
- dims()#
Return (m row, n col) representation of
self
dimension.EXAMPLES:
sage: MS = MatrixSpace(ZZ,4,6) sage: MS.dims() (4, 6)
- gen(n)#
Return the n-th generator of this matrix space.
This does not 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]
- identity_matrix()#
Return the identity matrix in
self
.self
must be a space of square matrices. The returned matrix is immutable. Please usecopy
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: identity matrix must be square
- is_dense()#
Return whether matrices in
self
are dense.EXAMPLES:
sage: Mat(RDF,2,3).is_sparse() False sage: Mat(RR,123456,22,sparse=True).is_sparse() True
- is_finite()#
Return whether this matrix space is finite.
EXAMPLES:
sage: MatrixSpace(GF(101), 10000).is_finite() True sage: MatrixSpace(QQ, 2).is_finite() False
- is_sparse()#
Return whether matrices in
self
are sparse.EXAMPLES:
sage: Mat(GF(2011),10000).is_sparse() False sage: Mat(GF(2011),10000,sparse=True).is_sparse() True
- matrix(x=None, **kwds)#
Create a matrix in
self
.INPUT:
x
– data to construct a new matrix from. Seematrix()
coerce
– (default:True
) if False, assume without checking that the values inx
lie in the base ring
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 isrows
(it used to be possible but was fixed by trac ticket #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: inconsistent number of rows: should be 3 but got 2
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]
- matrix_space(nrows=None, ncols=None, sparse=False)#
Return the matrix space with given number of rows, columns and sparsity 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.
This 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()#
Return the identity matrix in
self
.self
must be a space of square matrices. The returned matrix is immutable. Please usecopy
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: identity matrix must be square
- random_element(density=None, *args, **kwds)#
Return a random element from this matrix space.
INPUT:
density
-float
orNone
(default:None
); rough measure of the proportion of nonzero entries in the random matrix; if set toNone
, all entries of the matrix are randomized, allowing for any element of the underlying ring, but if set to afloat
, 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 therandomize
function on the zero matrix, which need not call therandom_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 argumentnonzero=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 optionnonzero=False
is passed to therandomize
method.EXAMPLES:
sage: M = Mat(ZZ, 2, 5).random_element() sage: TestSuite(M).run() sage: M = Mat(QQ, 2, 5).random_element(density=0.5) sage: TestSuite(M).run() sage: M = Mat(QQ, 3, sparse=True).random_element() sage: TestSuite(M).run() sage: M = Mat(GF(9,'a'), 3, sparse=True).random_element() sage: TestSuite(M).run()
- 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
- some_elements()#
Return some elements of this matrix space.
See
TestSuite
for a typical use case.OUTPUT:
An iterator.
EXAMPLES:
sage: M = MatrixSpace(ZZ, 2, 2) sage: tuple(M.some_elements()) ( [ 0 1] [1 0] [0 1] [0 0] [0 0] [-1 2], [0 0], [0 0], [1 0], [0 1] ) sage: M = MatrixSpace(QQ, 2, 3) sage: tuple(M.some_elements()) ( [ 1/2 -1/2 2] [1 0 0] [0 1 0] [0 0 1] [0 0 0] [0 0 0] [0 0 0] [ -2 0 1], [0 0 0], [0 0 0], [0 0 0], [1 0 0], [0 1 0], [0 0 1] ) sage: M = MatrixSpace(SR, 2, 2) sage: tuple(M.some_elements()) ( [some_variable some_variable] [1 0] [0 1] [0 0] [0 0] [some_variable some_variable], [0 0], [0 0], [1 0], [0 1] )
- submodule(gens, check=True, already_echelonized=False, unitriangular=False, support_order=None, category=None, *args, **opts)#
The submodule spanned by a finite set of matrices.
INPUT:
gens
– a list or family of elements ofself
check
– (default:True
) whether to verify that theelements of
gens
are inself
already_echelonized
– (default:False
) whetherthe elements of
gens
are already in (not necessarily reduced) echelon form
unitriangular
– (default:False
) whether the lift morphism is unitriangularsupport_order
– (optional) either something that can be converted into a tuple or a key function
If
already_echelonized
isFalse
, then the generators are put in reduced echelon form usingechelonize()
, and reindexed by \(0, 1, \ldots\).Warning
At this point, this method only works for finite dimensional submodules and if matrices can be echelonized over the base ring.
If in addition
unitriangular
isTrue
, then the generators are made such that the coefficients of the pivots are 1, so that lifting map is unitriangular.The basis of the submodule uses the same index set as the generators, and the lifting map sends \(y_i\) to \(gens[i]\).
EXAMPLES:
sage: M = MatrixSpace(QQ, 2) sage: mat = M.matrix([[1, 2], [3, 4]]) sage: X = M.submodule([mat], already_echelonized=True); X Free module generated by {0} over Rational Field sage: mat2 = M.matrix([[1, 0], [-3, 2]]) sage: X = M.submodule([mat, mat2]) sage: [X.lift(b) for b in X.basis()] [ [ 1 0] [0 1] [-3 2], [3 1] ] sage: A = matrix([[1, 1], [0, -1]]) sage: B = matrix([[0, 1], [0, 2]]) sage: X = M.submodule([A, B]) sage: Xp = M.submodule([A, B], support_order=[(0,1), (1,1), (0,0)]) sage: [X.lift(b) for b in X.basis()] [ [ 1 0] [0 1] [ 0 -3], [0 2] ] sage: [Xp.lift(b) for b in Xp.basis()] [ [2/3 1] [-1/3 0] [ 0 0], [ 0 1] ]
- transposed()#
The transposed matrix space, having the same base ring and sparseness, but number of columns and rows is swapped.
EXAMPLES:
sage: MS = MatrixSpace(GF(3), 7, 10) sage: MS.transposed Full MatrixSpace of 10 by 7 dense matrices over Finite Field of size 3 sage: MS = MatrixSpace(GF(3), 7, 7) sage: MS.transposed is MS True sage: M = MatrixSpace(ZZ, 2, 3) sage: M.transposed Full MatrixSpace of 3 by 2 dense matrices over Integer Ring
- zero()#
Return the zero matrix in
self
.self
must be a space of square matrices. The returned matrix is immutable. Please usecopy
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
- zero_matrix()#
Return the zero matrix in
self
.self
must be a space of square matrices. The returned matrix is immutable. Please usecopy
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
- 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.get_matrix_class(R, nrows, ncols, sparse, implementation)#
Return a matrix class according to the input.
Note
This returns the base class without the category.
INPUT:
R
– a base ringnrows
– number of rowsncols
– number of columnssparse
– (boolean) whether the matrix class should be sparseimplementation
– (None
or string or a matrix class) a possible implementation. See the documentation of the constructor ofMatrixSpace
.
EXAMPLES:
sage: from sage.matrix.matrix_space import get_matrix_class sage: get_matrix_class(ZZ, 4, 5, False, None) <class 'sage.matrix.matrix_integer_dense.Matrix_integer_dense'> sage: get_matrix_class(ZZ, 4, 5, True, None) <class 'sage.matrix.matrix_integer_sparse.Matrix_integer_sparse'> sage: get_matrix_class(ZZ, 3, 3, False, 'flint') <class 'sage.matrix.matrix_integer_dense.Matrix_integer_dense'> sage: get_matrix_class(ZZ, 3, 3, False, 'gap') <class 'sage.matrix.matrix_gap.Matrix_gap'> sage: get_matrix_class(ZZ, 3, 3, False, 'generic') <class 'sage.matrix.matrix_generic_dense.Matrix_generic_dense'> sage: get_matrix_class(GF(2^15), 3, 3, False, None) <class 'sage.matrix.matrix_gf2e_dense.Matrix_gf2e_dense'> sage: get_matrix_class(GF(2^17), 3, 3, False, None) <class 'sage.matrix.matrix_generic_dense.Matrix_generic_dense'> sage: get_matrix_class(GF(2), 2, 2, False, 'm4ri') <class 'sage.matrix.matrix_mod2_dense.Matrix_mod2_dense'> sage: get_matrix_class(GF(4), 2, 2, False, 'm4ri') <class 'sage.matrix.matrix_gf2e_dense.Matrix_gf2e_dense'> sage: get_matrix_class(GF(7), 2, 2, False, 'linbox-float') <class 'sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_float'> sage: get_matrix_class(GF(7), 2, 2, False, 'linbox-double') <class 'sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_double'> sage: get_matrix_class(RDF, 2, 2, False, 'numpy') <class 'sage.matrix.matrix_real_double_dense.Matrix_real_double_dense'> sage: get_matrix_class(CDF, 2, 3, False, 'numpy') <class 'sage.matrix.matrix_complex_double_dense.Matrix_complex_double_dense'> sage: get_matrix_class(GF(25,'x'), 4, 4, False, 'meataxe') # optional - meataxe <class 'sage.matrix.matrix_gfpn_dense.Matrix_gfpn_dense'> sage: get_matrix_class(IntegerModRing(3), 4, 4, False, 'meataxe') # optional - meataxe <class 'sage.matrix.matrix_gfpn_dense.Matrix_gfpn_dense'> sage: get_matrix_class(IntegerModRing(4), 4, 4, False, 'meataxe') Traceback (most recent call last): ... ValueError: 'meataxe' matrix can only deal with finite fields of order < 256 sage: get_matrix_class(GF(next_prime(255)), 4, 4, False, 'meataxe') Traceback (most recent call last): ... ValueError: 'meataxe' matrix can only deal with finite fields of order < 256 sage: get_matrix_class(ZZ, 3, 5, False, 'crazy_matrix') Traceback (most recent call last): ... ValueError: unknown matrix implementation 'crazy_matrix' over Integer Ring sage: get_matrix_class(GF(3), 2, 2, False, 'm4ri') Traceback (most recent call last): ... ValueError: 'm4ri' matrices are only available for fields of characteristic 2 and order <= 65536 sage: get_matrix_class(Zmod(2**30), 2, 2, False, 'linbox-float') Traceback (most recent call last): ... ValueError: 'linbox-float' matrices can only deal with order < 256 sage: get_matrix_class(Zmod(2**30), 2, 2, False, 'linbox-double') Traceback (most recent call last): ... ValueError: 'linbox-double' matrices can only deal with order < 8388608 sage: type(matrix(SR, 2, 2, 0)) <class 'sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense'> sage: type(matrix(GF(7), 2, range(4))) <class 'sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_float'> sage: type(matrix(GF(16007), 2, range(4))) <class 'sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_double'> sage: type(matrix(CBF, 2, range(4))) <class 'sage.matrix.matrix_complex_ball_dense.Matrix_complex_ball_dense'> sage: type(matrix(GF(2), 2, range(4))) <class 'sage.matrix.matrix_mod2_dense.Matrix_mod2_dense'> sage: type(matrix(GF(64,'z'), 2, range(4))) <class 'sage.matrix.matrix_gf2e_dense.Matrix_gf2e_dense'> sage: type(matrix(GF(125,'z'), 2, range(4))) # optional - meataxe <class 'sage.matrix.matrix_gfpn_dense.Matrix_gfpn_dense'>
- sage.matrix.matrix_space.is_MatrixSpace(x)#
Return whether
self
is an instance ofMatrixSpace
.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