Base class for sparse matrices

class sage.matrix.matrix_sparse.Matrix_sparse[source]

Bases: Matrix

antitranspose()[source]

Return the antitranspose of self, without changing self.

This is the mirror image along the other diagonal.

EXAMPLES:

sage: M = MatrixSpace(QQ, 2, sparse=True)
sage: A = M([1,2,3,4]); A
[1 2]
[3 4]
sage: A.antitranspose()
[4 2]
[3 1]
>>> from sage.all import *
>>> M = MatrixSpace(QQ, Integer(2), sparse=True)
>>> A = M([Integer(1),Integer(2),Integer(3),Integer(4)]); A
[1 2]
[3 4]
>>> A.antitranspose()
[4 2]
[3 1]
M = MatrixSpace(QQ, 2, sparse=True)
A = M([1,2,3,4]); A
A.antitranspose()

See also

transpose()

apply_map(phi, R=None, sparse=True)[source]

Apply the given map phi (an arbitrary Python function or callable object) to this matrix.

If R is not given, automatically determine the base ring of the resulting matrix.

INPUT:

  • phi – arbitrary Python function or callable object

  • R – (optional) ring

  • sparse – boolean (default: True); whether to return a sparse or a dense matrix

OUTPUT: a matrix over R

EXAMPLES:

sage: m = matrix(ZZ, 10000, {(1,2): 17}, sparse=True)

sage: # needs sage.rings.finite_rings
sage: k.<a> = GF(9)
sage: f = lambda x: k(x)
sage: n = m.apply_map(f)
sage: n.parent()
Full MatrixSpace of 10000 by 10000 sparse matrices
 over Finite Field in a of size 3^2
sage: n[1, 2]
2
>>> from sage.all import *
>>> m = matrix(ZZ, Integer(10000), {(Integer(1),Integer(2)): Integer(17)}, sparse=True)

>>> # needs sage.rings.finite_rings
>>> k = GF(Integer(9), names=('a',)); (a,) = k._first_ngens(1)
>>> f = lambda x: k(x)
>>> n = m.apply_map(f)
>>> n.parent()
Full MatrixSpace of 10000 by 10000 sparse matrices
 over Finite Field in a of size 3^2
>>> n[Integer(1), Integer(2)]
2
m = matrix(ZZ, 10000, {(1,2): 17}, sparse=True)
# needs sage.rings.finite_rings
k.<a> = GF(9)
f = lambda x: k(x)
n = m.apply_map(f)
n.parent()
n[1, 2]

An example where the codomain is explicitly specified.

sage: n = m.apply_map(lambda x: x%3, GF(3))
sage: n.parent()
Full MatrixSpace of 10000 by 10000 sparse matrices
 over Finite Field of size 3
sage: n[1, 2]
2
>>> from sage.all import *
>>> n = m.apply_map(lambda x: x%Integer(3), GF(Integer(3)))
>>> n.parent()
Full MatrixSpace of 10000 by 10000 sparse matrices
 over Finite Field of size 3
>>> n[Integer(1), Integer(2)]
2
n = m.apply_map(lambda x: x%3, GF(3))
n.parent()
n[1, 2]

If we did not specify the codomain, the resulting matrix in the above case ends up over \(\ZZ\) again:

sage: n = m.apply_map(lambda x: x%3)
sage: n.parent()
Full MatrixSpace of 10000 by 10000 sparse matrices over Integer Ring
sage: n[1, 2]
2
>>> from sage.all import *
>>> n = m.apply_map(lambda x: x%Integer(3))
>>> n.parent()
Full MatrixSpace of 10000 by 10000 sparse matrices over Integer Ring
>>> n[Integer(1), Integer(2)]
2
n = m.apply_map(lambda x: x%3)
n.parent()
n[1, 2]

If self is subdivided, the result will be as well:

sage: m = matrix(2, 2, [0, 0, 3, 0])
sage: m.subdivide(None, 1); m
[0|0]
[3|0]
sage: m.apply_map(lambda x: x*x)
[0|0]
[9|0]
>>> from sage.all import *
>>> m = matrix(Integer(2), Integer(2), [Integer(0), Integer(0), Integer(3), Integer(0)])
>>> m.subdivide(None, Integer(1)); m
[0|0]
[3|0]
>>> m.apply_map(lambda x: x*x)
[0|0]
[9|0]
m = matrix(2, 2, [0, 0, 3, 0])
m.subdivide(None, 1); m
m.apply_map(lambda x: x*x)

If the map sends zero to a nonzero value, then it may be useful to get the result as a dense matrix.

sage: m = matrix(ZZ, 3, 3, [0] * 7 + [1,2], sparse=True); m
[0 0 0]
[0 0 0]
[0 1 2]
sage: parent(m)
Full MatrixSpace of 3 by 3 sparse matrices over Integer Ring
sage: n = m.apply_map(lambda x: x+polygen(QQ), sparse=False); n
[    x     x     x]
[    x     x     x]
[    x x + 1 x + 2]
sage: parent(n)
Full MatrixSpace of 3 by 3 dense matrices over Univariate Polynomial Ring in x over Rational Field
>>> from sage.all import *
>>> m = matrix(ZZ, Integer(3), Integer(3), [Integer(0)] * Integer(7) + [Integer(1),Integer(2)], sparse=True); m
[0 0 0]
[0 0 0]
[0 1 2]
>>> parent(m)
Full MatrixSpace of 3 by 3 sparse matrices over Integer Ring
>>> n = m.apply_map(lambda x: x+polygen(QQ), sparse=False); n
[    x     x     x]
[    x     x     x]
[    x x + 1 x + 2]
>>> parent(n)
Full MatrixSpace of 3 by 3 dense matrices over Univariate Polynomial Ring in x over Rational Field
m = matrix(ZZ, 3, 3, [0] * 7 + [1,2], sparse=True); m
parent(m)
n = m.apply_map(lambda x: x+polygen(QQ), sparse=False); n
parent(n)
apply_morphism(phi)[source]

Apply the morphism phi to the coefficients of this sparse matrix.

The resulting matrix is over the codomain of phi.

INPUT:

  • phi – a morphism, so phi is callable and

    phi.domain() and phi.codomain() are defined. The codomain must be a ring.

OUTPUT: a matrix over the codomain of phi

EXAMPLES:

sage: m = matrix(ZZ, 3, range(9), sparse=True)
sage: phi = ZZ.hom(GF(5))
sage: m.apply_morphism(phi)
[0 1 2]
[3 4 0]
[1 2 3]
sage: m.apply_morphism(phi).parent()
Full MatrixSpace of 3 by 3 sparse matrices
 over Finite Field of size 5
>>> from sage.all import *
>>> m = matrix(ZZ, Integer(3), range(Integer(9)), sparse=True)
>>> phi = ZZ.hom(GF(Integer(5)))
>>> m.apply_morphism(phi)
[0 1 2]
[3 4 0]
[1 2 3]
>>> m.apply_morphism(phi).parent()
Full MatrixSpace of 3 by 3 sparse matrices
 over Finite Field of size 5
m = matrix(ZZ, 3, range(9), sparse=True)
phi = ZZ.hom(GF(5))
m.apply_morphism(phi)
m.apply_morphism(phi).parent()
augment(right, subdivide=False)[source]

Return the augmented matrix of the form:

[self | right].

EXAMPLES:

sage: M = MatrixSpace(QQ, 2, 2, sparse=True)
sage: A = M([1,2, 3,4])
sage: A
[1 2]
[3 4]
sage: N = MatrixSpace(QQ, 2, 1, sparse=True)
sage: B = N([9,8])
sage: B
[9]
[8]
sage: A.augment(B)
[1 2 9]
[3 4 8]
sage: B.augment(A)
[9 1 2]
[8 3 4]
>>> from sage.all import *
>>> M = MatrixSpace(QQ, Integer(2), Integer(2), sparse=True)
>>> A = M([Integer(1),Integer(2), Integer(3),Integer(4)])
>>> A
[1 2]
[3 4]
>>> N = MatrixSpace(QQ, Integer(2), Integer(1), sparse=True)
>>> B = N([Integer(9),Integer(8)])
>>> B
[9]
[8]
>>> A.augment(B)
[1 2 9]
[3 4 8]
>>> B.augment(A)
[9 1 2]
[8 3 4]
M = MatrixSpace(QQ, 2, 2, sparse=True)
A = M([1,2, 3,4])
A
N = MatrixSpace(QQ, 2, 1, sparse=True)
B = N([9,8])
B
A.augment(B)
B.augment(A)

A vector may be augmented to a matrix.

sage: A = matrix(QQ, 3, 4, range(12), sparse=True)
sage: v = vector(QQ, 3, range(3), sparse=True)
sage: A.augment(v)
[ 0  1  2  3  0]
[ 4  5  6  7  1]
[ 8  9 10 11  2]
>>> from sage.all import *
>>> A = matrix(QQ, Integer(3), Integer(4), range(Integer(12)), sparse=True)
>>> v = vector(QQ, Integer(3), range(Integer(3)), sparse=True)
>>> A.augment(v)
[ 0  1  2  3  0]
[ 4  5  6  7  1]
[ 8  9 10 11  2]
A = matrix(QQ, 3, 4, range(12), sparse=True)
v = vector(QQ, 3, range(3), sparse=True)
A.augment(v)

The subdivide option will add a natural subdivision between self and right. For more details about how subdivisions are managed when augmenting, see sage.matrix.matrix1.Matrix.augment().

sage: A = matrix(QQ, 3, 5, range(15), sparse=True)
sage: B = matrix(QQ, 3, 3, range(9), sparse=True)
sage: A.augment(B, subdivide=True)
[ 0  1  2  3  4| 0  1  2]
[ 5  6  7  8  9| 3  4  5]
[10 11 12 13 14| 6  7  8]
>>> from sage.all import *
>>> A = matrix(QQ, Integer(3), Integer(5), range(Integer(15)), sparse=True)
>>> B = matrix(QQ, Integer(3), Integer(3), range(Integer(9)), sparse=True)
>>> A.augment(B, subdivide=True)
[ 0  1  2  3  4| 0  1  2]
[ 5  6  7  8  9| 3  4  5]
[10 11 12 13 14| 6  7  8]
A = matrix(QQ, 3, 5, range(15), sparse=True)
B = matrix(QQ, 3, 3, range(9), sparse=True)
A.augment(B, subdivide=True)
change_ring(ring)[source]

Return the matrix obtained by coercing the entries of this matrix into the given ring.

Always returns a copy (unless self is immutable, in which case returns self).

EXAMPLES:

sage: x = polygen(ZZ, 'x')
sage: A = matrix(QQ['x,y'], 2, [0,-1,2*x,-2], sparse=True); A
[  0  -1]
[2*x  -2]
sage: A.change_ring(QQ['x,y,z'])
[  0  -1]
[2*x  -2]
>>> from sage.all import *
>>> x = polygen(ZZ, 'x')
>>> A = matrix(QQ['x,y'], Integer(2), [Integer(0),-Integer(1),Integer(2)*x,-Integer(2)], sparse=True); A
[  0  -1]
[2*x  -2]
>>> A.change_ring(QQ['x,y,z'])
[  0  -1]
[2*x  -2]
x = polygen(ZZ, 'x')
A = matrix(QQ['x,y'], 2, [0,-1,2*x,-2], sparse=True); A
A.change_ring(QQ['x,y,z'])

Subdivisions are preserved when changing rings:

sage: A.subdivide([2],[]); A
[  0  -1]
[2*x  -2]
[-------]
sage: A.change_ring(RR['x,y'])
[                 0  -1.00000000000000]
[2.00000000000000*x  -2.00000000000000]
[-------------------------------------]
>>> from sage.all import *
>>> A.subdivide([Integer(2)],[]); A
[  0  -1]
[2*x  -2]
[-------]
>>> A.change_ring(RR['x,y'])
[                 0  -1.00000000000000]
[2.00000000000000*x  -2.00000000000000]
[-------------------------------------]
A.subdivide([2],[]); A
A.change_ring(RR['x,y'])
charpoly(var='x', **kwds)[source]

Return the characteristic polynomial of this matrix.

Note

the generic sparse charpoly implementation in Sage is to just compute the charpoly of the corresponding dense matrix, so this could use a lot of memory. In particular, for this matrix, the charpoly will be computed using a dense algorithm.

EXAMPLES:

sage: A = matrix(ZZ, 4, range(16), sparse=True)
sage: A.charpoly()
x^4 - 30*x^3 - 80*x^2
sage: A.charpoly('y')
y^4 - 30*y^3 - 80*y^2
sage: A.charpoly()
x^4 - 30*x^3 - 80*x^2
>>> from sage.all import *
>>> A = matrix(ZZ, Integer(4), range(Integer(16)), sparse=True)
>>> A.charpoly()
x^4 - 30*x^3 - 80*x^2
>>> A.charpoly('y')
y^4 - 30*y^3 - 80*y^2
>>> A.charpoly()
x^4 - 30*x^3 - 80*x^2
A = matrix(ZZ, 4, range(16), sparse=True)
A.charpoly()
A.charpoly('y')
A.charpoly()
density()[source]

Return the density of the matrix.

By density we understand the ratio of the number of nonzero positions and the number self.nrows() * self.ncols(), i.e. the number of possible nonzero positions.

EXAMPLES:

sage: a = matrix([[],[],[],[]], sparse=True); a.density()
0
sage: a = matrix(5000,5000,{(1,2): 1}); a.density()
1/25000000
>>> from sage.all import *
>>> a = matrix([[],[],[],[]], sparse=True); a.density()
0
>>> a = matrix(Integer(5000),Integer(5000),{(Integer(1),Integer(2)): Integer(1)}); a.density()
1/25000000
a = matrix([[],[],[],[]], sparse=True); a.density()
a = matrix(5000,5000,{(1,2): 1}); a.density()
determinant(**kwds)[source]

Return the determinant of this matrix.

Note

the generic sparse determinant implementation in Sage is to just compute the determinant of the corresponding dense matrix, so this could use a lot of memory. In particular, for this matrix, the determinant will be computed using a dense algorithm.

EXAMPLES:

sage: A = matrix(ZZ, 4, range(16), sparse=True)
sage: B = A + identity_matrix(ZZ, 4, sparse=True)
sage: B.det()
-49
>>> from sage.all import *
>>> A = matrix(ZZ, Integer(4), range(Integer(16)), sparse=True)
>>> B = A + identity_matrix(ZZ, Integer(4), sparse=True)
>>> B.det()
-49
A = matrix(ZZ, 4, range(16), sparse=True)
B = A + identity_matrix(ZZ, 4, sparse=True)
B.det()
matrix_from_rows_and_columns(rows, columns)[source]

Return the matrix constructed from self from the given rows and columns.

EXAMPLES:

sage: M = MatrixSpace(Integers(8),3,3, sparse=True)
sage: A = M(range(9)); A
[0 1 2]
[3 4 5]
[6 7 0]
sage: A.matrix_from_rows_and_columns([1], [0,2])
[3 5]
sage: A.matrix_from_rows_and_columns([1,2], [1,2])
[4 5]
[7 0]
>>> from sage.all import *
>>> M = MatrixSpace(Integers(Integer(8)),Integer(3),Integer(3), sparse=True)
>>> A = M(range(Integer(9))); A
[0 1 2]
[3 4 5]
[6 7 0]
>>> A.matrix_from_rows_and_columns([Integer(1)], [Integer(0),Integer(2)])
[3 5]
>>> A.matrix_from_rows_and_columns([Integer(1),Integer(2)], [Integer(1),Integer(2)])
[4 5]
[7 0]
M = MatrixSpace(Integers(8),3,3, sparse=True)
A = M(range(9)); A
A.matrix_from_rows_and_columns([1], [0,2])
A.matrix_from_rows_and_columns([1,2], [1,2])

Note that row and column indices can be reordered or repeated:

sage: A.matrix_from_rows_and_columns([2,1], [2,1])
[0 7]
[5 4]
>>> from sage.all import *
>>> A.matrix_from_rows_and_columns([Integer(2),Integer(1)], [Integer(2),Integer(1)])
[0 7]
[5 4]
A.matrix_from_rows_and_columns([2,1], [2,1])

For example here we take from row 1 columns 2 then 0 twice, and do this 3 times.

sage: A.matrix_from_rows_and_columns([1,1,1],[2,0,0])
[5 3 3]
[5 3 3]
[5 3 3]
>>> from sage.all import *
>>> A.matrix_from_rows_and_columns([Integer(1),Integer(1),Integer(1)],[Integer(2),Integer(0),Integer(0)])
[5 3 3]
[5 3 3]
[5 3 3]
A.matrix_from_rows_and_columns([1,1,1],[2,0,0])

We can efficiently extract large submatrices:

sage: A = random_matrix(ZZ, 100000, density=.00005, sparse=True)  # long time (4s on sage.math, 2012)
sage: B = A[50000:,:50000]        # long time
sage: count = 0
sage: for i, j in A.nonzero_positions():  # long time
....:     if i >= 50000 and j < 50000:
....:         assert B[i-50000, j] == A[i, j]
....:         count += 1
sage: count == sum(1 for _ in B.nonzero_positions())  # long time
True
>>> from sage.all import *
>>> A = random_matrix(ZZ, Integer(100000), density=RealNumber('.00005'), sparse=True)  # long time (4s on sage.math, 2012)
>>> B = A[Integer(50000):,:Integer(50000)]        # long time
>>> count = Integer(0)
>>> for i, j in A.nonzero_positions():  # long time
...     if i >= Integer(50000) and j < Integer(50000):
...         assert B[i-Integer(50000), j] == A[i, j]
...         count += Integer(1)
>>> count == sum(Integer(1) for _ in B.nonzero_positions())  # long time
True
A = random_matrix(ZZ, 100000, density=.00005, sparse=True)  # long time (4s on sage.math, 2012)
B = A[50000:,:50000]        # long time
count = 0
for i, j in A.nonzero_positions():  # long time
    if i >= 50000 and j < 50000:
        assert B[i-50000, j] == A[i, j]
        count += 1
count == sum(1 for _ in B.nonzero_positions())  # long time

We must pass in a list of indices:

sage: A = random_matrix(ZZ,100,density=.02,sparse=True)
sage: A.matrix_from_rows_and_columns(1,[2,3])
Traceback (most recent call last):
...
TypeError: 'sage.rings.integer.Integer' object is not iterable

sage: A.matrix_from_rows_and_columns([1,2],3)
Traceback (most recent call last):
...
TypeError: 'sage.rings.integer.Integer' object is not iterable
>>> from sage.all import *
>>> A = random_matrix(ZZ,Integer(100),density=RealNumber('.02'),sparse=True)
>>> A.matrix_from_rows_and_columns(Integer(1),[Integer(2),Integer(3)])
Traceback (most recent call last):
...
TypeError: 'sage.rings.integer.Integer' object is not iterable

>>> A.matrix_from_rows_and_columns([Integer(1),Integer(2)],Integer(3))
Traceback (most recent call last):
...
TypeError: 'sage.rings.integer.Integer' object is not iterable
A = random_matrix(ZZ,100,density=.02,sparse=True)
A.matrix_from_rows_and_columns(1,[2,3])
A.matrix_from_rows_and_columns([1,2],3)

AUTHORS:

  • Jaap Spies (2006-02-18)

  • Didier Deshommes: some Pyrex speedups implemented

  • Jason Grout: sparse matrix optimizations

transpose()[source]

Return the transpose of self, without changing self.

EXAMPLES: We create a matrix, compute its transpose, and note that the original matrix is not changed.

sage: M = MatrixSpace(QQ, 2, sparse=True)
sage: A = M([1,2,3,4]); A
[1 2]
[3 4]
sage: B = A.transpose(); B
[1 3]
[2 4]
>>> from sage.all import *
>>> M = MatrixSpace(QQ, Integer(2), sparse=True)
>>> A = M([Integer(1),Integer(2),Integer(3),Integer(4)]); A
[1 2]
[3 4]
>>> B = A.transpose(); B
[1 3]
[2 4]
M = MatrixSpace(QQ, 2, sparse=True)
A = M([1,2,3,4]); A
B = A.transpose(); B

.T is a convenient shortcut for the transpose:

sage: A.T
[1 3]
[2 4]
>>> from sage.all import *
>>> A.T
[1 3]
[2 4]
A.T

See also

antitranspose()