Matrices and Spaces of Matrices
Release 10.4

The Sage Development TeamJul 23, 2024

CONTENTS

1Matrix Spaces

32

General matrix Constructor and display options

31

3

Constructors for special matrices

47

4

Helpers for creating matrices

109

5

Matrices over an arbitrary ring

129

6

Base class for matrices, part 0

141

7Base class for matrices, part 1

211

8Base class for matrices, part 2251

9Generic Asymptotically Fast Strassen Algorithms

583

10 Minimal Polynomials of Linear Recurrence Sequences589

11 Base class for dense matrices

591

12 Base class for sparse matrices593

13 Dense Matrices over a general ring603

14 Sparse Matrices over a general ring605

15 Dense matrices over the integer ring609

16 Sparse integer matrices

653

17 Modular algorithm to compute Hermite normal forms of integer matrices

661

18 Saturation over ZZ

681

19 Dense matrices over the rational field687

20 Sparse rational matrices

711

21 Dense matrices using a NumPy backend

717

22 Dense matrices over the Real Double Field using NumPy

783i

23 Dense matrices over GF(2) using the M4RI library785

24 Dense matrices over F2𝑒 for 2 ≤ 𝑒 ≤ 16 using the M4RIE library801

25 Dense matrices over Z/𝑛Z for 𝑛 < 94906266 using LinBox’s Modular<double>

813

26 Dense matrices over Z/𝑛Z for 𝑛 < 28 using LinBox’s Modular<float>

833

27 Sparse matrices over Z/𝑛Z for 𝑛 small

853

28 Symbolic dense matrices

861

29 Symbolic sparse matrices

883

30 Dense matrices over the Complex Double Field using NumPy

905

31 Arbitrary precision complex ball matrices

907

32 Dense matrices over univariate polynomials over fields

917

33 Dense matrices over multivariate polynomials over fields

987

34 Matrices over Cyclotomic Fields

993

35 Operation Tables

1001

36 Actions used by the coercion model for matrix and vector multiplications

1017

37 Functions for changing the base ring of matrices quickly

1021

38 Echelon matrices over finite fields.

1023

39 Miscellaneous matrix functions

1025

40 Matrix windows1029

41 Misc matrix algorithms

1031

42 Misc matrix algorithms using MPFR

1035

43 Misc matrix algorithms using FLINT

1037

44 Calculate symplectic bases for matrices over fields and the integers.

1039

45 𝐽-ideals of matrices

1051

46 Benchmarks for matrices

1067

47 Indices and Tables

1081

Python Module Index

1083

Index

1085

ii

Matrices and Spaces of Matrices, Release 10.4

Sage provides native support for working with matrices over any commutative or noncommutative ring. The parent object
for a matrix is a matrix space MatrixSpace(R, n, m) of all 𝑛 × 𝑚 matrices over a ring 𝑅.
To create a matrix, either use the matrix(...) function or create a matrix space using the MatrixSpace commandand coerce an object into it.
Matrices also act on row vectors, which you create using the vector(...) command or by making a VectorSpaceand coercing lists into it. The natural action of matrices on row vectors is from the right. Sage currently does not have acolumn vector class (on which matrices would act from the left), but this is planned.
In addition to native Sage matrices, Sage also includes the following additional ways to compute with matrices:• Several math software systems included with Sage have their own native matrix support, which can be used from
Sage. E.g., PARI, GAP, Maxima, and Singular all have a notion of matrices.
• The GSL C-library is included with Sage, and can be used via Cython.
• The scipy module provides support for sparse numerical linear algebra, among many other things.
• The numpy module, which you load by typing import numpy is included standard with Sage. It contains a very
sophisticated and well developed array class, plus optimized support for numerical linear algebra. Sage’s matrices
over RDF and CDF (native floating-point real and complex numbers) use numpy.
Finally, this module contains some data-structures for matrix-like objects like operation tables (e.g. the multiplicationtable of a group).

CONTENTS

1Matrices and Spaces of Matrices, Release 10.4

2

CONTENTSCHAPTERONEMATRIX SPACES

You can create any space Mat𝑛×𝑚 (𝑅) of either dense or sparse matrices with given number of rows and columns overany 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>>> from sage.all import *>>> MS = MatrixSpace(QQ, Integer(6),Integer(6), sparse=True); MS
Full MatrixSpace of 6 by 6 sparse matrices over Rational Field>>> MS.base_ring()
Rational Field>>> MS = MatrixSpace(ZZ, Integer(3),Integer(5), sparse=False); MS
Full MatrixSpace of 3 by 5 dense matrices over Integer Ringclass sage.matrix.matrix_space.MatrixSpace(base_ring, nrows, ncols, sparse, implementation)
Bases: UniqueRepresentation, Parent
The space of matrices of given size and base ring.
INPUT:• base_ring – a ring
• nrows or row_keys – (nonnegative integer) the number of rows, or a finite family of arbitrary objects thatindex the rows of the matrix• ncols or column_keys – (nonnegative integer, default nrows) the number of columns, or a finite familyof arbitrary objects that index the columns of the matrix• sparse – (boolean, default False) whether or not matrices
are given a sparse representation• implementation – (optional, a string or a matrix class) a possible implementation. Depending on thebase ring, the string can be–generic – on any base rings–

flint – for integers and rationals–

meataxe – finite fields using the optional package meataxe: Library for computing with modular
representations

3

Matrices and Spaces of Matrices, Release 10.4–

m4ri – for characteristic 2 using the m4ri: fast arithmetic with dense matrices over GF(2) library–linbox-float – for integer mod rings up to 28 = 256–

linbox-double – for integer mod rings up to 𝑓 𝑙𝑜𝑜𝑟(22 6 * 𝑠𝑞𝑟𝑡(2) + 1/2) = 94906266–

numpy – for real and complex floating point numbers

OUTPUT: a matrix space or, more generally, a homspace between free modules
This factory function creates instances of various specialized classes depending on the input. Not all combinationsof options are implemented.
• If the parameters row_keys or column_keys are provided, they must be finite families of objects. In thiscase, instances of CombinatorialFreeModule are created via the factory function FreeModule().
Then the homspace between these modules is returned.
EXAMPLES:
sage: MatrixSpace(QQ, 2)
Full MatrixSpace of 2 by 2 dense matrices over Rational Field
sage: MatrixSpace(ZZ, 3, 2)
Full MatrixSpace of 3 by 2 dense matrices over Integer Ringsage: MatrixSpace(ZZ, 3, sparse=False)
Full MatrixSpace of 3 by 3 dense matrices over Integer Ringsage: MatrixSpace(ZZ, 10, 5)
Full MatrixSpace of 10 by 5 dense matrices over Integer Ringsage: MatrixSpace(ZZ, 10, 5).category()
Category of infinite enumerated finite dimensional modules with basis over
(Dedekind domains and euclidean domains
and noetherian rings
and infinite enumerated sets and metric spaces)sage: MatrixSpace(ZZ, 10, 10).category()
Category of infinite enumerated finite dimensional algebras with basis over
(Dedekind domains and euclidean domains
and noetherian rings
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)>>> from sage.all import *>>> MatrixSpace(QQ, Integer(2))
Full MatrixSpace of 2 by 2 dense matrices over Rational Field>>> MatrixSpace(ZZ, Integer(3), Integer(2))
Full MatrixSpace of 3 by 2 dense matrices over Integer Ring>>> MatrixSpace(ZZ, Integer(3), sparse=False)
Full MatrixSpace of 3 by 3 dense matrices over Integer Ring>>> MatrixSpace(ZZ, Integer(10), Integer(5))
Full MatrixSpace of 10 by 5 dense matrices over Integer Ring>>> MatrixSpace(ZZ, Integer(10), Integer(5)).category()
Category of infinite enumerated finite dimensional modules with basis over
(Dedekind domains and euclidean domains
and noetherian rings
and infinite enumerated sets and metric spaces)>>> MatrixSpace(ZZ, Integer(10), Integer(10)).category()
Category of infinite enumerated finite dimensional algebras with basis over
(Dedekind domains and euclidean domains(continues on next page)

4

Chapter 1. Matrix Spaces

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)and noetherian rings
and infinite enumerated sets and metric spaces)>>> MatrixSpace(QQ, Integer(10)).category()
Category of infinite finite dimensional algebras with basis over(number fields and quotient fields and metric spaces)

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]); A
[1 2]
[3 4]
>>> from sage.all import *>>> MS = MatrixSpace(QQ, Integer(2))>>> MS.dimension()4>>> MS.dims()(2, 2)>>> B = MS.basis()>>> list(B)[[1 0] [0 1] [0 0] [0 0][0 0], [0 0], [1 0], [0 1]]>>> B[Integer(0),Integer(0)]
[1 0]
[0 0]
>>> B[Integer(0),Integer(1)]
[0 1]
[0 0]
>>> B[Integer(1),Integer(0)]
[0 0]
[1 0]
(continues on next page)5

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> B[Integer(1),Integer(1)]
[0 0]
[0 1]
>>> A = MS.matrix([Integer(1),Integer(2),Integer(3),Integer(4)]); 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]>>> from sage.all import *>>> MS2 = MatrixSpace(ZZ, Integer(2), Integer(3))>>> B = MS2.matrix([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5),˓→Integer(6)])>>> A * B
[ 9 12 15][19 26 33]

Using row_keys and column_keys:
sage: MS = MatrixSpace(ZZ, [ u , v ], [ a , b , c ]); MS
Set of Morphisms
from Free module generated by { a , b , c } over Integer Ring
to Free module generated by { u , v } over Integer Ringin Category of finite dimensional modules with basis over Integer Ring>>> from sage.all import *>>> MS = MatrixSpace(ZZ, [ u , v ], [ a , b , c ]); MS
Set of Morphisms
from Free module generated by { a , b , c } over Integer Ring
to Free module generated by { u , v } over Integer Ringin Category of finite dimensional modules with basis over Integer Ring

Check categories:
sage: MatrixSpace(ZZ, 10, 5)
Full MatrixSpace of 10 by 5 dense matrices over Integer Ringsage: MatrixSpace(ZZ, 10, 5).category()
Category of infinite enumerated finite dimensional modules with basis over
(Dedekind domains and euclidean domains
and noetherian rings
and infinite enumerated sets and metric spaces)sage: MatrixSpace(ZZ, 10, 10).category()
Category of infinite enumerated finite dimensional algebras with basis over
(Dedekind domains and euclidean domains
and noetherian rings
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)

6

Chapter 1. Matrix Spaces

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> MatrixSpace(ZZ, Integer(10), Integer(5))
Full MatrixSpace of 10 by 5 dense matrices over Integer Ring>>> MatrixSpace(ZZ, Integer(10), Integer(5)).category()
Category of infinite enumerated finite dimensional modules with basis over
(Dedekind domains and euclidean domains
and noetherian rings
and infinite enumerated sets and metric spaces)>>> MatrixSpace(ZZ, Integer(10), Integer(10)).category()
Category of infinite enumerated finite dimensional algebras with basis over
(Dedekind domains and euclidean domains
and noetherian rings
and infinite enumerated sets and metric spaces)>>> MatrixSpace(QQ, Integer(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>>> from sage.all import *>>> Mat(ZZ, Integer(3), Integer(5)).base_extend(QQ)
Full MatrixSpace of 3 by 5 dense matrices over Rational Field>>> Mat(QQ, Integer(3), Integer(5)).base_extend(GF(Integer(7)))
Traceback (most recent call last):...
TypeError: no base extension definedbasis()
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](continues on next page)7

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 0], [0 0], [1 0], [0 1]]>>> from sage.all import *>>> list(Mat(ZZ,Integer(2),Integer(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 hash5>>> from sage.all import *>>> class C:...
@cached_method...
def __hash__(self):...
print("compute hash")...
return int(Integer(5))...
@cached_method...
def f(self, x):...
print("computing cached method")...
return x*Integer(2)>>> c = C()>>> type(C.__hash__)<class sage.misc.cachefunc.CachedMethodCallerNoArgs >>>> hash(c)compute hash
5

When calling a cached method for the second time with the same arguments, the value is gotten from thecache, so that a new computation is not needed:sage: hash(c)5(continues on next page)

8

Chapter 1. Matrix Spaces

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: c.f(4)computing cached method8
sage: c.f(4) is c.f(4)True>>> from sage.all import *>>> hash(c)5>>> c.f(Integer(4))
computing cached method8>>> c.f(Integer(4)) is c.f(Integer(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)8sage: d.f(4)computing cached method
8>>> from sage.all import *>>> d = C()>>> d.f(Integer(4)) is c.f(Integer(4))
computing cached method
False>>> d.f.clear_cache()>>> c.f(Integer(4))
8>>> d.f(Integer(4))
computing cached method
8

Using cached methods for the hash and other special methods was implemented in Issue #12601, by meansof 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 ...>>>> from sage.all import *>>> cached_method(c.__hash__)<sage.misc.cachefunc.CachedSpecialMethod object at ...>>>> 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 thecached method. This can be dangerous with special methods such as __hash__:9

Matrices and Spaces of Matrices, Release 10.4

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>>> from sage.all import *>>> class C:...
@cached_method(do_pickle=True)...
def __hash__(self):...
return id(self)>>> import __main__>>> __main__.C = C>>> c = C()>>> hash(c) # random output>>> d = loads(dumps(c))>>> hash(d) == hash(c)TrueHowever, 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>>> from sage.all import *>>> class C:...
@cached_method...
def __hash__(self):...
return id(self)>>> __main__.C = C>>> c = C()>>> hash(c) # random output>>> d = loads(dumps(c))>>> hash(d) == hash(c)Falsecardinality()
Return the number of elements in self.

10

Chapter 1. Matrix Spaces

Matrices and Spaces of Matrices, Release 10.4

EXAMPLES:
sage: MatrixSpace(GF(3), 2, 3).cardinality()729
sage: MatrixSpace(ZZ, 2).cardinality()+Infinity
sage: MatrixSpace(ZZ, 0, 3).cardinality()1>>> from sage.all import *>>> MatrixSpace(GF(Integer(3)), Integer(2), Integer(3)).cardinality()729>>> MatrixSpace(ZZ, Integer(2)).cardinality()+Infinity>>> MatrixSpace(ZZ, Integer(0), Integer(3)).cardinality()
1change_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>>> from sage.all import *>>> Mat(QQ, Integer(3), Integer(5)).change_ring(GF(Integer(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()
˓→needs sage.rings.finite_rings
3>>> from sage.all import *>>> MatrixSpace(ZZ, Integer(2)).characteristic()
0>>> MatrixSpace(GF(Integer(9)), Integer(0)).characteristic()˓→# needs sage.rings.finite_rings
3

#␣

␣

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

Matrices and Spaces of Matrices, Release 10.4

EXAMPLES:
sage: M = Mat(GF(9, a ), 20, 5, sparse=True); M.column_space()
˓→needs sage.rings.finite_rings
Sparse vector space of dimension 20 over Finite Field in a of size 3^2#␣>>> from sage.all import *>>> M = Mat(GF(Integer(9), a ), Integer(20), Integer(5), sparse=True); M.
˓→column_space()# needs sage.rings.finite_rings
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>>> from sage.all import *>>> A = matrix(ZZ, Integer(2), (ellipsis_range(Integer(1),Ellipsis,
˓→Integer(4))), sparse=True)>>> A.parent().construction()(MatrixFunctor, Integer Ring)>>> A.parent().construction()[Integer(0)](QQ[ x ])Full MatrixSpace of 2 by 2 sparse matrices over
Univariate Polynomial Ring in x over Rational Field>>> parent(A/Integer(2))
Full MatrixSpace of 2 by 2 sparse matrices over Rational Field

diagonal_matrix(entries)
Create a diagonal matrix in self using the specified elements
INPUT:• entries – the elements to use as the diagonal entries
self must be a space of square matrices. The length of entries must be less than or equal to the matrix
dimensions. If the length of entries 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):...
(continues on next page)

12

Chapter 1. Matrix Spaces

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

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>>> from sage.all import *>>> MS1 = MatrixSpace(ZZ,Integer(4))>>> MS2 = MatrixSpace(QQ,Integer(3),Integer(4))>>> I = MS1.diagonal_matrix([Integer(1), Integer(2), Integer(3), Integer(4)])>>> I[1 0 0 0][0 2 0 0][0 0 3 0][0 0 0 4]>>> MS2.diagonal_matrix([Integer(1), Integer(2)])
Traceback (most recent call last):...
TypeError: diagonal matrix must be square>>> MS1.diagonal_matrix([Integer(1), Integer(2), Integer(3), Integer(4),␣
˓→Integer(5)])
Traceback (most recent call last):...
ValueError: number of diagonal matrix entries (5) exceeds the matrix size (4)>>> MS1.diagonal_matrix([Integer(1)/Integer(2), Integer(2), Integer(3),␣
˓→Integer(4)])
Traceback (most recent call last):...
TypeError: no conversion of this rational to integer

Check different implementations:sage: M1 = MatrixSpace(ZZ, 2, implementation= flint )˓→needs sage.libs.linbox
sage: M2 = MatrixSpace(ZZ, 2, implementation= generic )#␣sage: type(M1.diagonal_matrix([1, 2]))
˓→needs sage.libs.linbox<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 >#␣>>> from sage.all import *>>> M1 = MatrixSpace(ZZ, Integer(2), implementation= flint )˓→# needs sage.libs.linbox>>> M2 = MatrixSpace(ZZ, Integer(2), implementation= generic )>>> type(M1.diagonal_matrix([Integer(1), Integer(2)]))˓→# needs sage.libs.linbox<class sage.matrix.matrix_integer_dense.Matrix_integer_dense >>>> type(M2.diagonal_matrix([Integer(1), Integer(2)]))<class sage.matrix.matrix_generic_dense.Matrix_generic_dense >

␣

␣

13

Matrices and Spaces of Matrices, Release 10.4

dimension()
Return (m rows) * (n cols) of self as Integer.
EXAMPLES:
sage: MS = MatrixSpace(ZZ,4,6)
sage: u = MS.dimension()sage: u - 24 == 0
True>>> from sage.all import *>>> MS = MatrixSpace(ZZ,Integer(4),Integer(6))>>> u = MS.dimension()>>> u - Integer(24) == Integer(0)True

dims()
Return (m row, n col) representation of self dimension.
EXAMPLES:
sage: MS = MatrixSpace(ZZ,4,6)
sage: MS.dims()(4, 6)>>> from sage.all import *>>> MS = MatrixSpace(ZZ,Integer(4),Integer(6))>>> MS.dims()(4, 6)

from_vector(vector, order=None, coerce=True)
Build an element of self from a vector.
EXAMPLES:
sage: A = matrix([[1,2,3], [4,5,6]])
sage: v = vector(A); v(1, 2, 3, 4, 5, 6)
sage: MS = A.parent()
sage: MS.from_vector(v)[1 2 3][4 5 6]sage: order = [(1,2), (1,0), (0,1), (0,2), (0,0), (1,1)]
sage: MS.from_vector(v, order=order)[5 3 4][2 6 1]>>> from sage.all import *>>> A = matrix([[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),˓→Integer(6)]])>>> v = vector(A); v(1, 2, 3, 4, 5, 6)>>> MS = A.parent()>>> MS.from_vector(v)[1 2 3][4 5 6]>>> order = [(Integer(1),Integer(2)), (Integer(1),Integer(0)), (Integer(0),(continues on next page)

14

Chapter 1. Matrix Spaces

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Integer(1)), (Integer(0),Integer(2)), (Integer(0),Integer(0)), (Integer(1),˓→Integer(1))]>>> MS.from_vector(v, order=order)[5 3 4][2 6 1]˓→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]>>> from sage.all import *>>> M = Mat(GF(Integer(7)), Integer(10000), Integer(5)); M.ngens()
50000>>> a = M.gen(10)>>> a[:Integer(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 use copy if you wanta 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>>> from sage.all import *>>> MS1 = MatrixSpace(ZZ,Integer(4))>>> MS2 = MatrixSpace(QQ,Integer(3),Integer(4))(continues on next page)15

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> I = MS1.identity_matrix()>>> I[1 0 0 0][0 1 0 0][0 0 1 0][0 0 0 1]>>> 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>>> from sage.all import *>>> Mat(RDF,Integer(2),Integer(3)).is_sparse()
False>>> Mat(RR,Integer(123456),Integer(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>>> from sage.all import *>>> MatrixSpace(GF(Integer(101)), Integer(10000)).is_finite()
True>>> MatrixSpace(QQ, Integer(2)).is_finite()
False

is_sparse()
Return whether matrices in self are sparse.
EXAMPLES:
sage: Mat(GF(2011), 10000).is_sparse()
˓→needs sage.rings.finite_rings
False
sage: Mat(GF(2011), 10000, sparse=True).is_sparse()
˓→needs sage.rings.finite_rings
True

16

#␣

#␣

Chapter 1. Matrix Spaces

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> Mat(GF(Integer(2011)), Integer(10000)).is_sparse()˓→# needs sage.rings.finite_rings
False>>> Mat(GF(Integer(2011)), Integer(10000), sparse=True).is_sparse()˓→# needs sage.rings.finite_rings
True

␣

␣

matrix(x=None, **kwds)
Create a matrix in self.
INPUT:• x – data to construct a new matrix from. See matrix()• coerce – (default: True) if False, assume without checking that the values in x 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]
>>> from sage.all import *>>> M = MatrixSpace(ZZ, Integer(2))>>> M.matrix([[Integer(1),Integer(0)],[Integer(0),-Integer(1)]])[ 1 0][ 0 -1]>>> M.matrix([Integer(1),Integer(0),Integer(0),-Integer(1)])[ 1 0][ 0 -1]>>> M.matrix([Integer(1),Integer(2),Integer(3),Integer(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 Issue #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 Ringsage: M = MatrixSpace(ZZ, 3 , 2)
sage: M
Full MatrixSpace of 3 by 2 dense matrices over Integer Ringsage: M(projection)(continues on next page)17

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Traceback (most recent call last):...
ValueError: inconsistent number of rows: should be 3 but got 2>>> from sage.all import *>>> projection = matrix(ZZ,[[Integer(1),Integer(0),Integer(0)],[Integer(0),˓→Integer(1),Integer(0)]])>>> projection[1 0 0][0 1 0]>>> projection.parent()
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring>>> M = MatrixSpace(ZZ, Integer(3) , Integer(2))>>> M
Full MatrixSpace of 3 by 2 dense matrices over Integer Ring>>> 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]
>>> from sage.all import *>>> 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>>> from sage.all import *>>> M = Mat(GF(Integer(7)), Integer(100), Integer(200))>>> M.matrix_space(Integer(5000))Full MatrixSpace of 5000 by 200 dense matrices over Finite Field of size 7>>> M.matrix_space(ncols=Integer(5000))Full MatrixSpace of 100 by 5000 dense matrices over Finite Field of size 7>>> M.matrix_space(sparse=True)
Full MatrixSpace of 100 by 200 sparse matrices over Finite Field of size 7

18

Chapter 1. Matrix Spaces

Matrices and Spaces of Matrices, Release 10.4

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>>> from sage.all import *>>> M = Mat(ZZ[ x ], Integer(200000), Integer(500000), sparse=True)>>> M.ncols()
500000ngens()
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>>> from sage.all import *>>> M = Mat(GF(Integer(7)), Integer(100), Integer(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>>> from sage.all import *>>> M = Mat(ZZ, Integer(200000), Integer(500000))>>> M.nrows()
200000one()
Return the identity matrix in self.
self must be a space of square matrices. The returned matrix is immutable. Please use copy if you wanta 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](continues on next page)19

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 0 0 1]
sage: Er = MS2.identity_matrix()
Traceback (most recent call last):...
TypeError: identity matrix must be square>>> from sage.all import *>>> MS1 = MatrixSpace(ZZ,Integer(4))>>> MS2 = MatrixSpace(QQ,Integer(3),Integer(4))>>> I = MS1.identity_matrix()>>> I[1 0 0 0][0 1 0 0][0 0 1 0][0 0 0 1]>>> Er = MS2.identity_matrix()
Traceback (most recent call last):...
TypeError: identity matrix must be squarerandom_element(density=None, *args, **kwds)
Return 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-zeroelements 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 zeromatrix.
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: 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()(continues on next page)

20

Chapter 1. Matrix Spaces

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: M = Mat(QQ, 3, sparse=True).random_element()
sage: TestSuite(M).run()˓→needs sage.libs.pari#␣sage: M = Mat(GF(9, a ), 3, sparse=True).random_element()
˓→needs sage.rings.finite_rings
sage: TestSuite(M).run()˓→needs sage.rings.finite_rings#␣#␣>>> from sage.all import *>>> M = Mat(ZZ, Integer(2), Integer(5)).random_element()>>> TestSuite(M).run()>>> M = Mat(QQ, Integer(2), Integer(5)).random_element(density=RealNumber( 0.5
˓→ ))>>> TestSuite(M).run()>>> M = Mat(QQ, Integer(3), sparse=True).random_element()>>> TestSuite(M).run()˓→needs sage.libs.pari#␣>>> M = Mat(GF(Integer(9), a ), Integer(3), sparse=True).random_element()␣˓→# needs sage.rings.finite_rings>>> TestSuite(M).run()#␣˓→needs sage.rings.finite_rings

row_space()
Return the module spanned by all rows of matrices in this matrix space. This is a free module of rank thenumber 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>>> from sage.all import *>>> M = Mat(ZZ,Integer(20),Integer(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)(continues on next page)21

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

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
01], [0 0 0], [0 0 0], [0 0 0], [1 0 0], [0 1 0], [0 0 1])
sage: M = MatrixSpace(SR, 2, 2)
˓→needs sage.symbolic
sage: tuple(M.some_elements())
˓→needs sage.symbolic([some_variable some_variable] [1 0] [0 1] [0 0] [0 0][some_variable some_variable], [0 0], [0 0], [1 0], [0 1])>>> from sage.all import *>>> M = MatrixSpace(ZZ, Integer(2), Integer(2))>>> tuple(M.some_elements())([ 0 1] [1 0] [0 1] [0 0] [0 0][-1 2], [0 0], [0 0], [1 0], [0 1])>>> M = MatrixSpace(QQ, Integer(2), Integer(3))>>> 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
01], [0 0 0], [0 0 0], [0 0 0], [1 0 0], [0 1 0], [0 0 1])>>> M = MatrixSpace(SR, Integer(2), Integer(2))˓→# needs sage.symbolic>>> tuple(M.some_elements())
˓→needs sage.symbolic([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 of self
• check – (default: True) whether to verify that theelements of gens are in self
• already_echelonized – (default: False) whether
the elements of gens are already in (not necessarily reduced) echelon form
• unitriangular – (default: False) whether the lift morphism is unitriangular• support_order – (optional) either something that can be converted into a tuple or a key function
If already_echelonized is False, then the generators are put in reduced echelon form using echelonize(), and reindexed by 0, 1, . . ..

22

Chapter 1. Matrix Spaces

Matrices and Spaces of Matrices, Release 10.4

Warning: At this point, this method only works for finite dimensional submodules and if matrices canbe echelonized over the base ring.
If in addition unitriangular is True, then the generators are made such that the coefficients of thepivots 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 𝑦𝑖 to 𝑔𝑒𝑛𝑠[𝑖].
See also:
ModulesWithBasis.ParentMethods.submodule()
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]
]
>>> from sage.all import *>>> M = MatrixSpace(QQ, Integer(2))>>> mat = M.matrix([[Integer(1), Integer(2)], [Integer(3), Integer(4)]])>>> X = M.submodule([mat], already_echelonized=True); X
Free module generated by {0} over Rational Field>>> mat2 = M.matrix([[Integer(1), Integer(0)], [-Integer(3), Integer(2)]])>>> X = M.submodule([mat, mat2])>>> [X.lift(b) for b in X.basis()][[ 1 0] [0 1][-3 2], [3 1]]>>> A = matrix([[Integer(1), Integer(1)], [Integer(0), -Integer(1)]])(continues on next page)23

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> B = matrix([[Integer(0), Integer(1)], [Integer(0), Integer(2)]])>>> X = M.submodule([A, B])>>> Xp = M.submodule([A, B], support_order=[(Integer(0),Integer(1)),␣
˓→(Integer(1),Integer(1)), (Integer(0),Integer(0))])>>> [X.lift(b) for b in X.basis()][[ 1 0] [0 1][ 0 -3], [0 2]]>>> [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>>> from sage.all import *>>> MS = MatrixSpace(GF(Integer(3)), Integer(7), Integer(10))>>> MS.transposed
Full MatrixSpace of 10 by 7 dense matrices over Finite Field of size 3>>> MS = MatrixSpace(GF(Integer(3)), Integer(7), Integer(7))>>> MS.transposed is MS
True>>> M = MatrixSpace(ZZ, Integer(2), Integer(3))>>> M.transposed
Full MatrixSpace of 3 by 2 dense matrices over Integer Ringzero()
Return the zero matrix in self.
self must be a space of square matrices. The returned matrix is immutable. Please use copy if you wanta 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

24

Chapter 1. Matrix Spaces

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> z = MatrixSpace(GF(Integer(7)), Integer(2), Integer(4)).zero_matrix(); z[0 0 0 0][0 0 0 0]>>> 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 use copy if you wanta 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>>> from sage.all import *>>> z = MatrixSpace(GF(Integer(7)), Integer(2), Integer(4)).zero_matrix(); z[0 0 0 0][0 0 0 0]>>> 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]>>> from sage.all import *>>> from sage.matrix.matrix_space import dict_to_list>>> d = {}>>> d[(Integer(0),Integer(0))] = Integer(1)>>> d[(Integer(1),Integer(1))] = Integer(2)>>> dict_to_list(d, Integer(2), Integer(2))[1, 0, 0, 2]>>> dict_to_list(d, Integer(2), Integer(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.

25

Matrices and Spaces of Matrices, Release 10.4

INPUT:• R – a base ring
• nrows – number of rows
• ncols – number of columns• sparse – (boolean) whether the matrix class should be sparse• implementation – (None or string or a matrix class) a possible implementation. See the documentationof the constructor of MatrixSpace.
EXAMPLES:
sage: from sage.matrix.matrix_space import get_matrix_classsage: get_matrix_class(ZZ, 4, 5, False, None)˓→needs sage.libs.linbox<class sage.matrix.matrix_integer_dense.Matrix_integer_dense >sage: get_matrix_class(ZZ, 4, 5, True, None)˓→needs sage.libs.linbox<class sage.matrix.matrix_integer_sparse.Matrix_integer_sparse >#␣sage: get_matrix_class(ZZ, 3, 3, False, flint )˓→needs sage.libs.linbox<class sage.matrix.matrix_integer_dense.Matrix_integer_dense >sage: get_matrix_class(ZZ, 3, 3, False, gap )˓→needs sage.libs.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)˓→needs sage.rings.finite_rings<class sage.matrix.matrix_gf2e_dense.Matrix_gf2e_dense >sage: get_matrix_class(GF(2^17), 3, 3, False, None)˓→needs sage.rings.finite_rings<class sage.matrix.matrix_generic_dense.Matrix_generic_dense >#␣sage: get_matrix_class(GF(2), 2, 2, False, m4ri )˓→needs sage.libs.m4ri<class sage.matrix.matrix_mod2_dense.Matrix_mod2_dense >sage: get_matrix_class(GF(4), 2, 2, False, m4ri )˓→needs sage.libs.m4ri sage.rings.finite_rings<class sage.matrix.matrix_gf2e_dense.Matrix_gf2e_dense >sage: get_matrix_class(GF(7), 2, 2, False, linbox-float )˓→needs sage.libs.linbox<class sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_float >sage: get_matrix_class(GF(7), 2, 2, False, linbox-double )˓→needs sage.libs.linbox<class sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_double >#␣sage: get_matrix_class(RDF, 2, 2, False, numpy )˓→needs numpy<class sage.matrix.matrix_real_double_dense.Matrix_real_double_dense >sage: get_matrix_class(CDF, 2, 3, False, numpy )˓→needs numpy sage.rings.complex_double<class sage.matrix.matrix_complex_double_dense.Matrix_complex_double_dense >

#␣

#␣

#␣

#␣

#␣

#␣

#␣

#␣

(continues on next page)

26

Chapter 1. Matrix Spaces

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: get_matrix_class(GF(25, x ), 4, 4, False, meataxe )# optional -␣˓→meataxe, needs sage.rings.finite_rings<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 < 256sage: get_matrix_class(GF(next_prime(255)), 4, 4, False, meataxe )#␣˓→needs sage.rings.finite_rings
Traceback (most recent call last):...
ValueError: meataxe matrix can only deal with finite fields of order < 256sage: get_matrix_class(ZZ, 3, 5, False, crazy_matrix )Traceback (most recent call last):...
ValueError: unknown matrix implementation crazy_matrix over Integer Ringsage: 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 )˓→needs sage.libs.linbox
Traceback (most recent call last):...
ValueError: linbox-float matrices can only deal with order < 256sage: get_matrix_class(Zmod(2**30), 2, 2, False, linbox-double )˓→needs sage.libs.linbox
Traceback (most recent call last):...
ValueError: linbox-double matrices can only deal with order < 94906266
sage: type(matrix(SR, 2, 2, 0))
˓→needs sage.symbolic<class sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense >sage: type(matrix(SR, 2, 2, 0, sparse=True))
˓→needs sage.symbolic<class sage.matrix.matrix_symbolic_sparse.Matrix_symbolic_sparse >sage: type(matrix(GF(7), 2, range(4)))˓→needs sage.libs.linbox<class sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_float >sage: type(matrix(GF(16007), 2, range(4)))˓→needs sage.libs.linbox<class sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_double >sage: type(matrix(CBF, 2, range(4)))˓→needs sage.libs.flint<class sage.matrix.matrix_complex_ball_dense.Matrix_complex_ball_dense >sage: type(matrix(GF(2), 2, range(4)))˓→needs sage.libs.m4ri<class sage.matrix.matrix_mod2_dense.Matrix_mod2_dense >sage: type(matrix(GF(64, z ), 2, range(4)))˓→needs sage.libs.m4ri sage.rings.finite_rings<class sage.matrix.matrix_gf2e_dense.Matrix_gf2e_dense >

#␣

#␣

#␣

#␣

#␣

#␣

#␣

#␣

#␣

(continues on next page)27

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: type(matrix(GF(125, z ), 2, range(4)))˓→meataxe, needs sage.rings.finite_rings<class sage.matrix.matrix_gfpn_dense.Matrix_gfpn_dense ># optional -␣

>>> from sage.all import *>>> from sage.matrix.matrix_space import get_matrix_class>>> get_matrix_class(ZZ, Integer(4), Integer(5), False, None)˓→# needs sage.libs.linbox<class sage.matrix.matrix_integer_dense.Matrix_integer_dense >>>> get_matrix_class(ZZ, Integer(4), Integer(5), True, None)˓→# needs sage.libs.linbox<class sage.matrix.matrix_integer_sparse.Matrix_integer_sparse >␣>>> get_matrix_class(ZZ, Integer(3), Integer(3), False, flint )˓→# needs sage.libs.linbox<class sage.matrix.matrix_integer_dense.Matrix_integer_dense >>>> get_matrix_class(ZZ, Integer(3), Integer(3), False, gap )˓→# needs sage.libs.gap<class sage.matrix.matrix_gap.Matrix_gap >>>> get_matrix_class(ZZ, Integer(3), Integer(3), False, generic )<class sage.matrix.matrix_generic_dense.Matrix_generic_dense >

␣

␣

␣

>>> get_matrix_class(GF(Integer(2)**Integer(15)), Integer(3), Integer(3), False,␣
˓→None)# needs sage.rings.finite_rings<class sage.matrix.matrix_gf2e_dense.Matrix_gf2e_dense >>>> get_matrix_class(GF(Integer(2)**Integer(17)), Integer(3), Integer(3), False,␣
˓→None)# needs sage.rings.finite_rings<class sage.matrix.matrix_generic_dense.Matrix_generic_dense >>>> get_matrix_class(GF(Integer(2)), Integer(2), Integer(2), False, m4ri )␣˓→# needs sage.libs.m4ri<class sage.matrix.matrix_mod2_dense.Matrix_mod2_dense >>>> get_matrix_class(GF(Integer(4)), Integer(2), Integer(2), False, m4ri )␣˓→# needs sage.libs.m4ri sage.rings.finite_rings<class sage.matrix.matrix_gf2e_dense.Matrix_gf2e_dense >>>> get_matrix_class(GF(Integer(7)), Integer(2), Integer(2), False, linbox-float
˓→ )# needs sage.libs.linbox<class sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_float >>>> get_matrix_class(GF(Integer(7)), Integer(2), Integer(2), False, linbox-double
˓→ )# needs sage.libs.linbox<class sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_double >>>> get_matrix_class(RDF, Integer(2), Integer(2), False, numpy )˓→# needs numpy<class sage.matrix.matrix_real_double_dense.Matrix_real_double_dense >>>> get_matrix_class(CDF, Integer(2), Integer(3), False, numpy )˓→# needs numpy sage.rings.complex_double<class sage.matrix.matrix_complex_double_dense.Matrix_complex_double_dense >␣␣>>> get_matrix_class(GF(Integer(25), x ), Integer(4), Integer(4), False, meataxe
˓→ )# optional - meataxe, needs sage.rings.finite_rings<class sage.matrix.matrix_gfpn_dense.Matrix_gfpn_dense >>>> get_matrix_class(IntegerModRing(Integer(3)), Integer(4), Integer(4), False,
˓→ meataxe )# optional - meataxe<class sage.matrix.matrix_gfpn_dense.Matrix_gfpn_dense >(continues on next page)

28

Chapter 1. Matrix Spaces

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> get_matrix_class(IntegerModRing(Integer(4)), Integer(4), Integer(4), False,
˓→ meataxe )Traceback (most recent call last):...
ValueError: meataxe matrix can only deal with finite fields of order < 256>>> get_matrix_class(GF(next_prime(Integer(255))), Integer(4), Integer(4), False,
˓→ meataxe )# needs sage.rings.finite_rings
Traceback (most recent call last):...
ValueError: meataxe matrix can only deal with finite fields of order < 256>>> get_matrix_class(ZZ, Integer(3), Integer(5), False, crazy_matrix )Traceback (most recent call last):...
ValueError: unknown matrix implementation crazy_matrix over Integer Ring>>> get_matrix_class(GF(Integer(3)), Integer(2), Integer(2), False, m4ri )Traceback (most recent call last):...
ValueError: m4ri matrices are only available for fields of characteristic 2
and order <= 65536>>> get_matrix_class(Zmod(Integer(2)**Integer(30)), Integer(2), Integer(2), False,˓→linbox-float )# needs sage.libs.linbox
Traceback (most recent call last):...
ValueError: linbox-float matrices can only deal with order < 256>>> get_matrix_class(Zmod(Integer(2)**Integer(30)), Integer(2), Integer(2), False,˓→linbox-double )# needs sage.libs.linbox
Traceback (most recent call last):...
ValueError: linbox-double matrices can only deal with order < 94906266>>> type(matrix(SR, Integer(2), Integer(2), Integer(0)))˓→# needs sage.symbolic<class sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense >>>> type(matrix(SR, Integer(2), Integer(2), Integer(0), sparse=True))˓→# needs sage.symbolic<class sage.matrix.matrix_symbolic_sparse.Matrix_symbolic_sparse >>>> type(matrix(GF(Integer(7)), Integer(2), range(Integer(4))))˓→# needs sage.libs.linbox<class sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_float >>>> type(matrix(GF(Integer(16007)), Integer(2), range(Integer(4))))˓→# needs sage.libs.linbox<class sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_double >>>> type(matrix(CBF, Integer(2), range(Integer(4))))˓→# needs sage.libs.flint<class sage.matrix.matrix_complex_ball_dense.Matrix_complex_ball_dense >>>> type(matrix(GF(Integer(2)), Integer(2), range(Integer(4))))˓→# needs sage.libs.m4ri<class sage.matrix.matrix_mod2_dense.Matrix_mod2_dense >>>> type(matrix(GF(Integer(64), z ), Integer(2), range(Integer(4))))˓→# needs sage.libs.m4ri sage.rings.finite_rings<class sage.matrix.matrix_gf2e_dense.Matrix_gf2e_dense >>>> type(matrix(GF(Integer(125), z ), Integer(2), range(Integer(4))))˓→# optional - meataxe, needs sage.rings.finite_rings<class sage.matrix.matrix_gfpn_dense.Matrix_gfpn_dense >

␣

␣

␣

␣

␣

␣

␣

␣

sage.matrix.matrix_space.is_MatrixSpace(x)29Matrices and Spaces of Matrices, Release 10.4

Return whether self is 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)doctest:warning...
DeprecationWarning: the function is_MatrixSpace is deprecated;
use isinstance(..., MatrixSpace) instead
See https://github.com/sagemath/sage/issues/37924 for details.
Truesage: is_MatrixSpace(A)False
sage: is_MatrixSpace(5)False>>> from sage.all import *>>> from sage.matrix.matrix_space import is_MatrixSpace>>> MS = MatrixSpace(QQ,Integer(2))>>> A = MS.random_element()>>> is_MatrixSpace(MS)doctest:warning...
DeprecationWarning: the function is_MatrixSpace is deprecated;
use isinstance(..., MatrixSpace) instead
See https://github.com/sagemath/sage/issues/37924 for details.
True>>> is_MatrixSpace(A)False>>> is_MatrixSpace(Integer(5))
False

30

Chapter 1. Matrix Spaces

CHAPTERTWOGENERAL MATRIX CONSTRUCTOR AND DISPLAY OPTIONS

sage.matrix.constructor.Matrix(*args, **kwds)
Create a matrix.
This implements the matrix constructor:
sage: matrix([[1,2],[3,4]])
[1 2]
[3 4]
>>> from sage.all import *>>> matrix([[Integer(1),Integer(2)],[Integer(3),Integer(4)]])
[1 2]
[3 4]

It also contains methods to create special types of matrices, see matrix.[tab] for more options. For example:
sage: matrix.identity(2)
[1 0]
[0 1]
>>> from sage.all import *>>> matrix.identity(Integer(2))
[1 0]
[0 1]

INPUT:The matrix() command takes the entries of a matrix, optionally preceded by a ring and the dimensions of thematrix, and returns a matrix.
The entries of a matrix can be specified as a flat list of elements, a list of lists (i.e., a list of rows), a list of Sage
vectors, a callable object, or a dictionary having positions as keys and matrix entries as values (see the examples).
If you pass in a callable object, then you must specify the number of rows and columns. You can create a matrix ofzeros by passing an empty list or the integer zero for the entries. To construct a multiple of the identity (𝑐𝐼), you
can specify square dimensions and pass in 𝑐. Calling matrix() with a Sage object may return something thatmakes sense. Calling matrix() with a NumPy array will convert the array to a matrix.
All arguments (even the positional ones) are optional.
Positional and keyword arguments:• base_ring – parent of the entries of the matrix (despite the name, this is not a priori required to be a ring).
By default, determine this from the given entries, falling back to ZZ if no entries are given.

31

Matrices and Spaces of Matrices, Release 10.4

• nrows – the number of rows in the matrix, or a finite or enumerated family of arbitrary objects that index
the rows of the matrix• ncols – the number of columns in the matrix, or a finite or enumerated family of arbitrary objects that index
the columns of the matrix• entries – see examples below.
If any of nrows, ncols, row_keys, column_keys is given as keyword argument, then none of these may
be given as positional arguments.
Keyword-only arguments:• sparse – (boolean) create a sparse matrix. This defaults to True when the entries are given as a dictionary,
otherwise defaults to False.
• row_keys – a finite or enumerated family of arbitrary objects that index the rows of the matrix• column_keys – a finite or enumerated family of arbitrary objects that index the columns of the matrix• space – matrix space which will be the parent of the output matrix. This determines base_ring, nrows,
row_keys, ncols, column_keys, and sparse.
• immutable – (boolean) make the matrix immutable. By default, the output matrix is mutable.
OUTPUT: a matrix or, more generally, a homomorphism between free modules
EXAMPLES:
sage: m = matrix(2); m; m.parent()
[0 0]
[0 0]
Full MatrixSpace of 2 by 2 dense matrices over Integer Ring>>> from sage.all import *>>> m = matrix(Integer(2)); m; m.parent()
[0 0]
[0 0]
Full MatrixSpace of 2 by 2 dense matrices over Integer Ringsage: m = matrix(2, 3); m; m.parent()[0 0 0][0 0 0]
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring>>> from sage.all import *>>> m = matrix(Integer(2), Integer(3)); m; m.parent()[0 0 0][0 0 0]
Full MatrixSpace of 2 by 3 dense matrices over Integer Ringsage: m = matrix(QQ, [[1,2,3], [4,5,6]]); m; m.parent()[1 2 3][4 5 6]
Full MatrixSpace of 2 by 3 dense matrices over Rational Field>>> from sage.all import *>>> m = matrix(QQ, [[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),˓→Integer(6)]]); m; m.parent()(continues on next page)

32

Chapter 2. General matrix Constructor and display options

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[1 2 3][4 5 6]
Full MatrixSpace of 2 by 3 dense matrices over Rational Field
sage: m = matrix(QQ, 3, 3, lambda i, j: i + j); m[0 1 2][1 2 3][2 3 4]sage: m = matrix(3, lambda i, j: i - j); m[ 0 -1 -2][ 1 0 -1]
[ 2 1 0]>>> from sage.all import *>>> m = matrix(QQ, Integer(3), Integer(3), lambda i, j: i + j); m[0 1 2][1 2 3][2 3 4]>>> m = matrix(Integer(3), lambda i, j: i - j); m[ 0 -1 -2][ 1 0 -1]
[ 2 1 0]sage: matrix(QQ, 2, 3, lambda x, y: x + y)
[0 1 2][1 2 3]sage: matrix(QQ, 5, 5, lambda x, y: (x+1) / (y+1))[ 1 1/2 1/3 1/4 1/5]
[ 2
1 2/3 1/2 2/5]
[ 3 3/2
1 3/4 3/5]
[ 4
2 4/3
1 4/5][ 5 5/2 5/3 5/4
1]>>> from sage.all import *>>> matrix(QQ, Integer(2), Integer(3), lambda x, y: x + y)
[0 1 2][1 2 3]>>> matrix(QQ, Integer(5), Integer(5), lambda x, y: (x+Integer(1)) /␣˓→(y+Integer(1)))[ 1 1/2 1/3 1/4 1/5]
[ 2
1 2/3 1/2 2/5]
[ 3 3/2
1 3/4 3/5]
[ 4
2 4/3
1 4/5][ 5 5/2 5/3 5/4
1]
sage: v1 = vector((1,2,3))
sage: v2 = vector((4,5,6))
sage: m = matrix([v1,v2]); m; m.parent()[1 2 3][4 5 6]
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring>>> from sage.all import *>>> v1 = vector((Integer(1),Integer(2),Integer(3)))(continues on next page)33

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> v2 = vector((Integer(4),Integer(5),Integer(6)))>>> m = matrix([v1,v2]); m; m.parent()[1 2 3][4 5 6]
Full MatrixSpace of 2 by 3 dense matrices over Integer Ringsage: m = matrix(QQ, 2, [1,2,3,4,5,6]); m; m.parent()[1 2 3][4 5 6]
Full MatrixSpace of 2 by 3 dense matrices over Rational Field>>> from sage.all import *>>> m = matrix(QQ, Integer(2), [Integer(1),Integer(2),Integer(3),Integer(4),˓→Integer(5),Integer(6)]); m; m.parent()[1 2 3][4 5 6]
Full MatrixSpace of 2 by 3 dense matrices over Rational Field
sage: m = matrix(QQ, 2, 3, [1,2,3,4,5,6]); m; m.parent()[1 2 3][4 5 6]
Full MatrixSpace of 2 by 3 dense matrices over Rational Field>>> from sage.all import *>>> m = matrix(QQ, Integer(2), Integer(3), [Integer(1),Integer(2),Integer(3),˓→Integer(4),Integer(5),Integer(6)]); m; m.parent()[1 2 3][4 5 6]
Full MatrixSpace of 2 by 3 dense matrices over Rational Field
sage: m = matrix({(0,1): 2, (1,1): 2/5}); m; m.parent()[ 02][ 0 2/5]
Full MatrixSpace of 2 by 2 sparse matrices over Rational Field>>> from sage.all import *>>> m = matrix({(Integer(0),Integer(1)): Integer(2), (Integer(1),Integer(1)):␣
˓→Integer(2)/Integer(5)}); m; m.parent()[ 02][ 0 2/5]
Full MatrixSpace of 2 by 2 sparse matrices over Rational Field
sage: m = matrix(QQ, 2, 3, {(1,1): 2}); m; m.parent()[0 0 0][0 2 0]
Full MatrixSpace of 2 by 3 sparse matrices over Rational Field>>> from sage.all import *>>> m = matrix(QQ, Integer(2), Integer(3), {(Integer(1),Integer(1)): Integer(2)});
˓→ m; m.parent()[0 0 0][0 2 0]
Full MatrixSpace of 2 by 3 sparse matrices over Rational Field

34

Chapter 2. General matrix Constructor and display options

Matrices and Spaces of Matrices, Release 10.4

sage: import numpy
˓→needs numpy
sage: n = numpy.array([[1,2], [3,4]], float)
˓→needs numpy
sage: m = matrix(n); m; m.parent()
˓→needs numpy[1.0 2.0][3.0 4.0]
Full MatrixSpace of 2 by 2 dense matrices over Real Double Field

#␣
#␣
#␣

>>> from sage.all import *>>> import numpy#␣˓→needs numpy>>> n = numpy.array([[Integer(1),Integer(2)], [Integer(3),Integer(4)]], float)␣˓→# needs numpy>>> m = matrix(n); m; m.parent()#␣˓→needs numpy[1.0 2.0][3.0 4.0]
Full MatrixSpace of 2 by 2 dense matrices over Real Double Field
sage: v = vector(ZZ, [1, 10, 100])
sage: m = matrix(v); m; m.parent()[ 1 10 100]
Full MatrixSpace of 1 by 3 dense matrices over Integer Ringsage: m = matrix(GF(7), v); m; m.parent()[1 3 2]
Full MatrixSpace of 1 by 3 dense matrices over Finite Field of size 7
sage: m = matrix(GF(7), 3, 1, v); m; m.parent()
[1]
[3]
[2]
Full MatrixSpace of 3 by 1 dense matrices over Finite Field of size 7>>> from sage.all import *>>> v = vector(ZZ, [Integer(1), Integer(10), Integer(100)])>>> m = matrix(v); m; m.parent()[ 1 10 100]
Full MatrixSpace of 1 by 3 dense matrices over Integer Ring>>> m = matrix(GF(Integer(7)), v); m; m.parent()[1 3 2]
Full MatrixSpace of 1 by 3 dense matrices over Finite Field of size 7>>> m = matrix(GF(Integer(7)), Integer(3), Integer(1), v); m; m.parent()
[1]
[3]
[2]
Full MatrixSpace of 3 by 1 dense matrices over Finite Field of size 7
sage: matrix(pari.mathilbert(3))˓→needs sage.libs.pari[ 1 1/2 1/3]
[1/2 1/3 1/4]
[1/3 1/4 1/5]>>> from sage.all import *>>> matrix(pari.mathilbert(Integer(3)))#␣␣(continues on next page)35

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)# needs sage.libs.pari[ 1 1/2 1/3]
[1/2 1/3 1/4]
[1/3 1/4 1/5]
˓→sage: g = graphs.PetersenGraph()˓→needs sage.graphs
sage: m = matrix(g); m; m.parent()
˓→needs sage.graphs[0 1 0 0 1 1 0 0 0 0]
[1 0 1 0 0 0 1 0 0 0]
[0 1 0 1 0 0 0 1 0 0]
[0 0 1 0 1 0 0 0 1 0]
[1 0 0 1 0 0 0 0 0 1]
[1 0 0 0 0 0 0 1 1 0]
[0 1 0 0 0 0 0 0 1 1]
[0 0 1 0 0 1 0 0 0 1]
[0 0 0 1 0 1 1 0 0 0]
[0 0 0 0 1 0 1 1 0 0]
Full MatrixSpace of 10 by 10 dense matrices over Integer Ring>>> from sage.all import *>>> g = graphs.PetersenGraph()˓→needs sage.graphs>>> m = matrix(g); m; m.parent()
˓→needs sage.graphs[0 1 0 0 1 1 0 0 0 0]
[1 0 1 0 0 0 1 0 0 0]
[0 1 0 1 0 0 0 1 0 0]
[0 0 1 0 1 0 0 0 1 0]
[1 0 0 1 0 0 0 0 0 1]
[1 0 0 0 0 0 0 1 1 0]
[0 1 0 0 0 0 0 0 1 1]
[0 0 1 0 0 1 0 0 0 1]
[0 0 0 1 0 1 1 0 0 0]
[0 0 0 0 1 0 1 1 0 0]
Full MatrixSpace of 10 by 10 dense matrices over Integer Ring

#␣
#␣

#␣
#␣

sage: matrix(ZZ, 10, 10, range(100), sparse=True).parent()
Full MatrixSpace of 10 by 10 sparse matrices over Integer Ring>>> from sage.all import *>>> matrix(ZZ, Integer(10), Integer(10), range(Integer(100)), sparse=True).
˓→parent()
Full MatrixSpace of 10 by 10 sparse matrices over Integer Ringsage: R = PolynomialRing(QQ, 9, x )sage: A = matrix(R, 3, 3, R.gens()); A[x0 x1 x2][x3 x4 x5][x6 x7 x8]
sage: det(A)-x2*x4*x6 + x1*x5*x6 + x2*x3*x7 - x0*x5*x7 - x1*x3*x8 + x0*x4*x8

36

Chapter 2. General matrix Constructor and display options

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> R = PolynomialRing(QQ, Integer(9), x )>>> A = matrix(R, Integer(3), Integer(3), R.gens()); A[x0 x1 x2][x3 x4 x5][x6 x7 x8]>>> det(A)-x2*x4*x6 + x1*x5*x6 + x2*x3*x7 - x0*x5*x7 - x1*x3*x8 + x0*x4*x8
sage: M = Matrix([[1,2,3], [4,5,6], [7,8,9]], immutable=True)
sage: M[0] = [9,9,9]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).
>>> from sage.all import *>>> M = Matrix([[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),˓→Integer(6)], [Integer(7),Integer(8),Integer(9)]], immutable=True)>>> M[Integer(0)] = [Integer(9),Integer(9),Integer(9)]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).

Using row_keys and column_keys:
sage: M = matrix([[1,2,3], [4,5,6]],....:
column_keys=[ a , b , c ], row_keys=[ u , v ]); M
Generic morphism:
From: Free module generated by { a , b , c } over Integer Ring
To:
Free module generated by { u , v } over Integer Ringsage: print(M._unicode_art_matrix())
a b cu⎛1 2 3⎞v⎝4 5 6⎠>>> from sage.all import *>>> M = matrix([[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),˓→Integer(6)]],...
column_keys=[ a , b , c ], row_keys=[ u , v ]); M
Generic morphism:
From: Free module generated by { a , b , c } over Integer Ring
To:
Free module generated by { u , v } over Integer Ring>>> print(M._unicode_art_matrix())
a b cu⎛1 2 3⎞v⎝4 5 6⎠

It is allowed to specify dimensions redundantly:
sage: M = matrix(2, 3, [[1,2,3], [4,5,6]],....:
column_keys=[ a , b , c ], row_keys=[ u , v ]); M
Generic morphism:
From: Free module generated by { a , b , c } over Integer Ring
To:
Free module generated by { u , v } over Integer Ring

37

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> M = matrix(Integer(2), Integer(3), [[Integer(1),Integer(2),Integer(3)],␣
˓→[Integer(4),Integer(5),Integer(6)]],...
column_keys=[ a , b , c ], row_keys=[ u , v ]); M
Generic morphism:
From: Free module generated by { a , b , c } over Integer Ring
To:
Free module generated by { u , v } over Integer Ring

AUTHORS:• William Stein: Initial implementation• Jason Grout (2008-03): almost a complete rewrite, with bits and pieces from the original implementation• Jeroen Demeyer (2016-02-05): major clean up, see Issue #20015 and Issue #20016• Jeroen Demeyer (2018-02-20): completely rewritten using MatrixArgs, see Issue #24742
sage.matrix.constructor.matrix(*args, **kwds)
Create a matrix.
This implements the matrix constructor:
sage: matrix([[1,2],[3,4]])
[1 2]
[3 4]
>>> from sage.all import *>>> matrix([[Integer(1),Integer(2)],[Integer(3),Integer(4)]])
[1 2]
[3 4]

It also contains methods to create special types of matrices, see matrix.[tab] for more options. For example:
sage: matrix.identity(2)
[1 0]
[0 1]
>>> from sage.all import *>>> matrix.identity(Integer(2))
[1 0]
[0 1]

INPUT:The matrix() command takes the entries of a matrix, optionally preceded by a ring and the dimensions of thematrix, and returns a matrix.
The entries of a matrix can be specified as a flat list of elements, a list of lists (i.e., a list of rows), a list of Sage
vectors, a callable object, or a dictionary having positions as keys and matrix entries as values (see the examples).
If you pass in a callable object, then you must specify the number of rows and columns. You can create a matrix ofzeros by passing an empty list or the integer zero for the entries. To construct a multiple of the identity (𝑐𝐼), you
can specify square dimensions and pass in 𝑐. Calling matrix() with a Sage object may return something thatmakes sense. Calling matrix() with a NumPy array will convert the array to a matrix.
All arguments (even the positional ones) are optional.
Positional and keyword arguments:

38

Chapter 2. General matrix Constructor and display options

Matrices and Spaces of Matrices, Release 10.4

• base_ring – parent of the entries of the matrix (despite the name, this is not a priori required to be a ring).
By default, determine this from the given entries, falling back to ZZ if no entries are given.
• nrows – the number of rows in the matrix, or a finite or enumerated family of arbitrary objects that index
the rows of the matrix• ncols – the number of columns in the matrix, or a finite or enumerated family of arbitrary objects that index
the columns of the matrix• entries – see examples below.
If any of nrows, ncols, row_keys, column_keys is given as keyword argument, then none of these may
be given as positional arguments.
Keyword-only arguments:• sparse – (boolean) create a sparse matrix. This defaults to True when the entries are given as a dictionary,
otherwise defaults to False.
• row_keys – a finite or enumerated family of arbitrary objects that index the rows of the matrix• column_keys – a finite or enumerated family of arbitrary objects that index the columns of the matrix• space – matrix space which will be the parent of the output matrix. This determines base_ring, nrows,
row_keys, ncols, column_keys, and sparse.
• immutable – (boolean) make the matrix immutable. By default, the output matrix is mutable.
OUTPUT: a matrix or, more generally, a homomorphism between free modules
EXAMPLES:
sage: m = matrix(2); m; m.parent()
[0 0]
[0 0]
Full MatrixSpace of 2 by 2 dense matrices over Integer Ring>>> from sage.all import *>>> m = matrix(Integer(2)); m; m.parent()
[0 0]
[0 0]
Full MatrixSpace of 2 by 2 dense matrices over Integer Ringsage: m = matrix(2, 3); m; m.parent()[0 0 0][0 0 0]
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring>>> from sage.all import *>>> m = matrix(Integer(2), Integer(3)); m; m.parent()[0 0 0][0 0 0]
Full MatrixSpace of 2 by 3 dense matrices over Integer Ringsage: m = matrix(QQ, [[1,2,3], [4,5,6]]); m; m.parent()[1 2 3][4 5 6]
Full MatrixSpace of 2 by 3 dense matrices over Rational Field

39

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> m = matrix(QQ, [[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),˓→Integer(6)]]); m; m.parent()[1 2 3][4 5 6]
Full MatrixSpace of 2 by 3 dense matrices over Rational Field
sage: m = matrix(QQ, 3, 3, lambda i, j: i + j); m[0 1 2][1 2 3][2 3 4]sage: m = matrix(3, lambda i, j: i - j); m[ 0 -1 -2][ 1 0 -1]
[ 2 1 0]>>> from sage.all import *>>> m = matrix(QQ, Integer(3), Integer(3), lambda i, j: i + j); m[0 1 2][1 2 3][2 3 4]>>> m = matrix(Integer(3), lambda i, j: i - j); m[ 0 -1 -2][ 1 0 -1]
[ 2 1 0]sage: matrix(QQ, 2, 3, lambda x, y: x + y)
[0 1 2][1 2 3]sage: matrix(QQ, 5, 5, lambda x, y: (x+1) / (y+1))[ 1 1/2 1/3 1/4 1/5]
[ 2
1 2/3 1/2 2/5]
[ 3 3/2
1 3/4 3/5]
[ 4
2 4/3
1 4/5][ 5 5/2 5/3 5/4
1]>>> from sage.all import *>>> matrix(QQ, Integer(2), Integer(3), lambda x, y: x + y)
[0 1 2][1 2 3]>>> matrix(QQ, Integer(5), Integer(5), lambda x, y: (x+Integer(1)) /␣˓→(y+Integer(1)))[ 1 1/2 1/3 1/4 1/5]
[ 2
1 2/3 1/2 2/5]
[ 3 3/2
1 3/4 3/5]
[ 4
2 4/3
1 4/5][ 5 5/2 5/3 5/4
1]
sage: v1 = vector((1,2,3))
sage: v2 = vector((4,5,6))
sage: m = matrix([v1,v2]); m; m.parent()[1 2 3][4 5 6]
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring

40

Chapter 2. General matrix Constructor and display options

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> v1 = vector((Integer(1),Integer(2),Integer(3)))>>> v2 = vector((Integer(4),Integer(5),Integer(6)))>>> m = matrix([v1,v2]); m; m.parent()[1 2 3][4 5 6]
Full MatrixSpace of 2 by 3 dense matrices over Integer Ringsage: m = matrix(QQ, 2, [1,2,3,4,5,6]); m; m.parent()[1 2 3][4 5 6]
Full MatrixSpace of 2 by 3 dense matrices over Rational Field>>> from sage.all import *>>> m = matrix(QQ, Integer(2), [Integer(1),Integer(2),Integer(3),Integer(4),˓→Integer(5),Integer(6)]); m; m.parent()[1 2 3][4 5 6]
Full MatrixSpace of 2 by 3 dense matrices over Rational Field
sage: m = matrix(QQ, 2, 3, [1,2,3,4,5,6]); m; m.parent()[1 2 3][4 5 6]
Full MatrixSpace of 2 by 3 dense matrices over Rational Field>>> from sage.all import *>>> m = matrix(QQ, Integer(2), Integer(3), [Integer(1),Integer(2),Integer(3),˓→Integer(4),Integer(5),Integer(6)]); m; m.parent()[1 2 3][4 5 6]
Full MatrixSpace of 2 by 3 dense matrices over Rational Field
sage: m = matrix({(0,1): 2, (1,1): 2/5}); m; m.parent()[ 02][ 0 2/5]
Full MatrixSpace of 2 by 2 sparse matrices over Rational Field>>> from sage.all import *>>> m = matrix({(Integer(0),Integer(1)): Integer(2), (Integer(1),Integer(1)):␣
˓→Integer(2)/Integer(5)}); m; m.parent()[ 02][ 0 2/5]
Full MatrixSpace of 2 by 2 sparse matrices over Rational Field
sage: m = matrix(QQ, 2, 3, {(1,1): 2}); m; m.parent()[0 0 0][0 2 0]
Full MatrixSpace of 2 by 3 sparse matrices over Rational Field>>> from sage.all import *>>> m = matrix(QQ, Integer(2), Integer(3), {(Integer(1),Integer(1)): Integer(2)});
˓→ m; m.parent()[0 0 0][0 2 0]
Full MatrixSpace of 2 by 3 sparse matrices over Rational Field

41

Matrices and Spaces of Matrices, Release 10.4

sage: import numpy
˓→needs numpy
sage: n = numpy.array([[1,2], [3,4]], float)
˓→needs numpy
sage: m = matrix(n); m; m.parent()
˓→needs numpy[1.0 2.0][3.0 4.0]
Full MatrixSpace of 2 by 2 dense matrices over Real Double Field

#␣
#␣
#␣

>>> from sage.all import *>>> import numpy#␣˓→needs numpy>>> n = numpy.array([[Integer(1),Integer(2)], [Integer(3),Integer(4)]], float)␣˓→# needs numpy>>> m = matrix(n); m; m.parent()#␣˓→needs numpy[1.0 2.0][3.0 4.0]
Full MatrixSpace of 2 by 2 dense matrices over Real Double Field
sage: v = vector(ZZ, [1, 10, 100])
sage: m = matrix(v); m; m.parent()[ 1 10 100]
Full MatrixSpace of 1 by 3 dense matrices over Integer Ringsage: m = matrix(GF(7), v); m; m.parent()[1 3 2]
Full MatrixSpace of 1 by 3 dense matrices over Finite Field of size 7
sage: m = matrix(GF(7), 3, 1, v); m; m.parent()
[1]
[3]
[2]
Full MatrixSpace of 3 by 1 dense matrices over Finite Field of size 7>>> from sage.all import *>>> v = vector(ZZ, [Integer(1), Integer(10), Integer(100)])>>> m = matrix(v); m; m.parent()[ 1 10 100]
Full MatrixSpace of 1 by 3 dense matrices over Integer Ring>>> m = matrix(GF(Integer(7)), v); m; m.parent()[1 3 2]
Full MatrixSpace of 1 by 3 dense matrices over Finite Field of size 7>>> m = matrix(GF(Integer(7)), Integer(3), Integer(1), v); m; m.parent()
[1]
[3]
[2]
Full MatrixSpace of 3 by 1 dense matrices over Finite Field of size 7
sage: matrix(pari.mathilbert(3))˓→needs sage.libs.pari[ 1 1/2 1/3]
[1/2 1/3 1/4]
[1/3 1/4 1/5]>>> from sage.all import *>>> matrix(pari.mathilbert(Integer(3)))

42

#␣

␣

(continues on next page)

Chapter 2. General matrix Constructor and display options

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)# needs sage.libs.pari[ 1 1/2 1/3]
[1/2 1/3 1/4]
[1/3 1/4 1/5]
˓→sage: g = graphs.PetersenGraph()˓→needs sage.graphs
sage: m = matrix(g); m; m.parent()
˓→needs sage.graphs[0 1 0 0 1 1 0 0 0 0]
[1 0 1 0 0 0 1 0 0 0]
[0 1 0 1 0 0 0 1 0 0]
[0 0 1 0 1 0 0 0 1 0]
[1 0 0 1 0 0 0 0 0 1]
[1 0 0 0 0 0 0 1 1 0]
[0 1 0 0 0 0 0 0 1 1]
[0 0 1 0 0 1 0 0 0 1]
[0 0 0 1 0 1 1 0 0 0]
[0 0 0 0 1 0 1 1 0 0]
Full MatrixSpace of 10 by 10 dense matrices over Integer Ring>>> from sage.all import *>>> g = graphs.PetersenGraph()˓→needs sage.graphs>>> m = matrix(g); m; m.parent()
˓→needs sage.graphs[0 1 0 0 1 1 0 0 0 0]
[1 0 1 0 0 0 1 0 0 0]
[0 1 0 1 0 0 0 1 0 0]
[0 0 1 0 1 0 0 0 1 0]
[1 0 0 1 0 0 0 0 0 1]
[1 0 0 0 0 0 0 1 1 0]
[0 1 0 0 0 0 0 0 1 1]
[0 0 1 0 0 1 0 0 0 1]
[0 0 0 1 0 1 1 0 0 0]
[0 0 0 0 1 0 1 1 0 0]
Full MatrixSpace of 10 by 10 dense matrices over Integer Ring

#␣
#␣

#␣
#␣

sage: matrix(ZZ, 10, 10, range(100), sparse=True).parent()
Full MatrixSpace of 10 by 10 sparse matrices over Integer Ring>>> from sage.all import *>>> matrix(ZZ, Integer(10), Integer(10), range(Integer(100)), sparse=True).
˓→parent()
Full MatrixSpace of 10 by 10 sparse matrices over Integer Ringsage: R = PolynomialRing(QQ, 9, x )sage: A = matrix(R, 3, 3, R.gens()); A[x0 x1 x2][x3 x4 x5][x6 x7 x8]
sage: det(A)-x2*x4*x6 + x1*x5*x6 + x2*x3*x7 - x0*x5*x7 - x1*x3*x8 + x0*x4*x8

43Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> R = PolynomialRing(QQ, Integer(9), x )>>> A = matrix(R, Integer(3), Integer(3), R.gens()); A[x0 x1 x2][x3 x4 x5][x6 x7 x8]>>> det(A)-x2*x4*x6 + x1*x5*x6 + x2*x3*x7 - x0*x5*x7 - x1*x3*x8 + x0*x4*x8
sage: M = Matrix([[1,2,3], [4,5,6], [7,8,9]], immutable=True)
sage: M[0] = [9,9,9]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).
>>> from sage.all import *>>> M = Matrix([[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),˓→Integer(6)], [Integer(7),Integer(8),Integer(9)]], immutable=True)>>> M[Integer(0)] = [Integer(9),Integer(9),Integer(9)]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).

Using row_keys and column_keys:
sage: M = matrix([[1,2,3], [4,5,6]],....:
column_keys=[ a , b , c ], row_keys=[ u , v ]); M
Generic morphism:
From: Free module generated by { a , b , c } over Integer Ring
To:
Free module generated by { u , v } over Integer Ringsage: print(M._unicode_art_matrix())
a b cu⎛1 2 3⎞v⎝4 5 6⎠>>> from sage.all import *>>> M = matrix([[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),˓→Integer(6)]],...
column_keys=[ a , b , c ], row_keys=[ u , v ]); M
Generic morphism:
From: Free module generated by { a , b , c } over Integer Ring
To:
Free module generated by { u , v } over Integer Ring>>> print(M._unicode_art_matrix())
a b cu⎛1 2 3⎞v⎝4 5 6⎠

It is allowed to specify dimensions redundantly:
sage: M = matrix(2, 3, [[1,2,3], [4,5,6]],....:
column_keys=[ a , b , c ], row_keys=[ u , v ]); M
Generic morphism:
From: Free module generated by { a , b , c } over Integer Ring
To:
Free module generated by { u , v } over Integer Ring

44

Chapter 2. General matrix Constructor and display options

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> M = matrix(Integer(2), Integer(3), [[Integer(1),Integer(2),Integer(3)],␣
˓→[Integer(4),Integer(5),Integer(6)]],...
column_keys=[ a , b , c ], row_keys=[ u , v ]); M
Generic morphism:
From: Free module generated by { a , b , c } over Integer Ring
To:
Free module generated by { u , v } over Integer Ring

AUTHORS:• William Stein: Initial implementation• Jason Grout (2008-03): almost a complete rewrite, with bits and pieces from the original implementation• Jeroen Demeyer (2016-02-05): major clean up, see Issue #20015 and Issue #20016• Jeroen Demeyer (2018-02-20): completely rewritten using MatrixArgs, see Issue #24742
sage.matrix.constructor.options(*get_value, **set_value)
Global options for matrices.
OPTIONS:• format_numeric – (default: {:.{prec}}) string used for formatting floating point numbers of an(optional) precision prec; only supported for entry types implementing __format__• max_cols – (default: 49) maximum number of columns to display• max_rows – (default: 19) maximum number of rows to display• precision – (default: None) number of digits to display for floating point entries; if None, the exact
representation is used instead. This option is also set by the IPython magic %precision.
EXAMPLES:
sage: matrix.options.max_cols = 6
sage: matrix.options.max_rows = 3
sage: matrix(ZZ, 3, 6)[0 0 0 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 0 0]
sage: matrix(ZZ, 3, 7)
3 x 7 dense matrix over Integer Ring...
sage: matrix(ZZ, 4, 6)
4 x 6 dense matrix over Integer Ring...
sage: matrix.options._reset()>>> from sage.all import *>>> matrix.options.max_cols = Integer(6)>>> matrix.options.max_rows = Integer(3)>>> matrix(ZZ, Integer(3), Integer(6))[0 0 0 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 0 0]>>> matrix(ZZ, Integer(3), Integer(7))
3 x 7 dense matrix over Integer Ring...
>>> matrix(ZZ, Integer(4), Integer(6))
4 x 6 dense matrix over Integer Ring...
>>> matrix.options._reset()45

Matrices and Spaces of Matrices, Release 10.4

The precision can also be set via the IPython magic:
sage: from sage.repl.interpreter import get_test_shell
sage: shell = get_test_shell()sage: shell.run_cell( %precision 5 )%.5fsage: matrix.options.precision5
sage: A = matrix(RR, [[200/3]]); A[66.667]>>> from sage.all import *>>> from sage.repl.interpreter import get_test_shell>>> shell = get_test_shell()>>> shell.run_cell( %precision 5 )%.5f>>> matrix.options.precision5>>> A = matrix(RR, [[Integer(200)/Integer(3)]]); A[66.667]

The number format can be specified as well:sage: matrix.options.format_numeric =sage: A
[6.66667e+1]
sage: matrix.options.format_numeric =sage: A
[66.66667]
sage: matrix.options.format_numeric =sage: A[+66.667]
sage: matrix.options._reset()>>> from sage.all import *>>> matrix.options.format_numeric =>>> A[6.66667e+1]>>> matrix.options.format_numeric =>>> A[66.66667]>>> matrix.options.format_numeric =>>> A[+66.667]>>> matrix.options._reset(){:.{prec}e}{:.{prec}f}{:+.{prec}g}{:.{prec}e}{:.{prec}f}{:+.{prec}g}

See GlobalOptions for more features of these options.

46

Chapter 2. General matrix Constructor and display options

CHAPTER

THREE

CONSTRUCTORS FOR SPECIAL MATRICESThis module gathers several constructors for special, commonly used or interesting matrices. These can be reachedthrough matrix.<tab>.
For example, here is a circulant matrix of order five:sage: matrix.circulant(SR.var( a b c d e ))˓→needs sage.symbolic[a b c d e][e a b c d][d e a b c][c d e a b][b c d e a]>>> from sage.all import *>>> matrix.circulant(SR.var( a b c d e ))˓→needs sage.symbolic[a b c d e][e a b c d][d e a b c][c d e a b][b c d e a]#␣#␣

The following constructions are available:

47

Matrices and Spaces of Matrices, Release 10.4

block_diagonal_matrix()
block_matrix()
circulant()
column_matrix()
companion_matrix()
diagonal_matrix()
elementary_matrix()
hankel()hilbert()identity_matrix()
ith_to_zero_rotation_matrix()
jordan_block()lehmer()ones_matrix()
random_matrix()
random_diagonalizable_matrix()
random_echelonizable_matrix()
random_rref_matrix()
random_subspaces_matrix()
random_unimodular_matrix()
toeplitz()vandermonde()
vector_on_axis_rotation_matrix()
zero_matrix()
The Combinatorics module provides further matrix constructors, such as Hadamard matrices and Latin squares. See:• sage.combinat.matrices.hadamard_matrix• sage.combinat.matrices.latin
sage.matrix.special.block_diagonal_matrix(*sub_matrices, **kwds)
This function is available as block_diagonal_matrix(…) and matrix.block_diagonal(…).
Create a block matrix whose diagonal block entries are given by sub_matrices, with zero elsewhere.
See also block_matrix().
EXAMPLES:
sage: A = matrix(ZZ, 2, [1,2,3,4])
sage: block_diagonal_matrix(A, A)[1 2|0 0][3 4|0 0][---+---][0 0|1 2][0 0|3 4]>>> from sage.all import *>>> A = matrix(ZZ, Integer(2), [Integer(1),Integer(2),Integer(3),Integer(4)])>>> block_diagonal_matrix(A, A)[1 2|0 0][3 4|0 0][---+---][0 0|1 2][0 0|3 4]48

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

The sub-matrices need not be square:
sage: B = matrix(QQ, 2, 3, range(6))
sage: block_diagonal_matrix(~A, B)
[ -2
1|
0
0
0]
[ 3/2 -1/2|000][---------+--------------]
[
0
0|
0
1
2]
[
0
0|
3
4
5]
>>> from sage.all import *>>> B = matrix(QQ, Integer(2), Integer(3), range(Integer(6)))>>> block_diagonal_matrix(~A, B)
[ -2
1|
0
0
0]
[ 3/2 -1/2|000][---------+--------------]
[
0
0|
0
1
2]
[
0
0|
3
4
5]

sage.matrix.special.block_matrix(*args, **kwds)
This function is available as block_matrix(…) and matrix.block(…).
Return a larger matrix made by concatenating submatrices (rows first, then columns). For example, the matrix[ A B ][ C D ]

is made up of submatrices A, B, C, and D.
INPUT:The block_matrix command takes a list of submatrices to add as blocks, optionally preceded by a ring and thenumber of block rows and block columns, and returns a matrix.
The submatrices can be specified as a list of matrices (using nrows and ncols to determine their layout), or alist of lists of matrices, where each list forms a row.
• ring – the base ring
• nrows – the number of block rows
• ncols – the number of block cols
• sub_matrices – matrices (see below for syntax)• subdivide – boolean, whether or not to add subdivision information to the matrix• sparse – boolean, whether to make the resulting matrix sparse
EXAMPLES:
sage: A = matrix(QQ, 2, 2, [3,9,6,10])
sage: block_matrix([ [A, -A], [~A, 100*A] ])
[
3
9|
-3
-9]
[
6
10|
-6
-10]
[-----------+-----------][-5/12
3/8| 300900][ 1/4 -1/8| 600 1000]

49

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = matrix(QQ, Integer(2), Integer(2), [Integer(3),Integer(9),Integer(6),˓→Integer(10)])>>> block_matrix([ [A, -A], [~A, Integer(100)*A] ])
[
3
9|
-3
-9]
[
6
10|
-6
-10]
[-----------+-----------][-5/12
3/8| 300900][ 1/4 -1/8| 600 1000]

If the number of submatrices in each row is the same, you can specify the submatrices as a single list too:sage: block_matrix(2, 2, [ A, A, A, A ])[ 3 9| 3 9]
[ 6 10| 6 10][-----+-----][ 3 9| 3 9]
[ 6 10| 6 10]>>> from sage.all import *>>> block_matrix(Integer(2), Integer(2), [ A, A, A, A ])[ 3 9| 3 9]
[ 6 10| 6 10][-----+-----][ 3 9| 3 9]
[ 6 10| 6 10]

One can use constant entries:
sage: block_matrix([ [1, A], [0, 1] ])[ 1 0| 3 9]
[ 0 1| 6 10][-----+-----][ 0 0| 1 0]
[ 0 0| 0 1]>>> from sage.all import *>>> block_matrix([ [Integer(1), A], [Integer(0), Integer(1)] ])[ 1 0| 3 9]
[ 0 1| 6 10][-----+-----][ 0 0| 1 0]
[ 0 0| 0 1]

A zero entry may represent any square or non-square zero matrix:
sage: B = matrix(QQ, 1, 1, [ 1 ] )sage: C = matrix(QQ, 2, 2, [ 2, 3, 4, 5 ] )sage: block_matrix([ [B, 0], [0, C] ])[1|0 0][-+---][0|2 3][0|4 5]>>> from sage.all import *>>> B = matrix(QQ, Integer(1), Integer(1), [ Integer(1) ] )(continues on next page)

50

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> C = matrix(QQ, Integer(2), Integer(2), [ Integer(2), Integer(3), Integer(4),␣
˓→Integer(5) ] )>>> block_matrix([ [B, Integer(0)], [Integer(0), C] ])[1|0 0][-+---][0|2 3][0|4 5]One can specify the number of rows or columns as keywords too:sage: block_matrix([A, -A, ~A, 100*A], ncols=4)
[
3
9|
-3
-9|-5/12
3/8| 300
900]
[
6
10|
-6
-10| 1/4 -1/8| 600 1000]
sage: block_matrix([A, -A, ~A, 100*A], nrows=1)
[
3
9|
-3
-9|-5/12
3/8| 300
900]
[
6
10|
-6
-10| 1/4 -1/8| 600 1000]>>> from sage.all import *>>> block_matrix([A, -A, ~A, Integer(100)*A], ncols=Integer(4))
[
3
9|
-3
-9|-5/12
3/8| 300
900]
[
6
10|
-6
-10| 1/4 -1/8| 600 1000]>>> block_matrix([A, -A, ~A, Integer(100)*A], nrows=Integer(1))
[
3
9|
-3
-9|-5/12
3/8| 300
900]
[
6
10|
-6
-10| 1/4 -1/8| 600 1000]

It handles base rings nicely too:sage: R.<x> = ZZ[ x ]sage: block_matrix(2, 2, [1/2, A, 0, x-1])
[ 1/2
0|
3
9]
[
0
1/2|
6
10]
[-----------+-----------][
00|x - 10][0
0|0 x - 1]
sage: block_matrix(2, 2, [1/2, A, 0, x-1]).parent()
Full MatrixSpace of 4 by 4 dense matrices over Univariate Polynomial Ring in x␣˓→over Rational Field>>> from sage.all import *>>> R = ZZ[ x ]; (x,) = R._first_ngens(1)>>> block_matrix(Integer(2), Integer(2), [Integer(1)/Integer(2), A, Integer(0), x˓→Integer(1)])
[ 1/2
0|
3
9]
[
0
1/2|
6
10]
[-----------+-----------][
00|x - 10][0
0|0 x - 1]>>> block_matrix(Integer(2), Integer(2), [Integer(1)/Integer(2), A, Integer(0), x˓→Integer(1)]).parent()
Full MatrixSpace of 4 by 4 dense matrices over Univariate Polynomial Ring in x␣˓→over Rational Field

Subdivisions are optional. If they are disabled, the columns need not line up:
51

Matrices and Spaces of Matrices, Release 10.4

sage: B = matrix(QQ, 2, 3, range(6))
sage: block_matrix([ [~A, B], [B, ~A] ], subdivide=False)[-5/123/8
0
1
2][ 1/4 -1/8
3
4
5]
[
0
1
2 -5/12
3/8]
[
3
4
5
1/4 -1/8]>>> from sage.all import *>>> B = matrix(QQ, Integer(2), Integer(3), range(Integer(6)))>>> block_matrix([ [~A, B], [B, ~A] ], subdivide=False)[-5/123/8
0
1
2][ 1/4 -1/8
3
4
5]
[
0
1
2 -5/12
3/8]
[
3
4
5
1/4 -1/8]

Without subdivisions it also deduces dimensions for scalars if possible:
sage: C = matrix(ZZ, 1, 2, range(2))
sage: block_matrix([ [ C, 0 ], [ 3, 4 ], [ 5, 6, C ] ], subdivide=False )[0 1 0 0][3 0 4 0][0 3 0 4][5 6 0 1]>>> from sage.all import *>>> C = matrix(ZZ, Integer(1), Integer(2), range(Integer(2)))>>> block_matrix([ [ C, Integer(0) ], [ Integer(3), Integer(4) ], [ Integer(5),␣
˓→Integer(6), C ] ], subdivide=False )[0 1 0 0][3 0 4 0][0 3 0 4][5 6 0 1]

If all submatrices are sparse (unless there are none at all), the result will be a sparse matrix. Otherwise it will bedense by default. The sparse keyword can be used to override this:sage: A = Matrix(ZZ, 2, 2, [0, 1, 0, 0], sparse=True)
sage: block_matrix([ [ A ], [ A ] ]).parent()
Full MatrixSpace of 4 by 2 sparse matrices over Integer Ringsage: block_matrix([ [ A ], [ A ] ], sparse=False).parent()
Full MatrixSpace of 4 by 2 dense matrices over Integer Ring>>> from sage.all import *>>> A = Matrix(ZZ, Integer(2), Integer(2), [Integer(0), Integer(1), Integer(0),␣
˓→Integer(0)], sparse=True)>>> block_matrix([ [ A ], [ A ] ]).parent()
Full MatrixSpace of 4 by 2 sparse matrices over Integer Ring>>> block_matrix([ [ A ], [ A ] ], sparse=False).parent()
Full MatrixSpace of 4 by 2 dense matrices over Integer Ring

Consecutive zero submatrices are consolidated.
sage: B = matrix(2, range(4))
sage: C = matrix(2, 8, range(16))
sage: block_matrix(2, [[B,0,0,B],[C]], subdivide=False)[ 0 1 0 0 0 0 0 1]
(continues on next page)

52

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[ 2
[ 0
[ 8

3 0 0 0 0 2 3]
1 2 3 4 5 6 7]
9 10 11 12 13 14 15]>>> from sage.all import *>>> B = matrix(Integer(2), range(Integer(4)))>>> C = matrix(Integer(2), Integer(8), range(Integer(16)))>>> block_matrix(Integer(2), [[B,Integer(0),Integer(0),B],[C]], subdivide=False)[ 0 1 0 0 0 0 0 1]
[ 2 3 0 0 0 0 2 3]
[ 0 1 2 3 4 5 6 7]
[ 8 9 10 11 12 13 14 15]

Ambiguity is not tolerated.
sage: B = matrix(2, range(4))
sage: C = matrix(2, 8, range(16))
sage: block_matrix(2, [[B,0,B,0],[C]], subdivide=False)
Traceback (most recent call last):...
ValueError: insufficient information to determine submatrix widths>>> from sage.all import *>>> B = matrix(Integer(2), range(Integer(4)))>>> C = matrix(Integer(2), Integer(8), range(Integer(16)))>>> block_matrix(Integer(2), [[B,Integer(0),B,Integer(0)],[C]], subdivide=False)
Traceback (most recent call last):...
ValueError: insufficient information to determine submatrix widths

Giving only a flat list of submatrices does not work:
sage: A = matrix(2, 3, range(6))
sage: B = matrix(3, 3, range(9))
sage: block_matrix([A, A, B, B])
Traceback (most recent call last):...
ValueError: must specify either nrows or ncols>>> from sage.all import *>>> A = matrix(Integer(2), Integer(3), range(Integer(6)))>>> B = matrix(Integer(3), Integer(3), range(Integer(9)))>>> block_matrix([A, A, B, B])
Traceback (most recent call last):...
ValueError: must specify either nrows or ncols

sage.matrix.special.circulant(v, sparse=None)
This function is available as circulant(…) and matrix.circulant(…).
Return the circulant matrix specified by its 1st row 𝑣
A circulant 𝑛 × 𝑛 matrix specified by the 1st row 𝑣 = (𝑣0 ...𝑣𝑛−1 ) is the matrix (𝑐𝑖𝑗 )0≤𝑖,𝑗≤𝑛−1 , where 𝑐𝑖𝑗 =𝑣𝑗−𝑖 mod 𝑏 .
INPUT:

53

Matrices and Spaces of Matrices, Release 10.4

• v – a list or a vector of values• sparse – None by default; if sparse is set to True, the output will be sparse. Respectively, setting it toFalse produces dense output. If sparse is not set, and if v is a vector, the output sparsity is determinedby the sparsity of v; else, the output will be dense.
EXAMPLES:
sage: v = [1,2,3,4,8]
sage: matrix.circulant(v)[1 2 3 4 8][8 1 2 3 4]
[4 8 1 2 3]
[3 4 8 1 2]
[2 3 4 8 1]
sage: m = matrix.circulant(vector(GF(3),[0,1,-1],sparse=True)); m[0 1 2][2 0 1][1 2 0]sage: m.is_sparse()
True>>> from sage.all import *>>> v = [Integer(1),Integer(2),Integer(3),Integer(4),Integer(8)]>>> matrix.circulant(v)[1 2 3 4 8][8 1 2 3 4]
[4 8 1 2 3]
[3 4 8 1 2]
[2 3 4 8 1]>>> m = matrix.circulant(vector(GF(Integer(3)),[Integer(0),Integer(1),˓→Integer(1)],sparse=True)); m[0 1 2][2 0 1][1 2 0]>>> m.is_sparse()
Truesage.matrix.special.column_matrix(*args, **kwds)
This function is available as column_matrix(…) and matrix.column(…).
Construct a matrix, and then swap rows for columns and columns for rows.
Note: Linear algebra in Sage favors rows over columns. So, generally, when creating a matrix, input vectors andlists are treated as rows. This function is a convenience that turns around this convention when creating a matrix.
If you are not familiar with the usual matrix() constructor, you might want to consider it first.
INPUT:
Inputs are almost exactly the same as for the matrix() constructor, which are documented there. But see examples below for how dimensions are handled.
OUTPUT:
Output is exactly the transpose of what the matrix() constructor would return. In other words, the matrix
constructor builds a matrix and then this function exchanges rows for columns, and columns for rows.
EXAMPLES:

54

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

The most compelling use of this function is when you have a collection of lists or vectors that you would like tobecome the columns of a matrix. In almost any other situation, the matrix () constructor can probably do thejob just as easily, or easier.
sage: col_1 = [1,2,3]
sage: col_2 = [4,5,6]
sage: column_matrix([col_1, col_2])
[1 4]
[2 5]
[3 6]
sage: v1 = vector(QQ, [10, 20])
sage: v2 = vector(QQ, [30, 40])
sage: column_matrix(QQ, [v1, v2])
[10 30][20 40]>>> from sage.all import *>>> col_1 = [Integer(1),Integer(2),Integer(3)]>>> col_2 = [Integer(4),Integer(5),Integer(6)]>>> column_matrix([col_1, col_2])
[1 4]
[2 5]
[3 6]
>>> v1 = vector(QQ, [Integer(10), Integer(20)])>>> v2 = vector(QQ, [Integer(30), Integer(40)])>>> column_matrix(QQ, [v1, v2])
[10 30][20 40]If you only specify one dimension along with a flat list of entries, then it will be the number of columns in the result(which is different from the behavior of the matrix constructor).
sage: column_matrix(ZZ, 8, range(24))[ 0 3 6 9 12 15 18 21][ 1 4 7 10 13 16 19 22][ 2 5 8 11 14 17 20 23]>>> from sage.all import *>>> column_matrix(ZZ, Integer(8), range(Integer(24)))[ 0 3 6 9 12 15 18 21][ 1 4 7 10 13 16 19 22][ 2 5 8 11 14 17 20 23]

And when you specify two dimensions, then they should be number of columns first, then the number of rows,
which is the reverse of how they would be specified for the matrix constructor.
sage: column_matrix(QQ, 5, 3, range(15))[ 0 3 6 9 12][ 1 4 7 10 13][ 2 5 8 11 14]>>> from sage.all import *>>> column_matrix(QQ, Integer(5), Integer(3), range(Integer(15)))[ 0 3 6 9 12](continues on next page)55

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[ 1
[ 2

4
5

7 10 13]
8 11 14]

And a few unproductive, but illustrative, examples.
sage: A = matrix(ZZ, 3, 4, range(12))
sage: B = column_matrix(ZZ, 3, 4, range(12))
sage: A == B.transpose()True
sage: A = matrix(QQ, 7, 12, range(84))
sage: A == column_matrix(A.columns())
Truesage: A = column_matrix(QQ, matrix(ZZ, 3, 2, range(6)) )sage: A[0 2 4][1 3 5]sage: A.parent()
Full MatrixSpace of 2 by 3 dense matrices over Rational Field>>> from sage.all import *>>> A = matrix(ZZ, Integer(3), Integer(4), range(Integer(12)))>>> B = column_matrix(ZZ, Integer(3), Integer(4), range(Integer(12)))>>> A == B.transpose()
True>>> A = matrix(QQ, Integer(7), Integer(12), range(Integer(84)))>>> A == column_matrix(A.columns())
True>>> A = column_matrix(QQ, matrix(ZZ, Integer(3), Integer(2), range(Integer(6))) )>>> A[0 2 4][1 3 5]>>> A.parent()
Full MatrixSpace of 2 by 3 dense matrices over Rational Field

sage.matrix.special.companion_matrix(poly, format='right')
This function is available as companion_matrix(…) and matrix.companion(…).
Create a companion matrix from a monic polynomial.
INPUT:• poly – a univariate polynomial, or an iterable containing the coefficients of a polynomial, with low-degree
coefficients first. The polynomial (or the polynomial implied by the coefficients) must be monic. In otherwords, the leading coefficient must be one. A symbolic expression that might also be a polynomial is notproper input, see examples below.
• format – (default: ‘right’); specifies one of four variations of a companion matrix. Allowable values are‘right’, ‘left’, ‘top’ and ‘bottom’, which indicates which border of the matrix contains the negatives of thecoefficients.
OUTPUT:
A square matrix with a size equal to the degree of the polynomial. The returned matrix has ones above, or below
the diagonal, and the negatives of the coefficients along the indicated border of the matrix (excepting the leading

56

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

one coefficient). See the first examples below for precise illustrations.
EXAMPLES:
Each of the four possibilities. Notice that the coefficients are specified and their negatives become the entries ofthe matrix. The leading one must be given, but is not used. The permutation matrix P is the identity matrix, withthe columns reversed. The last three statements test the general relationships between the four variants.
sage: poly = [-2, -3, -4, -5, -6, 1]
sage: R = companion_matrix(poly, format= right ); R
[0 0 0 0 2]
[1 0 0 0 3]
[0 1 0 0 4]
[0 0 1 0 5]
[0 0 0 1 6]
sage: L = companion_matrix(poly, format= left ); L
[6 1 0 0 0]
[5 0 1 0 0]
[4 0 0 1 0]
[3 0 0 0 1]
[2 0 0 0 0]
sage: B = companion_matrix(poly, format= bottom ); B
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]
[2 3 4 5 6]sage: T = companion_matrix(poly, format= top ); T
[6 5 4 3 2]
[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
sage: perm = Permutation([5, 4, 3, 2, 1])
sage: P = perm.to_matrix()
sage: L == P*R*P
True
sage: B == R.transpose()True
sage: T == P*R.transpose()*P
True>>> from sage.all import *>>> poly = [-Integer(2), -Integer(3), -Integer(4), -Integer(5), -Integer(6),␣
˓→Integer(1)]>>> R = companion_matrix(poly, format= right ); R
[0 0 0 0 2]
[1 0 0 0 3]
[0 1 0 0 4]
[0 0 1 0 5]
[0 0 0 1 6]>>> L = companion_matrix(poly, format= left ); L
[6 1 0 0 0]
[5 0 1 0 0]
[4 0 0 1 0]
[3 0 0 0 1]
[2 0 0 0 0](continues on next page)57

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> B = companion_matrix(poly, format= bottom ); B
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]
[2 3 4 5 6]>>> T = companion_matrix(poly, format= top ); T
[6 5 4 3 2]
[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]>>> perm = Permutation([Integer(5), Integer(4), Integer(3), Integer(2),␣
˓→Integer(1)])>>> P = perm.to_matrix()>>> L == P*R*P
True>>> B == R.transpose()
True>>> T == P*R.transpose()*PTrue

A polynomial may be used as input, however a symbolic expression, even if it looks like a polynomial, is notregarded as such when used as input to this routine. Obtaining the list of coefficients from a symbolic polynomial
is one route to the companion matrix.
sage: x = polygen(QQ, x )sage: p = x^3 - 4*x^2 + 8*x - 12sage: companion_matrix(p)[ 0 0 12]
[ 1 0 -8]
[ 0 1 4]sage: # needs sage.symbolic
sage: y = var( y )sage: q = y^3 - 2*y + 1
sage: companion_matrix(q)Traceback (most recent call last):...
TypeError: input must be a polynomial (not a symbolic expression, see docstring),
or other iterable, not y^3 - 2*y + 1
sage: coeff_list = [q(y=0)] + [q.coefficient(y^k)....:
for k in range(1, q.degree(y) + 1)]
sage: coeff_list[1, -2, 0, 1]
sage: companion_matrix(coeff_list)[ 0 0 -1]
[ 1 0 2][ 0 1 0]>>> from sage.all import *>>> x = polygen(QQ, x )>>> p = x**Integer(3) - Integer(4)*x**Integer(2) + Integer(8)*x - Integer(12)>>> companion_matrix(p)[ 0 0 12]
(continues on next page)

58

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[ 1
[ 0

0 -8]
1 4]

>>> # needs sage.symbolic>>> y = var( y )>>> q = y**Integer(3) - Integer(2)*y + Integer(1)>>> companion_matrix(q)Traceback (most recent call last):...
TypeError: input must be a polynomial (not a symbolic expression, see docstring),
or other iterable, not y^3 - 2*y + 1>>> coeff_list = [q(y=Integer(0))] + [q.coefficient(y**k)...
for k in range(Integer(1), q.degree(y) + Integer(1))]>>> coeff_list[1, -2, 0, 1]>>> companion_matrix(coeff_list)[ 0 0 -1]
[ 1 0 2][ 0 1 0]The minimal polynomial of a companion matrix is equal to the polynomial used to create it. Used in a block
diagonal construction, they can be used to create matrices with any desired minimal polynomial, or characteristic
polynomial.
sage: t = polygen(QQ, t )sage: p = t^12 - 7*t^4 + 28*t^2 - 456
sage: C = companion_matrix(p, format= top )sage: q = C.minpoly(var= t ); q˓→needs sage.libs.parit^12 - 7*t^4 + 28*t^2 - 456
sage: p == q˓→needs sage.libs.pari
True

#␣

#␣

sage: p = t^3 + 3*t - 8sage: q = t^5 + t - 17sage: A = block_diagonal_matrix( companion_matrix(p),....:companion_matrix(p^2),....:
companion_matrix(q),....:companion_matrix(q) )sage: A.charpoly(var= t ).factor()˓→needs sage.libs.pari(t^3 + 3*t - 8)^3 * (t^5 + t - 17)^2
sage: A.minpoly(var= t ).factor()˓→needs sage.libs.pari(t^3 + 3*t - 8)^2 * (t^5 + t - 17)#␣#␣>>> from sage.all import *>>> t = polygen(QQ, t )>>> p = t**Integer(12) - Integer(7)*t**Integer(4) + Integer(28)*t**Integer(2) -␣˓→Integer(456)>>> C = companion_matrix(p, format= top )>>> q = C.minpoly(var= t ); q#␣˓→needs sage.libs.parit^12 - 7*t^4 + 28*t^2 - 456>>> p == q#␣(continues on next page)59

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)needs sage.libs.pariTrue˓→>>> p = t**Integer(3) + Integer(3)*t - Integer(8)>>> q = t**Integer(5) + t - Integer(17)>>> A = block_diagonal_matrix( companion_matrix(p),...
companion_matrix(p**Integer(2)),...
companion_matrix(q),...
companion_matrix(q) )>>> A.charpoly(var= t ).factor()˓→needs sage.libs.pari(t^3 + 3*t - 8)^3 * (t^5 + t - 17)^2>>> A.minpoly(var= t ).factor()˓→needs sage.libs.pari(t^3 + 3*t - 8)^2 * (t^5 + t - 17)#␣#␣

AUTHOR:• Rob Beezer (2011-05-19)
sage.matrix.special.diagonal_matrix(arg0=None, arg1=None, arg2=None, sparse=True)
This function is available as diagonal_matrix(…) and matrix.diagonal(…).
Return a square matrix with specified diagonal entries, and zeros elsewhere.
FORMATS:
1. diagonal_matrix(entries)
2. diagonal_matrix(nrows, entries)
3. diagonal_matrix(ring, entries)
4. diagonal_matrix(ring, nrows, entries)
INPUT:• entries – the values to place along the diagonal of the returned matrix. This may be a flat list, a flat tuple,
a vector or free module element, or a one-dimensional NumPy array.
• nrows – the size of the returned matrix, which will have an equal number of columns• ring – the ring containing the entries of the diagonal entries. This may not be specified in combination witha NumPy array.
• sparse – (default: True); whether or not the result has a sparse implementation.
OUTPUT:
A square matrix over the given ring with a size given by nrows. If the ring is not given it is inferred from thegiven entries. The values on the diagonal of the returned matrix come from entries. If the number of entries is
not enough to fill the whole diagonal, it is padded with zeros.
EXAMPLES:
We first demonstrate each of the input formats with various different ways to specify the entries.
Format 1: a flat list of entries.
sage: A = diagonal_matrix([2, 1.3, 5]); A[ 2.00000000000000 0.000000000000000 0.000000000000000][0.000000000000000 1.30000000000000 0.000000000000000](continues on next page)

60

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0.000000000000000 0.000000000000000 5.00000000000000]
sage: A.parent()
Full MatrixSpace of 3 by 3 sparse matrices over Real Field with 53 bits of␣˓→precision>>> from sage.all import *>>> A = diagonal_matrix([Integer(2), RealNumber( 1.3 ), Integer(5)]); A[ 2.00000000000000 0.000000000000000 0.000000000000000][0.000000000000000 1.30000000000000 0.000000000000000][0.000000000000000 0.000000000000000 5.00000000000000]>>> A.parent()
Full MatrixSpace of 3 by 3 sparse matrices over Real Field with 53 bits of␣˓→precision

Format 2: size specified, a tuple with initial entries. Note that a short list of entries is effectively padded with zeros.
sage: A = diagonal_matrix(3, (4, 5)); A[4 0 0][0 5 0][0 0 0]sage: A.parent()
Full MatrixSpace of 3 by 3 sparse matrices over Integer Ring>>> from sage.all import *>>> A = diagonal_matrix(Integer(3), (Integer(4), Integer(5))); A[4 0 0][0 5 0][0 0 0]>>> A.parent()
Full MatrixSpace of 3 by 3 sparse matrices over Integer Ring

Format 3: ring specified, a vector of entries.
sage: A = diagonal_matrix(QQ, vector(ZZ, [1,2,3])); A[1 0 0][0 2 0][0 0 3]sage: A.parent()
Full MatrixSpace of 3 by 3 sparse matrices over Rational Field>>> from sage.all import *>>> A = diagonal_matrix(QQ, vector(ZZ, [Integer(1),Integer(2),Integer(3)])); A[1 0 0][0 2 0][0 0 3]>>> A.parent()
Full MatrixSpace of 3 by 3 sparse matrices over Rational Field

Format 4: ring, size and list of entries.
sage: A = diagonal_matrix(FiniteField(3), 3, [2, 16]); A[2 0 0][0 1 0][0 0 0]sage: A.parent()
Full MatrixSpace of 3 by 3 sparse matrices over Finite Field of size 361

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = diagonal_matrix(FiniteField(Integer(3)), Integer(3), [Integer(2),␣
˓→Integer(16)]); A[2 0 0][0 1 0][0 0 0]>>> A.parent()
Full MatrixSpace of 3 by 3 sparse matrices over Finite Field of size 3

NumPy arrays may be used as input.
sage: # needs numpy
sage: import numpy
sage: entries = numpy.array([1.2, 5.6]); entries
array([1.2, 5.6])
sage: A = diagonal_matrix(3, entries); A[1.2 0.0 0.0]
[0.0 5.6 0.0]
[0.0 0.0 0.0]
sage: A.parent()
Full MatrixSpace of 3 by 3 sparse matrices over Real Double Field
sage: # needs numpy
sage: j = complex(0,1)
sage: entries = numpy.array([2.0+j, 8.1, 3.4+2.6*j]); entries
array([2. +1.j , 8.1+0.j , 3.4+2.6j])
sage: A = diagonal_matrix(entries); A[2.0 + 1.0*I
0.0
0.0]
[
0.0
8.1
0.0]
[
0.0
0.0 3.4 + 2.6*I]
sage: A.parent()
Full MatrixSpace of 3 by 3 sparse matrices over Complex Double Field
sage: # needs numpy
sage: entries = numpy.array([4, 5, 6])
sage: A = diagonal_matrix(entries); A[4 0 0][0 5 0][0 0 6]sage: A.parent()
Full MatrixSpace of 3 by 3 sparse matrices over Integer Ringsage: entries = numpy.array([4.1, 5.2, 6.3])
˓→needs numpy
sage: A = diagonal_matrix(ZZ, entries); A˓→needs numpy
Traceback (most recent call last):...
TypeError: unable to convert 4.1 to an element of Integer Ring#␣#␣>>> from sage.all import *>>> # needs numpy>>> import numpy>>> entries = numpy.array([RealNumber( 1.2 ), RealNumber( 5.6 )]); entries
array([1.2, 5.6])>>> A = diagonal_matrix(Integer(3), entries); A[1.2 0.0 0.0]
(continues on next page)

62

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0.0 5.6 0.0]
[0.0 0.0 0.0]>>> A.parent()
Full MatrixSpace of 3 by 3 sparse matrices over Real Double Field>>> # needs numpy>>> j = complex(Integer(0),Integer(1))>>> entries = numpy.array([RealNumber( 2.0 )+j, RealNumber( 8.1 ), RealNumber( 3.4
˓→ )+RealNumber( 2.6 )*j]); entries
array([2. +1.j , 8.1+0.j , 3.4+2.6j])>>> A = diagonal_matrix(entries); A[2.0 + 1.0*I
0.0
0.0]
[
0.0
8.1
0.0]
[
0.0
0.0 3.4 + 2.6*I]>>> A.parent()
Full MatrixSpace of 3 by 3 sparse matrices over Complex Double Field>>> # needs numpy>>> entries = numpy.array([Integer(4), Integer(5), Integer(6)])>>> A = diagonal_matrix(entries); A[4 0 0][0 5 0][0 0 6]>>> A.parent()
Full MatrixSpace of 3 by 3 sparse matrices over Integer Ring>>> entries = numpy.array([RealNumber( 4.1 ), RealNumber( 5.2 ), RealNumber( 6.3
˓→ )])# needs numpy>>> A = diagonal_matrix(ZZ, entries); A#␣˓→needs numpy
Traceback (most recent call last):...
TypeError: unable to convert 4.1 to an element of Integer Ring

By default returned matrices have a sparse implementation. This can be changed when using any of the formats.
sage: A = diagonal_matrix([1,2,3], sparse=False)
sage: A.parent()
Full MatrixSpace of 3 by 3 dense matrices over Integer Ring>>> from sage.all import *>>> A = diagonal_matrix([Integer(1),Integer(2),Integer(3)], sparse=False)>>> A.parent()
Full MatrixSpace of 3 by 3 dense matrices over Integer Ring

An empty list and no ring specified defaults to the integers.
sage: A = diagonal_matrix([])
sage: A.parent()
Full MatrixSpace of 0 by 0 sparse matrices over Integer Ring>>> from sage.all import *>>> A = diagonal_matrix([])>>> A.parent()
Full MatrixSpace of 0 by 0 sparse matrices over Integer Ring

Giving the entries improperly may first complain about not being iterable:
63

Matrices and Spaces of Matrices, Release 10.4

sage: diagonal_matrix(QQ, 5, 10)
Traceback (most recent call last):...
TypeError: sage.rings.integer.Integer

object is not iterable>>> from sage.all import *>>> diagonal_matrix(QQ, Integer(5), Integer(10))
Traceback (most recent call last):...
TypeError: sage.rings.integer.Integer object is not iterable

Giving too many entries will raise an error.
sage: diagonal_matrix(QQ, 3, [1,2,3,4])
Traceback (most recent call last):...
ValueError: number of diagonal matrix entries (4) exceeds the requested matrix␣˓→size (3)>>> from sage.all import *>>> diagonal_matrix(QQ, Integer(3), [Integer(1),Integer(2),Integer(3),Integer(4)])
Traceback (most recent call last):...
ValueError: number of diagonal matrix entries (4) exceeds the requested matrix␣˓→size (3)A negative size sometimes causes the error that there are too many elements.
sage: diagonal_matrix(-2, [2])Traceback (most recent call last):...
ValueError: number of diagonal matrix entries (1) exceeds the requested matrix␣˓→size (-2)>>> from sage.all import *>>> diagonal_matrix(-Integer(2), [Integer(2)])
Traceback (most recent call last):...
ValueError: number of diagonal matrix entries (1) exceeds the requested matrix␣˓→size (-2)

Types for the entries need to be iterable (tuple, list, vector, NumPy array, etc):
sage: diagonal_matrix(x^2)
˓→needs sage.symbolic
Traceback (most recent call last):...
TypeError: sage.symbolic.expression.Expression>>> from sage.all import *>>> diagonal_matrix(x**Integer(2))˓→# needs sage.symbolic
Traceback (most recent call last):...
TypeError: sage.symbolic.expression.Expression#␣object is not iterable␣

object is not iterable

AUTHOR:
64

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

• Rob Beezer (2011-01-11): total rewrite
sage.matrix.special.elementary_matrix(arg0, arg1=None, **kwds)
This function is available as elementary_matrix(…) and matrix.elementary(…).
Creates a square matrix that corresponds to a row operation or a column operation.
FORMATS:In each case, R is the base ring, and is optional. n is the size of the square matrix created. Any call may include the sparse keyword to determine the representation used. The default is False which leads to a dense
representation. We describe the matrices by their associated row operation, see the output description for more.
• elementary_matrix(R, n, row1=i, row2=j)
The matrix which swaps rows i and j.
• elementary_matrix(R, n, row1=i, scale=s)
The matrix which multiplies row i by s.
• elementary_matrix(R, n, row1=i, row2=j, scale=s)
The matrix which multiplies row j by s and adds it to row i.
Elementary matrices representing column operations are created in an entirely analogous way, replacing row1 by
col1 and replacing row2 by col2.
Specifying the ring for entries of the matrix is optional. If it is not given, and a scale parameter is provided, then aring containing the value of scale will be used. Otherwise, the ring defaults to the integers.
OUTPUT:An elementary matrix is a square matrix that is very close to being an identity matrix. If E is an elementary matrix
and A is any matrix with the same number of rows, then E*A is the result of applying a row operation to A. This is
how the three types created by this function are described. Similarly, an elementary matrix can be associated witha column operation, so if E has the same number of columns as A then A*E is the result of performing a column
operation on A.
An elementary matrix representing a row operation is created if row1 is specified, while an elementary matrix
representing a column operation is created if col1 is specified.
EXAMPLES:Over the integers, creating row operations. Recall that row and column numbering begins at zero.
sage: A = matrix(ZZ, 4, 10, range(40)); A[ 0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19][20 21 22 23 24 25 26 27 28 29][30 31 32 33 34 35 36 37 38 39]
sage: E = elementary_matrix(4, row1=1, row2=3); E[1 0 0 0][0 0 0 1][0 0 1 0][0 1 0 0]
sage: E*A
[ 0 1 2 3 4 5 6 7 8 9][30 31 32 33 34 35 36 37 38 39][20 21 22 23 24 25 26 27 28 29][10 11 12 13 14 15 16 17 18 19](continues on next page)65

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: E = elementary_matrix(4, row1=2, scale=10); E[ 1 0 0 0]
[ 0 1 0 0]
[ 0 0 10 0][ 0 0 0 1]
sage: E*A
[ 0
1
2
3
4
5
6
7
8
9]
[ 10 11 12 13 14 15 16 17 18 19][200 210 220 230 240 250 260 270 280 290]
[ 30 31 32 33 34 35 36 37 38 39]
sage: E = elementary_matrix(4, row1=2, row2=1, scale=10); E[ 1 0 0 0]
[ 0 1 0 0]
[ 0 10 1 0]
[ 0 0 0 1]
sage: E*A
[ 0
1
2
3
4
5
6
7
8
9]
[ 10 11 12 13 14 15 16 17 18 19][120 131 142 153 164 175 186 197 208 219]
[ 30 31 32 33 34 35 36 37 38 39]>>> from sage.all import *>>> A = matrix(ZZ, Integer(4), Integer(10), range(Integer(40))); A[ 0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19][20 21 22 23 24 25 26 27 28 29][30 31 32 33 34 35 36 37 38 39]>>> E = elementary_matrix(Integer(4), row1=Integer(1), row2=Integer(3)); E[1 0 0 0][0 0 0 1][0 0 1 0][0 1 0 0]>>> E*A[ 0 1 2 3 4 5 6 7 8 9][30 31 32 33 34 35 36 37 38 39][20 21 22 23 24 25 26 27 28 29][10 11 12 13 14 15 16 17 18 19]>>> E = elementary_matrix(Integer(4), row1=Integer(2), scale=Integer(10)); E[ 1 0 0 0]
[ 0 1 0 0]
[ 0 0 10 0][ 0 0 0 1]>>> E*A
[ 0
1
2
3
4
5
6
7
8
9]
[ 10 11 12 13 14 15 16 17 18 19][200 210 220 230 240 250 260 270 280 290]
[ 30 31 32 33 34 35 36 37 38 39]>>> E = elementary_matrix(Integer(4), row1=Integer(2), row2=Integer(1),␣
˓→scale=Integer(10)); E[ 1 0 0 0]
[ 0 1 0 0]
[ 0 10 1 0]
(continues on next page)

66

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 0 0 0 1]>>> E*A
[ 0
1
2
3
4
5
6
7
8
9]
[ 10 11 12 13 14 15 16 17 18 19][120 131 142 153 164 175 186 197 208 219]
[ 30 31 32 33 34 35 36 37 38 39]

Over the rationals, now as column operations. Recall that row and column numbering begins at zero. Checks now
have the elementary matrix on the right.
sage: A = matrix(QQ, 5, 4, range(20)); A[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11][12 13 14 15][16 17 18 19]
sage: E = elementary_matrix(QQ, 4, col1=1, col2=3); E[1 0 0 0][0 0 0 1][0 0 1 0][0 1 0 0]
sage: A*E
[ 0 3 2 1]
[ 4 7 6 5]
[ 8 11 10 9][12 15 14 13][16 19 18 17]
sage: E = elementary_matrix(QQ, 4, col1=2, scale=1/2); E
[ 1
0
0
0]
[ 0
1
0
0]
[ 0
0 1/2
0]
[ 0
0
0
1]
sage: A*E
[ 0 1 1 3]
[ 4 5 3 7]
[ 8 9 5 11][12 13 7 15][16 17 9 19]
sage: E = elementary_matrix(QQ, 4, col1=2, col2=1, scale=10); E[ 1 0 0 0]
[ 0 1 10 0][ 0 0 1 0]
[ 0 0 0 1]
sage: A*E
[ 0
1 12
3]
[ 4
5 56
7]
[ 8
9 100 11]
[ 12 13 144 15][ 16 17 188 19]>>> from sage.all import *>>> A = matrix(QQ, Integer(5), Integer(4), range(Integer(20))); A[ 0 1 2 3]
(continues on next page)67

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 4 5 6 7]
[ 8 9 10 11][12 13 14 15][16 17 18 19]>>> E = elementary_matrix(QQ, Integer(4), col1=Integer(1), col2=Integer(3)); E[1 0 0 0][0 0 0 1][0 0 1 0][0 1 0 0]>>> A*E[ 0 3 2 1]
[ 4 7 6 5]
[ 8 11 10 9][12 15 14 13][16 19 18 17]>>> E = elementary_matrix(QQ, Integer(4), col1=Integer(2), scale=Integer(1)/˓→Integer(2)); E
[ 1
0
0
0]
[ 0
1
0
0]
[ 0
0 1/2
0]
[ 0
0
0
1]
>>> A*E[ 0 1 1 3]
[ 4 5 3 7]
[ 8 9 5 11][12 13 7 15][16 17 9 19]>>> E = elementary_matrix(QQ, Integer(4), col1=Integer(2), col2=Integer(1),␣
˓→scale=Integer(10)); E[ 1 0 0 0]
[ 0 1 10 0][ 0 0 1 0]
[ 0 0 0 1]>>> A*E
[ 0
1 12
3]
[ 4
5 56
7]
[ 8
9 100 11]
[ 12 13 144 15][ 16 17 188 19]

An elementary matrix is always nonsingular. Then repeated row operations can be represented by products ofelementary matrices, and this product is again nonsingular. If row operations are to preserve fundamental propertiesof a matrix (like rank), we do not allow scaling a row by zero. Similarly, the corresponding elementary matrix is
not constructed. Also, we do not allow adding a multiple of a row to itself, since this could also lead to a new zerorow.
sage: A = matrix(QQ, 4, 10, range(40)); A[ 0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19][20 21 22 23 24 25 26 27 28 29][30 31 32 33 34 35 36 37 38 39]
sage: E1 = elementary_matrix(QQ, 4, row1=0, row2=1)(continues on next page)

68

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: E2 = elementary_matrix(QQ, 4, row1=3, row2=0, scale=100)
sage: E = E2*E1
sage: E.is_singular()False
sage: E*A
[ 10
11
12
13
14
15
16
17
18
19]
[
0
1
2
3
4
5
6
7
8
9]
[ 20
21
22
23
24
25
26
27
28
29]
[1030 1131 1232 1333 1434 1535 1636 1737 1838 1939]
sage: E3 = elementary_matrix(QQ, 4, row1=3, scale=0)
Traceback (most recent call last):...
ValueError: scale parameter of row of elementary matrix must be non-zerosage: E4 = elementary_matrix(QQ, 4, row1=3, row2=3, scale=12)
Traceback (most recent call last):...
ValueError: cannot add a multiple of a row to itself>>> from sage.all import *>>> A = matrix(QQ, Integer(4), Integer(10), range(Integer(40))); A[ 0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19][20 21 22 23 24 25 26 27 28 29][30 31 32 33 34 35 36 37 38 39]>>> E1 = elementary_matrix(QQ, Integer(4), row1=Integer(0), row2=Integer(1))>>> E2 = elementary_matrix(QQ, Integer(4), row1=Integer(3), row2=Integer(0),␣
˓→scale=Integer(100))>>> E = E2*E1>>> E.is_singular()False>>> E*A
[ 10
11
12
13
14
15
16
17
18
19]
[
0
1
2
3
4
5
6
7
8
9]
[ 20
21
22
23
24
25
26
27
28
29]
[1030 1131 1232 1333 1434 1535 1636 1737 1838 1939]>>> E3 = elementary_matrix(QQ, Integer(4), row1=Integer(3), scale=Integer(0))
Traceback (most recent call last):...
ValueError: scale parameter of row of elementary matrix must be non-zero>>> E4 = elementary_matrix(QQ, Integer(4), row1=Integer(3), row2=Integer(3),␣
˓→scale=Integer(12))
Traceback (most recent call last):...
ValueError: cannot add a multiple of a row to itself

If the ring is not specified, and a scale parameter is given, the base ring for the matrix is chosen to contain the scaleparameter. Otherwise, if no ring is given, the default is the integers.
sage: E = elementary_matrix(4, row1=1, row2=3)
sage: E.parent()
Full MatrixSpace of 4 by 4 dense matrices over Integer Ring
(continues on next page)69

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: E = elementary_matrix(4, row1=1, scale=4/3)
sage: E.parent()
Full MatrixSpace of 4 by 4 dense matrices over Rational Field
sage: # needs sage.symbolic
sage: E = elementary_matrix(4, row1=1, scale=I)
sage: E.parent()
Full MatrixSpace of 4 by 4 dense matrices overNumber Field in I with defining polynomial x^2 + 1 with I = 1*I
sage: # needs sage.rings.complex_double sage.symbolic
sage: E = elementary_matrix(4, row1=1, scale=CDF(I))
sage: E.parent()
Full MatrixSpace of 4 by 4 dense matrices over Complex Double Field
sage: # needs sage.rings.number_field sage.symbolic
sage: E = elementary_matrix(4, row1=1, scale=QQbar(I))
sage: E.parent()
Full MatrixSpace of 4 by 4 dense matrices over Algebraic Field>>> from sage.all import *>>> E = elementary_matrix(Integer(4), row1=Integer(1), row2=Integer(3))>>> E.parent()
Full MatrixSpace of 4 by 4 dense matrices over Integer Ring>>> E = elementary_matrix(Integer(4), row1=Integer(1), scale=Integer(4)/˓→Integer(3))>>> E.parent()
Full MatrixSpace of 4 by 4 dense matrices over Rational Field>>> # needs sage.symbolic>>> E = elementary_matrix(Integer(4), row1=Integer(1), scale=I)>>> E.parent()
Full MatrixSpace of 4 by 4 dense matrices overNumber Field in I with defining polynomial x^2 + 1 with I = 1*I>>> # needs sage.rings.complex_double sage.symbolic>>> E = elementary_matrix(Integer(4), row1=Integer(1), scale=CDF(I))>>> E.parent()
Full MatrixSpace of 4 by 4 dense matrices over Complex Double Field>>> # needs sage.rings.number_field sage.symbolic>>> E = elementary_matrix(Integer(4), row1=Integer(1), scale=QQbar(I))>>> E.parent()
Full MatrixSpace of 4 by 4 dense matrices over Algebraic Field

Returned matrices have a dense implementation by default, but a sparse implementation may be requested.
sage: E = elementary_matrix(4, row1=0, row2=1)
sage: E.is_dense()
True
sage: E = elementary_matrix(4, row1=0, row2=1, sparse=True)
sage: E.is_sparse()
True

70

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> E = elementary_matrix(Integer(4), row1=Integer(0), row2=Integer(1))>>> E.is_dense()
True>>> E = elementary_matrix(Integer(4), row1=Integer(0), row2=Integer(1),␣
˓→sparse=True)>>> E.is_sparse()
True

And the ridiculously small cases. The zero-row matrix cannot be built since then there are no rows to manipulate.
sage: elementary_matrix(QQ, 1, row1=0, row2=0)[1]
sage: elementary_matrix(QQ, 0, row1=0, row2=0)
Traceback (most recent call last):...
ValueError: size of elementary matrix must be 1 or greater, not 0>>> from sage.all import *>>> elementary_matrix(QQ, Integer(1), row1=Integer(0), row2=Integer(0))[1]>>> elementary_matrix(QQ, Integer(0), row1=Integer(0), row2=Integer(0))
Traceback (most recent call last):...
ValueError: size of elementary matrix must be 1 or greater, not 0

AUTHOR:• Rob Beezer (2011-03-04)
sage.matrix.special.hankel(c, r=None, ring=None)
This function is available as hankel(…) and matrix.hankel(…).
Return a Hankel matrix of given first column and whose elements are zero below the first anti-diagonal.
The Hankel matrix is symmetric and constant across the anti-diagonals, with elements
𝐻𝑖𝑗 = 𝑣𝑖+𝑗−1 ,𝑖 = 1, . . . , 𝑚, 𝑗 = 1, . . . , 𝑛,where the vector 𝑣𝑖 = 𝑐𝑖 for 𝑖 = 1, . . . , 𝑚 and 𝑣𝑚+𝑖 = 𝑟𝑖 for 𝑖 = 1, . . . , 𝑛 − 1 completely determines the Hankel
matrix. If the last row, 𝑟, is not given, the Hankel matrix is square by default and 𝑟 = 0. For more information see
the Wikipedia article Hankel_matrix.
INPUT:• c – vector, first column of the Hankel matrix• r – vector (default: None), last row of the Hankel matrix, from the second to the last column• ring – base ring (default: None) of the resulting matrix
EXAMPLES:
A Hankel matrix with symbolic entries:
sage: matrix.hankel(SR.var( a, b, c, d, e ))˓→needs sage.symbolic[a b c d e][b c d e 0]#␣(continues on next page)71

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[c d e 0 0]
[d e 0 0 0]
[e 0 0 0 0]>>> from sage.all import *>>> matrix.hankel(SR.var( a, b, c, d, e ))˓→needs sage.symbolic[a b c d e][b c d e 0]
[c d e 0 0]
[d e 0 0 0]
[e 0 0 0 0]#␣

We can also pass the elements of the last row, starting at the second column:
sage: matrix.hankel(SR.var( a, b, c, d, e ), SR.var( f, g, h, i ))˓→needs sage.symbolic[a b c d e][b c d e f]
[c d e f g]
[d e f g h][e f g h i]#␣>>> from sage.all import *>>> matrix.hankel(SR.var( a, b, c, d, e ), SR.var( f, g, h, i ))˓→needs sage.symbolic[a b c d e][b c d e f]
[c d e f g]
[d e f g h][e f g h i]#␣A third order Hankel matrix in the integers:
sage: matrix.hankel([1, 2, 3])[1 2 3][2 3 0][3 0 0]>>> from sage.all import *>>> matrix.hankel([Integer(1), Integer(2), Integer(3)])[1 2 3][2 3 0][3 0 0]The second argument allows to customize the last row:sage: matrix.hankel([1..3], [7..10])[ 1 2 3 7 8]
[ 2 3 7 8 9]
[ 3 7 8 9 10]>>> from sage.all import *>>> matrix.hankel((ellipsis_range(Integer(1),Ellipsis,Integer(3))), (ellipsis_
˓→range(Integer(7),Ellipsis,Integer(10))))(continues on next page)

72

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[ 1
[ 2
[ 3

2
3
7

3
7
8

7 8]
8 9]
9 10]

sage.matrix.special.hilbert(dim, ring=Rational Field)
This function is available as hilbert(…) and matrix.hilbert(…).
Return a Hilbert matrix of the given dimension.
The 𝑛 dimensional Hilbert matrix is a square matrix with entries being unit fractions,
𝐻𝑖𝑗 =

1
,
𝑖+𝑗−1

𝑖, 𝑗 = 1, . . . , 𝑛.

For more information see the Wikipedia article Hilbert_matrix.
INPUT:• dim – integer, the dimension of the Hilbert matrix• ring – base ring (default: \QQ) of the resulting matrix
EXAMPLES:
sage: matrix.hilbert(5)[ 1 1/2 1/3 1/4 1/5]
[1/2 1/3 1/4 1/5 1/6]
[1/3 1/4 1/5 1/6 1/7]
[1/4 1/5 1/6 1/7 1/8]
[1/5 1/6 1/7 1/8 1/9]>>> from sage.all import *>>> matrix.hilbert(Integer(5))[ 1 1/2 1/3 1/4 1/5]
[1/2 1/3 1/4 1/5 1/6]
[1/3 1/4 1/5 1/6 1/7]
[1/4 1/5 1/6 1/7 1/8]
[1/5 1/6 1/7 1/8 1/9]

sage.matrix.special.identity_matrix(ring, n=0, sparse=False)
This function is available as identity_matrix(…) and matrix.identity(…).
Return the 𝑛 × 𝑛 identity matrix over the given ring.
The default ring is the integers.
EXAMPLES:
sage: M = identity_matrix(QQ, 2); M
[1 0]
[0 1]
sage: M.parent()
Full MatrixSpace of 2 by 2 dense matrices over Rational Field
sage: M = identity_matrix(2); M
[1 0]
[0 1]
sage: M.parent()
Full MatrixSpace of 2 by 2 dense matrices over Integer Ringsage: M.is_mutable()(continues on next page)73

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)True
sage: M = identity_matrix(3, sparse=True); M[1 0 0][0 1 0][0 0 1]
sage: M.parent()
Full MatrixSpace of 3 by 3 sparse matrices over Integer Ringsage: M.is_mutable()True>>> from sage.all import *>>> M = identity_matrix(QQ, Integer(2)); M
[1 0]
[0 1]
>>> M.parent()
Full MatrixSpace of 2 by 2 dense matrices over Rational Field>>> M = identity_matrix(Integer(2)); M
[1 0]
[0 1]
>>> M.parent()
Full MatrixSpace of 2 by 2 dense matrices over Integer Ring>>> M.is_mutable()
True>>> M = identity_matrix(Integer(3), sparse=True); M[1 0 0][0 1 0][0 0 1]>>> M.parent()
Full MatrixSpace of 3 by 3 sparse matrices over Integer Ring>>> M.is_mutable()True

sage.matrix.special.ith_to_zero_rotation_matrix(v, i, ring=None)
This function is available as ith_to_zero_rotation_matrix(…) and matrix.ith_to_zero_rotation(…).
Return a rotation matrix that sends the i-th coordinates of the vector v to zero by doing a rotation with the (i-1)-thcoordinate.
INPUT:• v – vector• i – integer• ring – ring (default: None) of the resulting matrix
OUTPUT:
A matrix
EXAMPLES:
sage: from sage.matrix.constructor import ith_to_zero_rotation_matrix
sage: v = vector((1,2,3))
sage: ith_to_zero_rotation_matrix(v, 2)
˓→needs sage.symbolic
[
1
0
0]
[
0 2/13*sqrt(13) 3/13*sqrt(13)][0 -3/13*sqrt(13) 2/13*sqrt(13)]#␣(continues on next page)

74

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: ith_to_zero_rotation_matrix(v, 2) * v
˓→needs sage.symbolic(1, sqrt(13), 0)>>> from sage.all import *>>> from sage.matrix.constructor import ith_to_zero_rotation_matrix>>> v = vector((Integer(1),Integer(2),Integer(3)))>>> ith_to_zero_rotation_matrix(v, Integer(2))˓→# needs sage.symbolic
[
1
0
0]
[
0 2/13*sqrt(13) 3/13*sqrt(13)][0 -3/13*sqrt(13) 2/13*sqrt(13)]>>> ith_to_zero_rotation_matrix(v, Integer(2)) * v
˓→# needs sage.symbolic(1, sqrt(13), 0)
sage: ith_to_zero_rotation_matrix(v, 0)
˓→needs sage.symbolic[ 3/10*sqrt(10)0 -1/10*sqrt(10)][01
0][ 1/10*sqrt(10)0 3/10*sqrt(10)]sage: ith_to_zero_rotation_matrix(v, 1)
˓→needs sage.symbolic[ 1/5*sqrt(5) 2/5*sqrt(5)0][-2/5*sqrt(5) 1/5*sqrt(5)
0]
[
0
0
1]
sage: ith_to_zero_rotation_matrix(v, 2)
˓→needs sage.symbolic
[
1
0
0]
[
0 2/13*sqrt(13) 3/13*sqrt(13)][0 -3/13*sqrt(13) 2/13*sqrt(13)]>>> from sage.all import *>>> ith_to_zero_rotation_matrix(v, Integer(0))˓→# needs sage.symbolic[ 3/10*sqrt(10)0 -1/10*sqrt(10)][01
0][ 1/10*sqrt(10)0 3/10*sqrt(10)]>>> ith_to_zero_rotation_matrix(v, Integer(1))˓→# needs sage.symbolic[ 1/5*sqrt(5) 2/5*sqrt(5)0][-2/5*sqrt(5) 1/5*sqrt(5)
0]
[
0
0
1]
>>> ith_to_zero_rotation_matrix(v, Integer(2))˓→# needs sage.symbolic
[
1
0
0]
[
0 2/13*sqrt(13) 3/13*sqrt(13)][0 -3/13*sqrt(13) 2/13*sqrt(13)]sage: ith_to_zero_rotation_matrix(v, 0) * v
˓→needs sage.symbolic(0, 2, sqrt(10))
sage: ith_to_zero_rotation_matrix(v, 1) * v
˓→needs sage.symbolic(sqrt(5), 0, 3)

#␣

␣

␣

#␣

#␣

#␣

␣

␣

␣

#␣

#␣

(continues on next page)75

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: ith_to_zero_rotation_matrix(v, 2) * v
˓→needs sage.symbolic(1, sqrt(13), 0)>>> from sage.all import *>>> ith_to_zero_rotation_matrix(v, Integer(0)) * v
˓→# needs sage.symbolic(0, 2, sqrt(10))>>> ith_to_zero_rotation_matrix(v, Integer(1)) * v
˓→# needs sage.symbolic(sqrt(5), 0, 3)>>> ith_to_zero_rotation_matrix(v, Integer(2)) * v
˓→# needs sage.symbolic(1, sqrt(13), 0)

#␣

␣

␣

␣

Other ring:sage: ith_to_zero_rotation_matrix(v, 2, ring=RR)[ 1.00000000000000 0.000000000000000 0.000000000000000][ 0.000000000000000 0.554700196225229 0.832050294337844][ 0.000000000000000 -0.832050294337844 0.554700196225229]
sage: ith_to_zero_rotation_matrix(v, 2, ring=RDF)
[
1.0
0.0
0.0]
[
0.0 0.5547001962252291 0.8320502943378437][
0.0 -0.8320502943378437 0.5547001962252291]>>> from sage.all import *>>> ith_to_zero_rotation_matrix(v, Integer(2), ring=RR)[ 1.00000000000000 0.000000000000000 0.000000000000000][ 0.000000000000000 0.554700196225229 0.832050294337844][ 0.000000000000000 -0.832050294337844 0.554700196225229]>>> ith_to_zero_rotation_matrix(v, Integer(2), ring=RDF)
[
1.0
0.0
0.0]
[
0.0 0.5547001962252291 0.8320502943378437][
0.0 -0.8320502943378437 0.5547001962252291]

On the symbolic ring:sage: # needs sage.symbolic
sage: x,y,z = var( x,y,z )sage: v = vector((x,y,z))
sage: ith_to_zero_rotation_matrix(v, 2)
[
1
0
0]
[
0 y/sqrt(y^2 + z^2) z/sqrt(y^2 + z^2)][
0 -z/sqrt(y^2 + z^2) y/sqrt(y^2 + z^2)]
sage: ith_to_zero_rotation_matrix(v, 2) * v(x, y^2/sqrt(y^2 + z^2) + z^2/sqrt(y^2 + z^2), 0)>>> from sage.all import *>>> # needs sage.symbolic>>> x,y,z = var( x,y,z )>>> v = vector((x,y,z))>>> ith_to_zero_rotation_matrix(v, Integer(2))
[
1
0
0]
[
0 y/sqrt(y^2 + z^2) z/sqrt(y^2 + z^2)](continues on next page)

76

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[
0 -z/sqrt(y^2 + z^2) y/sqrt(y^2 + z^2)]>>> ith_to_zero_rotation_matrix(v, Integer(2)) * v(x, y^2/sqrt(y^2 + z^2) + z^2/sqrt(y^2 + z^2), 0)

AUTHORS:
Sébastien Labbé (April 2010)sage.matrix.special.jordan_block(eigenvalue, size, sparse=False)
This function is available as jordan_block(…) and matrix.jordan_block(…).
Return the Jordan block for the given eigenvalue with given size.
INPUT:• eigenvalue – eigenvalue for the diagonal entries of the block• size – size of the square matrix• sparse – (default: False); if True, return a sparse matrix
EXAMPLES:
sage: jordan_block(5, 3)[5 1 0][0 5 1][0 0 5]>>> from sage.all import *>>> jordan_block(Integer(5), Integer(3))[5 1 0][0 5 1][0 0 5]sage.matrix.special.lehmer(ring, n=0)This function is available as lehmer(…) and matrix.lehmer(…).
Return the 𝑛 × 𝑛 Lehmer matrix.
The default ring is the rationals.
Element (𝑖, 𝑗) in the Lehmer matrix is 𝑚𝑖𝑛(𝑖, 𝑗)/𝑚𝑎𝑥(𝑖, 𝑗).
See Wikipedia article Lehmer_matrix.
EXAMPLES:
sage: matrix.lehmer(3)[ 1 1/2 1/3]
[1/2
1 2/3][1/3 2/3
1]>>> from sage.all import *>>> matrix.lehmer(Integer(3))[ 1 1/2 1/3]
[1/2
1 2/3][1/3 2/3
1]77

Matrices and Spaces of Matrices, Release 10.4

sage.matrix.special.matrix_method(func=None, name=None)
Allows a function to be tab-completed on the global matrix constructor object.
INPUT:• *function – a single argument. The function that is being decorated.
• **kwds – a single optional keyword argument name=<string>. The name of the corresponding methodin the global matrix constructor object. If not given, it is derived from the function name.
EXAMPLES:
sage: from sage.matrix.constructor import matrix_method
sage: def foo_matrix(n): return matrix.diagonal(range(n))
sage: matrix_method(foo_matrix)<function foo_matrix at ...>
sage: matrix.foo(5)[0 0 0 0 0]
[0 1 0 0 0]
[0 0 2 0 0]
[0 0 0 3 0]
[0 0 0 0 4]
sage: matrix_method(foo_matrix, name= bar )<function foo_matrix at ...>
sage: matrix.bar(3)[0 0 0][0 1 0][0 0 2]>>> from sage.all import *>>> from sage.matrix.constructor import matrix_method>>> def foo_matrix(n): return matrix.diagonal(range(n))>>> matrix_method(foo_matrix)<function foo_matrix at ...>>>> matrix.foo(Integer(5))[0 0 0 0 0]
[0 1 0 0 0]
[0 0 2 0 0]
[0 0 0 3 0]
[0 0 0 0 4]>>> matrix_method(foo_matrix, name= bar )<function foo_matrix at ...>>>> matrix.bar(Integer(3))[0 0 0][0 1 0][0 0 2]sage.matrix.special.ones_matrix(ring, nrows=None, ncols=None, sparse=False)
This function is available as ones_matrix(…) and matrix.ones(…).
Return a matrix with all entries equal to 1.
CALL FORMATS:
In each case, the optional keyword sparse can be used.
1. ones_matrix(ring, nrows, ncols)
2. ones_matrix(ring, nrows)
3. ones_matrix(nrows, ncols)
78

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

4. ones_matrix(nrows)
INPUT:• ring – (default: ZZ); base ring for the matrix.
• nrows – number of rows in the matrix.
• ncols – number of columns in the matrix. If omitted, defaults to the number of rows, producing a squarematrix.
• sparse – (default: False); if True creates a sparse representation.
OUTPUT:
A matrix of size nrows by ncols over the ring with every entry equal to 1. While the result is far from sparse,
you may wish to choose a sparse representation when mixing this matrix with other sparse matrices.
EXAMPLES:
A call specifying the ring and the size.
sage: M= ones_matrix(QQ, 2, 5); M[1 1 1 1 1]
[1 1 1 1 1]
sage: M.parent()
Full MatrixSpace of 2 by 5 dense matrices over Rational Field>>> from sage.all import *>>> M= ones_matrix(QQ, Integer(2), Integer(5)); M[1 1 1 1 1]
[1 1 1 1 1]>>> M.parent()
Full MatrixSpace of 2 by 5 dense matrices over Rational Field

Without specifying the number of columns, the result is square.
sage: M = ones_matrix(RR, 2); M[1.00000000000000 1.00000000000000][1.00000000000000 1.00000000000000]
sage: M.parent()
Full MatrixSpace of 2 by 2 dense matrices over Real Field with 53 bits of␣˓→precision>>> from sage.all import *>>> M = ones_matrix(RR, Integer(2)); M[1.00000000000000 1.00000000000000][1.00000000000000 1.00000000000000]>>> M.parent()
Full MatrixSpace of 2 by 2 dense matrices over Real Field with 53 bits of␣˓→precision

The ring defaults to the integers if not given.
sage: M = ones_matrix(2, 3); M[1 1 1][1 1 1]
sage: M.parent()
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring

79

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> M = ones_matrix(Integer(2), Integer(3)); M[1 1 1][1 1 1]>>> M.parent()
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring

A lone integer input produces a square matrix over the integers.
sage: M = ones_matrix(3); M[1 1 1][1 1 1][1 1 1]
sage: M.parent()
Full MatrixSpace of 3 by 3 dense matrices over Integer Ring>>> from sage.all import *>>> M = ones_matrix(Integer(3)); M[1 1 1][1 1 1][1 1 1]>>> M.parent()
Full MatrixSpace of 3 by 3 dense matrices over Integer Ring

The result can have a sparse implementation.
sage: M = ones_matrix(3, 1, sparse=True); M
[1]
[1]
[1]
sage: M.parent()
Full MatrixSpace of 3 by 1 sparse matrices over Integer Ring>>> from sage.all import *>>> M = ones_matrix(Integer(3), Integer(1), sparse=True); M
[1]
[1]
[1]
>>> M.parent()
Full MatrixSpace of 3 by 1 sparse matrices over Integer Ring

Giving just a ring will yield an error.
sage: ones_matrix(CC)Traceback (most recent call last):...
ValueError: constructing an all ones matrix requires at least one dimension>>> from sage.all import *>>> ones_matrix(CC)Traceback (most recent call last):...
ValueError: constructing an all ones matrix requires at least one dimension

sage.matrix.special.random_diagonalizable_matrix(parent, eigenvalues=None,dimensions=None)
This function is available as random_diagonalizable_matrix(…) and matrix.random_diagonalizable(…).
80

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

Create a random matrix that diagonalizes nicely.
To be used as a teaching tool. Return matrices have only real eigenvalues.
INPUT:
If eigenvalues and dimensions are not specified in a list, they will be assigned randomly.
• parent – the desired size of the square matrix.
• eigenvalues – the list of desired eigenvalues (default=None).
• dimensions – the list of dimensions corresponding to each eigenspace (default=None).
OUTPUT:
A square, diagonalizable, matrix with only integer entries. The eigenspaces of this matrix, if computed by hand,
give basis vectors with only integer entries.
Note:
It is easiest to use this function via a call to the random_matrix() function with thealgorithm= diagonalizable keyword. We provide one example accessing this function directly, while
the remainder will use this more general function.
EXAMPLES:
A diagonalizable matrix, size 5.
sage: from sage.matrix.constructor import random_diagonalizable_matrix
sage: matrix_space = sage.matrix.matrix_space.MatrixSpace(QQ, 5)
sage: A = random_diagonalizable_matrix(matrix_space)sage: # needs sage.rings.number_fieldsage: eigenvalues = A.eigenvalues()
sage: S = A.right_eigenmatrix()[1]sage: eigenvalues2 = (S.inverse()*A*S).diagonal()
sage: sorted(eigenvalues) == sorted(eigenvalues2)
True>>> from sage.all import *>>> from sage.matrix.constructor import random_diagonalizable_matrix>>> matrix_space = sage.matrix.matrix_space.MatrixSpace(QQ, Integer(5))>>> A = random_diagonalizable_matrix(matrix_space)>>> # needs sage.rings.number_field>>> eigenvalues = A.eigenvalues()>>> S = A.right_eigenmatrix()[Integer(1)]>>> eigenvalues2 = (S.inverse()*A*S).diagonal()>>> sorted(eigenvalues) == sorted(eigenvalues2)
True

A diagonalizable matrix with eigenvalues and dimensions designated, with a check that if eigenvectors were calculated by hand entries would all be integers.
sage: eigenvalues = [ZZ.random_element() for _ in range(3)]sage: B = random_matrix(QQ, 6, algorithm= diagonalizable ,....:eigenvalues=eigenvalues, dimensions=[2,3,1])
sage: all(x in ZZ for x in (B-(-12*identity_matrix(6))).rref().list())
True
sage: all(x in ZZ for x in (B-(4*identity_matrix(6))).rref().list())(continues on next page)81

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)True
sage: all(x in ZZ for x in (B-(6*identity_matrix(6))).rref().list())
True
sage: # needs sage.rings.number_fieldsage: S = B.right_eigenmatrix()[1]sage: eigenvalues2 = (S.inverse()*B*S).diagonal()
sage: all(e in eigenvalues for e in eigenvalues2)
True>>> from sage.all import *>>> eigenvalues = [ZZ.random_element() for _ in range(Integer(3))]>>> B = random_matrix(QQ, Integer(6), algorithm= diagonalizable ,...
eigenvalues=eigenvalues, dimensions=[Integer(2),Integer(3),˓→Integer(1)])>>> all(x in ZZ for x in (B-(-Integer(12)*identity_matrix(Integer(6)))).rref().
˓→list())
True>>> all(x in ZZ for x in (B-(Integer(4)*identity_matrix(Integer(6)))).rref().
˓→list())
True>>> all(x in ZZ for x in (B-(Integer(6)*identity_matrix(Integer(6)))).rref().
˓→list())
True>>> # needs sage.rings.number_field>>> S = B.right_eigenmatrix()[Integer(1)]>>> eigenvalues2 = (S.inverse()*B*S).diagonal()>>> all(e in eigenvalues for e in eigenvalues2)
True

Todo: Modify the routine to allow for complex eigenvalues.
AUTHOR:
Billy Wonderly (2010-07)
sage.matrix.special.random_echelonizable_matrix(parent, rank, upper_bound=None,
max_tries=100)
This function is available as random_echelonizable_matrix(…) and matrix.random_echelonizable(…).
Generate a matrix of a desired size and rank, over a desired ring, whose reduced row-echelon form has only integral
values.
INPUT:• parent – A matrix space specifying the base ring, dimensions and representation (dense/sparse) for the
result. The base ring must be exact.
• rank – Rank of result, i.e the number of non-zero rows in the reduced row echelon form.
• upper_bound – If designated, size control of the matrix entries is desired. Set upper_bound to 1 morethan the maximum value entries can achieve. If None, no size control occurs. But see the warning below.
(default: None)• max_tries – If designated, number of tries used to generate each new random row; only matters whenupper_bound!=None. Used to prevent endless looping. (default: 100)82

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

OUTPUT:
A matrix not in reduced row-echelon form with the desired dimensions and properties.
Warning: When upper_bound is set, it is possible for this constructor to fail with a ValueError.
This may happen when the upper_bound, rank and/or matrix dimensions are all so small that it becomes
infeasible or unlikely to create the requested matrix. If you must have this routine return successfully, do not
set upper_bound.

Note:
It is easiest to use this function via a call to the random_matrix() function with thealgorithm= echelonizable keyword. We provide one example accessing this function directly, while
the remainder will use this more general function.
EXAMPLES:
Generated matrices have the desired dimensions, rank and entry size. The matrix in reduced row-echelon form has
only integer entries.
sage: from sage.matrix.constructor import random_echelonizable_matrix
sage: matrix_space = sage.matrix.matrix_space.MatrixSpace(QQ, 5, 6)
sage: A = random_echelonizable_matrix(matrix_space, rank=4, upper_bound=40)
sage: A.rank()
4sage: max(map(abs,A.list())) < 40Truesage: A.rref() == A.rref().change_ring(ZZ)
True>>> from sage.all import *>>> from sage.matrix.constructor import random_echelonizable_matrix>>> matrix_space = sage.matrix.matrix_space.MatrixSpace(QQ, Integer(5),␣
˓→Integer(6))>>> A = random_echelonizable_matrix(matrix_space, rank=Integer(4), upper_
˓→bound=Integer(40))>>> A.rank()
4>>> max(map(abs,A.list())) < Integer(40)True>>> A.rref() == A.rref().change_ring(ZZ)
True

An example with default settings (i.e. no entry size control).
sage: C = random_matrix(QQ, 6, 7, algorithm= echelonizable , rank=5)
sage: C.rank()
5sage: C.rref() == C.rref().change_ring(ZZ)
True>>> from sage.all import *>>> C = random_matrix(QQ, Integer(6), Integer(7), algorithm= echelonizable ,␣˓→rank=Integer(5))>>> C.rank()
5(continues on next page)83

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> C.rref() == C.rref().change_ring(ZZ)
True

A matrix without size control may have very large entry sizes.
sage: D = random_matrix(ZZ, 7, 8, algorithm= echelonizable , rank=6); D[
1
28-35 -178 -239 -284
778]
[
4
9
37 -163 -827 -1111 -1324 3624][
56
21-88 -454 -607 -708 1951]
[
-4
-5
-22
97
491
656
779 -2140][
4413-55 -283 -377 -436 1206][
4
11
43 -194 -982 -1319 -1576 4310]
[
-1
-2
-13
59
294
394
481 -1312]# random>>> from sage.all import *>>> D = random_matrix(ZZ, Integer(7), Integer(8), algorithm= echelonizable ,␣˓→rank=Integer(6)); D# random[
1
2
8-35 -178 -239 -284
778]
[
4
9
37 -163 -827 -1111 -1324 3624][
56
21-88 -454 -607 -708 1951]
[
-4
-5
-22
97
491
656
779 -2140][
4413-55 -283 -377 -436 1206][
4
11
43 -194 -982 -1319 -1576 4310]
[
-1
-2
-13
59
294
394
481 -1312]

Matrices can be generated over any exact ring.
sage: # needs sage.rings.finite_rings
sage: F.<a> = GF(2^3)
sage: B = random_matrix(F, 4, 5, algorithm= echelonizable , rank=4,....:
upper_bound=None)sage: B.rank()
4sage: B.base_ring() is F
True>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> F = GF(Integer(2)**Integer(3), names=( a ,)); (a,) = F._first_ngens(1)>>> B = random_matrix(F, Integer(4), Integer(5), algorithm= echelonizable ,␣˓→rank=Integer(4),...
upper_bound=None)>>> B.rank()
4>>> B.base_ring() is F
TrueSquare matrices over ZZ or QQ with full rank are always unimodular.
sage: E = random_matrix(QQ, 7, 7, algorithm= echelonizable , rank=7)
sage: det(E)1sage: E = random_matrix(ZZ, 7, 7, algorithm= echelonizable , rank=7)
sage: det(E)184Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> E = random_matrix(QQ, Integer(7), Integer(7), algorithm= echelonizable ,␣˓→rank=Integer(7))>>> det(E)1>>> E = random_matrix(ZZ, Integer(7), Integer(7), algorithm= echelonizable ,␣˓→rank=Integer(7))>>> det(E)
1

AUTHOR:
Billy Wonderly (2010-07)
sage.matrix.special.random_matrix(ring, nrows, ncols=None, algorithm='randomize',
implementation=None, *args, **kwds)
This function is available as random_matrix(…) and matrix.random(…).
Return a random matrix with entries in a specified ring, and possibly with additional properties.
INPUT:• ring – base ring for entries of the matrix• nrows – Integer; number of rows
• ncols – (default: None); number of columns; if None defaults to nrows• algorithm – (default: randomize); determines what properties the matrix will have. See examples
below for possible additional arguments.
– randomize – create a matrix of random elements from the base ring, possibly controlling the density
of non-zero entries.
– echelon_form – creates a matrix in echelon form
– echelonizable – creates a matrix that has a predictable echelon form
– subspaces – creates a matrix whose four subspaces, when explored, have reasonably sized, integral
valued, entries.
– unimodular – creates a matrix of determinant 1.
– diagonalizable – creates a diagonalizable matrix whose eigenvectors, if computed by hand, will
have only integer entries.
• implementation – (None or string or a matrix class) a possible implementation. See the documentationof the constructor of MatrixSpace.
• *args, **kwds – arguments and keywords to describe additional properties. See more detailed documentation below.
Warning:Matrices generated are not uniformly distributed. For unimodular matrices over finite
field this function does not even generate all of them: for example Matrix.random(GF(3), 2,
algorithm= unimodular ) never generates [[2,0],[0,2]]. This function is made for teaching
purposes.

85

Matrices and Spaces of Matrices, Release 10.4

Warning: An upper bound on the absolute value of the entries may be set when the algorithm is echelonizable or unimodular. In these cases it is possible for this constructor to fail with a ValueError.
If you must have this routine return successfully, do not set upper_bound. This behavior can be partiallycontrolled by a max_tries keyword.

Note:
When constructing matrices with random entries and no additional properties (i.e.
whenalgorithm= randomize ), most of the randomness is controlled by the random_element method forelements of the base ring of the matrix, so the documentation of that method may be relevant or useful.
EXAMPLES:
Random integer matrices. With no arguments, the majority of the entries are zero, -1, and 1, and rarely “large.”
sage: from collections import defaultdict
sage: total_count = 0
sage: dic = defaultdict(Integer)
sage: def add_samples(*args, **kwds):....:
global dic, total_count....:for _ in range(100):....:A = random_matrix(*args, **kwds)....:
for a in A.list():....:dic[a] += 1....:
total_count += 1.0
sage: expected = lambda n : 2 / (5*abs(n)*(abs(n) + 1)) if n != 0 else 1/5
sage: expected(0)1/5
sage: expected(0) == expected(1) == expected(-1)
Truesage: expected(100)
1/25250
sage: add_samples(ZZ, 5, 5)
sage: while not all(abs(dic[a]/total_count - expected(a)) < 0.001 for a in dic):....:
add_samples(ZZ, 5, 5)>>> from sage.all import *>>> from collections import defaultdict>>> total_count = Integer(0)>>> dic = defaultdict(Integer)>>> def add_samples(*args, **kwds):...
global dic, total_count...
for _ in range(Integer(100)):...
A = random_matrix(*args, **kwds)...
for a in A.list():...
dic[a] += Integer(1)...
total_count += RealNumber( 1.0 )>>> expected = lambda n : Integer(2) / (Integer(5)*abs(n)*(abs(n) + Integer(1)))␣
˓→if n != Integer(0) else Integer(1)/Integer(5)>>> expected(Integer(0))
1/5>>> expected(Integer(0)) == expected(Integer(1)) == expected(-Integer(1))
True>>> expected(Integer(100))(continues on next page)

86

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

1/25250>>> add_samples(ZZ, Integer(5), Integer(5))>>> while not all(abs(dic[a]/total_count - expected(a)) < RealNumber( 0.001 ) for␣
˓→a in dic):...
add_samples(ZZ, Integer(5), Integer(5))

The distribution keyword set to uniform will limit values between -2 and 2.
sage: expected = lambda n : 1/5 if n in range(-2, 3) else 0sage: total_count = 0
sage: dic = defaultdict(Integer)
sage: add_samples(ZZ, 5, 5, distribution= uniform )sage: while not all(abs(dic[a]/total_count - expected(a)) < 0.001 for a in dic):....:
add_samples(ZZ, 5, 5, distribution= uniform )>>> from sage.all import *>>> expected = lambda n : Integer(1)/Integer(5) if n in range(-Integer(2),␣
˓→Integer(3)) else Integer(0)>>> total_count = Integer(0)>>> dic = defaultdict(Integer)>>> add_samples(ZZ, Integer(5), Integer(5), distribution= uniform )>>> while not all(abs(dic[a]/total_count - expected(a)) < RealNumber( 0.001 ) for␣
˓→a in dic):...
add_samples(ZZ, Integer(5), Integer(5), distribution= uniform )The x and y keywords can be used to distribute entries uniformly. When both are used x is the minimum and y is
one greater than the maximum.
sage: expected = lambda n : 1/30 if n in range(70, 100) else 0sage: total_count = 0
sage: dic = defaultdict(Integer)
sage: add_samples(ZZ, 4, 8, x=70, y=100)
sage: while not all(abs(dic[a]/total_count - expected(a)) < 0.001 for a in dic):....:
add_samples(ZZ, 4, 8, x=70, y=100)
sage: expected = lambda n : 1/10 if n in range(-5, 5) else 0sage: total_count = 0
sage: dic = defaultdict(Integer)
sage: add_samples(ZZ, 3, 7, x=-5, y=5)
sage: while not all(abs(dic[a]/total_count - expected(a)) < 0.001 for a in dic):....:
add_samples(ZZ, 3, 7, x=-5, y=5)>>> from sage.all import *>>> expected = lambda n : Integer(1)/Integer(30) if n in range(Integer(70),␣
˓→Integer(100)) else Integer(0)>>> total_count = Integer(0)>>> dic = defaultdict(Integer)>>> add_samples(ZZ, Integer(4), Integer(8), x=Integer(70), y=Integer(100))>>> while not all(abs(dic[a]/total_count - expected(a)) < RealNumber( 0.001 ) for␣
˓→a in dic):...
add_samples(ZZ, Integer(4), Integer(8), x=Integer(70), y=Integer(100))>>> expected = lambda n : Integer(1)/Integer(10) if n in range(-Integer(5),␣
˓→Integer(5)) else Integer(0)>>> total_count = Integer(0)>>> dic = defaultdict(Integer)(continues on next page)87

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> add_samples(ZZ, Integer(3), Integer(7), x=-Integer(5), y=Integer(5))>>> while not all(abs(dic[a]/total_count - expected(a)) < RealNumber( 0.001 ) for␣
˓→a in dic):...
add_samples(ZZ, Integer(3), Integer(7), x=-Integer(5), y=Integer(5))

If only x is given, then it is used as the upper bound of a range starting at 0.
sage: expected = lambda n : 1/25 if n in range(25) else 0sage: total_count = 0
sage: dic = defaultdict(Integer)
sage: add_samples(ZZ, 5, 5, x=25)
sage: while not all(abs(dic[a]/total_count - expected(a)) < 0.001 for a in dic):....:
add_samples(ZZ, 5, 5, x=25)>>> from sage.all import *>>> expected = lambda n : Integer(1)/Integer(25) if n in range(Integer(25)) else␣
˓→Integer(0)>>> total_count = Integer(0)>>> dic = defaultdict(Integer)>>> add_samples(ZZ, Integer(5), Integer(5), x=Integer(25))>>> while not all(abs(dic[a]/total_count - expected(a)) < RealNumber( 0.001 ) for␣
˓→a in dic):...
add_samples(ZZ, Integer(5), Integer(5), x=Integer(25))

To control the number of nonzero entries, use the density keyword at a value strictly below the default of 1.0.
The density keyword is used to compute the number of entries per row that will be nonzero, but the same entry
may be selected more than once. So the value provided will be an upper bound for the density of the created matrix.
Note that for a square matrix it is only necessary to set a single dimension.
sage: def add_sample(*args, **kwds):....:
global density_sum, total_count....:total_count += 1.0....:
A = random_matrix(*args, **kwds)....:
density_sum += float(A.density())
sage: # needs sage.libs.linbox (otherwise timeout)
sage: density_sum = 0.0
sage: total_count = 0.0
sage: add_sample(ZZ, 5, x=-10, y=10, density=0.75)
sage: expected_density = (1 - (4/5)^3)
sage: float(expected_density)
0.488
sage: while abs(density_sum/total_count - expected_density) > 0.001:....:
add_sample(ZZ, 5, x=-10, y=10, density=0.75)
sage: # needs sage.libs.linbox (otherwise timeout)
sage: density_sum = 0.0
sage: total_count = 0.0
sage: add_sample(ZZ, 5, x=20, y=30, density=0.75)
sage: while abs(density_sum/total_count - expected_density) > 0.001:....:
add_sample(ZZ, 5, x=20, y=30, density=0.75)
sage: # needs sage.libs.linbox (otherwise timeout)
sage: density_sum = 0.0
sage: total_count = 0.0
sage: add_sample(ZZ, 100, x=20, y=30, density=0.75)(continues on next page)

88

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: expected_density = (1 - (99/100)^75)
sage: float(expected_density)
0.529...
sage: while abs(density_sum/total_count - expected_density) > 0.001:....:
add_sample(ZZ, 100, x=20, y=30, density=0.75)>>> from sage.all import *>>> def add_sample(*args, **kwds):...
global density_sum, total_count...
total_count += RealNumber( 1.0 )...
A = random_matrix(*args, **kwds)...
density_sum += float(A.density())>>> # needs sage.libs.linbox (otherwise timeout)>>> density_sum = RealNumber( 0.0 )>>> total_count = RealNumber( 0.0 )>>> add_sample(ZZ, Integer(5), x=-Integer(10), y=Integer(10), density=RealNumber(
˓→ 0.75 ))>>> expected_density = (Integer(1) - (Integer(4)/Integer(5))**Integer(3))>>> float(expected_density)
0.488>>> while abs(density_sum/total_count - expected_density) > RealNumber( 0.001 ):...
add_sample(ZZ, Integer(5), x=-Integer(10), y=Integer(10),␣
˓→density=RealNumber( 0.75 ))>>> # needs sage.libs.linbox (otherwise timeout)>>> density_sum = RealNumber( 0.0 )>>> total_count = RealNumber( 0.0 )>>> add_sample(ZZ, Integer(5), x=Integer(20), y=Integer(30), density=RealNumber(
˓→ 0.75 ))>>> while abs(density_sum/total_count - expected_density) > RealNumber( 0.001 ):...
add_sample(ZZ, Integer(5), x=Integer(20), y=Integer(30),␣
˓→density=RealNumber( 0.75 ))>>> # needs sage.libs.linbox (otherwise timeout)>>> density_sum = RealNumber( 0.0 )>>> total_count = RealNumber( 0.0 )>>> add_sample(ZZ, Integer(100), x=Integer(20), y=Integer(30), density=RealNumber(
˓→ 0.75 ))>>> expected_density = (Integer(1) - (Integer(99)/Integer(100))**Integer(75))>>> float(expected_density)
0.529...
>>> while abs(density_sum/total_count - expected_density) > RealNumber( 0.001 ):...
add_sample(ZZ, Integer(100), x=Integer(20), y=Integer(30),␣
˓→density=RealNumber( 0.75 ))For a matrix with low density it may be advisable to insist on a sparse representation, as this representation is notselected automatically.
sage: A = random_matrix(ZZ, 5, 5)
sage: A.is_sparse()
False
sage: A = random_matrix(ZZ, 5, 5, sparse=True)
sage: A.is_sparse()
True

89

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = random_matrix(ZZ, Integer(5), Integer(5))>>> A.is_sparse()
False>>> A = random_matrix(ZZ, Integer(5), Integer(5), sparse=True)>>> A.is_sparse()
True

For algorithm testing you might want to control the number of bits, say 10,000 entries, each limited to 16 bits.
sage: # needs sage.libs.linbox (otherwise timeout)
sage: A = random_matrix(ZZ, 100, 100, x=2^16); A
100 x 100 dense matrix over Integer Ring (use the .str()
˓→entries)

method to see the␣>>> from sage.all import *>>> # needs sage.libs.linbox (otherwise timeout)>>> A = random_matrix(ZZ, Integer(100), Integer(100), x=Integer(2)**Integer(16));␣
˓→A
100 x 100 dense matrix over Integer Ring (use the .str() method to see the␣˓→entries)

One can prescribe a specific matrix implementation:
sage: K.<a> = FiniteField(2^8)˓→needs sage.rings.finite_rings
sage: type(random_matrix(K, 2, 5))
˓→needs sage.libs.m4ri sage.rings.finite_rings<class sage.matrix.matrix_gf2e_dense.Matrix_gf2e_dense >sage: type(random_matrix(K, 2, 5, implementation="generic"))
˓→needs sage.rings.finite_rings<class sage.matrix.matrix_generic_dense.Matrix_generic_dense >

#␣
#␣

#␣

>>> from sage.all import *>>> K = FiniteField(Integer(2)**Integer(8), names=( a ,)); (a,) = K._first_
˓→ngens(1)# needs sage.rings.finite_rings>>> type(random_matrix(K, Integer(2), Integer(5)))˓→# needs sage.libs.m4ri sage.rings.finite_rings<class sage.matrix.matrix_gf2e_dense.Matrix_gf2e_dense >>>> type(random_matrix(K, Integer(2), Integer(5), implementation="generic"))
˓→# needs sage.rings.finite_rings<class sage.matrix.matrix_generic_dense.Matrix_generic_dense >␣␣Random rational matrices. Now num_bound and den_bound control the generation of random elements, byspecifying limits on the absolute value of numerators and denominators (respectively). Entries will be positive andnegative (map the absolute value function through the entries to get all positive values). If either the numerator or
denominator bound (or both) is not used, then the values default to 2:
sage: A = random_matrix(QQ, 2, 8, num_bound=20, den_bound=4)
sage: A.dimensions()(2, 8)
sage: type(A)<class sage.matrix.matrix_rational_dense.Matrix_rational_dense >sage: all(a.numerator() in range(-20, 21) and....:a.denominator() in range(1, 5)....:
for a in A.list())(continues on next page)

90

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)True
sage: A = random_matrix(QQ, 4, density=0.5, sparse=True)
sage: type(A)<class sage.matrix.matrix_rational_sparse.Matrix_rational_sparse >sage: A.density() <= 0.5
True
sage: A = random_matrix(QQ, 3, 10, num_bound = 99, den_bound = 99)
sage: positives = list(map(abs, A.list()))
sage: A1 = matrix(QQ, 3, 10, positives)
sage: all(abs(A.list()[i]) == A1.list()[i] for i in range(30))
True
sage: all(a.numerator() in range(100) and....:a.denominator() in range(1, 100)....:for a in A1.list())
True
sage: A = random_matrix(QQ, 4, 10, den_bound = 10)
sage: all(a.numerator() in range(-2, 3) and....:a.denominator() in range(1, 11)....:
for a in A.list())
True
sage: A = random_matrix(QQ, 4, 10)
sage: all(a.numerator() in range(-2, 3) and....:a.denominator() in range(1, 3)....:
for a in A.list())
True>>> from sage.all import *>>> A = random_matrix(QQ, Integer(2), Integer(8), num_bound=Integer(20), den_
˓→bound=Integer(4))>>> A.dimensions()(2, 8)>>> type(A)<class sage.matrix.matrix_rational_dense.Matrix_rational_dense >>>> all(a.numerator() in range(-Integer(20), Integer(21)) and...
a.denominator() in range(Integer(1), Integer(5))...
for a in A.list())
True>>> A = random_matrix(QQ, Integer(4), density=RealNumber( 0.5 ), sparse=True)>>> type(A)<class sage.matrix.matrix_rational_sparse.Matrix_rational_sparse >>>> A.density() <= RealNumber( 0.5 )True>>> A = random_matrix(QQ, Integer(3), Integer(10), num_bound = Integer(99), den_
˓→bound = Integer(99))>>> positives = list(map(abs, A.list()))>>> A1 = matrix(QQ, Integer(3), Integer(10), positives)>>> all(abs(A.list()[i]) == A1.list()[i] for i in range(Integer(30)))
True>>> all(a.numerator() in range(Integer(100)) and...
a.denominator() in range(Integer(1), Integer(100))(continues on next page)91

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

...
True

for a in A1.list())>>> A = random_matrix(QQ, Integer(4), Integer(10), den_bound = Integer(10))>>> all(a.numerator() in range(-Integer(2), Integer(3)) and...
a.denominator() in range(Integer(1), Integer(11))...
for a in A.list())
True>>> A = random_matrix(QQ, Integer(4), Integer(10))>>> all(a.numerator() in range(-Integer(2), Integer(3)) and...
a.denominator() in range(Integer(1), Integer(3))...
for a in A.list())
True

Random matrices over other rings. Several classes of matrices have specialized randomize() methods. You
can locate these with the Sage command:search_def( randomize )The default implementation of randomize() relies on the random_element() method for the base ring.
The density and sparse keywords behave as described above. Since we have a different randomisation whenusing the optional meataxe package, we have to make sure that we use the default implementation in this test:
sage: K.<a> = FiniteField(3^2)˓→needs sage.rings.finite_rings
sage: A = random_matrix(K, 2, 5, implementation= generic )˓→needs sage.rings.finite_rings
sage: type(A)<class sage.matrix.matrix_generic_dense.Matrix_generic_dense >sage: A.base_ring() is K
˓→needs sage.rings.finite_rings
True
sage: TestSuite(A).run()

#␣
#␣

#␣

sage: A = random_matrix(RR, 3, 4, density=0.66)
sage: type(A)<class sage.matrix.matrix_generic_dense.Matrix_generic_dense >sage: A.base_ring() is RR
True
sage: TestSuite(A).run()sage: A = random_matrix(ComplexField(32), 3, density=0.8, sparse=True)
sage: A.is_sparse()
True
sage: type(A)<class sage.matrix.matrix_generic_sparse.Matrix_generic_sparse >sage: A.base_ring() is ComplexField(32)True
sage: TestSuite(A).run()>>> from sage.all import *>>> K = FiniteField(Integer(3)**Integer(2), names=( a ,)); (a,) = K._first_
˓→ngens(1)# needs sage.rings.finite_rings>>> A = random_matrix(K, Integer(2), Integer(5), implementation= generic )˓→# needs sage.rings.finite_rings␣(continues on next page)

92

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> type(A)<class sage.matrix.matrix_generic_dense.Matrix_generic_dense >>>> A.base_ring() is K
˓→needs sage.rings.finite_rings
True>>> TestSuite(A).run()#␣>>> A = random_matrix(RR, Integer(3), Integer(4), density=RealNumber( 0.66 ))>>> type(A)<class sage.matrix.matrix_generic_dense.Matrix_generic_dense >>>> A.base_ring() is RR
True>>> TestSuite(A).run()>>> A = random_matrix(ComplexField(Integer(32)), Integer(3), density=RealNumber(
˓→ 0.8 ), sparse=True)>>> A.is_sparse()
True>>> type(A)<class sage.matrix.matrix_generic_sparse.Matrix_generic_sparse >>>> A.base_ring() is ComplexField(Integer(32))
True>>> TestSuite(A).run()

Random matrices in echelon form. The algorithm= echelon_form keyword, along with a requested
number of non-zero rows (num_pivots) will return a random matrix in echelon form. When the base ring is QQ
the result has integer entries. Other exact rings may be also specified.
sage: A = random_matrix(QQ, 4, 8, algorithm= echelon_form , num_pivots=3)
sage: A.base_ring()
Rational Field
sage: (A.nrows(), A.ncols())(4, 8)
sage: A in sage.matrix.matrix_space.MatrixSpace(ZZ, 4, 8)
True
sage: A.rank()
3sage: A == A.rref()True>>> from sage.all import *>>> A = random_matrix(QQ, Integer(4), Integer(8), algorithm= echelon_form , num_
˓→pivots=Integer(3))>>> A.base_ring()
Rational Field>>> (A.nrows(), A.ncols())(4, 8)>>> A in sage.matrix.matrix_space.MatrixSpace(ZZ, Integer(4), Integer(8))
True>>> A.rank()
3>>> A == A.rref()True

For more, see the documentation of the random_rref_matrix() function. In the notebook or at the Sagecommand-line, first execute the following to make this further documentation available:

93Matrices and Spaces of Matrices, Release 10.4

from sage.matrix.constructor import random_rref_matrix

Random matrices with predictable echelon forms. The algorithm= echelonizable keyword, along witha requested rank (rank) and optional size control (upper_bound) will return a random matrix in echelon form.
When the base ring is ZZ or QQ the result has integer entries, whose magnitudes can be limited by the valueof upper_bound, and the echelon form of the matrix also has integer entries. Other exact rings may be also
specified, but there is no notion of controlling the size. Square matrices of full rank generated by this function
always have determinant one, and can be constructed with the unimodular keyword.
sage: A = random_matrix(QQ, 4, 8, algorithm= echelonizable , rank=3, upper_
˓→bound=60)
sage: A.base_ring()
Rational Field
sage: (A.nrows(), A.ncols())(4, 8)
sage: A in sage.matrix.matrix_space.MatrixSpace(ZZ, 4, 8)
True
sage: A.rank()
3sage: all(abs(x)<60 for x in A.list())
True
sage: A.rref() in sage.matrix.matrix_space.MatrixSpace(ZZ, 4, 8)
True>>> from sage.all import *>>> A = random_matrix(QQ, Integer(4), Integer(8), algorithm= echelonizable ,␣˓→rank=Integer(3), upper_bound=Integer(60))>>> A.base_ring()
Rational Field>>> (A.nrows(), A.ncols())(4, 8)>>> A in sage.matrix.matrix_space.MatrixSpace(ZZ, Integer(4), Integer(8))
True>>> A.rank()
3>>> all(abs(x)<Integer(60) for x in A.list())
True>>> A.rref() in sage.matrix.matrix_space.MatrixSpace(ZZ, Integer(4), Integer(8))
True

For more, see the documentation of the random_echelonizable_matrix() function. In the notebook orat the Sage command-line, first execute the following to make this further documentation available:from sage.matrix.constructor import random_echelonizable_matrix

Random diagonalizable matrices. The algorithm= diagonalizable keyword, along with a requested
matrix size (size) and optional lists of eigenvalues (eigenvalues) and the corresponding eigenspace dimensions (dimensions) will return a random diagonalizable matrix. When the eigenvalues and dimensions
are not specified the result will have randomly generated values for both that fit with the designated size.
sage: A = random_matrix(QQ, 5, algorithm= diagonalizable , # random....:
eigenvalues=[2,3,-1], dimensions=[1,2,2]); A
sage: all(x in ZZ for x in (A - (2*identity_matrix(5))).rref().list())
True
sage: all(x in ZZ for x in (A - 3*identity_matrix(5)).rref().list())
True(continues on next page)

94

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: all(x in ZZ for x in (A - (-1)*identity_matrix(5)).rref().list())
True
sage: A.jordan_form()
˓→needs sage.combinat sage.libs.pari[ 2| 0| 0| 0| 0][--+--+--+--+--][ 0| 3| 0| 0| 0][--+--+--+--+--][ 0| 0| 3| 0| 0][--+--+--+--+--][ 0| 0| 0|-1| 0][--+--+--+--+--][ 0| 0| 0| 0|-1]#␣>>> from sage.all import *>>> A = random_matrix(QQ, Integer(5), algorithm= diagonalizable , # random...
eigenvalues=[Integer(2),Integer(3),-Integer(1)],␣
˓→dimensions=[Integer(1),Integer(2),Integer(2)]); A>>> all(x in ZZ for x in (A - (Integer(2)*identity_matrix(Integer(5)))).rref().
˓→list())
True>>> all(x in ZZ for x in (A - Integer(3)*identity_matrix(Integer(5))).rref().
˓→list())
True>>> all(x in ZZ for x in (A - (-Integer(1))*identity_matrix(Integer(5))).rref().
˓→list())
True>>> A.jordan_form()#␣˓→needs sage.combinat sage.libs.pari[ 2| 0| 0| 0| 0][--+--+--+--+--][ 0| 3| 0| 0| 0][--+--+--+--+--][ 0| 0| 3| 0| 0][--+--+--+--+--][ 0| 0| 0|-1| 0][--+--+--+--+--][ 0| 0| 0| 0|-1]

For more, see the documentation of the random_diagonalizable_matrix() function. In the notebook
or at the Sage command-line, first execute the following to make this further documentation available:from sage.matrix.constructor import random_diagonalizable_matrix

Random matrices with predictable subspaces. The algorithm= subspaces keyword, along with an optionalrank (rank) will return a matrix whose natural basis vectors for its four fundamental subspaces, if computed as
described in the documentation of the random_subspaces_matrix() contain only integer entries. If rank,
is not set, the rank of the matrix will be generated randomly.
sage: B = random_matrix(QQ, 5, 6, algorithm= subspaces , rank=3); B # random
sage: B_expanded = B.augment(identity_matrix(5)).rref()sage: (B.nrows(), B.ncols())(5, 6)
sage: all(x in ZZ for x in B_expanded.list())
True
sage: C = B_expanded.submatrix(0, 0, B.nrows() - B.nullity(), B.ncols())(continues on next page)95

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: L = B_expanded.submatrix(B.nrows() - B.nullity(), B.ncols())
sage: B.right_kernel() == C.right_kernel()True
sage: B.row_space() == C.row_space()
True
sage: B.column_space() == L.right_kernel()True
sage: B.left_kernel() == L.row_space()
True>>> from sage.all import *>>> B = random_matrix(QQ, Integer(5), Integer(6), algorithm= subspaces ,␣˓→rank=Integer(3)); B# random>>> B_expanded = B.augment(identity_matrix(Integer(5))).rref()>>> (B.nrows(), B.ncols())(5, 6)>>> all(x in ZZ for x in B_expanded.list())
True>>> C = B_expanded.submatrix(Integer(0), Integer(0), B.nrows() - B.nullity(), B.
˓→ncols())>>> L = B_expanded.submatrix(B.nrows() - B.nullity(), B.ncols())>>> B.right_kernel() == C.right_kernel()True>>> B.row_space() == C.row_space()
True>>> B.column_space() == L.right_kernel()True>>> B.left_kernel() == L.row_space()
True

For more, see the documentation of the random_subspaces_matrix() function. In the notebook or at theSage command-line, first execute the following to make this further documentation available:from sage.matrix.constructor import random_subspaces_matrix

Random unimodular matrices. The algorithm= unimodular keyword, along with an optional entry size
control (upper_bound) will return a matrix of determinant 1. When the base ring is ZZ or QQ the result has
integer entries, whose magnitudes can be limited by the value of upper_bound.
sage: C = random_matrix(QQ, 5, algorithm= unimodular , upper_bound=70); C
˓→randomsage: det(C)1
sage: C.base_ring()
Rational Field
sage: (C.nrows(), C.ncols())(5, 5)
sage: all(abs(x)<70 for x in C.list())
True

#␣

>>> from sage.all import *>>> C = random_matrix(QQ, Integer(5), algorithm= unimodular , upper_
˓→bound=Integer(70)); C# random>>> det(C)1>>> C.base_ring()(continues on next page)

96

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Rational Field>>> (C.nrows(), C.ncols())(5, 5)>>> all(abs(x)<Integer(70) for x in C.list())
True

For more, see the documentation of the random_unimodular_matrix() function. In the notebook or at
the Sage command-line, first execute the following to make this further documentation available:from sage.matrix.constructor import random_unimodular_matrix

AUTHOR:• William Stein (2007-02-06)• Rob Beezer (2010-08-25) Documentation, code to allow additional types of output
sage.matrix.special.random_rref_matrix(parent, num_pivots)
This function is available as random_rref_matrix(…) and matrix.random_rref(…).
Generate a matrix in reduced row-echelon form with a specified number of non-zero rows.
INPUT:• parent – A matrix space specifying the base ring, dimensions and representation (dense/sparse) for the
result. The base ring must be exact.
• num_pivots – The number of non-zero rows in the result, i.e. the rank.
OUTPUT:
A matrix in reduced row echelon form with num_pivots non-zero rows. If the base ring is 𝑍𝑍 or 𝑄𝑄 then theentries are all integers.
Note:
It is easiest to use this function via a call to the random_matrix() function with thealgorithm= echelon_form keyword. We provide one example accessing this function directly, while
the remainder will use this more general function.
EXAMPLES:
Matrices generated are in reduced row-echelon form with specified rank. If the base ring is 𝑄𝑄 the result has only
integer entries.
sage: from sage.matrix.constructor import random_rref_matrix
sage: matrix_space = sage.matrix.matrix_space.MatrixSpace(QQ, 5, 6)
sage: A = random_rref_matrix(matrix_space, num_pivots=4); A # random[ 1 0 0 -6 0 -3][ 0 1 0 2 0 3]
[ 0 0 1 -4 0 -2][ 0 0 0 0 1 3]
[ 0 0 0 0 0 0]
sage: A.base_ring()
Rational Field
sage: (A.nrows(), A.ncols())(5, 6)
sage: A in sage.matrix.matrix_space.MatrixSpace(ZZ, 5, 6)
True
sage: A.rank()(continues on next page)97

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)4
sage: A == A.rref()True>>> from sage.all import *>>> from sage.matrix.constructor import random_rref_matrix>>> matrix_space = sage.matrix.matrix_space.MatrixSpace(QQ, Integer(5),␣
˓→Integer(6))>>> A = random_rref_matrix(matrix_space, num_pivots=Integer(4)); A # random[ 1 0 0 -6 0 -3][ 0 1 0 2 0 3]
[ 0 0 1 -4 0 -2][ 0 0 0 0 1 3]
[ 0 0 0 0 0 0]>>> A.base_ring()
Rational Field>>> (A.nrows(), A.ncols())(5, 6)>>> A in sage.matrix.matrix_space.MatrixSpace(ZZ, Integer(5), Integer(6))
True>>> A.rank()
4>>> A == A.rref()
True

Matrices can be generated over other exact rings.
sage: B = random_matrix(FiniteField(7), 4, 4, # random....:algorithm= echelon_form , num_pivots=3); B[1 0 0 0][0 1 0 6][0 0 1 1][0 0 0 0]
sage: B.rank() == 3
True
sage: B.base_ring()
Finite Field of size 7
sage: B == B.rref()True>>> from sage.all import *>>> B = random_matrix(FiniteField(Integer(7)), Integer(4), Integer(4), # random...
algorithm= echelon_form , num_pivots=Integer(3)); B[1 0 0 0][0 1 0 6][0 0 1 1][0 0 0 0]>>> B.rank() == Integer(3)True>>> B.base_ring()
Finite Field of size 7>>> B == B.rref()True

AUTHOR:
Billy Wonderly (2010-07)
98

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

sage.matrix.special.random_subspaces_matrix(parent, rank=None)
This function is available as random_subspaces_matrix(…) and matrix.random_subspaces(…).
Create a matrix of the designated size and rank whose right and left null spaces, column space, and row space havedesirable properties that simplify the subspaces.
INPUT:• parent – A matrix space specifying the base ring, dimensions, and representation (dense/sparse) for the
result. The base ring must be exact.
• rank – The desired rank of the return matrix (default: None).
OUTPUT:
A matrix whose natural basis vectors for its four subspaces, when computed, have reasonably sized, integral valued,
entries.
Note:
It is easiest to use this function via a call to the random_matrix() function with thealgorithm= subspaces keyword. We provide one example accessing this function directly, while theremainder will use this more general function.
EXAMPLES:
A 6x8 matrix with designated rank of 3. The four subspaces are determined using one simple routine in which
we augment the original matrix with the equal row dimension identity matrix. The resulting matrix is then put inreduced row-echelon form and the subspaces can then be determined by analyzing subdivisions of this matrix. See
the four subspaces routine in [Bee] for more.
sage: from sage.matrix.constructor import random_subspaces_matrix
sage: matrix_space = sage.matrix.matrix_space.MatrixSpace(QQ, 6, 8)
sage: B = random_subspaces_matrix(matrix_space, rank=3)
sage: B.rank()
3sage: B.nullity()3
sage: (B.nrows(), B.ncols())(6, 8)
sage: all(x in ZZ for x in B.list())
True
sage: B_expanded = B.augment(identity_matrix(6)).rref()sage: all(x in ZZ for x in B_expanded.list())
True>>> from sage.all import *>>> from sage.matrix.constructor import random_subspaces_matrix>>> matrix_space = sage.matrix.matrix_space.MatrixSpace(QQ, Integer(6),␣
˓→Integer(8))>>> B = random_subspaces_matrix(matrix_space, rank=Integer(3))>>> B.rank()
3>>> B.nullity()3>>> (B.nrows(), B.ncols())(6, 8)>>> all(x in ZZ for x in B.list())
True>>> B_expanded = B.augment(identity_matrix(Integer(6))).rref()(continues on next page)99

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> all(x in ZZ for x in B_expanded.list())
True

Check that we fixed Issue #10543 (echelon forms should be immutable):sage: B_expanded.is_immutable()True>>> from sage.all import *>>> B_expanded.is_immutable()True

We want to modify B_expanded, so replace it with a copy:
sage: B_expanded = copy(B_expanded)sage: B_expanded.subdivide(B.nrows()-B.nullity(), B.ncols())
sage: C = B_expanded.subdivision(0, 0)
sage: L = B_expanded.subdivision(1, 1)
sage: B.right_kernel() == C.right_kernel()True
sage: B.row_space() == C.row_space()
True
sage: B.column_space() == L.right_kernel()True
sage: B.left_kernel() == L.row_space()
True>>> from sage.all import *>>> B_expanded = copy(B_expanded)>>> B_expanded.subdivide(B.nrows()-B.nullity(), B.ncols())>>> C = B_expanded.subdivision(Integer(0), Integer(0))>>> L = B_expanded.subdivision(Integer(1), Integer(1))>>> B.right_kernel() == C.right_kernel()True>>> B.row_space() == C.row_space()
True>>> B.column_space() == L.right_kernel()True>>> B.left_kernel() == L.row_space()
True

A matrix to show that the null space of the L matrix is the column space of the starting matrix.
sage: A = random_matrix(QQ, 5, 7, algorithm= subspaces , rank=None)sage: (A.nrows(), A.ncols())(5, 7)
sage: all(x in ZZ for x in A.list())
True
sage: A_expanded = A.augment(identity_matrix(5)).rref()sage: all(x in ZZ for x in A_expanded.list())
True
sage: C = A_expanded.submatrix(0, 0, A.nrows() - A.nullity(), A.ncols())
sage: L = A_expanded.submatrix(A.nrows() - A.nullity(), A.ncols())
sage: A.right_kernel() == C.right_kernel()True
sage: A.row_space() == C.row_space()(continues on next page)

100

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)True
sage: A.column_space() == L.right_kernel()True
sage: A.left_kernel() == L.row_space()
True>>> from sage.all import *>>> A = random_matrix(QQ, Integer(5), Integer(7), algorithm= subspaces ,␣˓→rank=None)>>> (A.nrows(), A.ncols())(5, 7)>>> all(x in ZZ for x in A.list())
True>>> A_expanded = A.augment(identity_matrix(Integer(5))).rref()>>> all(x in ZZ for x in A_expanded.list())
True>>> C = A_expanded.submatrix(Integer(0), Integer(0), A.nrows() - A.nullity(), A.
˓→ncols())>>> L = A_expanded.submatrix(A.nrows() - A.nullity(), A.ncols())>>> A.right_kernel() == C.right_kernel()True>>> A.row_space() == C.row_space()
True>>> A.column_space() == L.right_kernel()True>>> A.left_kernel() == L.row_space()
True

AUTHOR:
Billy Wonderly (2010-07)
sage.matrix.special.random_unimodular_matrix(parent, upper_bound=None, max_tries=100)
This function is available as random_unimodular_matrix(…) and matrix.random_unimodular(…).
Generate a random unimodular (determinant 1) matrix of a desired size over a desired ring.
INPUT:• parent – A matrix space specifying the base ring, dimensions and representation (dense/sparse) for the
result. The base ring must be exact.
• upper_bound – For large matrices over QQ or ZZ, upper_bound is the largest value matrix entries canachieve. But see the warning below.
• max_tries – If designated, number of tries used to generate each new random row; only matters whenupper_bound!=None. Used to prevent endless looping. (default: 100)
A matrix not in reduced row-echelon form with the desired dimensions and properties.
OUTPUT:
An invertible matrix with the desired properties and determinant 1.
Warning: When upper_bound is set, it is possible for this constructor to fail with a ValueError.
This may happen when the upper_bound, rank and/or matrix dimensions are all so small that it becomes
infeasible or unlikely to create the requested matrix. If you must have this routine return successfully, do not
set upper_bound.

101Matrices and Spaces of Matrices, Release 10.4

Note:
It is easiest to use this function via a call to the random_matrix() function with thealgorithm= unimodular keyword. We provide one example accessing this function directly, while theremainder will use this more general function.
EXAMPLES:
A matrix size 5 over QQ.
sage: from sage.matrix.constructor import random_unimodular_matrix
sage: matrix_space = sage.matrix.matrix_space.MatrixSpace(QQ, 5)
sage: A = random_unimodular_matrix(matrix_space)sage: det(A)1>>> from sage.all import *>>> from sage.matrix.constructor import random_unimodular_matrix>>> matrix_space = sage.matrix.matrix_space.MatrixSpace(QQ, Integer(5))>>> A = random_unimodular_matrix(matrix_space)>>> det(A)1A matrix size 6 with entries no larger than 50.
sage: B = random_matrix(ZZ, 7, algorithm= unimodular , upper_bound=50)
sage: det(B)1sage: all(abs(b) < 50 for b in B.list())
True>>> from sage.all import *>>> B = random_matrix(ZZ, Integer(7), algorithm= unimodular , upper_
˓→bound=Integer(50))>>> det(B)1>>> all(abs(b) < Integer(50) for b in B.list())
True

A matrix over the number Field in 𝑦 with defining polynomial 𝑦 2 − 2𝑦 − 2.
sage: # needs sage.rings.number_fieldsage: y = polygen(ZZ, y )sage: K = NumberField(y^2 - 2*y - 2, y )sage: C = random_matrix(K, 3, algorithm= unimodular )sage: det(C)1
sage: C.base_ring() is K
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> y = polygen(ZZ, y )>>> K = NumberField(y**Integer(2) - Integer(2)*y - Integer(2),>>> C = random_matrix(K, Integer(3), algorithm= unimodular )>>> det(C)1y )(continues on next page)

102

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> C.base_ring() is K
True

AUTHOR:
Billy Wonderly (2010-07)
sage.matrix.special.toeplitz(c, r, ring=None)
This function is available as toeplitz(…) and matrix.toeplitz(…).
Return a Toeplitz matrix of given first column and first row.
In a Toeplitz matrix, each descending diagonal from left to right is constant, such that:
𝑇𝑖,𝑗 = 𝑇𝑖+1,𝑗+1 .
For more information see the Wikipedia article Toeplitz_matrix.
INPUT:• c – vector, first column of the Toeplitz matrix• r – vector, first row of the Toeplitz matrix, counting from the second column• ring – base ring (default: None) of the resulting matrix
EXAMPLES:
A rectangular Toeplitz matrix:
sage: matrix.toeplitz([1..4], [5..6])[1 5 6][2 1 5][3 2 1][4 3 2]>>> from sage.all import *>>> matrix.toeplitz((ellipsis_range(Integer(1),Ellipsis,Integer(4))), (ellipsis_
˓→range(Integer(5),Ellipsis,Integer(6))))[1 5 6][2 1 5][3 2 1][4 3 2]

The following 𝑁 × 𝑁 Toeplitz matrix arises in the discretization of boundary value problems:sage: N = 4
sage: matrix.toeplitz([-2, 1] + [0]*(N-2), [1] + [0]*(N-2))[-2 1 0 0]
[ 1 -2 1 0]
[ 0 1 -2 1][ 0 0 1 -2]>>> from sage.all import *>>> N = Integer(4)>>> matrix.toeplitz([-Integer(2), Integer(1)] + [Integer(0)]*(N-Integer(2)),␣
˓→[Integer(1)] + [Integer(0)]*(N-Integer(2)))[-2 1 0 0]
[ 1 -2 1 0]
(continues on next page)103

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[ 0
[ 0

1 -2 1]0 1 -2]sage.matrix.special.vandermonde(v, ring=None)
This function is available as vandermonde(…) and matrix.vandermonde(…).
Return a Vandermonde matrix of the given vector.
The 𝑛 dimensional Vandermonde matrix is a square matrix with columns being the powers of a given vector 𝑣,
𝑉𝑖𝑗 = 𝑣𝑖𝑗−1 ,𝑖, 𝑗 = 1, . . . , 𝑛.

For more information see the Wikipedia article Vandermonde_matrix.
INPUT:• v – vector, the second column of the Vandermonde matrix• ring – base ring (default: None) of the resulting matrix
EXAMPLES:
A Vandermonde matrix of order three over the symbolic ring:sage: matrix.vandermonde(SR.var([ x0 ,˓→needs sage.symbolic[
1x0 x0^2][
1
x1 x1^2][
1
x2 x2^2]>>> from sage.all import *>>> matrix.vandermonde(SR.var([ x0 ,˓→needs sage.symbolic[
1x0 x0^2][
1
x1 x1^2][
1
x2 x2^2]

x1 ,

x1 ,

x2 ]))x2 ]))#␣#␣

sage.matrix.special.vector_on_axis_rotation_matrix(v, i, ring=None)
This function is available as vector_on_axis_rotation_matrix(…) and matrix.vector_on_axis_rotation(…).
Return a rotation matrix 𝑀 such that 𝑑𝑒𝑡(𝑀 ) = 1 sending the vector 𝑣 on the i-th axis so that all other coordinatesof 𝑀 𝑣 are zero.
Note: Such a matrix is not uniquely determined. This function returns one such matrix.
INPUT:• v – vector• i – integer• ring – ring (default: None) of the resulting matrix
OUTPUT:
A matrix
EXAMPLES:

104

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

sage: from sage.matrix.constructor import vector_on_axis_rotation_matrix
sage: v = vector((1,2,3))
sage: vector_on_axis_rotation_matrix(v, 2) * v
˓→needs sage.symbolic(0, 0, sqrt(14))
sage: vector_on_axis_rotation_matrix(v, 1) * v
˓→needs sage.symbolic(0, sqrt(14), 0)
sage: vector_on_axis_rotation_matrix(v, 0) * v
˓→needs sage.symbolic(sqrt(14), 0, 0)>>> from sage.all import *>>> from sage.matrix.constructor import vector_on_axis_rotation_matrix>>> v = vector((Integer(1),Integer(2),Integer(3)))>>> vector_on_axis_rotation_matrix(v, Integer(2)) * v
˓→# needs sage.symbolic(0, 0, sqrt(14))>>> vector_on_axis_rotation_matrix(v, Integer(1)) * v
˓→# needs sage.symbolic(0, sqrt(14), 0)>>> vector_on_axis_rotation_matrix(v, Integer(0)) * v
˓→# needs sage.symbolic(sqrt(14), 0, 0)

#␣

#␣

#␣

␣

␣

␣

sage: # needs sage.symbolic
sage: x,y = var( x,y )sage: v = vector((x,y))
sage: vector_on_axis_rotation_matrix(v, 1)[ y/sqrt(x^2 + y^2) -x/sqrt(x^2 + y^2)][ x/sqrt(x^2 + y^2) y/sqrt(x^2 + y^2)]
sage: vector_on_axis_rotation_matrix(v, 0)[ x/sqrt(x^2 + y^2) y/sqrt(x^2 + y^2)][-y/sqrt(x^2 + y^2) x/sqrt(x^2 + y^2)]
sage: vector_on_axis_rotation_matrix(v, 0) * v(x^2/sqrt(x^2 + y^2) + y^2/sqrt(x^2 + y^2), 0)
sage: vector_on_axis_rotation_matrix(v, 1) * v(0, x^2/sqrt(x^2 + y^2) + y^2/sqrt(x^2 + y^2))>>> from sage.all import *>>> # needs sage.symbolic>>> x,y = var( x,y )>>> v = vector((x,y))>>> vector_on_axis_rotation_matrix(v, Integer(1))[ y/sqrt(x^2 + y^2) -x/sqrt(x^2 + y^2)][ x/sqrt(x^2 + y^2) y/sqrt(x^2 + y^2)]>>> vector_on_axis_rotation_matrix(v, Integer(0))[ x/sqrt(x^2 + y^2) y/sqrt(x^2 + y^2)][-y/sqrt(x^2 + y^2) x/sqrt(x^2 + y^2)]>>> vector_on_axis_rotation_matrix(v, Integer(0)) * v(x^2/sqrt(x^2 + y^2) + y^2/sqrt(x^2 + y^2), 0)>>> vector_on_axis_rotation_matrix(v, Integer(1)) * v(0, x^2/sqrt(x^2 + y^2) + y^2/sqrt(x^2 + y^2))
sage: v = vector((1,2,3,4))
sage: vector_on_axis_rotation_matrix(v, 0) * v#␣(continues on next page)105

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)needs sage.symbolic(sqrt(30), 0, 0, 0)
sage: vector_on_axis_rotation_matrix(v, 0, ring=RealField(10))[ 0.18 0.37 0.55 0.73][-0.98 0.068 0.10 0.14][ 0.00 -0.93 0.22 0.30][ 0.00 0.00 -0.80 0.60]
sage: vector_on_axis_rotation_matrix(v, 0, ring=RealField(10)) * v(5.5, 0.00..., 0.00..., 0.00...)˓→>>> from sage.all import *>>> v = vector((Integer(1),Integer(2),Integer(3),Integer(4)))>>> vector_on_axis_rotation_matrix(v, Integer(0)) * v
␣˓→# needs sage.symbolic(sqrt(30), 0, 0, 0)>>> vector_on_axis_rotation_matrix(v, Integer(0), ring=RealField(Integer(10)))[ 0.18 0.37 0.55 0.73][-0.98 0.068 0.10 0.14][ 0.00 -0.93 0.22 0.30][ 0.00 0.00 -0.80 0.60]>>> vector_on_axis_rotation_matrix(v, Integer(0), ring=RealField(Integer(10))) * v(5.5, 0.00..., 0.00..., 0.00...)AUTHORS:
Sébastien Labbé (April 2010)sage.matrix.special.zero_matrix(ring, nrows=None, ncols=None, sparse=False)
This function is available as zero_matrix(…) and matrix.zero(…).
Return the 𝑛𝑟𝑜𝑤𝑠 × 𝑛𝑐𝑜𝑙𝑠 zero matrix over the given ring.
The default ring is the integers.
EXAMPLES:
sage: M = zero_matrix(QQ, 2); M
[0 0]
[0 0]
sage: M.parent()
Full MatrixSpace of 2 by 2 dense matrices over Rational Field
sage: M = zero_matrix(2, 3); M[0 0 0][0 0 0]sage: M.parent()
Full MatrixSpace of 2 by 3 dense matrices over Integer Ringsage: M.is_mutable()True
sage: M = zero_matrix(3, 1, sparse=True); M
[0]
[0]
[0]
sage: M.parent()
Full MatrixSpace of 3 by 1 sparse matrices over Integer Ringsage: M.is_mutable()True
sage: matrix.zero(5)[0 0 0 0 0](continues on next page)

106

Chapter 3. Constructors for special matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 0 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]>>> from sage.all import *>>> M = zero_matrix(QQ, Integer(2)); M
[0 0]
[0 0]
>>> M.parent()
Full MatrixSpace of 2 by 2 dense matrices over Rational Field>>> M = zero_matrix(Integer(2), Integer(3)); M[0 0 0][0 0 0]>>> M.parent()
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring>>> M.is_mutable()
True>>> M = zero_matrix(Integer(3), Integer(1), sparse=True); M
[0]
[0]
[0]
>>> M.parent()
Full MatrixSpace of 3 by 1 sparse matrices over Integer Ring>>> M.is_mutable()True>>> matrix.zero(Integer(5))[0 0 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]107

Matrices and Spaces of Matrices, Release 10.4

108

Chapter 3. Constructors for special matrices

CHAPTERFOUR

HELPERS FOR CREATING MATRICES

class sage.matrix.args.MatrixArgs
Bases: object
Collect arguments for constructing a matrix.
This class is meant to pass around arguments, for example from the global matrix() constructor to the matrix
space or to the element class constructor.
A typical use case is first creating a MatrixArgs instance, possibly adjusting the attributes. This instance canthen be passed around and a matrix can be constructed from it using the matrix() method. Also, a flat list canbe constructed using list() or a sparse dict using dict(). It is safe to construct multiple objects (of the sameor a different kind) from the same MatrixArgs instance.
MatrixArgs also supports iteration using the iter() method. This is a more low-level interface.
When MatrixArgs produces output, it is first finalized. This means that all missing attributes are derived or
guessed. After finalization, you should no longer change the attributes or it will end up in an inconsistent state. You
can also finalize explicitly by calling the finalized() method.
A MatrixArgs can contain invalid input. This is not checked when constructing the MatrixArgs instance,
but it is checked either when finalizing or when constructing an object from it.
Warning: Instances of this class should only be temporary, they are not meant to be stored long-term.
EXAMPLES:
sage: from sage.matrix.args import MatrixArgs
sage: ma = MatrixArgs(2, 2, (x for x in range(4))); ma<MatrixArgs for None; typ=UNKNOWN; entries=<generator ...>>
sage: ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Integer Ring; typ=SEQ_FLAT; entries=[0, 1, 2, 3]>>>> from sage.all import *>>> from sage.matrix.args import MatrixArgs>>> ma = MatrixArgs(Integer(2), Integer(2), (x for x in range(Integer(4)))); ma<MatrixArgs for None; typ=UNKNOWN; entries=<generator ...>>>>> ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Integer Ring; typ=SEQ_FLAT; entries=[0, 1, 2, 3]>Many types of input are possible:

109

Matrices and Spaces of Matrices, Release 10.4

sage: ma = MatrixArgs(2, 2, entries=None); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Integer Ring; typ=ZERO; entries=None>sage: ma.matrix()
[0 0]
[0 0]
sage: ma = MatrixArgs(2, 2, entries={}); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 sparse matrices
over Integer Ring; typ=SEQ_SPARSE; entries=[]>sage: ma.matrix()
[0 0]
[0 0]
sage: ma = MatrixArgs(2, 2, entries=[1,2,3,4]); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Integer Ring; typ=SEQ_FLAT; entries=[1, 2, 3, 4]>
sage: ma.matrix()
[1 2]
[3 4]
sage: ma = MatrixArgs(2, 2, entries=math.pi); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Real Double Field; typ=SCALAR; entries=3.141592653589793>
sage: ma.matrix()[3.141592653589793
0.0][
0.0 3.141592653589793]
sage: ma = MatrixArgs(2, 2, entries=pi); ma.finalized()
˓→needs sage.symbolic<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Symbolic Ring; typ=SCALAR; entries=pi>
sage: ma.matrix()
˓→needs sage.symbolic[pi 0][ 0 pi]sage: ma = MatrixArgs(ZZ, 2, 2, entries={(0,0): 7}); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 sparse matrices
over Integer Ring; typ=SEQ_SPARSE; entries=[SparseEntry(0, 0, 7)]>sage: ma.matrix()
[7 0]
[0 0]
sage: ma = MatrixArgs(ZZ, 2, 2, entries=((1,2), (3,4))); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Integer Ring; typ=SEQ_SEQ; entries=((1, 2), (3, 4))>sage: ma.matrix()
[1 2]
[3 4]
sage: ma = MatrixArgs(ZZ, 2, 2, entries=(1,2,3,4)); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Integer Ring; typ=SEQ_FLAT; entries=(1, 2, 3, 4)>
sage: ma.matrix()
[1 2]
[3 4]

#␣

#␣

sage: # needs sage.libs.pari
sage: ma = MatrixArgs(QQ, entries=pari("[1,2;3,4]")); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Rational Field; typ=SEQ_FLAT; entries=[1, 2, 3, 4]>
sage: ma.matrix()[1 2](continues on next page)

110

Chapter 4. Helpers for creating matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[3 4]
sage: ma = MatrixArgs(QQ, 2, 2, entries=pari("[1,2,3,4]")); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Rational Field; typ=SEQ_FLAT; entries=[1, 2, 3, 4]>
sage: ma.matrix()
[1 2]
[3 4]
sage: ma = MatrixArgs(QQ, 2, 2, entries=pari("3/5")); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Rational Field; typ=SCALAR; entries=3/5>
sage: ma.matrix()[3/5
0][ 0 3/5]
sage: ma = MatrixArgs(entries=matrix(2,2)); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Integer Ring; typ=MATRIX; entries=[0 0][0 0]>
sage: ma.matrix()
[0 0]
[0 0]
sage: ma = MatrixArgs(2, 2, entries=lambda i,j: 1+2*i+j); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Integer Ring; typ=SEQ_FLAT; entries=[1, 2, 3, 4]>
sage: ma.matrix()
[1 2]
[3 4]
sage: ma = MatrixArgs(ZZ, 2, 2, entries=lambda i,j: 1+2*i+j); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Integer Ring; typ=CALLABLE; entries=<function ...>>
sage: ma.matrix()
[1 2]
[3 4]
sage: # needs numpy
sage: from numpy import arraysage: ma = MatrixArgs(array([[1,2],[3,4]])); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Integer Ring; typ=SEQ_SEQ; entries=array([[1, 2], [3, 4]])>sage: ma.matrix()
[1 2]
[3 4]
sage: ma = MatrixArgs(array([[1.,2.],[3.,4.]])); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Real Double Field; typ=MATRIX; entries=[1.0 2.0]
[3.0 4.0]>
sage: ma.matrix()[1.0 2.0][3.0 4.0]
sage: ma = MatrixArgs(RealField(20), array([[1.,2.],[3.,4.]])); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices over Real Field
with 20 bits of precision; typ=MATRIX; entries=[1.0 2.0]
[3.0 4.0]>
sage: ma.matrix()[1.0000 2.0000][3.0000 4.0000](continues on next page)111

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: # needs sage.graphs
sage: ma = MatrixArgs(graphs.CycleGraph(3)); ma.finalized()<MatrixArgs for Full MatrixSpace of 3 by 3 dense matrices
over Integer Ring; typ=MATRIX; entries=[0 1 1]
[1 0 1][1 1 0]>sage: ma.matrix()[0 1 1][1 0 1][1 1 0]sage: ma = MatrixArgs([vector([0,1], sparse=True),....:
vector([0,0], sparse=True)], sparse=True)
sage: ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 sparse matrices overInteger Ring; typ=SEQ_SPARSE; entries=[SparseEntry(0, 1, 1)]>
sage: ma.matrix()
[0 1]
[0 0]
>>> from sage.all import *>>> ma = MatrixArgs(Integer(2), Integer(2), entries=None); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Integer Ring; typ=ZERO; entries=None>>>> ma.matrix()
[0 0]
[0 0]
>>> ma = MatrixArgs(Integer(2), Integer(2), entries={}); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 sparse matrices
over Integer Ring; typ=SEQ_SPARSE; entries=[]>>>> ma.matrix()
[0 0]
[0 0]
>>> ma = MatrixArgs(Integer(2), Integer(2), entries=[Integer(1),Integer(2),˓→Integer(3),Integer(4)]); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Integer Ring; typ=SEQ_FLAT; entries=[1, 2, 3, 4]>>>> ma.matrix()
[1 2]
[3 4]
>>> ma = MatrixArgs(Integer(2), Integer(2), entries=math.pi); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Real Double Field; typ=SCALAR; entries=3.141592653589793>>>> ma.matrix()[3.141592653589793
0.0][
0.0 3.141592653589793]>>> ma = MatrixArgs(Integer(2), Integer(2), entries=pi); ma.finalized()␣˓→# needs sage.symbolic<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Symbolic Ring; typ=SCALAR; entries=pi>>>> ma.matrix()#␣˓→needs sage.symbolic[pi 0][ 0 pi]>>> ma = MatrixArgs(ZZ, Integer(2), Integer(2), entries={(Integer(0),Integer(0)):␣
˓→Integer(7)}); ma.finalized()(continues on next page)

112

Chapter 4. Helpers for creating matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)<MatrixArgs for Full MatrixSpace of 2 by 2 sparse matrices
over Integer Ring; typ=SEQ_SPARSE; entries=[SparseEntry(0, 0, 7)]>>>> ma.matrix()
[7 0]
[0 0]
>>> ma = MatrixArgs(ZZ, Integer(2), Integer(2), entries=((Integer(1),Integer(2)),␣
˓→(Integer(3),Integer(4)))); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Integer Ring; typ=SEQ_SEQ; entries=((1, 2), (3, 4))>>>> ma.matrix()
[1 2]
[3 4]
>>> ma = MatrixArgs(ZZ, Integer(2), Integer(2), entries=(Integer(1),Integer(2),˓→Integer(3),Integer(4))); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Integer Ring; typ=SEQ_FLAT; entries=(1, 2, 3, 4)>>>> ma.matrix()
[1 2]
[3 4]
>>> # needs sage.libs.pari>>> ma = MatrixArgs(QQ, entries=pari("[1,2;3,4]")); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Rational Field; typ=SEQ_FLAT; entries=[1, 2, 3, 4]>>>> ma.matrix()
[1 2]
[3 4]
>>> ma = MatrixArgs(QQ, Integer(2), Integer(2), entries=pari("[1,2,3,4]")); ma.
˓→finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Rational Field; typ=SEQ_FLAT; entries=[1, 2, 3, 4]>>>> ma.matrix()
[1 2]
[3 4]
>>> ma = MatrixArgs(QQ, Integer(2), Integer(2), entries=pari("3/5")); ma.
˓→finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Rational Field; typ=SCALAR; entries=3/5>>>> ma.matrix()[3/5
0][ 0 3/5]>>> ma = MatrixArgs(entries=matrix(Integer(2),Integer(2))); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Integer Ring; typ=MATRIX; entries=[0 0][0 0]>>>> ma.matrix()
[0 0]
[0 0]
>>> ma = MatrixArgs(Integer(2), Integer(2), entries=lambda i,j:␣
˓→Integer(1)+Integer(2)*i+j); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Integer Ring; typ=SEQ_FLAT; entries=[1, 2, 3, 4]>>>> ma.matrix()
[1 2]
[3 4]
>>> ma = MatrixArgs(ZZ, Integer(2), Integer(2), entries=lambda i,j:␣
(continues on next page)113

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Integer(1)+Integer(2)*i+j); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Integer Ring; typ=CALLABLE; entries=<function ...>>>>> ma.matrix()
[1 2]
[3 4]
˓→

>>> # needs numpy>>> from numpy import array>>> ma = MatrixArgs(array([[Integer(1),Integer(2)],[Integer(3),Integer(4)]])); ma.
˓→finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Integer Ring; typ=SEQ_SEQ; entries=array([[1, 2], [3, 4]])>>>> ma.matrix()
[1 2]
[3 4]
>>> ma = MatrixArgs(array([[RealNumber( 1. ),RealNumber( 2. )],[RealNumber( 3. ),˓→RealNumber( 4. )]])); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
over Real Double Field; typ=MATRIX; entries=[1.0 2.0]
[3.0 4.0]>>>> ma.matrix()[1.0 2.0][3.0 4.0]>>> ma = MatrixArgs(RealField(Integer(20)), array([[RealNumber( 1. ),RealNumber(
˓→ 2. )],[RealNumber( 3. ),RealNumber( 4. )]])); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices over Real Field
with 20 bits of precision; typ=MATRIX; entries=[1.0 2.0]
[3.0 4.0]>>>> ma.matrix()[1.0000 2.0000][3.0000 4.0000]>>> # needs sage.graphs>>> ma = MatrixArgs(graphs.CycleGraph(Integer(3))); ma.finalized()<MatrixArgs for Full MatrixSpace of 3 by 3 dense matrices
over Integer Ring; typ=MATRIX; entries=[0 1 1]
[1 0 1][1 1 0]>>>> ma.matrix()[0 1 1][1 0 1][1 1 0]>>> ma = MatrixArgs([vector([Integer(0),Integer(1)], sparse=True),...
vector([Integer(0),Integer(0)], sparse=True)], sparse=True)>>> ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 2 sparse matrices overInteger Ring; typ=SEQ_SPARSE; entries=[SparseEntry(0, 1, 1)]>>>> ma.matrix()
[0 1]
[0 0]

Test invalid input:
sage: MatrixArgs(ZZ, 2, 2, entries="abcd").finalized()
Traceback (most recent call last):(continues on next page)

114

Chapter 4. Helpers for creating matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
TypeError: unable to convert abcd to a matrix
sage: MatrixArgs(ZZ, 2, 2, entries=MatrixArgs()).finalized()
Traceback (most recent call last):...
TypeError: unable to convert <MatrixArgs for None; typ=UNKNOWN; entries=None> to␣˓→a matrix>>> from sage.all import *>>> MatrixArgs(ZZ, Integer(2), Integer(2), entries="abcd").finalized()
Traceback (most recent call last):...
TypeError: unable to convert abcd to a matrix>>> MatrixArgs(ZZ, Integer(2), Integer(2), entries=MatrixArgs()).finalized()
Traceback (most recent call last):...
TypeError: unable to convert <MatrixArgs for None; typ=UNKNOWN; entries=None> to␣˓→a matrix

base
column_keys
dict(convert=True)
Return the entries of the matrix as a dict.
The keys of this dict are the non-zero positions (i,j). The corresponding value is the entry at that
position. Zero values are skipped.
If convert is True, the entries are converted to the base ring. Otherwise, the entries are returned as given.
EXAMPLES:
sage: from sage.matrix.args import MatrixArgs
sage: L = list(range(6))
sage: MatrixArgs(2, 3, L).dict(){(0, 1): 1, (0, 2): 2, (1, 0): 3, (1, 1): 4, (1, 2): 5}>>> from sage.all import *>>> from sage.matrix.args import MatrixArgs>>> L = list(range(Integer(6)))>>> MatrixArgs(Integer(2), Integer(3), L).dict(){(0, 1): 1, (0, 2): 2, (1, 0): 3, (1, 1): 4, (1, 2): 5}
sage: ma = MatrixArgs(GF(2), 2, 3, L)
sage: ma.dict(convert=False){(0, 1): 1, (0, 2): 2, (1, 0): 3, (1, 1): 4, (1, 2): 5}
sage: ma.dict(){(0, 1): 1, (1, 0): 1, (1, 2): 1}>>> from sage.all import *>>> ma = MatrixArgs(GF(Integer(2)), Integer(2), Integer(3), L)>>> ma.dict(convert=False){(0, 1): 1, (0, 2): 2, (1, 0): 3, (1, 1): 4, (1, 2): 5}>>> ma.dict(){(0, 1): 1, (1, 0): 1, (1, 2): 1}

115

Matrices and Spaces of Matrices, Release 10.4

element(immutable=False)
Return the matrix or morphism.
INPUT:• immutable – boolean; if True, the result will be immutable.
OUTPUT: an element of self.space
Note: This may change self.entries, making it unsafe to access the self.entries attribute after
calling this method.
EXAMPLES:
sage: from sage.matrix.args import MatrixArgs
sage: M = matrix(2, 3, range(6), sparse=True)
sage: ma = MatrixArgs(M); ma.finalized()<MatrixArgs for
Full MatrixSpace of 2 by 3 sparse matrices over Integer Ring;
typ=MATRIX; entries=[0 1 2]
[3 4 5]>sage: M2 = ma.element(immutable=True); M2.parent()
Full MatrixSpace of 2 by 3 sparse matrices over Integer Ringsage: M2.is_immutable()True
sage: ma = MatrixArgs(M, row_keys=[ u , v ], column_keys=[ a , b , c ])sage: ma.finalized()<MatrixArgs for
Set of Morphisms
from Free module generated by { a , b , c } over Integer Ring
to Free module generated by { u , v } over Integer Ringin Category of finite dimensional modules with basis over Integer Ring;
typ=MATRIX; entries=[0 1 2]
[3 4 5]>sage: phi = ma.element(); phi
Generic morphism:
From: Free module generated by { a , b , c } over Integer Ring
To:
Free module generated by { u , v } over Integer Ring>>> from sage.all import *>>> from sage.matrix.args import MatrixArgs>>> M = matrix(Integer(2), Integer(3), range(Integer(6)), sparse=True)>>> ma = MatrixArgs(M); ma.finalized()<MatrixArgs for
Full MatrixSpace of 2 by 3 sparse matrices over Integer Ring;
typ=MATRIX; entries=[0 1 2]
[3 4 5]>>>> M2 = ma.element(immutable=True); M2.parent()
Full MatrixSpace of 2 by 3 sparse matrices over Integer Ring>>> M2.is_immutable()True>>> ma = MatrixArgs(M, row_keys=[ u , v ], column_keys=[ a , b , c ])>>> ma.finalized()<MatrixArgs for
Set of Morphisms(continues on next page)

116

Chapter 4. Helpers for creating matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)from Free module generated by { a , b , c } over Integer Ring
to Free module generated by { u , v } over Integer Ringin Category of finite dimensional modules with basis over Integer Ring;
typ=MATRIX; entries=[0 1 2]
[3 4 5]>>>> phi = ma.element(); phi
Generic morphism:
From: Free module generated by { a , b , c } over Integer Ring
To:
Free module generated by { u , v } over Integer Ring

entries
finalized()
Determine all missing values.
Depending on the input, this might be a non-trivial operation. In some cases, this will do most of the workof constructing the matrix. That is actually not a problem since we eventually want to construct the matrix
anyway. However, care is taken to avoid double work or needless checking or copying.
OUTPUT: self
EXAMPLES:
sage: from sage.matrix.args import MatrixArgs
sage: MatrixArgs(pi).finalized()
˓→needs sage.symbolic
Traceback (most recent call last):...
TypeError: the dimensions of the matrix must be specified
sage: MatrixArgs(RR, pi).finalized()
˓→needs sage.symbolic
Traceback (most recent call last):...
TypeError: the dimensions of the matrix must be specified
sage: MatrixArgs(2, 3, 0.0).finalized()<MatrixArgs for Full MatrixSpace of 2 by 3 dense matrices over Real
Field with 53 bits of precision; typ=ZERO; entries=0.000000000000000>
sage: MatrixArgs(RR, 2, 3, 1.0).finalized()
Traceback (most recent call last):...
TypeError: nonzero scalar matrix must be square>>> from sage.all import *>>> from sage.matrix.args import MatrixArgs>>> MatrixArgs(pi).finalized()
˓→needs sage.symbolic
Traceback (most recent call last):...
TypeError: the dimensions of the matrix must be specified>>> MatrixArgs(RR, pi).finalized()
˓→needs sage.symbolic
Traceback (most recent call last):...
TypeError: the dimensions of the matrix must be specified>>> MatrixArgs(Integer(2), Integer(3), RealNumber( 0.0 )).finalized()<MatrixArgs for Full MatrixSpace of 2 by 3 dense matrices over Real
Field with 53 bits of precision; typ=ZERO; entries=0.000000000000000>

#␣

#␣

#␣

#␣

(continues on next page)117

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> MatrixArgs(RR, Integer(2), Integer(3), RealNumber( 1.0 )).finalized()
Traceback (most recent call last):...
TypeError: nonzero scalar matrix must be square

Check Issue #19134:
sage: matrix(2, 3, [])Traceback (most recent call last):...
ValueError: sequence too short (expected length 6, got 0)
sage: matrix(ZZ, 2, 3, [])Traceback (most recent call last):...
ValueError: sequence too short (expected length 6, got 0)
sage: matrix(2, 3, [1])Traceback (most recent call last):...
ValueError: sequence too short (expected length 6, got 1)>>> from sage.all import *>>> matrix(Integer(2), Integer(3), [])Traceback (most recent call last):...
ValueError: sequence too short (expected length 6, got 0)>>> matrix(ZZ, Integer(2), Integer(3), [])Traceback (most recent call last):...
ValueError: sequence too short (expected length 6, got 0)>>> matrix(Integer(2), Integer(3), [Integer(1)])
Traceback (most recent call last):...
ValueError: sequence too short (expected length 6, got 1)

Check github issue #36065:
sage: # needs sage.rings.number_field sage: class MyAlgebraicNumber(sage.rings.qqbar.AlgebraicNumber): ….: def __bool__(self): ….: raise ValueError sage: matrix(1, 1, MyAlgebraicNumber(0)) [0] sage: matrix(1, 1, MyAlgebraicNumber(3)) [3] sage: matrix(1, 2, MyAlgebraicNumber(0)) Traceback (most recent call last): … TypeError: scalar matrix must be square if the value
cannot be determined to be zero sage: matrix(1, 2, MyAlgebraicNumber(3)) Traceback (most recent call last): … TypeError: scalar matrix must be square if the value cannot be determined to bezeroiter(convert=True, sparse=False)
Iteration over the entries in the matrix
INPUT:• convert – If True, the entries are converted to the base right. If False, the entries are returned asgiven.
• sparse – See OUTPUT below.
OUTPUT: iterator• If sparse is False: yield all entries of the matrix in the following order:

118

Chapter 4. Helpers for creating matrices

Matrices and Spaces of Matrices, Release 10.4

[1 2 3][4 5 6]• If sparse is True: yield instances of SparseEntry. The indices (i, j) are guaranteed to lie
within the matrix. Zero entries in the input are not skipped.
Warning: If an iterator is given as input to MatrixArgs, it may be exhausted breaking any further
usage. Otherwise, it is safe to iterate multiple times.
EXAMPLES:
sage: from sage.matrix.args import SparseEntry, MatrixArgs
sage: ma = MatrixArgs(ZZ, 2, 3, iter(range(6)))
sage: list(ma.iter())[0, 1, 2, 3, 4, 5]
sage: ma = MatrixArgs(ZZ, 3, 3, [SparseEntry(0, 0, 0)])sage: list(ma.iter())
Traceback (most recent call last):...
TypeError: dense iteration is not supported for sparse input>>> from sage.all import *>>> from sage.matrix.args import SparseEntry, MatrixArgs>>> ma = MatrixArgs(ZZ, Integer(2), Integer(3), iter(range(Integer(6))))>>> list(ma.iter())[0, 1, 2, 3, 4, 5]>>> ma = MatrixArgs(ZZ, Integer(3), Integer(3), [SparseEntry(Integer(0),␣
˓→Integer(0), Integer(0))])>>> list(ma.iter())
Traceback (most recent call last):...
TypeError: dense iteration is not supported for sparse input

Sparse examples:sage: ma = MatrixArgs(3, 3, pi)
˓→needs sage.symbolic
sage: list(ma.iter(sparse=True))
˓→needs sage.symbolic[SparseEntry(0, 0, pi), SparseEntry(1, 1, pi), SparseEntry(2, 2, pi)]sage: ma = MatrixArgs(2, 3)
sage: list(ma.iter(sparse=True))[]sage: ma = MatrixArgs(2, 2, lambda i, j: i > j)sage: list(ma.iter(convert=False, sparse=True))[SparseEntry(0, 0, False),
SparseEntry(0, 1, False),
SparseEntry(1, 0, True),SparseEntry(1, 1, False)]
sage: ma = MatrixArgs(2, 2, {(1,0):88, (0,1):89})
sage: sorted(tuple(x) for x in ma.iter(sparse=True))[(0, 1, 89), (1, 0, 88)]
sage: ma = MatrixArgs(QQ, 2, 1, {(1,0):88, (0,1):89})
sage: ma.finalized()
Traceback (most recent call last):#␣#␣(continues on next page)119

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
IndexError: invalid column index 1
sage: ma = MatrixArgs(QQ, 1, 2, {(1,0):88, (0,1):89})
sage: ma.finalized()
Traceback (most recent call last):...
IndexError: invalid row index 1>>> from sage.all import *>>> ma = MatrixArgs(Integer(3), Integer(3), pi)˓→# needs sage.symbolic>>> list(ma.iter(sparse=True))
˓→needs sage.symbolic[SparseEntry(0, 0, pi), SparseEntry(1, 1, pi), SparseEntry(2, 2, pi)]>>> ma = MatrixArgs(Integer(2), Integer(3))>>> list(ma.iter(sparse=True))[]>>> ma = MatrixArgs(Integer(2), Integer(2), lambda i, j: i > j)>>> list(ma.iter(convert=False, sparse=True))[SparseEntry(0, 0, False),
SparseEntry(0, 1, False),
SparseEntry(1, 0, True),SparseEntry(1, 1, False)]>>> ma = MatrixArgs(Integer(2), Integer(2), {(Integer(1),˓→Integer(0)):Integer(88), (Integer(0),Integer(1)):Integer(89)})>>> sorted(tuple(x) for x in ma.iter(sparse=True))[(0, 1, 89), (1, 0, 88)]>>> ma = MatrixArgs(QQ, Integer(2), Integer(1), {(Integer(1),˓→Integer(0)):Integer(88), (Integer(0),Integer(1)):Integer(89)})>>> ma.finalized()
Traceback (most recent call last):...
IndexError: invalid column index 1>>> ma = MatrixArgs(QQ, Integer(1), Integer(2), {(Integer(1),˓→Integer(0)):Integer(88), (Integer(0),Integer(1)):Integer(89)})>>> ma.finalized()
Traceback (most recent call last):...
IndexError: invalid row index 1

␣
#␣

kwds
list(convert=True)
Return the entries of the matrix as a flat list of scalars.
If possible and convert=False, this returns a direct reference to self.entries without copying.
INPUT:• convert – If True, the entries are converted to the base ring. Otherwise, the entries are returned asgiven.
Note: This changes self.entries to the returned list. This means that it is unsafe to access the self.
entries attribute after calling this method.
EXAMPLES:

120

Chapter 4. Helpers for creating matrices

Matrices and Spaces of Matrices, Release 10.4

sage: from sage.matrix.args import MatrixArgs
sage: L = list(range(6))
sage: MatrixArgs(2, 3, L).list()[0, 1, 2, 3, 4, 5]>>> from sage.all import *>>> from sage.matrix.args import MatrixArgs>>> L = list(range(Integer(6)))>>> MatrixArgs(Integer(2), Integer(3), L).list()[0, 1, 2, 3, 4, 5]
sage: ma = MatrixArgs(RDF, 2, 3, L)
sage: ma.list(convert=False)[0, 1, 2, 3, 4, 5]
sage: ma.list()[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]>>> from sage.all import *>>> ma = MatrixArgs(RDF, Integer(2), Integer(3), L)>>> ma.list(convert=False)[0, 1, 2, 3, 4, 5]>>> ma.list()[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]

If we remove our reference to the input L and convert=False, no copy is made:sage: idL = id(L)sage: ma = MatrixArgs(2, 3, L)
sage: del L
sage: L = ma.list(convert=False)
sage: id(L) == idL
True>>> from sage.all import *>>> idL = id(L)>>> ma = MatrixArgs(Integer(2), Integer(3), L)>>> del L>>> L = ma.list(convert=False)>>> id(L) == idL
Truematrix(convert=True)
Return the entries of the matrix as a Sage Matrix.
If possible, this returns a direct reference to self.entries without copying.
INPUT:• convert – if True, the matrix is guaranteed to have the correct parent matrix space. If False, theinput matrix may be returned even if it lies in the wrong space.
Note: This changes self.entries to the returned matrix. This means that it is unsafe to access theself.entries attribute after calling this method.
EXAMPLES:

121

Matrices and Spaces of Matrices, Release 10.4

sage: from sage.matrix.args import MatrixArgs
sage: M = matrix(2, 3, range(6), sparse=True)>>> from sage.all import *>>> from sage.matrix.args import MatrixArgs>>> M = matrix(Integer(2), Integer(3), range(Integer(6)), sparse=True)
sage: ma = MatrixArgs(M); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 3 sparse matrices
over Integer Ring; typ=MATRIX; entries=[0 1 2]
[3 4 5]>sage: ma.matrix()[0 1 2][3 4 5]>>> from sage.all import *>>> ma = MatrixArgs(M); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 3 sparse matrices
over Integer Ring; typ=MATRIX; entries=[0 1 2]
[3 4 5]>>>> ma.matrix()[0 1 2][3 4 5]sage: ma = MatrixArgs(M, sparse=False); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 3 dense matrices
over Integer Ring; typ=MATRIX; entries=[0 1 2]
[3 4 5]>sage: ma.matrix()[0 1 2][3 4 5]>>> from sage.all import *>>> ma = MatrixArgs(M, sparse=False); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 3 dense matrices
over Integer Ring; typ=MATRIX; entries=[0 1 2]
[3 4 5]>>>> ma.matrix()[0 1 2][3 4 5]sage: ma = MatrixArgs(RDF, M); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 3 sparse matrices
over Real Double Field; typ=MATRIX; entries=[0 1 2]
[3 4 5]>sage: ma.matrix(convert=False)[0 1 2][3 4 5]sage: ma.matrix()[0.0 1.0 2.0]
[3.0 4.0 5.0]>>> from sage.all import *>>> ma = MatrixArgs(RDF, M); ma.finalized()<MatrixArgs for Full MatrixSpace of 2 by 3 sparse matrices(continues on next page)

122

Chapter 4. Helpers for creating matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

over Real Double Field; typ=MATRIX; entries=[0 1 2]
[3 4 5]>>>> ma.matrix(convert=False)[0 1 2][3 4 5]>>> ma.matrix()[0.0 1.0 2.0]
[3.0 4.0 5.0]

If we remove our reference to the input M, no copy is made:sage: idM = id(M)sage: ma = MatrixArgs(M)sage: del M
sage: M = ma.matrix()
sage: id(M) == idM
True>>> from sage.all import *>>> idM = id(M)>>> ma = MatrixArgs(M)>>> del M>>> M = ma.matrix()>>> id(M) == idM
True

Immutable matrices are never copied:sage: M.set_immutable()sage: matrix(M) is M
True>>> from sage.all import *>>> M.set_immutable()>>> matrix(M) is M
True

ncols
nrows
row_keys
set_column_keys(column_keys)
Set the column keys with consistency checking.
If the value was previously set, it must remain the same.
EXAMPLES:
sage: from sage.matrix.args import MatrixArgs
sage: ma = MatrixArgs(2, 4)
sage: ma.set_column_keys( xyz )Traceback (most recent call last):...
ValueError: inconsistent column keys: should be of cardinality 4 but got xyz(continues on next page)123

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: ma.set_column_keys( abcd )0sage: ma.finalized()<MatrixArgs for
Set of Morphisms
from Free module generated by { a , b , c , d } over Integer Ringto Ambient free module of rank 2 over the principal ideal domain
Integer Ringin Category of finite dimensional modules with basis over
(Dedekind domains and euclidean domains
and noetherian rings and infinite enumerated sets
and metric spaces);
typ=ZERO; entries=None>>>> from sage.all import *>>> from sage.matrix.args import MatrixArgs>>> ma = MatrixArgs(Integer(2), Integer(4))>>> ma.set_column_keys( xyz )Traceback (most recent call last):...
ValueError: inconsistent column keys: should be of cardinality 4 but got xyz>>> ma.set_column_keys( abcd )0>>> ma.finalized()<MatrixArgs for
Set of Morphisms
from Free module generated by { a , b , c , d } over Integer Ringto Ambient free module of rank 2 over the principal ideal domain
Integer Ringin Category of finite dimensional modules with basis over
(Dedekind domains and euclidean domains
and noetherian rings and infinite enumerated sets
and metric spaces);
typ=ZERO; entries=None>

set_row_keys(row_keys)
Set the row keys with consistency checking.
If the value was previously set, it must remain the same.
EXAMPLES:
sage: from sage.matrix.args import MatrixArgs
sage: ma = MatrixArgs(2, 4)
sage: ma.set_row_keys( xyz )Traceback (most recent call last):...
ValueError: inconsistent row keys: should be of cardinality 2 but got xyz
sage: ma.set_row_keys([ u , v ])0
sage: ma.finalized()<MatrixArgs for
Set of Morphisms
from Ambient free module of rank 4 over the principal ideal domain
Integer Ring
to Free module generated by { u , v } over Integer Ringin Category of finite dimensional modules with basis over(continues on next page)

124

Chapter 4. Helpers for creating matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)(Dedekind domains and euclidean domains
and noetherian rings and infinite enumerated sets
and metric spaces);
typ=ZERO; entries=None>>>> from sage.all import *>>> from sage.matrix.args import MatrixArgs>>> ma = MatrixArgs(Integer(2), Integer(4))>>> ma.set_row_keys( xyz )Traceback (most recent call last):...
ValueError: inconsistent row keys: should be of cardinality 2 but got xyz>>> ma.set_row_keys([ u , v ])0>>> ma.finalized()<MatrixArgs for
Set of Morphisms
from Ambient free module of rank 4 over the principal ideal domain
Integer Ring
to Free module generated by { u , v } over Integer Ringin Category of finite dimensional modules with basis over
(Dedekind domains and euclidean domains
and noetherian rings and infinite enumerated sets
and metric spaces);
typ=ZERO; entries=None>

set_space(space)
Set inputs from a given matrix space.
INPUT:• space – a MatrixSpace or a homset of modules with basis
EXAMPLES:
sage: from sage.matrix.args import MatrixArgs
sage: ma = MatrixArgs()
sage: S = MatrixSpace(QQ, 3, 2, sparse=True)
sage: _ = ma.set_space(S)sage: ma.finalized()<MatrixArgs for Full MatrixSpace of 3 by 2 sparse matrices
over Rational Field; typ=ZERO; entries=None>sage: M = ma.matrix(); M
[0 0]
[0 0]
[0 0]
sage: M.parent() is S
True>>> from sage.all import *>>> from sage.matrix.args import MatrixArgs>>> ma = MatrixArgs()>>> S = MatrixSpace(QQ, Integer(3), Integer(2), sparse=True)>>> _ = ma.set_space(S)>>> ma.finalized()<MatrixArgs for Full MatrixSpace of 3 by 2 sparse matrices
over Rational Field; typ=ZERO; entries=None>(continues on next page)125

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> M = ma.matrix(); M
[0 0]
[0 0]
[0 0]
>>> M.parent() is S
True

From a homset:
sage: C = CombinatorialFreeModule(ZZ, [ a , b , c ])sage: R = CombinatorialFreeModule(ZZ, [ u , v ])sage: S = Hom(C, R); S
Set of Morphisms
from Free module generated by { a , b , c } over Integer Ring
to Free module generated by { u , v } over Integer Ringin Category of finite dimensional modules with basis over Integer Ringsage: ma = MatrixArgs()
sage: _ = ma.set_space(S)sage: ma.finalized()<MatrixArgs for Set of Morphisms
from Free module generated by { a , b , c } over Integer Ring
to Free module generated by { u , v } over Integer Ringin Category of finite dimensional modules with basis over Integer Ring;
typ=ZERO; entries=None>>>> from sage.all import *>>> C = CombinatorialFreeModule(ZZ, [ a , b , c ])>>> R = CombinatorialFreeModule(ZZ, [ u , v ])>>> S = Hom(C, R); S
Set of Morphisms
from Free module generated by { a , b , c } over Integer Ring
to Free module generated by { u , v } over Integer Ringin Category of finite dimensional modules with basis over Integer Ring>>> ma = MatrixArgs()>>> _ = ma.set_space(S)>>> ma.finalized()<MatrixArgs for Set of Morphisms
from Free module generated by { a , b , c } over Integer Ring
to Free module generated by { u , v } over Integer Ringin Category of finite dimensional modules with basis over Integer Ring;
typ=ZERO; entries=None>spacesparsesage.matrix.args.MatrixArgs_init(space, entries)
Construct a MatrixArgs object from a matrix space and entries. This is the typical use in a matrix constructor.
If the given entries is already an instance of MatrixArgs, then just set the space and return the same object.
EXAMPLES:
sage: from sage.matrix.args import MatrixArgs_init
sage: S = MatrixSpace(GF(2), 2, 4)
sage: ma = MatrixArgs_init(S, {(1, 3): 7})sage: M = ma.matrix(); M(continues on next page)

126

Chapter 4. Helpers for creating matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 0 0 0][0 0 0 1]
sage: parent(M) is S
True>>> from sage.all import *>>> from sage.matrix.args import MatrixArgs_init>>> S = MatrixSpace(GF(Integer(2)), Integer(2), Integer(4))>>> ma = MatrixArgs_init(S, {(Integer(1), Integer(3)): Integer(7)})>>> M = ma.matrix(); M[0 0 0 0][0 0 0 1]>>> parent(M) is S
Trueclass sage.matrix.args.SparseEntry
Bases: object
Specialized class for dealing with sparse input in MatrixArgs. An instance of SparseEntry represents one
position in a matrix to be constructed. To construct a sparse matrix, one would typically make a list of such.
Previous versions of Sage used a dict as data structure for sparse input, but that is not so suitable because thekeys are not guaranteed to be of the correct format. There is also the performance cost of creating tuples of Python
integers.
Users of this class are expected to know what they are doing, so the indices are not checked when constructing amatrix.
INPUT:• i, j – row and column index• entry – value to be put at position (𝑖, 𝑗)
EXAMPLES:
sage: from sage.matrix.args import SparseEntry
sage: SparseEntry(123, 456, "abc")
SparseEntry(123, 456, abc )sage: SparseEntry(1/3, 2/3, x)
˓→needs sage.symbolic
Traceback (most recent call last):...
TypeError: unable to convert rational 1/3 to an integer>>> from sage.all import *>>> from sage.matrix.args import SparseEntry>>> SparseEntry(Integer(123), Integer(456), "abc")
SparseEntry(123, 456, abc )>>> SparseEntry(Integer(1)/Integer(3), Integer(2)/Integer(3), x)˓→# needs sage.symbolic
Traceback (most recent call last):...
TypeError: unable to convert rational 1/3 to an integer

#␣

␣

entry

127

Matrices and Spaces of Matrices, Release 10.4

i
j

128

Chapter 4. Helpers for creating matrices

CHAPTERFIVE

MATRICES OVER AN ARBITRARY RINGAUTHORS:• William Stein• Martin Albrecht: conversion to Pyrex• Jaap Spies: various functions• Gary Zablackis: fixed a sign bug in generic determinant.
• William Stein and Robert Bradshaw - complete restructuring.
• Rob Beezer - refactor kernel functions.
Elements of matrix spaces are of class Matrix (or a class derived from Matrix). They can be either sparse or dense, andcan be defined over any base ring.
EXAMPLES:
We create the 2 × 3 matrix(︂1
4
as an element of a matrix space over

2
5

3
6

)︂

:

sage: M = MatrixSpace(QQ,2,3)
sage: A = M([1,2,3, 4,5,6]); A[1 2 3][4 5 6]sage: A.parent()
Full MatrixSpace of 2 by 3 dense matrices over Rational Field>>> from sage.all import *>>> M = MatrixSpace(QQ,Integer(2),Integer(3))>>> A = M([Integer(1),Integer(2),Integer(3), Integer(4),Integer(5),Integer(6)]); A[1 2 3][4 5 6]>>> A.parent()
Full MatrixSpace of 2 by 3 dense matrices over Rational Field

Alternatively, we could create A more directly as follows (which would completely avoid having to create the matrix
space):
sage: A = matrix(QQ, 2, [1,2,3, 4,5,6]); A[1 2 3][4 5 6]129

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = matrix(QQ, Integer(2), [Integer(1),Integer(2),Integer(3), Integer(4),˓→Integer(5),Integer(6)]); A[1 2 3][4 5 6]

We next change the top-right entry of 𝐴. Note that matrix indexing is 0-based in Sage, so the top right entry is (0, 2),which should be thought of as “row number 0, column number 2”.
sage: A[0,2] = 389
sage: A[ 1
2 389][ 4
5
6]>>> from sage.all import *>>> A[Integer(0),Integer(2)] = Integer(389)
>>> A
[ 1
2 389][ 4
5
6]

Also notice how matrices print. All columns have the same width and entries in a given column are right justified. Next
we compute the reduced row echelon form of 𝐴.
sage: A.rref()[1
0 -1933/3][
0
1 1550/3]>>> from sage.all import *>>> A.rref()[1
0 -1933/3][
0
1 1550/3]

5.1 Indexing
Sage has quite flexible ways of extracting elements or submatrices from a matrix:
sage: m=[(1, -2, -1, -1,9), (1, 8, 6, 2,2), (1, 1, -1, 1,4), (-1, 2, -2, -1,4)] ; M =␣˓→matrix(m)sage: M[ 1 -2 -1 -1 9][ 1 8 6 2 2]
[ 1 1 -1 1 4][-1 2 -2 -1 4]>>> from sage.all import *>>> m=[(Integer(1), -Integer(2), -Integer(1), -Integer(1),Integer(9)), (Integer(1),␣
˓→Integer(8), Integer(6), Integer(2),Integer(2)), (Integer(1), Integer(1), ˓→Integer(1), Integer(1),Integer(4)), (-Integer(1), Integer(2), -Integer(2), ˓→Integer(1),Integer(4))] ; M = matrix(m)>>> M[ 1 -2 -1 -1 9][ 1 8 6 2 2]
[ 1 1 -1 1 4][-1 2 -2 -1 4]

130

Chapter 5. Matrices over an arbitrary ring

Matrices and Spaces of Matrices, Release 10.4

Get the 2 x 2 submatrix of M, starting at row index and column index 1:
sage: M[1:3,1:3][ 8 6][ 1 -1]>>> from sage.all import *>>> M[Integer(1):Integer(3),Integer(1):Integer(3)][ 8 6][ 1 -1]

Get the 2 x 3 submatrix of M starting at row index and column index 1:
sage: M[1:3,[1..3]][ 8 6 2]
[ 1 -1 1]>>> from sage.all import *>>> M[Integer(1):Integer(3),(ellipsis_range(Integer(1),Ellipsis,Integer(3)))][ 8 6 2]
[ 1 -1 1]

Get the second column of M:
sage: M[:,1]
[-2]
[ 8]
[ 1]
[ 2]
>>> from sage.all import *>>> M[:,Integer(1)]
[-2]
[ 8]
[ 1]
[ 2]

Get the first row of M:
sage: M[0,:][ 1 -2 -1 -1

9]>>> from sage.all import *>>> M[Integer(0),:][ 1 -2 -1 -1 9]

Get the last row of M (negative numbers count from the end):
sage: M[-1,:][-1 2 -2 -1 4]>>> from sage.all import *>>> M[-Integer(1),:][-1 2 -2 -1 4]More examples:

5.1. Indexing131Matrices and Spaces of Matrices, Release 10.4

sage: M[range(2),:][ 1 -2 -1 -1 9][ 1 8 6 2 2]
sage: M[range(2),4][9][2]
sage: M[range(3),range(5)][ 1 -2 -1 -1 9][ 1 8 6 2 2]
[ 1 1 -1 1 4]
sage: M[3,range(5)][-1 2 -2 -1 4]
sage: M[3,:][-1 2 -2 -1 4]
sage: M[3,4]4sage: M[-1,:][-1 2 -2 -1 4]
sage: A = matrix(ZZ,3,4, [3, 2, -5, 0, 1, -1, 1, -4, 1, 0, 1, -3]); A[ 3 2 -5 0][ 1 -1 1 -4][ 1 0 1 -3]>>> from sage.all import *>>> M[range(Integer(2)),:][ 1 -2 -1 -1 9][ 1 8 6 2 2]>>> M[range(Integer(2)),Integer(4)][9][2]>>> M[range(Integer(3)),range(Integer(5))][ 1 -2 -1 -1 9][ 1 8 6 2 2]
[ 1 1 -1 1 4]>>> M[Integer(3),range(Integer(5))][-1 2 -2 -1 4]>>> M[Integer(3),:][-1 2 -2 -1 4]>>> M[Integer(3),Integer(4)]4>>> M[-Integer(1),:][-1 2 -2 -1 4]>>> A = matrix(ZZ,Integer(3),Integer(4), [Integer(3), Integer(2), -Integer(5),␣
˓→Integer(0), Integer(1), -Integer(1), Integer(1), -Integer(4), Integer(1),␣
˓→Integer(0), Integer(1), -Integer(3)]); A[ 3 2 -5 0][ 1 -1 1 -4][ 1 0 1 -3]

A series of three numbers, separated by colons, like n:m:s, means numbers from n up to (but not including) m, in stepsof s. So 0:5:2 means the sequence [0,2,4]:132

Chapter 5. Matrices over an arbitrary ring

Matrices and Spaces of Matrices, Release 10.4

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

We can also change submatrices using these indexing features:

5.1. Indexing133

Matrices and Spaces of Matrices, Release 10.4

sage: M=matrix([(1, -2, -1, -1,9), (1, 8, 6, 2,2), (1, 1, -1, 1,4), (-1, 2, -2, -1,˓→4)]); M[ 1 -2 -1 -1 9][ 1 8 6 2 2]
[ 1 1 -1 1 4][-1 2 -2 -1 4]>>> from sage.all import *>>> M=matrix([(Integer(1), -Integer(2), -Integer(1), -Integer(1),Integer(9)),␣
˓→(Integer(1), Integer(8), Integer(6), Integer(2),Integer(2)), (Integer(1),␣
˓→Integer(1), -Integer(1), Integer(1),Integer(4)), (-Integer(1), Integer(2), ˓→Integer(2), -Integer(1),Integer(4))]); M[ 1 -2 -1 -1 9][ 1 8 6 2 2]
[ 1 1 -1 1 4][-1 2 -2 -1 4]

Set the 2 x 2 submatrix of M, starting at row index and column index 1:
sage: M[1:3,1:3] = [[1,0],[0,1]]; M[ 1 -2 -1 -1 9][ 1 1 0 2 2]
[ 1 0 1 1 4][-1 2 -2 -1 4]>>> from sage.all import *>>> M[Integer(1):Integer(3),Integer(1):Integer(3)] = [[Integer(1),Integer(0)],˓→[Integer(0),Integer(1)]]; M[ 1 -2 -1 -1 9][ 1 1 0 2 2]
[ 1 0 1 1 4][-1 2 -2 -1 4]

Set the 2 x 3 submatrix of M starting at row index and column index 1:
sage: M[1:3,[1..3]] = M[2:4,0:3]; M[ 1 -2 -1 -1 9][ 1 1 0 1 2]
[ 1 -1 2 -2 4][-1 2 -2 -1 4]>>> from sage.all import *>>> M[Integer(1):Integer(3),(ellipsis_range(Integer(1),Ellipsis,Integer(3)))] =␣
˓→M[Integer(2):Integer(4),Integer(0):Integer(3)]; M[ 1 -2 -1 -1 9][ 1 1 0 1 2]
[ 1 -1 2 -2 4][-1 2 -2 -1 4]

Set part of the first column of M:
sage: M[1:,0]=[[2],[3],[4]]; M[ 1 -2 -1 -1 9][ 2 1 0 1 2]
[ 3 -1 2 -2 4][ 4 2 -2 -1 4]

134

Chapter 5. Matrices over an arbitrary ring

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> M[Integer(1):,Integer(0)]=[[Integer(2)],[Integer(3)],[Integer(4)]]; M[ 1 -2 -1 -1 9][ 2 1 0 1 2]
[ 3 -1 2 -2 4][ 4 2 -2 -1 4]

Or do a similar thing with a vector:
sage: M[1:,0]=vector([-2,-3,-4]); M[ 1 -2 -1 -1 9][-2 1 0 1 2][-3 -1 2 -2 4][-4 2 -2 -1 4]>>> from sage.all import *>>> M[Integer(1):,Integer(0)]=vector([-Integer(2),-Integer(3),-Integer(4)]); M[ 1 -2 -1 -1 9][-2 1 0 1 2][-3 -1 2 -2 4][-4 2 -2 -1 4]

Or a constant:sage: M[1:,0]=30; M[ 1 -2 -1 -1 9][30 1 0 1 2]
[30 -1 2 -2 4][30 2 -2 -1 4]>>> from sage.all import *>>> M[Integer(1):,Integer(0)]=Integer(30); M[ 1 -2 -1 -1 9][30 1 0 1 2]
[30 -1 2 -2 4][30 2 -2 -1 4]

Set the first row of M:
sage: M[0,:]=[[20,21,22,23,24]]; M[20 21 22 23 24][30 1 0 1 2]
[30 -1 2 -2 4][30 2 -2 -1 4]
sage: M[0,:]=vector([0,1,2,3,4]); M[ 0 1 2 3 4][30 1 0 1 2]
[30 -1 2 -2 4][30 2 -2 -1 4]
sage: M[0,:]=-3; M[-3 -3 -3 -3 -3][30 1 0 1 2]
[30 -1 2 -2 4][30 2 -2 -1 4]

sage: A = matrix(ZZ,3,4, [3, 2, -5, 0, 1, -1, 1, -4, 1, 0, 1, -3]); A(continues on next page)

5.1. Indexing

135

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 3 2 -5 0][ 1 -1 1 -4][ 1 0 1 -3]>>> from sage.all import *>>> M[Integer(0),:]=[[Integer(20),Integer(21),Integer(22),Integer(23),Integer(24)]]; M[20 21 22 23 24][30 1 0 1 2]
[30 -1 2 -2 4][30 2 -2 -1 4]>>> M[Integer(0),:]=vector([Integer(0),Integer(1),Integer(2),Integer(3),Integer(4)]);␣
˓→M[ 0 1 2 3 4][30 1 0 1 2]
[30 -1 2 -2 4][30 2 -2 -1 4]>>> M[Integer(0),:]=-Integer(3); M[-3 -3 -3 -3 -3][30 1 0 1 2]
[30 -1 2 -2 4][30 2 -2 -1 4]>>> A = matrix(ZZ,Integer(3),Integer(4), [Integer(3), Integer(2), -Integer(5),␣
˓→Integer(0), Integer(1), -Integer(1), Integer(1), -Integer(4), Integer(1),␣
˓→Integer(0), Integer(1), -Integer(3)]); A[ 3 2 -5 0][ 1 -1 1 -4][ 1 0 1 -3]

We can use the step feature of slices to set every other column:
sage: A[:,0:3:2] = 5; A
[ 5 2 5 0]
[ 5 -1 5 -4][ 5 0 5 -3]
sage: A[1:,0:4:2] = [[100,200],[300,400]]; A
[ 5
2
5
0]
[100 -1 200 -4][300
0 400 -3]>>> from sage.all import *>>> A[:,Integer(0):Integer(3):Integer(2)] = Integer(5); A[ 5 2 5 0]
[ 5 -1 5 -4][ 5 0 5 -3]>>> A[Integer(1):,Integer(0):Integer(4):Integer(2)] = [[Integer(100),Integer(200)],
˓→[Integer(300),Integer(400)]]; A
[ 5
2
5
0]
[100 -1 200 -4][300
0 400 -3]

We can also count backwards to flip the matrix upside down:

136

Chapter 5. Matrices over an arbitrary ring

Matrices and Spaces of Matrices, Release 10.4

sage: A[::-1,:]=A; A[300
0 400 -3][100 -1 200 -4]
[ 5
2
5
0]

sage: A[1:,3::-1]=[[2,3,0,1],[9,8,7,6]]; A[300
0 400 -3]
[ 1
0
3
2]
[ 6
7
8
9]
sage: A[1:,::-2] = A[1:,::2]; A[300
0 400 -3]
[ 1
3
3
1]
[ 6
8
8
6]
sage: A[::-1,3:1:-1] = [[4,3],[1,2],[-1,-2]]; A[300
0 -2 -1]
[ 1
3
2
1]
[ 6
8
3
4]
>>> from sage.all import *>>> A[::-Integer(1),:]=A; A[300
0 400 -3][100 -1 200 -4]
[ 5
2
5
0]

>>> A[Integer(1):,Integer(3)::-Integer(1)]=[[Integer(2),Integer(3),Integer(0),˓→Integer(1)],[Integer(9),Integer(8),Integer(7),Integer(6)]]; A[300
0 400 -3]
[ 1
0
3
2]
[ 6
7
8
9]
>>> A[Integer(1):,::-Integer(2)] = A[Integer(1):,::Integer(2)]; A[300
0 400 -3]
[ 1
3
3
1]
[ 6
8
8
6]
>>> A[::-Integer(1),Integer(3):Integer(1):-Integer(1)] = [[Integer(4),Integer(3)],
˓→[Integer(1),Integer(2)],[-Integer(1),-Integer(2)]]; A[300
0 -2 -1]
[ 1
3
2
1]
[ 6
8
3
4]

We save and load a matrix:
sage: A = matrix(Integers(8),3,range(9))
sage: loads(dumps(A)) == A
True>>> from sage.all import *>>> A = matrix(Integers(Integer(8)),Integer(3),range(Integer(9)))>>> loads(dumps(A)) == A
True

MUTABILITY: Matrices are either immutable or not. When initially created, matrices are typically mutable, so one can

5.1. Indexing137

Matrices and Spaces of Matrices, Release 10.4

change their entries. Once a matrix 𝐴 is made immutable using A.set_immutable() the entries of 𝐴 cannot bechanged, and 𝐴 can never be made mutable again. However, properties of 𝐴 such as its rank, characteristic polynomial,etc., are all cached so computations involving 𝐴 may be more efficient. Once 𝐴 is made immutable it cannot be changed
back. However, one can obtain a mutable copy of 𝐴 using copy(A).
EXAMPLES:
sage: A = matrix(RR,2,[1,10,3.5,2])
sage: A.set_immutable()sage: copy(A) is A
False>>> from sage.all import *>>> A = matrix(RR,Integer(2),[Integer(1),Integer(10),RealNumber( 3.5 ),Integer(2)])>>> A.set_immutable()>>> copy(A) is A
False

The echelon form method always returns immutable matrices with known rank.
EXAMPLES:
sage: A = matrix(Integers(8),3,range(9))
sage: A.determinant()
0sage: A[0,0] = 5
sage: A.determinant()
1sage: A.set_immutable()sage: A[0,0] = 5
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).
>>> from sage.all import *>>> A = matrix(Integers(Integer(8)),Integer(3),range(Integer(9)))>>> A.determinant()
0>>> A[Integer(0),Integer(0)] = Integer(5)>>> A.determinant()
1>>> A.set_immutable()>>> A[Integer(0),Integer(0)] = Integer(5)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).

138

Chapter 5. Matrices over an arbitrary ring

Matrices and Spaces of Matrices, Release 10.4

5.1.1 Implementation and Design
Class Diagram (an x means that class is currently supported):x Matrixx
Matrix_sparsex
Matrix_generic_sparsex
Matrix_integer_sparsex
Matrix_rational_sparse
Matrix_cyclo_sparsex
Matrix_modn_sparse
Matrix_RR_sparse
Matrix_CC_sparse
Matrix_RDF_sparse
Matrix_CDF_sparsexxxx

Matrix_dense
Matrix_generic_dense
Matrix_integer_dense
Matrix_rational_dense
Matrix_cyclo_dense-- idea: restrict scalars to QQ, compute charpoly there,␣˓→then factorxMatrix_modn_dense
Matrix_RR_dense
Matrix_CC_densexMatrix_real_double_densexMatrix_complex_double_densexMatrix_complex_ball_dense

The corresponding files in the sage/matrix library code directory are named[matrix] [base ring] [dense or sparse].
New matrices types can only be implemented in Cython.
*********** LEVEL 1 **********NON-OPTIONAL
For each base field it is *absolutely* essential to completely
implement the following functionality for that base ring:* __cinit__-- should use check_allocarray from cysignals.memory(only needed if allocate memory)-- this signature: def __init__(self, parent, entries, copy,␣

* __init__
coerce)* __dealloc__-- use sig_free (only needed if allocate memory)* set_unsafe(self, size_t i, size_t j, x) -- doesn t do bounds or any other checks;
˓→ assumes x is in self._base_ring* get_unsafe(self, size_t i, size_t j) -- doesn t do checks* __richcmp__-- always the same (I don t know why its needed -- bug in PYREX).
˓→

Note that the __init__ function must construct the all zero matrix if
˓→None.
*********** LEVEL 2

entries ==␣

**********

IMPORTANT (and *highly* recommended):(continues on next page)

5.1. Indexing139

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

After getting the special class with all level 1 functionality towork, implement all of the following (they should not change
functionality, except speed (always faster!) in any way):* def _pickle(self):
return data, version* def _unpickle(self, data, int version)reconstruct matrix from given data and version; may assume _parent, _nrows,␣
˓→and _ncols are set.
Use version numbers >= 0 so if you change the pickle strategy thenold objects still unpickle.
* cdef _list -- list of underlying elements (need not be a copy)* cdef _dict -- sparse dictionary of underlying elements* cdef _add_ -- add two matrices with identical parents* _matrix_times_matrix_c_impl -- multiply two matrices with compatible dimensions␣˓→andidentical base rings (both sparse or both dense)* cpdef _richcmp_ -- compare two matrices with identical parents* cdef _lmul_c_impl -- multiply this matrix on the right by a scalar, i.e., self *␣˓→scalar* cdef _rmul_c_impl -- multiply this matrix on the left by a scalar, i.e., scalar␣
˓→* self* __copy__* __neg__
The list and dict returned by _list and _dict will *not* be changedby any internal algorithms and are not accessible to the user.
*********** LEVEL 3
OPTIONAL:*********** cdef _sub_* __invert__* _multiply_classical* __deepcopy__
Further special support:* Matrix windows -- to support Strassen multiplication for a given base ring.
* Other functions, e.g., transpose, for which knowing thespecific representation can be helpful.
.. note::- For caching, use self.fetch and self.cache.
- Any method that can change the matrix should callcheck_mutability()
first. There are also many fast cdef d bounds checking␣˓→methods.
- Kernels of matrices
Implement only a left_kernel() or right_kernel() method, whichever requires
the least overhead (usually meaning little or no transposing). Let themethods in the matrix2 class handle left, right, generic kernel distinctions.

140

Chapter 5. Matrices over an arbitrary ring

CHAPTER

SIXBASE CLASS FOR MATRICES, PART 0

Note: For design documentation see matrix/docs.py.
EXAMPLES:
sage: matrix(2, [1,2,3,4])
[1 2]
[3 4]
>>> from sage.all import *>>> matrix(Integer(2), [Integer(1),Integer(2),Integer(3),Integer(4)])
[1 2]
[3 4]

class sage.matrix.matrix0.Matrix
Bases: Matrix
A generic matrix.
The Matrix class is the base class for all matrix classes. To create a Matrix, first create a MatrixSpace, thencoerce a list of elements into the MatrixSpace. See the documentation of MatrixSpace for more details.
EXAMPLES:
We illustrate matrices and matrix spaces. Note that no actual matrix that you make should have class Matrix; theclass should always be derived from Matrix.
sage: M = MatrixSpace(CDF,2,3); M
Full MatrixSpace of 2 by 3 dense matrices over Complex Double Field
sage: a = M([1,2,3, 4,5,6]); a[1.0 2.0 3.0]
[4.0 5.0 6.0]
sage: type(a)<class sage.matrix.matrix_complex_double_dense.Matrix_complex_double_dense >sage: parent(a)Full MatrixSpace of 2 by 3 dense matrices over Complex Double Field>>> from sage.all import *>>> M = MatrixSpace(CDF,Integer(2),Integer(3)); M
Full MatrixSpace of 2 by 3 dense matrices over Complex Double Field>>> a = M([Integer(1),Integer(2),Integer(3), Integer(4),Integer(5),Integer(6)]);␣
˓→a[1.0 2.0 3.0]
(continues on next page)141

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[4.0 5.0 6.0]>>> type(a)<class sage.matrix.matrix_complex_double_dense.Matrix_complex_double_dense >>>> parent(a)Full MatrixSpace of 2 by 3 dense matrices over Complex Double Field
sage: matrix(CDF, 2,3, [1,2,3, 4,5,6])[1.0 2.0 3.0]
[4.0 5.0 6.0]
sage: Mat(CDF,2,3)(range(1,7))[1.0 2.0 3.0]
[4.0 5.0 6.0]>>> from sage.all import *>>> matrix(CDF, Integer(2),Integer(3), [Integer(1),Integer(2),Integer(3),␣
˓→Integer(4),Integer(5),Integer(6)])[1.0 2.0 3.0]
[4.0 5.0 6.0]>>> Mat(CDF,Integer(2),Integer(3))(range(Integer(1),Integer(7)))[1.0 2.0 3.0]
[4.0 5.0 6.0]
sage: Q.<i,j,k> = QuaternionAlgebra(QQ, -1,-1)
sage: matrix(Q,2,1,[1,2])[1][2]>>> from sage.all import *>>> Q = QuaternionAlgebra(QQ, -Integer(1),-Integer(1), names=( i ,˓→(i, j, k,) = Q._first_ngens(3)>>> matrix(Q,Integer(2),Integer(1),[Integer(1),Integer(2)])
[1]
[2]

j ,

k ,));␣

act_on_polynomial(f)Return the polynomial f(self*x).
INPUT:• self – an nxn matrix• f – a polynomial in n variables x=(x1,…,xn)
OUTPUT: The polynomial f(self*x).
EXAMPLES:
sage: R.<x,y> = QQ[]
sage: x, y = R.gens()
sage: f = x**2 - y**2
sage: M = MatrixSpace(QQ, 2)
sage: A = M([1,2,3,4])
sage: A.act_on_polynomial(f)-8*x^2 - 20*x*y - 12*y^2142Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> R = QQ[ x, y ]; (x, y,) = R._first_ngens(2)>>> x, y = R.gens()>>> f = x**Integer(2) - y**Integer(2)>>> M = MatrixSpace(QQ, Integer(2))>>> A = M([Integer(1),Integer(2),Integer(3),Integer(4)])>>> A.act_on_polynomial(f)-8*x^2 - 20*x*y - 12*y^2

add_multiple_of_column(i, j, s, start_row=0)
Add s times column j to column i.
EXAMPLES: We add -1 times the third column to the second column of an integer matrix, remembering tostart numbering cols at zero:sage: a = matrix(ZZ,2,3,range(6)); a[0 1 2][3 4 5]sage: a.add_multiple_of_column(1,2,-1)
sage: a[ 0 -1 2][ 3 -1 5]>>> from sage.all import *>>> a = matrix(ZZ,Integer(2),Integer(3),range(Integer(6))); a[0 1 2][3 4 5]>>> a.add_multiple_of_column(Integer(1),Integer(2),-Integer(1))>>> a[ 0 -1 2][ 3 -1 5]

To add a rational multiple, we first need to change the base ring:sage: a = a.change_ring(QQ)
sage: a.add_multiple_of_column(1,0,1/3)
sage: a[ 0 -1 2][ 3 0 5]>>> from sage.all import *>>> a = a.change_ring(QQ)>>> a.add_multiple_of_column(Integer(1),Integer(0),Integer(1)/Integer(3))>>> a[ 0 -1 2][ 3 0 5]

If not, we get an error message:
sage: a.add_multiple_of_column(1, 0, SR.I())
˓→needs sage.symbolic
Traceback (most recent call last):...
TypeError: Multiplying column by Symbolic Ring element cannot be done over
Rational Field, use change_ring or with_added_multiple_of_column instead.

#␣

143

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> a.add_multiple_of_column(Integer(1), Integer(0), SR.I())˓→# needs sage.symbolic
Traceback (most recent call last):...
TypeError: Multiplying column by Symbolic Ring element cannot be done over
Rational Field, use change_ring or with_added_multiple_of_column instead.

␣

add_multiple_of_row(i, j, s, start_col=0)
Add s times row j to row i.
EXAMPLES: We add -3 times the first row to the second row of an integer matrix, remembering to start
numbering rows at zero:sage: a = matrix(ZZ,2,3,range(6)); a[0 1 2][3 4 5]sage: a.add_multiple_of_row(1,0,-3)
sage: a[ 0 1 2]
[ 3 1 -1]>>> from sage.all import *>>> a = matrix(ZZ,Integer(2),Integer(3),range(Integer(6))); a[0 1 2][3 4 5]>>> a.add_multiple_of_row(Integer(1),Integer(0),-Integer(3))>>> a[ 0 1 2]
[ 3 1 -1]

To add a rational multiple, we first need to change the base ring:sage: a = a.change_ring(QQ)
sage: a.add_multiple_of_row(1,0,1/3)
sage: a[0
1
2][
3 4/3 -1/3]>>> from sage.all import *>>> a = a.change_ring(QQ)>>> a.add_multiple_of_row(Integer(1),Integer(0),Integer(1)/Integer(3))
>>> a
[
0
1
2]
[
3 4/3 -1/3]

If not, we get an error message:
sage: a.add_multiple_of_row(1, 0, SR.I())
˓→needs sage.symbolic
Traceback (most recent call last):...
TypeError: Multiplying row by Symbolic Ring element cannot be done over
Rational Field, use change_ring or with_added_multiple_of_row instead.

144

#␣

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> a.add_multiple_of_row(Integer(1), Integer(0), SR.I())˓→# needs sage.symbolic
Traceback (most recent call last):...
TypeError: Multiplying row by Symbolic Ring element cannot be done over
Rational Field, use change_ring or with_added_multiple_of_row instead.

␣

add_to_entry(i, j, elt)
Add elt to the entry at position (i, j).
EXAMPLES:
sage: m = matrix(QQ[ x,y ], 2, 2)
sage: m.add_to_entry(0, 1, 2)
sage: m[0 2]
[0 0]>>> from sage.all import *>>> m = matrix(QQ[ x,y ], Integer(2), Integer(2))>>> m.add_to_entry(Integer(0), Integer(1), Integer(2))
>>> m
[0 2]
[0 0]

anticommutator(other)
Return the anticommutator self and other.
The anticommutator of two 𝑛 × 𝑛 matrices 𝐴 and 𝐵 is defined as {𝐴, 𝐵} := 𝐴𝐵 + 𝐵𝐴 (sometimes this is
written as [𝐴, 𝐵]+ ).
EXAMPLES:
sage: A = Matrix(ZZ, 2, 2, range(4))
sage: B = Matrix(ZZ, 2, 2, [0, 1, 0, 0])
sage: A.anticommutator(B)
[2 3]
[0 2]
sage: A.anticommutator(B) == B.anticommutator(A)True
sage: A.commutator(B) + B.anticommutator(A) == 2*A*B
True>>> from sage.all import *>>> A = Matrix(ZZ, Integer(2), Integer(2), range(Integer(4)))>>> B = Matrix(ZZ, Integer(2), Integer(2), [Integer(0), Integer(1),␣
˓→Integer(0), Integer(0)])>>> A.anticommutator(B)
[2 3]
[0 2]
>>> A.anticommutator(B) == B.anticommutator(A)True>>> A.commutator(B) + B.anticommutator(A) == Integer(2)*A*B
True

base_ring()

145

Matrices and Spaces of Matrices, Release 10.4

Return the base ring of the matrix.
EXAMPLES:
sage: m = matrix(QQ, 2, [1,2,3,4])
sage: m.base_ring()
Rational Field>>> from sage.all import *>>> m = matrix(QQ, Integer(2), [Integer(1),Integer(2),Integer(3),Integer(4)])>>> m.base_ring()
Rational Fieldchange_ring(ring)
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: A = Matrix(QQ, 2, 2, [1/2, 1/3, 1/3, 1/4])
sage: A.parent()
Full MatrixSpace of 2 by 2 dense matrices over Rational Field
sage: A.change_ring(GF(25, a ))˓→needs sage.rings.finite_rings
[3 2]
[2 4]
sage: A.change_ring(GF(25, a )).parent()
˓→needs sage.rings.finite_rings
Full MatrixSpace of 2 by 2 dense matrices
over Finite Field in a of size 5^2sage: A.change_ring(ZZ)
˓→needs sage.rings.finite_rings
Traceback (most recent call last):...
TypeError: matrix has denominators so can...t change to ZZ

#␣

#␣

#␣

>>> from sage.all import *>>> A = Matrix(QQ, Integer(2), Integer(2), [Integer(1)/Integer(2), Integer(1)/˓→Integer(3), Integer(1)/Integer(3), Integer(1)/Integer(4)])>>> A.parent()
Full MatrixSpace of 2 by 2 dense matrices over Rational Field>>> A.change_ring(GF(Integer(25), a ))␣˓→
# needs sage.rings.finite_rings
[3 2]
[2 4]
>>> A.change_ring(GF(Integer(25), a )).parent()␣˓→# needs sage.rings.finite_rings
Full MatrixSpace of 2 by 2 dense matrices
over Finite Field in a of size 5^2>>> A.change_ring(ZZ)#␣˓→needs sage.rings.finite_rings
Traceback (most recent call last):...
TypeError: matrix has denominators so can...t change to ZZ

Changing rings preserves subdivisions:146

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

sage: A.subdivide([1], []); A[1/2 1/3][-------][1/3 1/4]
sage: A.change_ring(GF(25, a ))˓→needs sage.rings.finite_rings
[3 2]
[---]
[2 4]

#␣

>>> from sage.all import *>>> A.subdivide([Integer(1)], []); A[1/2 1/3][-------][1/3 1/4]>>> A.change_ring(GF(Integer(25), a ))˓→
# needs sage.rings.finite_rings
[3 2]
[---]
[2 4]

␣

commutator(other)
Return the commutator self*other - other*self.
EXAMPLES:
sage: A = Matrix(ZZ, 2, 2, range(4))
sage: B = Matrix(ZZ, 2, 2, [0, 1, 0, 0])
sage: A.commutator(B)[-2 -3][ 0 2]
sage: A.commutator(B) == -B.commutator(A)True>>> from sage.all import *>>> A = Matrix(ZZ, Integer(2), Integer(2), range(Integer(4)))>>> B = Matrix(ZZ, Integer(2), Integer(2), [Integer(0), Integer(1),␣
˓→Integer(0), Integer(0)])>>> A.commutator(B)[-2 -3][ 0 2]>>> A.commutator(B) == -B.commutator(A)True

dense_coefficient_list(order=None)
Return a list of all coefficients of self.
By default, this is the same as list().
INPUT:• order – (optional) an ordering of the basis indexing set
EXAMPLES:
sage: A = matrix([[1,2,3], [4,5,6]])
sage: A.dense_coefficient_list()[1, 2, 3, 4, 5, 6](continues on next page)147

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: A.dense_coefficient_list([(1,2), (1,0), (0,1), (0,2), (0,0), (1,1)])[6, 4, 2, 3, 1, 5]>>> from sage.all import *>>> A = matrix([[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),˓→Integer(6)]])>>> A.dense_coefficient_list()[1, 2, 3, 4, 5, 6]>>> A.dense_coefficient_list([(Integer(1),Integer(2)), (Integer(1),˓→Integer(0)), (Integer(0),Integer(1)), (Integer(0),Integer(2)), (Integer(0),˓→Integer(0)), (Integer(1),Integer(1))])[6, 4, 2, 3, 1, 5]

dict(copy=True)
Dictionary of the elements of self with keys pairs (i,j) and values the nonzero entries of self.
INPUT:• copy – (default: True) make a copy of the dict corresponding to self
If copy=True, then is safe to change the returned dictionary. Otherwise, this can cause undesired behavior
by mutating the dict.
EXAMPLES:
sage: R.<x,y> = QQ[]
sage: a = matrix(R,2,[x,y,0, 0,0,2*x+y]); a
[
x
y
0]
[
0
0 2*x + y]sage: d = a.dict(); d{(0, 0): x, (0, 1): y, (1, 2): 2*x + y}>>> from sage.all import *>>> R = QQ[ x, y ]; (x, y,) = R._first_ngens(2)>>> a = matrix(R,Integer(2),[x,y,Integer(0), Integer(0),Integer(0),˓→Integer(2)*x+y]); a
[
x
y
0]
[
0
0 2*x + y]>>> d = a.dict(); d{(0, 0): x, (0, 1): y, (1, 2): 2*x + y}

Notice that changing the returned list does not change a (the list is a copy):
sage: d[0,0] = 25
sage: a
[
x
y
0]
[
0
0 2*x + y]>>> from sage.all import *>>> d[Integer(0),Integer(0)] = Integer(25)
>>> a
[
x
y
0]
[
0
0 2*x + y]dimensions()
Return the dimensions of this matrix as the tuple (nrows, ncols).

148

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

EXAMPLES:
sage: M = matrix([[1,2,3],[4,5,6]])
sage: N = M.transpose()sage: M.dimensions()(2, 3)
sage: N.dimensions()(3, 2)>>> from sage.all import *>>> M = matrix([[Integer(1),Integer(2),Integer(3)],[Integer(4),Integer(5),˓→Integer(6)]])>>> N = M.transpose()>>> M.dimensions()(2, 3)>>> N.dimensions()(3, 2)AUTHORS:• Benjamin Lundell (2012-02-09): examples
inverse_of_unit(algorithm=None)
Return the inverse of this matrix in the same matrix space.
The matrix must be invertible on the base ring. Otherwise, an ArithmeticError is raised.
The computation goes through the matrix of cofactors and avoids division. In particular the base ring does
not need to have a fraction field.
INPUT:• algorithm – (default: None) either None or "df" (for division free)
EXAMPLES:
sage: R.<a,b,c,d> = ZZ[]
sage: RR = R.quotient(a*d - b*c - 1)sage: a,b,c,d = RR.gens()
˓→needs sage.libs.singularsage: m = matrix(2, [a,b, c,d])sage: n = m.inverse_of_unit()
˓→needs sage.libs.singularsage: m * n
˓→needs sage.libs.singular
[1 0]
[0 1]

#␣

#␣
#␣

sage: matrix(RR, 2, 1, [a,b]).inverse_of_unit()
˓→needs sage.libs.singularTraceback (most recent call last):...
ArithmeticError: self must be a square matrix#␣

sage: matrix(RR, 1, 1, [2]).inverse_of_unit()
˓→needs sage.libs.singularTraceback (most recent call last):...
ArithmeticError: non-invertible matrix#␣(continues on next page)149

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: R = ZZ.cartesian_product(ZZ)
sage: m = matrix(R, 2, [R((2,1)), R((1,1)), R((1,1)), R((1,2))])sage: m * m.inverse_of_unit()[(1, 1) (0, 0)][(0, 0) (1, 1)]>>> from sage.all import *>>> R = ZZ[ a, b, c, d ]; (a, b, c, d,) = R._first_ngens(4)>>> RR = R.quotient(a*d - b*c - Integer(1))>>> a,b,c,d = RR.gens()
˓→needs sage.libs.singular>>> m = matrix(Integer(2), [a,b, c,d])>>> n = m.inverse_of_unit()
˓→needs sage.libs.singular>>> m * n˓→needs sage.libs.singular
[1 0]
[0 1]

#␣

#␣
#␣

>>> matrix(RR, Integer(2), Integer(1), [a,b]).inverse_of_unit()˓→# needs sage.libs.singularTraceback (most recent call last):...
ArithmeticError: self must be a square matrix

␣>>> matrix(RR, Integer(1), Integer(1), [Integer(2)]).inverse_of_unit()˓→# needs sage.libs.singularTraceback (most recent call last):...
ArithmeticError: non-invertible matrix

␣>>> R = ZZ.cartesian_product(ZZ)>>> m = matrix(R, Integer(2), [R((Integer(2),Integer(1))), R((Integer(1),˓→Integer(1))), R((Integer(1),Integer(1))), R((Integer(1),Integer(2)))])>>> m * m.inverse_of_unit()[(1, 1) (0, 0)][(0, 0) (1, 1)]

Tests for Issue #28570:
sage: P = posets.TamariLattice(7)˓→needs sage.graphs
sage: M = P._hasse_diagram._leq_matrix
˓→needs sage.graphs
sage: M.inverse_of_unit()# this was very slow, now 1s
˓→needs sage.graphs
429 x 429 sparse matrix over Integer Ring...

#␣
#␣
#␣

sage: m = matrix(Zmod(2**2), 1, 1, [1], sparse=True)
sage: mi = ~m; mi[1]
sage: mi.parent()
Full MatrixSpace of 1 by 1 sparse matrices over Ring of integers modulo 4>>> from sage.all import *>>> P = posets.TamariLattice(Integer(7))␣(continues on next page)

150

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)# needs sage.graphs>>> M = P._hasse_diagram._leq_matrix
˓→needs sage.graphs>>> M.inverse_of_unit()# this was very slow, now 1s
˓→needs sage.graphs
429 x 429 sparse matrix over Integer Ring...
˓→

#␣
#␣

>>> m = matrix(Zmod(Integer(2)**Integer(2)), Integer(1), Integer(1),␣
˓→[Integer(1)], sparse=True)>>> mi = ~m; mi[1]>>> mi.parent()
Full MatrixSpace of 1 by 1 sparse matrices over Ring of integers modulo 4

is_alternating()
Return True if self is an alternating matrix.
Here, “alternating matrix” means a square matrix 𝐴 satisfying 𝐴𝑇 = −𝐴 and such that the diagonal entries
of 𝐴 are 0. Notice that the condition that the diagonal entries be 0 is not redundant for matrices over arbitrary
ground rings (but it is redundant when 2 is invertible in the ground ring). A square matrix 𝐴 only required
to satisfy 𝐴𝑇 = −𝐴 is said to be “skew-symmetric”, and this property is checked by the is_skew_symmetric() method.
EXAMPLES:
sage: m = matrix(QQ, [[0,2], [-2,0]])
sage: m.is_alternating()True
sage: m = matrix(QQ, [[1,2], [2,1]])
sage: m.is_alternating()
False>>> from sage.all import *>>> m = matrix(QQ, [[Integer(0),Integer(2)], [-Integer(2),Integer(0)]])>>> m.is_alternating()
True>>> m = matrix(QQ, [[Integer(1),Integer(2)], [Integer(2),Integer(1)]])>>> m.is_alternating()
False

In contrast to the property of being skew-symmetric, the property of being alternating does not toleratenonzero entries on the diagonal even if they are their own negatives:
sage: n = matrix(Zmod(4), [[0, 1], [-1, 2]])sage: n.is_alternating()
False>>> from sage.all import *>>> n = matrix(Zmod(Integer(4)), [[Integer(0), Integer(1)], [-Integer(1),␣
˓→Integer(2)]])>>> n.is_alternating()
False

is_dense()
Return True if this is a dense matrix.
In Sage, being dense is a property of the underlying representation, not the number of nonzero entries.
151

Matrices and Spaces of Matrices, Release 10.4

EXAMPLES:
sage: matrix(QQ, 2, 2, range(4)).is_dense()
True
sage: matrix(QQ, 2, 2, range(4), sparse=True).is_dense()
False>>> from sage.all import *>>> matrix(QQ, Integer(2), Integer(2), range(Integer(4))).is_dense()
True>>> matrix(QQ, Integer(2), Integer(2), range(Integer(4)), sparse=True).is_˓→dense()False

is_hermitian()
Return True if the matrix is equal to its conjugate-transpose.
OUTPUT:
True if the matrix is square and equal to the transpose with every entry conjugated, and False otherwise.
Note that if conjugation has no effect on elements of the base ring (such as for integers), then the is_symmetric() method is equivalent and faster.
This routine is for matrices over exact rings and so may not work properly for matrices over RR or CC.
For matrices with approximate entries, the rings of double-precision floating-point numbers, RDF and CDF,
are a better choice since the sage.matrix.matrix_double_dense.Matrix_double_dense.
is_hermitian() method has a tolerance parameter. This provides control over allowing for minor discrepancies between entries when checking equality.
The result is cached.
EXAMPLES:
sage: # needs sage.rings.number_fieldsage: A = matrix(QQbar, [[ 1 + I, 1 - 6*I, -1 - I],....:[-3 - I,
-4*I,
-2],
....:
[-1 + I, -2 - 8*I, 2 + I]])
sage: A.is_hermitian()False
sage: B = A * A.conjugate_transpose()sage: B.is_hermitian()True>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQbar, [[ Integer(1) + I, Integer(1) - Integer(6)*I, ˓→Integer(1) - I],...
[-Integer(3) - I,
-Integer(4)*I,-Integer(2)],...
[-Integer(1) + I, -Integer(2) - Integer(8)*I, ␣
˓→Integer(2) + I]])>>> A.is_hermitian()
False>>> B = A * A.conjugate_transpose()>>> B.is_hermitian()
True

Sage has several fields besides the entire complex numbers where conjugation is non-trivial.

152

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

sage: # needs sage.rings.number_fieldsage: F.<b> = QuadraticField(-7)
sage: C = matrix(F, [[-2*b - 3, 7*b - 6, -b + 3],....:[-2*b - 3, -3*b + 2,
-2*b],....:[
b + 1,
0,-2]])
sage: C.is_hermitian()False
sage: C = C*C.conjugate_transpose()sage: C.is_hermitian()True>>> from sage.all import *>>> # needs sage.rings.number_field>>> F = QuadraticField(-Integer(7), names=( b ,)); (b,) = F._first_ngens(1)>>> C = matrix(F, [[-Integer(2)*b - Integer(3), Integer(7)*b - Integer(6), ˓→b + Integer(3)],...
[-Integer(2)*b - Integer(3), -Integer(3)*b + Integer(2), ␣˓→-Integer(2)*b],...
[b + Integer(1),Integer(0),-Integer(2)]])>>> C.is_hermitian()
False>>> C = C*C.conjugate_transpose()>>> C.is_hermitian()True

A matrix that is nearly Hermitian, but for a non-real diagonal entry.
sage: # needs sage.rings.number_fieldsage: A = matrix(QQbar, [[2,2-I, 1+4*I],....:[ 2+I,
3+I, 2-6*I],....:[1-4*I, 2+6*I,
5]])sage: A.is_hermitian()False
sage: A[1, 1] = 132
sage: A.is_hermitian()True>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQbar, [[Integer(2),Integer(2)-I,␣
˓→Integer(1)+Integer(4)*I],...
[ Integer(2)+I,
Integer(3)+I, Integer(2)˓→Integer(6)*I],...
[Integer(1)-Integer(4)*I, Integer(2)+Integer(6)*I,
˓→Integer(5)]])>>> A.is_hermitian()
False>>> A[Integer(1), Integer(1)] = Integer(132)>>> A.is_hermitian()
True␣

Rectangular matrices are never Hermitian.
sage: A = matrix(QQbar, 3, 4)
˓→needs sage.rings.number_fieldsage: A.is_hermitian()#␣#␣(continues on next page)153

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)needs sage.rings.number_field
False
˓→

>>> from sage.all import *>>> A = matrix(QQbar, Integer(3), Integer(4))˓→# needs sage.rings.number_field>>> A.is_hermitian()
˓→needs sage.rings.number_field
False

␣
#␣

A square, empty matrix is trivially Hermitian.
sage: A = matrix(QQ, 0, 0)
sage: A.is_hermitian()True>>> from sage.all import *>>> A = matrix(QQ, Integer(0), Integer(0))>>> A.is_hermitian()
True

is_immutable()
Return True if this matrix is immutable.
See the documentation for self.set_immutable for more details about mutability.
EXAMPLES:
sage: A = Matrix(QQ[ t , s ], 2, 2, range(4))
sage: A.is_immutable()False
sage: A.set_immutable()sage: A.is_immutable()True>>> from sage.all import *>>> A = Matrix(QQ[ t , s ], Integer(2), Integer(2), range(Integer(4)))>>> A.is_immutable()
False>>> A.set_immutable()>>> A.is_immutable()True

is_invertible()
Return True if this matrix is invertible.
EXAMPLES: The following matrix is invertible overbut not over Z.

sage: A = MatrixSpace(ZZ, 2)(range(4))
sage: A.is_invertible()False
sage: A.matrix_over_field().is_invertible()
True

154

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = MatrixSpace(ZZ, Integer(2))(range(Integer(4)))>>> A.is_invertible()
False>>> A.matrix_over_field().is_invertible()
True

The inverse function is a constructor for matrices over the fraction field, so it can work even if A is notinvertible.
sage: ~A# inverse of A[-3/2 1/2][
1
0]>>> from sage.all import *>>> ~A# inverse of A[-3/2 1/2][
10]

The next matrix is invertible over Z.
sage: A = MatrixSpace(IntegerRing(), 2)([1,10,0,-1])
sage: A.is_invertible()True
sage: ~A
# compute the inverse[ 1 10][ 0 -1]>>> from sage.all import *>>> A = MatrixSpace(IntegerRing(), Integer(2))([Integer(1),Integer(10),
˓→Integer(0),-Integer(1)])>>> A.is_invertible()True>>> ~A# compute the inverse[ 1 10][ 0 -1]

The following nontrivial matrix is invertible over Z[𝑥].
sage: R.<x> = PolynomialRing(IntegerRing())
sage: A = MatrixSpace(R, 2)([1,x,0,-1])
sage: A.is_invertible()True
sage: ~A
[ 1 x][ 0 -1]>>> from sage.all import *>>> R = PolynomialRing(IntegerRing(), names=( x ,)); (x,) = R._first_ngens(1)>>> A = MatrixSpace(R, Integer(2))([Integer(1),x,Integer(0),-Integer(1)])>>> A.is_invertible()True>>> ~A[ 1 x][ 0 -1]155

Matrices and Spaces of Matrices, Release 10.4

is_mutable()
Return True if this matrix is mutable.
See the documentation for self.set_immutable for more details about mutability.
EXAMPLES:
sage: A = Matrix(QQ[ t , s ], 2, 2, range(4))
sage: A.is_mutable()True
sage: A.set_immutable()sage: A.is_mutable()
False>>> from sage.all import *>>> A = Matrix(QQ[ t , s ], Integer(2), Integer(2), range(Integer(4)))>>> A.is_mutable()
True>>> A.set_immutable()>>> A.is_mutable()False

is_singular()
Return True if self is singular.
OUTPUT:
A square matrix is singular if it has a zero determinant and this method will return True in exactly this case.
When the entries of the matrix come from a field, this is equivalent to having a nontrivial kernel, or lacking
an inverse, or having linearly dependent rows, or having linearly dependent columns.
For square matrices over a field the methods is_invertible() and is_singular() are logical opposites. However, it is an error to apply is_singular() to a matrix that is not square, while is_invertible() will always return False for a matrix that is not square.
EXAMPLES:
A singular matrix over the field QQ.
sage: A = matrix(QQ, 4, [-1,2,-3,6, 0,-1,-1,0, -1,1,-5,7, -1,6,5,2])
sage: A.is_singular()True
sage: A.right_kernel().dimension()1>>> from sage.all import *>>> A = matrix(QQ, Integer(4), [-Integer(1),Integer(2),-Integer(3),Integer(6),˓→ Integer(0),-Integer(1),-Integer(1),Integer(0), -Integer(1),Integer(1),˓→Integer(5),Integer(7), -Integer(1),Integer(6),Integer(5),Integer(2)])>>> A.is_singular()True>>> A.right_kernel().dimension()1

A matrix that is not singular, i.e. nonsingular, over a field.
sage: B = matrix(QQ, 4, [1,-3,-1,-5, 2,-5,-2,-7, -2,5,3,4, -1,4,2,6])
sage: B.is_singular()
False(continues on next page)

156

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: B.left_kernel().dimension()0>>> from sage.all import *>>> B = matrix(QQ, Integer(4), [Integer(1),-Integer(3),-Integer(1),˓→Integer(5), Integer(2),-Integer(5),-Integer(2),-Integer(7), -Integer(2),˓→Integer(5),Integer(3),Integer(4), -Integer(1),Integer(4),Integer(2),˓→Integer(6)])>>> B.is_singular()False>>> B.left_kernel().dimension()0

For rectangular matrices, invertibility is always False, but asking about singularity will give an error.
sage: C = matrix(QQ, 5, range(30))
sage: C.is_invertible()False
sage: C.is_singular()Traceback (most recent call last):...
ValueError: self must be a square matrix>>> from sage.all import *>>> C = matrix(QQ, Integer(5), range(Integer(30)))>>> C.is_invertible()
False>>> C.is_singular()Traceback (most recent call last):...
ValueError: self must be a square matrix

When the base ring is not a field, then a matrix may be both not invertible and not singular.
sage: D = matrix(ZZ, 4, [2,0,-4,8, 2,1,-2,7, 2,5,7,0, 0,1,4,-6])
sage: D.is_invertible()False
sage: D.is_singular()False
sage: d = D.determinant(); d2sage: d.is_unit()
False>>> from sage.all import *>>> D = matrix(ZZ, Integer(4), [Integer(2),Integer(0),-Integer(4),Integer(8),␣
˓→Integer(2),Integer(1),-Integer(2),Integer(7), Integer(2),Integer(5),˓→Integer(7),Integer(0), Integer(0),Integer(1),Integer(4),-Integer(6)])>>> D.is_invertible()
False>>> D.is_singular()False>>> d = D.determinant(); d2>>> d.is_unit()
False

157

Matrices and Spaces of Matrices, Release 10.4

is_skew_hermitian()
Return True if the matrix is equal to the negative of its conjugate transpose.
OUTPUT:
True if the matrix is square and equal to the negative of its conjugate transpose, and False otherwise.
Note that if conjugation has no effect on elements of the base ring (such as for integers), then theis_skew_symmetric() method is equivalent and faster.
This routine is for matrices over exact rings and so may not work properly for matrices over RR or CC.
For matrices with approximate entries, the rings of double-precision floating-point numbers, RDF and CDF,
are a better choice since the sage.matrix.matrix_double_dense.Matrix_double_dense.
is_skew_hermitian() method has a tolerance parameter. This provides control over allowing forminor discrepancies between entries when checking equality.
The result is cached.
EXAMPLES:
sage: A = matrix(QQbar, [[0, -1],
˓→needs sage.rings.number_field....:[1, 0]])
sage: A.is_skew_hermitian()
˓→needs sage.rings.number_field
True

#␣

#␣

>>> from sage.all import *>>> A = matrix(QQbar, [[Integer(0), -Integer(1)],˓→# needs sage.rings.number_field...
[Integer(1), Integer(0)]])>>> A.is_skew_hermitian()
˓→needs sage.rings.number_field
True

␣

#␣

A matrix that is nearly skew-Hermitian, but for a non-real diagonal entry.
sage: # needs sage.rings.number_fieldsage: A = matrix(QQbar, [[ -I, -1, 1-I],....:[
1, 1, -1],....:[-1-I, 1, -I]])
sage: A.is_skew_hermitian()False
sage: A[1, 1] = -I
sage: A.is_skew_hermitian()True>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQbar, [[ -I, -Integer(1), Integer(1)-I],...
[
Integer(1), Integer(1), -Integer(1)],...
[-Integer(1)-I, Integer(1), -I]])>>> A.is_skew_hermitian()
False>>> A[Integer(1), Integer(1)] = -I>>> A.is_skew_hermitian()
True

Rectangular matrices are never skew-Hermitian.

158

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

sage: A = matrix(QQbar, 3, 4)
˓→needs sage.rings.number_fieldsage: A.is_skew_hermitian()
˓→needs sage.rings.number_field
False>>> from sage.all import *>>> A = matrix(QQbar, Integer(3), Integer(4))˓→# needs sage.rings.number_field>>> A.is_skew_hermitian()
˓→needs sage.rings.number_field
False

#␣
#␣

␣
#␣

A square, empty matrix is trivially Hermitian.
sage: A = matrix(QQ, 0, 0)
sage: A.is_skew_hermitian()True>>> from sage.all import *>>> A = matrix(QQ, Integer(0), Integer(0))>>> A.is_skew_hermitian()Trueis_skew_symmetric()
Return True if self is a skew-symmetric matrix.
Here, “skew-symmetric matrix” means a square matrix 𝐴 satisfying 𝐴𝑇 = −𝐴. It does not require that the
diagonal entries of 𝐴 are 0 (although this automatically follows from 𝐴𝑇 = −𝐴 when 2 is invertible in the
ground ring over which the matrix is considered). Skew-symmetric matrices 𝐴 whose diagonal entries are 0
are said to be “alternating”, and this property is checked by the is_alternating() method.
EXAMPLES:
sage: m = matrix(QQ, [[0,2], [-2,0]])
sage: m.is_skew_symmetric()True
sage: m = matrix(QQ, [[1,2], [2,1]])
sage: m.is_skew_symmetric()
False>>> from sage.all import *>>> m = matrix(QQ, [[Integer(0),Integer(2)], [-Integer(2),Integer(0)]])>>> m.is_skew_symmetric()True>>> m = matrix(QQ, [[Integer(1),Integer(2)], [Integer(2),Integer(1)]])>>> m.is_skew_symmetric()
False

Skew-symmetric is not the same as alternating when 2 is a zero-divisor in the ground ring:sage: n = matrix(Zmod(4), [[0, 1], [-1, 2]])sage: n.is_skew_symmetric()
True

159

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> n = matrix(Zmod(Integer(4)), [[Integer(0), Integer(1)], [-Integer(1),␣
˓→Integer(2)]])>>> n.is_skew_symmetric()True

but yet the diagonal cannot be completely arbitrary in this case:sage: n = matrix(Zmod(4), [[0, 1], [-1, 3]])sage: n.is_skew_symmetric()
False>>> from sage.all import *>>> n = matrix(Zmod(Integer(4)), [[Integer(0), Integer(1)], [-Integer(1),␣
˓→Integer(3)]])>>> n.is_skew_symmetric()
False

is_skew_symmetrizable(return_diag=False, positive=True)
This function takes a square matrix over an ordered integral domain and checks if it is skew-symmetrizable.
A matrix 𝐵 is skew-symmetrizable iff there exists an invertible diagonal matrix 𝐷 such that 𝐷𝐵 is
skew-symmetric.
Warning: Expects self to be a matrix over an ordered integral domain.
INPUT:• return_diag – bool(default: False) if True and self is skew-symmetrizable the diagonal entriesof the matrix 𝐷 are returned.
• positive – bool(default: True) if True, the condition that 𝐷 has positive entries is added.
OUTPUT:• True – if self is skew-symmetrizable and return_diag is False• the diagonal entries of a matrix 𝐷 such that 𝐷𝐵 is skew-symmetric – iff self is skew-symmetrizable
and return_diag is True
• False – iff self is not skew-symmetrizable
EXAMPLES:
sage: matrix([[0,6],[3,0]]).is_skew_symmetrizable(positive=False)
True
sage: matrix([[0,6],[3,0]]).is_skew_symmetrizable(positive=True)
False
sage: M = matrix(4, [0,1,0,0, -1,0,-1,0, 0,2,0,1, 0,0,-1,0]); M[ 0 1 0 0][-1 0 -1 0][ 0 2 0 1]
[ 0 0 -1 0]
sage: M.is_skew_symmetrizable(return_diag=True)[1, 1, 1/2, 1/2]
(continues on next page)

160

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: M2 = diagonal_matrix([1,1,1/2,1/2]) * M; M2
[
0
1
0
0]
[ -1
0
-1
0]
[
0
1
0 1/2][
0
0 -1/20]
sage: M2.is_skew_symmetric()
True>>> from sage.all import *>>> matrix([[Integer(0),Integer(6)],[Integer(3),Integer(0)]]).is_skew_
˓→symmetrizable(positive=False)
True>>> matrix([[Integer(0),Integer(6)],[Integer(3),Integer(0)]]).is_skew_
˓→symmetrizable(positive=True)
False>>> M = matrix(Integer(4), [Integer(0),Integer(1),Integer(0),Integer(0), ˓→Integer(1),Integer(0),-Integer(1),Integer(0), Integer(0),Integer(2),˓→Integer(0),Integer(1), Integer(0),Integer(0),-Integer(1),Integer(0)]); M[ 0 1 0 0][-1 0 -1 0][ 0 2 0 1]
[ 0 0 -1 0]>>> M.is_skew_symmetrizable(return_diag=True)[1, 1, 1/2, 1/2]>>> M2 = diagonal_matrix([Integer(1),Integer(1),Integer(1)/Integer(2),˓→Integer(1)/Integer(2)]) * M; M2
[
0
1
0
0]
[ -1
0
-1
0]
[
0
1
0 1/2][
0
0 -1/20]>>> M2.is_skew_symmetric()
True

REFERENCES:• [FZ2001]
is_sparse()
Return True if this is a sparse matrix.
In Sage, being sparse is a property of the underlying representation, not the number of nonzero entries.
EXAMPLES:
sage: matrix(QQ, 2, 2, range(4)).is_sparse()
False
sage: matrix(QQ, 2, 2, range(4), sparse=True).is_sparse()
True>>> from sage.all import *>>> matrix(QQ, Integer(2), Integer(2), range(Integer(4))).is_sparse()
False(continues on next page)161

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> matrix(QQ, Integer(2), Integer(2), range(Integer(4)), sparse=True).is_˓→sparse()
True

is_square()Return True precisely if this matrix is square, i.e., has the same number of rows and columns.
EXAMPLES:
sage: matrix(QQ, 2, 2, range(4)).is_square()True
sage: matrix(QQ, 2, 3, range(6)).is_square()False>>> from sage.all import *>>> matrix(QQ, Integer(2), Integer(2), range(Integer(4))).is_square()True>>> matrix(QQ, Integer(2), Integer(3), range(Integer(6))).is_square()False

is_symmetric()
Return True if this is a symmetric matrix.
A symmetric matrix is necessarily square.
EXAMPLES:
sage: m = Matrix(QQ, 2, range(0,4))
sage: m.is_symmetric()
False
sage: m = Matrix(QQ, 2, (1,1,1,1,1,1))
sage: m.is_symmetric()
False
sage: m = Matrix(QQ, 1, (2,))
sage: m.is_symmetric()
True>>> from sage.all import *>>> m = Matrix(QQ, Integer(2), range(Integer(0),Integer(4)))>>> m.is_symmetric()
False>>> m = Matrix(QQ, Integer(2), (Integer(1),Integer(1),Integer(1),Integer(1),˓→Integer(1),Integer(1)))>>> m.is_symmetric()
False>>> m = Matrix(QQ, Integer(1), (Integer(2),))>>> m.is_symmetric()True

is_symmetrizable(return_diag=False, positive=True)
This function takes a square matrix over an ordered integral domain and checks if it is symmetrizable. A
matrix 𝐵 is symmetrizable iff there exists an invertible diagonal matrix 𝐷 such that 𝐷𝐵 is symmetric.

162

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

Warning: Expects self to be a matrix over an ordered integral domain.
INPUT:• return_diag – bool(default: False) if True and self is symmetrizable the diagonal entries of thematrix 𝐷 are returned.
• positive – bool(default: True) if True, the condition that 𝐷 has positive entries is added.
OUTPUT:• True – if self is symmetrizable and return_diag is False• the diagonal entries of a matrix 𝐷 such that 𝐷𝐵 is symmetric – iff self is symmetrizable and return_diag is True
• False – iff self is not symmetrizable
EXAMPLES:
sage: matrix([[0,6],[3,0]]).is_symmetrizable(positive=False)
True
sage: matrix([[0,6],[3,0]]).is_symmetrizable(positive=True)
True
sage: matrix([[0,6],[0,0]]).is_symmetrizable(return_diag=True)
False
sage: matrix([2]).is_symmetrizable(positive=True)
True
sage: matrix([[1,2],[3,4]]).is_symmetrizable(return_diag=true)[1, 2/3]>>> from sage.all import *>>> matrix([[Integer(0),Integer(6)],[Integer(3),Integer(0)]]).is_˓→symmetrizable(positive=False)
True>>> matrix([[Integer(0),Integer(6)],[Integer(3),Integer(0)]]).is_˓→symmetrizable(positive=True)
True>>> matrix([[Integer(0),Integer(6)],[Integer(0),Integer(0)]]).is_˓→symmetrizable(return_diag=True)
False>>> matrix([Integer(2)]).is_symmetrizable(positive=True)
True>>> matrix([[Integer(1),Integer(2)],[Integer(3),Integer(4)]]).is_˓→symmetrizable(return_diag=true)[1, 2/3]

REFERENCES:• [FZ2001]

163

Matrices and Spaces of Matrices, Release 10.4

is_unit()
Return True if this matrix is invertible.
EXAMPLES: The following matrix is invertible overbut not over Z.

sage: A = MatrixSpace(ZZ, 2)(range(4))
sage: A.is_invertible()False
sage: A.matrix_over_field().is_invertible()True>>> from sage.all import *>>> A = MatrixSpace(ZZ, Integer(2))(range(Integer(4)))>>> A.is_invertible()
False>>> A.matrix_over_field().is_invertible()
True

The inverse function is a constructor for matrices over the fraction field, so it can work even if A is notinvertible.
sage: ~A# inverse of A[-3/2 1/2][
1
0]>>> from sage.all import *>>> ~A# inverse of A[-3/2 1/2][
10]

The next matrix is invertible over Z.
sage: A = MatrixSpace(IntegerRing(), 2)([1,10,0,-1])
sage: A.is_invertible()True
sage: ~A
# compute the inverse[ 1 10][ 0 -1]>>> from sage.all import *>>> A = MatrixSpace(IntegerRing(), Integer(2))([Integer(1),Integer(10),
˓→Integer(0),-Integer(1)])>>> A.is_invertible()True>>> ~A# compute the inverse[ 1 10][ 0 -1]

The following nontrivial matrix is invertible over Z[𝑥].
sage: R.<x> = PolynomialRing(IntegerRing())
sage: A = MatrixSpace(R, 2)([1,x,0,-1])
sage: A.is_invertible()True
sage: ~A
[ 1 x][ 0 -1]164

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> R = PolynomialRing(IntegerRing(), names=( x ,)); (x,) = R._first_ngens(1)>>> A = MatrixSpace(R, Integer(2))([Integer(1),x,Integer(0),-Integer(1)])>>> A.is_invertible()True>>> ~A[ 1 x][ 0 -1]

items()
Return an iterable of ((i,j), value) elements.
This may (but is not guaranteed to) suppress zero values.
EXAMPLES:
sage: a = matrix(QQ[ x,y ], 2, range(6), sparse=True); a[0 1 2][3 4 5]sage: list(a.items())[((0, 1), 1), ((0, 2), 2), ((1, 0), 3), ((1, 1), 4), ((1, 2), 5)]>>> from sage.all import *>>> a = matrix(QQ[ x,y ], Integer(2), range(Integer(6)), sparse=True); a[0 1 2][3 4 5]>>> list(a.items())[((0, 1), 1), ((0, 2), 2), ((1, 0), 3), ((1, 1), 4), ((1, 2), 5)]

iterates(v, n, rows=True)
Let 𝐴 be this matrix and 𝑣 be a free module element. If rows is True, return a matrix whose rows are theentries of the following vectors:𝑣, 𝑣𝐴, 𝑣𝐴2 , . . . , 𝑣𝐴𝑛−1 .
If rows is False, return a matrix whose columns are the entries of the following vectors:𝑣, 𝐴𝑣, 𝐴2 𝑣, . . . , 𝐴𝑛−1 𝑣.
INPUT:• v – free module element• n – nonnegative integer
EXAMPLES:
sage: A = matrix(ZZ, 2, [1,1,3,5]); A
[1 1]
[3 5]
sage: v = vector([1,0])
sage: A.iterates(v, 0)[]
sage: A.iterates(v, 5)
[ 1
0]
[ 1
1]
[ 4
6]
[ 22 34][124 192]

165

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = matrix(ZZ, Integer(2), [Integer(1),Integer(1),Integer(3),Integer(5)]);
˓→ A
[1 1]
[3 5]
>>> v = vector([Integer(1),Integer(0)])>>> A.iterates(v, Integer(0))[]>>> A.iterates(v, Integer(5))
[ 1
0]
[ 1
1]
[ 4
6]
[ 22 34][124 192]

Another example:
sage: a = matrix(ZZ, 3, range(9)); a[0 1 2][3 4 5][6 7 8]sage: v = vector([1,0,0])
sage: a.iterates(v, 4)
[ 1
0
0]
[ 0
1
2]
[ 15 18 21][180 234 288]
sage: a.iterates(v, 4, rows=False)[ 1
0 15 180][ 0
3 42 558][ 0
6 69 936]>>> from sage.all import *>>> a = matrix(ZZ, Integer(3), range(Integer(9))); a[0 1 2][3 4 5][6 7 8]>>> v = vector([Integer(1),Integer(0),Integer(0)])>>> a.iterates(v, Integer(4))
[ 1
0
0]
[ 0
1
2]
[ 15 18 21][180 234 288]>>> a.iterates(v, Integer(4), rows=False)[ 1
0 15 180][ 0
3 42 558][ 0
6 69 936]

linear_combination_of_columns(v)Return the linear combination of the columns of self given by the coefficients in the list v.
INPUT:• v – a list of scalars. The length can be less than the number of columns of self but not greater.
OUTPUT:The vector (or free module element) that is a linear combination of the columns of self. If the list of scalars
has fewer entries than the number of columns, additional zeros are appended to the list until it has as many
166

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

entries as the number of columns.
EXAMPLES:
sage: a = matrix(ZZ, 2, 3, range(6)); a[0 1 2][3 4 5]sage: a.linear_combination_of_columns([1,1,1])(3, 12)sage: a.linear_combination_of_columns([0,0,0])(0, 0)
sage: a.linear_combination_of_columns([1/2,2/3,3/4])(13/6, 95/12)>>> from sage.all import *>>> a = matrix(ZZ, Integer(2), Integer(3), range(Integer(6))); a[0 1 2][3 4 5]>>> a.linear_combination_of_columns([Integer(1),Integer(1),Integer(1)])(3, 12)>>> a.linear_combination_of_columns([Integer(0),Integer(0),Integer(0)])(0, 0)>>> a.linear_combination_of_columns([Integer(1)/Integer(2),Integer(2)/˓→Integer(3),Integer(3)/Integer(4)])(13/6, 95/12)

The list v can be anything that is iterable. Perhaps most naturally, a vector may be used.
sage: v = vector(ZZ, [1,2,3])
sage: a.linear_combination_of_columns(v)(8, 26)>>> from sage.all import *>>> v = vector(ZZ, [Integer(1),Integer(2),Integer(3)])>>> a.linear_combination_of_columns(v)(8, 26)

We check that a matrix with no columns behaves properly.
sage: matrix(QQ, 2, 0).linear_combination_of_columns([])(0, 0)>>> from sage.all import *>>> matrix(QQ, Integer(2), Integer(0)).linear_combination_of_columns([])(0, 0)The object returned is a vector, or a free module element.
sage: B = matrix(ZZ, 4, 3, range(12))
sage: w = B.linear_combination_of_columns([-1,2,-3])
sage: w(-4, -10, -16, -22)
sage: w.parent()(continues on next page)

167

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Ambient free module of rank 4 over the principal ideal domain Integer Ringsage: x = B.linear_combination_of_columns([1/2,1/3,1/4])
sage: x
(5/6, 49/12, 22/3, 127/12)
sage: x.parent()
Vector space of dimension 4 over Rational Field>>> from sage.all import *>>> B = matrix(ZZ, Integer(4), Integer(3), range(Integer(12)))>>> w = B.linear_combination_of_columns([-Integer(1),Integer(2),-Integer(3)])>>> w(-4, -10, -16, -22)>>> w.parent()
Ambient free module of rank 4 over the principal ideal domain Integer Ring>>> x = B.linear_combination_of_columns([Integer(1)/Integer(2),Integer(1)/˓→Integer(3),Integer(1)/Integer(4)])>>> x(5/6, 49/12, 22/3, 127/12)>>> x.parent()
Vector space of dimension 4 over Rational Field

The length of v can be less than the number of columns, but not greater.
sage: A = matrix(QQ, 3, 5, range(15))
sage: A.linear_combination_of_columns([1,-2,3,-4])(-8, -18, -28)
sage: A.linear_combination_of_columns([1,2,3,4,5,6])
Traceback (most recent call last):...
ValueError: length of v must be at most the number of columns of self>>> from sage.all import *>>> A = matrix(QQ, Integer(3), Integer(5), range(Integer(15)))>>> A.linear_combination_of_columns([Integer(1),-Integer(2),Integer(3),˓→Integer(4)])(-8, -18, -28)>>> A.linear_combination_of_columns([Integer(1),Integer(2),Integer(3),˓→Integer(4),Integer(5),Integer(6)])
Traceback (most recent call last):...
ValueError: length of v must be at most the number of columns of selflinear_combination_of_rows(v)Return the linear combination of the rows of self given by the coefficients in the list v.
INPUT:• v – a list of scalars. The length can be less than the number of rows of self but not greater.
OUTPUT:The vector (or free module element) that is a linear combination of the rows of self. If the list of scalars
has fewer entries than the number of rows, additional zeros are appended to the list until it has as many entries
as the number of rows.
EXAMPLES:

168

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

sage: a = matrix(ZZ, 2, 3, range(6)); a[0 1 2][3 4 5]sage: a.linear_combination_of_rows([1,2])(6, 9, 12)
sage: a.linear_combination_of_rows([0,0])(0, 0, 0)
sage: a.linear_combination_of_rows([1/2,2/3])(2, 19/6, 13/3)>>> from sage.all import *>>> a = matrix(ZZ, Integer(2), Integer(3), range(Integer(6))); a[0 1 2][3 4 5]>>> a.linear_combination_of_rows([Integer(1),Integer(2)])(6, 9, 12)>>> a.linear_combination_of_rows([Integer(0),Integer(0)])(0, 0, 0)>>> a.linear_combination_of_rows([Integer(1)/Integer(2),Integer(2)/˓→Integer(3)])(2, 19/6, 13/3)

The list v can be anything that is iterable. Perhaps most naturally, a vector may be used.
sage: v = vector(ZZ, [1,2])
sage: a.linear_combination_of_rows(v)(6, 9, 12)>>> from sage.all import *>>> v = vector(ZZ, [Integer(1),Integer(2)])>>> a.linear_combination_of_rows(v)(6, 9, 12)

We check that a matrix with no rows behaves properly.
sage: matrix(QQ, 0, 2).linear_combination_of_rows([])(0, 0)>>> from sage.all import *>>> matrix(QQ, Integer(0), Integer(2)).linear_combination_of_rows([])(0, 0)The object returned is a vector, or a free module element.
sage: B = matrix(ZZ, 4, 3, range(12))
sage: w = B.linear_combination_of_rows([-1,2,-3,4])
sage: w
(24, 26, 28)
sage: w.parent()
Ambient free module of rank 3 over the principal ideal domain Integer Ringsage: x = B.linear_combination_of_rows([1/2,1/3,1/4,1/5])
sage: x(continues on next page)169

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)(43/10, 67/12, 103/15)
sage: x.parent()
Vector space of dimension 3 over Rational Field>>> from sage.all import *>>> B = matrix(ZZ, Integer(4), Integer(3), range(Integer(12)))>>> w = B.linear_combination_of_rows([-Integer(1),Integer(2),-Integer(3),˓→Integer(4)])>>> w(24, 26, 28)>>> w.parent()
Ambient free module of rank 3 over the principal ideal domain Integer Ring>>> x = B.linear_combination_of_rows([Integer(1)/Integer(2),Integer(1)/˓→Integer(3),Integer(1)/Integer(4),Integer(1)/Integer(5)])>>> x(43/10, 67/12, 103/15)>>> x.parent()
Vector space of dimension 3 over Rational Field

The length of v can be less than the number of rows, but not greater.
sage: A = matrix(QQ, 3, 4, range(12))
sage: A.linear_combination_of_rows([2,3])(12, 17, 22, 27)
sage: A.linear_combination_of_rows([1,2,3,4])
Traceback (most recent call last):...
ValueError: length of v must be at most the number of rows of self>>> from sage.all import *>>> A = matrix(QQ, Integer(3), Integer(4), range(Integer(12)))>>> A.linear_combination_of_rows([Integer(2),Integer(3)])(12, 17, 22, 27)>>> A.linear_combination_of_rows([Integer(1),Integer(2),Integer(3),˓→Integer(4)])
Traceback (most recent call last):...
ValueError: length of v must be at most the number of rows of selflist()
List of the elements of self ordered by elements in each row. It is safe to change the returned list.
Warning: This function returns a list of the entries in the matrix self. It does not return a listof the rows of self, so it is different than the output of list(self), which returns [self[0],self[1],...].
EXAMPLES:
sage: R.<x,y> = QQ[]
sage: a = matrix(R,2,[x,y,x*y, y,x,2*x+y]); a
[
x
y
x*y]
[
y
x 2*x + y]sage: v = a.list(); v[x, y, x*y, y, x, 2*x + y]

170

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> R = QQ[ x, y ]; (x, y,) = R._first_ngens(2)>>> a = matrix(R,Integer(2),[x,y,x*y, y,x,Integer(2)*x+y]); a
[
x
y
x*y]
[
y
x 2*x + y]>>> v = a.list(); v[x, y, x*y, y, x, 2*x + y]

Note that list(a) is different than a.list():sage: a.list()[x, y, x*y, y, x, 2*x + y]sage: list(a)[(x, y, x*y), (y, x, 2*x + y)]>>> from sage.all import *>>> a.list()[x, y, x*y, y, x, 2*x + y]>>> list(a)[(x, y, x*y), (y, x, 2*x + y)]

Notice that changing the returned list does not change a (the list is a copy):
sage: v[0] = 25
sage: a
[
x
y
x*y]
[
y
x 2*x + y]>>> from sage.all import *>>> v[Integer(0)] = Integer(25)
>>> a
[
x
y
x*y]
[
y
x 2*x + y]mod(p)
Return matrix mod 𝑝, over the reduced ring.
EXAMPLES:
sage: M = matrix(ZZ, 2, 2, [5, 9, 13, 15])
sage: M.mod(7)
[5 2]
[6 1]
sage: parent(M.mod(7))
Full MatrixSpace of 2 by 2 dense matrices over Ring of integers modulo 7>>> from sage.all import *>>> M = matrix(ZZ, Integer(2), Integer(2), [Integer(5), Integer(9),␣
˓→Integer(13), Integer(15)])>>> M.mod(Integer(7))
[5 2]
[6 1]
>>> parent(M.mod(Integer(7)))
Full MatrixSpace of 2 by 2 dense matrices over Ring of integers modulo 7

monomial_coefficients(copy=True)
Dictionary of the elements of self with keys pairs (i,j) and values the nonzero entries of self.
171

Matrices and Spaces of Matrices, Release 10.4

INPUT:• copy – (default: True) make a copy of the dict corresponding to self
If copy=True, then is safe to change the returned dictionary. Otherwise, this can cause undesired behavior
by mutating the dict.
EXAMPLES:
sage: R.<x,y> = QQ[]
sage: a = matrix(R,2,[x,y,0, 0,0,2*x+y]); a
[
x
y
0]
[
0
0 2*x + y]sage: d = a.dict(); d{(0, 0): x, (0, 1): y, (1, 2): 2*x + y}>>> from sage.all import *>>> R = QQ[ x, y ]; (x, y,) = R._first_ngens(2)>>> a = matrix(R,Integer(2),[x,y,Integer(0), Integer(0),Integer(0),˓→Integer(2)*x+y]); a
[
x
y
0]
[
0
0 2*x + y]>>> d = a.dict(); d{(0, 0): x, (0, 1): y, (1, 2): 2*x + y}

Notice that changing the returned list does not change a (the list is a copy):
sage: d[0,0] = 25
sage: a
[
x
y
0]
[
0
0 2*x + y]>>> from sage.all import *>>> d[Integer(0),Integer(0)] = Integer(25)
>>> a
[
x
y
0]
[
0
0 2*x + y]multiplicative_order()Return the multiplicative order of this matrix, which must therefore be invertible.
Only implemented over finite fields and over Z.
EXAMPLES:Over finite fields:
sage: A = matrix(GF(59), 3, [10,56,39,53,56,33,58,24,55])
sage: A.multiplicative_order()˓→needs sage.libs.pari580
sage: (A^580).is_one()True
sage: B = matrix(GF(10007^3, b ), 0)
˓→needs sage.rings.finite_rings
sage: B.multiplicative_order()˓→needs sage.rings.finite_rings
1

#␣

#␣
#␣

(continues on next page)

172

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: # needs sage.rings.finite_rings
sage: M = MatrixSpace(GF(11^2, e ), 5)
sage: E = M.random_element()
sage: while E.det() == 0:....:
E = M.random_element()
sage: (E^E.multiplicative_order()).is_one()True>>> from sage.all import *>>> A = matrix(GF(Integer(59)), Integer(3), [Integer(10),Integer(56),
˓→Integer(39),Integer(53),Integer(56),Integer(33),Integer(58),Integer(24),
˓→Integer(55)])>>> A.multiplicative_order()#␣˓→needs sage.libs.pari580>>> (A**Integer(580)).is_one()
True>>> B = matrix(GF(Integer(10007)**Integer(3), b ), Integer(0))˓→# needs sage.rings.finite_rings>>> B.multiplicative_order()˓→needs sage.rings.finite_rings
1>>> # needs sage.rings.finite_rings>>> M = MatrixSpace(GF(Integer(11)**Integer(2),>>> E = M.random_element()>>> while E.det() == Integer(0):...
E = M.random_element()>>> (E**E.multiplicative_order()).is_one()
True

␣
#␣

e ), Integer(5))

Over Z:
sage: m = matrix(ZZ, 2, 2, [-1,1,-1,0])
sage: m.multiplicative_order()˓→needs sage.libs.pari3#␣

sage: m = posets.ChainPoset(6).coxeter_transformation()
˓→needs sage.combinat sage.graphs
sage: m.multiplicative_order()˓→needs sage.combinat sage.graphs sage.groups7#␣

sage: P = posets.TamariLattice(4).coxeter_transformation()
˓→needs sage.combinat sage.graphs
sage: P.multiplicative_order()˓→needs sage.combinat sage.graphs sage.groups10#␣

sage: M = matrix(ZZ, 2, 2, [1, 1, 0, 1])
sage: M.multiplicative_order()˓→needs sage.libs.pari+Infinity

#␣

#␣

#␣

(continues on next page)

173

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: for k in range(600):
˓→needs sage.groups sage.modular....:
m = SL2Z.random_element()....:o = m.multiplicative_order()....:if o != Infinity and m**o != SL2Z.one():....:raise RuntimeError#␣

sage: m24 = matrix.companion(cyclotomic_polynomial(24))
sage: def val(i, j):....:
if i < j:....:return 0....:
elif i == j:....:return 1
....:
else:
....:
return ZZ.random_element(-100,100)
sage: rnd = matrix(ZZ, 8, 8, val)
sage: (rnd * m24 * rnd.inverse_of_unit()).multiplicative_order()˓→needs sage.libs.pari24#␣>>> from sage.all import *>>> m = matrix(ZZ, Integer(2), Integer(2), [-Integer(1),Integer(1),˓→Integer(1),Integer(0)])>>> m.multiplicative_order()˓→needs sage.libs.pari
3>>> m = posets.ChainPoset(Integer(6)).coxeter_transformation()˓→# needs sage.combinat sage.graphs>>> m.multiplicative_order()˓→needs sage.combinat sage.graphs sage.groups
7

#␣

␣
#␣

>>> P = posets.TamariLattice(Integer(4)).coxeter_transformation()˓→# needs sage.combinat sage.graphs>>> P.multiplicative_order()˓→needs sage.combinat sage.graphs sage.groups10#␣>>> M = matrix(ZZ, Integer(2), Integer(2), [Integer(1), Integer(1),␣
˓→Integer(0), Integer(1)])>>> M.multiplicative_order()˓→needs sage.libs.pari+Infinity#␣>>> for k in range(Integer(600)):˓→# needs sage.groups sage.modular...
m = SL2Z.random_element()...
o = m.multiplicative_order()...
if o != Infinity and m**o != SL2Z.one():...
raise RuntimeError␣␣>>> m24 = matrix.companion(cyclotomic_polynomial(Integer(24)))>>> def val(i, j):...
if i < j:(continues on next page)

174

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
return Integer(0)...
elif i == j:...
return Integer(1)
...
else:
...
return ZZ.random_element(-Integer(100),Integer(100))>>> rnd = matrix(ZZ, Integer(8), Integer(8), val)>>> (rnd * m24 * rnd.inverse_of_unit()).multiplicative_order()˓→needs sage.libs.pari
24#␣

REFERENCES:• [CLG1997]• [KP2002b]
mutate(k)Mutates self at row and column index k.
Warning: Only makes sense if self is skew-symmetrizable.
INPUT:• k – integer at which row/column self is mutated.
EXAMPLES:
Mutation of the B-matrix of the quiver of type 𝐴3 :sage: M = matrix(ZZ, 3, [0,1,0,-1,0,-1,0,1,0]); M[ 0 1 0][-1 0 -1]
[ 0 1 0]sage: M.mutate(0); M[ 0 -1 0][ 1 0 -1]
[ 0 1 0]sage: M.mutate(1); M[ 0 1 -1][-1 0 1]
[ 1 -1 0]
sage: M = matrix(ZZ, 6, [0,1,0,-1,0,-1,0,1,0,1,0,0,0,1,0,0,0,1]); M[ 0 1 0][-1 0 -1]
[ 0 1 0]
[ 1 0 0][ 0 1 0][ 0 0 1]
sage: M.mutate(0); M[ 0 -1 0][ 1 0 -1]
[ 0 1 0][-1 1 0](continues on next page)

175

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[ 0
[ 0

1
0

0]
1]

>>> from sage.all import *>>> M = matrix(ZZ, Integer(3), [Integer(0),Integer(1),Integer(0),-Integer(1),˓→Integer(0),-Integer(1),Integer(0),Integer(1),Integer(0)]); M[ 0 1 0][-1 0 -1]
[ 0 1 0]>>> M.mutate(Integer(0)); M[ 0 -1 0][ 1 0 -1]
[ 0 1 0]>>> M.mutate(Integer(1)); M[ 0 1 -1][-1 0 1]
[ 1 -1 0]>>> M = matrix(ZZ, Integer(6), [Integer(0),Integer(1),Integer(0),-Integer(1),˓→Integer(0),-Integer(1),Integer(0),Integer(1),Integer(0),Integer(1),˓→Integer(0),Integer(0),Integer(0),Integer(1),Integer(0),Integer(0),˓→Integer(0),Integer(1)]); M[ 0 1 0][-1 0 -1]
[ 0 1 0]
[ 1 0 0][ 0 1 0][ 0 0 1]>>> M.mutate(Integer(0)); M[ 0 -1 0][ 1 0 -1]
[ 0 1 0][-1 1 0][ 0 1 0][ 0 0 1]REFERENCES:• [FZ2001]
ncols()
Return the number of columns of this matrix.
EXAMPLES:
sage: M = MatrixSpace(QQ, 2, 3)
sage: A = M([1,2,3, 4,5,6])
sage: A[1 2 3][4 5 6]sage: A.ncols()
3
sage: A.nrows()
2

176

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> M = MatrixSpace(QQ, Integer(2), Integer(3))>>> A = M([Integer(1),Integer(2),Integer(3), Integer(4),Integer(5),˓→Integer(6)])>>> A[1 2 3][4 5 6]>>> A.ncols()
3>>> A.nrows()
2

AUTHORS:• Naqi Jaffery (2006-01-24): examples
nonpivots()
Return the list of i such that the i-th column of self is NOT a pivot column of the reduced row echelon formof self.
OUTPUT: sorted tuple of (Python) integers
EXAMPLES:
sage: a = matrix(QQ, 3, 3, range(9)); a[0 1 2][3 4 5][6 7 8]sage: a.echelon_form()[ 1 0 -1]
[ 0 1 2][ 0 0 0]sage: a.nonpivots()(2,)>>> from sage.all import *>>> a = matrix(QQ, Integer(3), Integer(3), range(Integer(9))); a[0 1 2][3 4 5][6 7 8]>>> a.echelon_form()[ 1 0 -1]
[ 0 1 2][ 0 0 0]>>> a.nonpivots()(2,)

nonzero_positions(copy=True, column_order=False)
Return the sorted list of pairs (i,j) such that self[i,j] != 0.
INPUT:• copy – (default: True) it is safe to change the resulting list (unless you give the option copy=False)• column_order – (default: False) If True, returns the list of pairs (i,j) such that self[i,j]!= 0, but sorted by columns, i.e., column j=0 entries occur first, then column j=1 entries, etc.
EXAMPLES:

177

Matrices and Spaces of Matrices, Release 10.4

sage: a = matrix(QQ, 2,3, [1,2,0,2,0,0]); a[1 2 0][2 0 0]sage: a.nonzero_positions()[(0, 0), (0, 1), (1, 0)]
sage: a.nonzero_positions(copy=False)[(0, 0), (0, 1), (1, 0)]
sage: a.nonzero_positions(column_order=True)[(0, 0), (1, 0), (0, 1)]
sage: a = matrix(QQ, 2,3, [1,2,0,2,0,0], sparse=True); a[1 2 0][2 0 0]sage: a.nonzero_positions()[(0, 0), (0, 1), (1, 0)]
sage: a.nonzero_positions(copy=False)[(0, 0), (0, 1), (1, 0)]
sage: a.nonzero_positions(column_order=True)[(0, 0), (1, 0), (0, 1)]>>> from sage.all import *>>> a = matrix(QQ, Integer(2),Integer(3), [Integer(1),Integer(2),Integer(0),˓→Integer(2),Integer(0),Integer(0)]); a[1 2 0][2 0 0]>>> a.nonzero_positions()[(0, 0), (0, 1), (1, 0)]>>> a.nonzero_positions(copy=False)[(0, 0), (0, 1), (1, 0)]>>> a.nonzero_positions(column_order=True)[(0, 0), (1, 0), (0, 1)]>>> a = matrix(QQ, Integer(2),Integer(3), [Integer(1),Integer(2),Integer(0),˓→Integer(2),Integer(0),Integer(0)], sparse=True); a[1 2 0][2 0 0]>>> a.nonzero_positions()[(0, 0), (0, 1), (1, 0)]>>> a.nonzero_positions(copy=False)[(0, 0), (0, 1), (1, 0)]>>> a.nonzero_positions(column_order=True)[(0, 0), (1, 0), (0, 1)]

nonzero_positions_in_column(i)Return a sorted list of the integers j such that self[j,i] is nonzero, i.e., such that the j-th position of
the i-th column is nonzero.
INPUT:• i – an integer
OUTPUT: list
EXAMPLES:
sage: a = matrix(QQ, 3,2, [1,2,0,2,0,0]); a
[1 2]
[0 2]
[0 0]
sage: a.nonzero_positions_in_column(0)(continues on next page)

178

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0]
sage: a.nonzero_positions_in_column(1)[0, 1]>>> from sage.all import *>>> a = matrix(QQ, Integer(3),Integer(2), [Integer(1),Integer(2),Integer(0),˓→Integer(2),Integer(0),Integer(0)]); a
[1 2]
[0 2]
[0 0]
>>> a.nonzero_positions_in_column(Integer(0))[0]>>> a.nonzero_positions_in_column(Integer(1))[0, 1]

You will get an IndexError if you select an invalid column:
sage: a.nonzero_positions_in_column(2)Traceback (most recent call last):...
IndexError: matrix column index out of range>>> from sage.all import *>>> a.nonzero_positions_in_column(Integer(2))
Traceback (most recent call last):...
IndexError: matrix column index out of range

nonzero_positions_in_row(i)Return the integers j such that self[i,j] is nonzero, i.e., such that the j-th position of the i-th row isnonzero.
INPUT:• i – an integer
OUTPUT: list
EXAMPLES:
sage: a = matrix(QQ, 3,2, [1,2,0,2,0,0]); a
[1 2]
[0 2]
[0 0]
sage: a.nonzero_positions_in_row(0)[0, 1]
sage: a.nonzero_positions_in_row(1)[1]sage: a.nonzero_positions_in_row(2)[]>>> from sage.all import *>>> a = matrix(QQ, Integer(3),Integer(2), [Integer(1),Integer(2),Integer(0),˓→Integer(2),Integer(0),Integer(0)]); a
[1 2]
[0 2]
(continues on next page)179

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 0]>>> a.nonzero_positions_in_row(Integer(0))[0, 1]>>> a.nonzero_positions_in_row(Integer(1))[1]>>> a.nonzero_positions_in_row(Integer(2))[]

nrows()
Return the number of rows of this matrix.
EXAMPLES:
sage: M = MatrixSpace(QQ,6,7)
sage: A = M([1,2,3,4,5,6,7, 22,3/4,34,11,7,5,3, 99,65,1/2,2/3,3/5,4/5,5/6, 9,
˓→8/9, 9/8,7/6,6/7,76,4, 0,9,8,7,6,5,4, 123,99,91,28,6,1024,1])
sage: A
[
1
2
3
4
5
6
7]
[ 22 3/4
34
11
7
5
3]
[ 99
65 1/2 2/3 3/5 4/5 5/6][
9 8/9 9/8 7/6 6/7
76
4]
[
0
9
8
7
6
5
4]
[ 123
99
91
28
6 10241]sage: A.ncols()
7
sage: A.nrows()
6>>> from sage.all import *>>> M = MatrixSpace(QQ,Integer(6),Integer(7))>>> A = M([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5),Integer(6),˓→Integer(7), Integer(22),Integer(3)/Integer(4),Integer(34),Integer(11),
˓→Integer(7),Integer(5),Integer(3), Integer(99),Integer(65),Integer(1)/˓→Integer(2),Integer(2)/Integer(3),Integer(3)/Integer(5),Integer(4)/˓→Integer(5),Integer(5)/Integer(6), Integer(9),Integer(8)/Integer(9),␣
˓→Integer(9)/Integer(8),Integer(7)/Integer(6),Integer(6)/Integer(7),˓→Integer(76),Integer(4), Integer(0),Integer(9),Integer(8),Integer(7),˓→Integer(6),Integer(5),Integer(4), Integer(123),Integer(99),Integer(91),
˓→Integer(28),Integer(6),Integer(1024),Integer(1)])
>>> A
[
1
2
3
4
5
6
7]
[ 22 3/4
34
11
7
5
3]
[ 99
65 1/2 2/3 3/5 4/5 5/6][
9 8/9 9/8 7/6 6/7
76
4]
[
0
9
8
7
6
5
4]
[ 123
99
91
28
6 1024
1]>>> A.ncols()
7>>> A.nrows()
6

AUTHORS:• Naqi Jaffery (2006-01-24): examples
permute_columns(permutation)
Permute the columns of self by applying the permutation group element permutation.

180

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

As permutation group elements act on integers {1, . . . , 𝑛}, columns are considered numbered from 1 for thisoperation.
INPUT:• permutation – a PermutationGroupElement.
EXAMPLES: We create a matrix:
sage: M = matrix(ZZ, [[1,0,0,0,0],[0,2,0,0,0],[0,0,3,0,0],[0,0,0,4,0],[0,0,0,
˓→0,5]])
sage: M
[1 0 0 0 0]
[0 2 0 0 0]
[0 0 3 0 0]
[0 0 0 4 0]
[0 0 0 0 5]>>> from sage.all import *>>> M = matrix(ZZ, [[Integer(1),Integer(0),Integer(0),Integer(0),Integer(0)],˓→[Integer(0),Integer(2),Integer(0),Integer(0),Integer(0)],[Integer(0),˓→Integer(0),Integer(3),Integer(0),Integer(0)],[Integer(0),Integer(0),˓→Integer(0),Integer(4),Integer(0)],[Integer(0),Integer(0),Integer(0),˓→Integer(0),Integer(5)]])>>> M[1 0 0 0 0]
[0 2 0 0 0]
[0 0 3 0 0]
[0 0 0 4 0]
[0 0 0 0 5]

Next of all, create a permutation group element and act on M with it:
sage: # needs sage.groups
sage: G = PermutationGroup([ (1,2,3)(4,5) ,sage: sigma, tau = G.gens()
sage: sigma(1,2,3)(4,5)
sage: M.permute_columns(sigma)
sage: M
[0 0 1 0 0]
[2 0 0 0 0]
[0 3 0 0 0]
[0 0 0 0 4]
[0 0 0 5 0]>>> from sage.all import *>>> # needs sage.groups>>> G = PermutationGroup([ (1,2,3)(4,5) ,>>> sigma, tau = G.gens()>>> sigma(1,2,3)(4,5)>>> M.permute_columns(sigma)>>> M[0 0 1 0 0]
[2 0 0 0 0]
[0 3 0 0 0]
[0 0 0 0 4]
[0 0 0 5 0]

(1,2,3,4,5) ])(1,2,3,4,5) ])181

Matrices and Spaces of Matrices, Release 10.4

permute_rows(permutation)
Permute the rows of self by applying the permutation group element permutation.
As permutation group elements act on integers {1, . . . , 𝑛}, rows are considered numbered from 1 for thisoperation.
INPUT:• permutation – a PermutationGroupElement
EXAMPLES: We create a matrix:
sage: M = matrix(ZZ, [[1,0,0,0,0],[0,2,0,0,0],[0,0,3,0,0],[0,0,0,4,0],[0,0,0,
˓→0,5]])
sage: M
[1 0 0 0 0]
[0 2 0 0 0]
[0 0 3 0 0]
[0 0 0 4 0]
[0 0 0 0 5]>>> from sage.all import *>>> M = matrix(ZZ, [[Integer(1),Integer(0),Integer(0),Integer(0),Integer(0)],˓→[Integer(0),Integer(2),Integer(0),Integer(0),Integer(0)],[Integer(0),˓→Integer(0),Integer(3),Integer(0),Integer(0)],[Integer(0),Integer(0),˓→Integer(0),Integer(4),Integer(0)],[Integer(0),Integer(0),Integer(0),˓→Integer(0),Integer(5)]])>>> M[1 0 0 0 0]
[0 2 0 0 0]
[0 0 3 0 0]
[0 0 0 4 0]
[0 0 0 0 5]

Next of all, create a permutation group element and act on M:
sage: # needs sage.groups
sage: G = PermutationGroup([ (1,2,3)(4,5) ,sage: sigma, tau = G.gens()
sage: sigma(1,2,3)(4,5)
sage: M.permute_rows(sigma)
sage: M
[0 2 0 0 0]
[0 0 3 0 0]
[1 0 0 0 0]
[0 0 0 0 5]
[0 0 0 4 0]>>> from sage.all import *>>> # needs sage.groups>>> G = PermutationGroup([ (1,2,3)(4,5) ,>>> sigma, tau = G.gens()>>> sigma(1,2,3)(4,5)>>> M.permute_rows(sigma)>>> M[0 2 0 0 0]

(1,2,3,4,5) ])(1,2,3,4,5) ])(continues on next page)

182

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 0 3 0 0]
[1 0 0 0 0]
[0 0 0 0 5]
[0 0 0 4 0]

permute_rows_and_columns(row_permutation, column_permutation)
Permute the rows and columns of self by applying the permutation group elements row_permutationand column_permutation respectively.
As permutation group elements act on integers {1, . . . , 𝑛}, rows and columns are considered numbered from
1 for this operation.
INPUT:• row_permutation – a PermutationGroupElement• column_permutation – a PermutationGroupElement
OUTPUT:• A matrix.
EXAMPLES: We create a matrix:
sage: M = matrix(ZZ, [[1,0,0,0,0],[0,2,0,0,0],[0,0,3,0,0],[0,0,0,4,0],[0,0,0,
˓→0,5]])
sage: M
[1 0 0 0 0]
[0 2 0 0 0]
[0 0 3 0 0]
[0 0 0 4 0]
[0 0 0 0 5]>>> from sage.all import *>>> M = matrix(ZZ, [[Integer(1),Integer(0),Integer(0),Integer(0),Integer(0)],˓→[Integer(0),Integer(2),Integer(0),Integer(0),Integer(0)],[Integer(0),˓→Integer(0),Integer(3),Integer(0),Integer(0)],[Integer(0),Integer(0),˓→Integer(0),Integer(4),Integer(0)],[Integer(0),Integer(0),Integer(0),˓→Integer(0),Integer(5)]])>>> M[1 0 0 0 0]
[0 2 0 0 0]
[0 0 3 0 0]
[0 0 0 4 0]
[0 0 0 0 5]

Next of all, create a permutation group element and act on M:
sage: # needs sage.groups
sage: G = PermutationGroup([ (1,2,3)(4,5) ,sage: sigma, tau = G.gens()
sage: sigma(1,2,3)(4,5)
sage: M.permute_rows_and_columns(sigma,tau)
sage: M
[2 0 0 0 0]
[0 3 0 0 0]
[0 0 0 0 1]

(1,2,3,4,5) ])(continues on next page)183

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 0 0 5 0]
[0 0 4 0 0]>>> from sage.all import *>>> # needs sage.groups>>> G = PermutationGroup([ (1,2,3)(4,5) ,>>> sigma, tau = G.gens()>>> sigma(1,2,3)(4,5)>>> M.permute_rows_and_columns(sigma,tau)>>> M[2 0 0 0 0]
[0 3 0 0 0]
[0 0 0 0 1]
[0 0 0 5 0]
[0 0 4 0 0]

(1,2,3,4,5) ])pivots()Return the pivot column positions of this matrix.
OUTPUT: a tuple of Python integers: the position of the first nonzero entry in each row of the echelon form.
This returns a tuple so it is immutable; see Issue #10752.
EXAMPLES:
sage: A = matrix(QQ, 2, 2, range(4))
sage: A.pivots()(0, 1)>>> from sage.all import *>>> A = matrix(QQ, Integer(2), Integer(2), range(Integer(4)))>>> A.pivots()(0, 1)

rank()
Return the rank of this matrix.
EXAMPLES:
sage: m = matrix(GF(7), 5, range(25))
sage: m.rank()
2>>> from sage.all import *>>> m = matrix(GF(Integer(7)), Integer(5), range(Integer(25)))>>> m.rank()
2

Rank is not implemented over the integers modulo a composite yet.:sage: m = matrix(Integers(4), 2, [2,2,2,2])
sage: m.rank()
Traceback (most recent call last):...
NotImplementedError: Echelon form not implemented over˓→modulo 4 .

184

Ring of integers␣

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> m = matrix(Integers(Integer(4)), Integer(2), [Integer(2),Integer(2),˓→Integer(2),Integer(2)])>>> m.rank()
Traceback (most recent call last):...
NotImplementedError: Echelon form not implemented over Ring of integers␣
˓→modulo 4 .

rescale_col(i, s, start_row=0)
Replace i-th col of self by s times i-th col of self.
INPUT:• i – ith column• s – scalar• start_row – only rescale entries at this row and lower
EXAMPLES: We rescale the last column of a matrix over the rational numbers:
sage: a = matrix(QQ, 2, 3, range(6)); a[0 1 2][3 4 5]sage: a.rescale_col(2, 1/2); a
[ 0
1
1]
[ 3
4 5/2]
sage: R.<x> = QQ[]>>> from sage.all import *>>> a = matrix(QQ, Integer(2), Integer(3), range(Integer(6))); a[0 1 2][3 4 5]>>> a.rescale_col(Integer(2), Integer(1)/Integer(2)); a
[ 0
1
1]
[ 3
4 5/2]>>> R = QQ[ x ]; (x,) = R._first_ngens(1)We rescale the last column of a matrix over a polynomial ring:sage: a = matrix(R, 2, 3, [1,x,x^2,x^3,x^4,x^5]); a[ 1x x^2][x^3 x^4 x^5]
sage: a.rescale_col(2, 1/2); a[1
x 1/2*x^2][x^3x^4 1/2*x^5]>>> from sage.all import *>>> a = matrix(R, Integer(2), Integer(3), [Integer(1),x,x**Integer(2),˓→x**Integer(3),x**Integer(4),x**Integer(5)]); a[ 1x x^2][x^3 x^4 x^5]>>> a.rescale_col(Integer(2), Integer(1)/Integer(2)); a[1
x 1/2*x^2][x^3x^4 1/2*x^5]

We try and fail to rescale a matrix over the integers by a non-integer:

185

Matrices and Spaces of Matrices, Release 10.4

sage: a = matrix(ZZ, 2, 3, [0,1,2, 3,4,4]); a[0 1 2][3 4 4]sage: a.rescale_col(2, 1/2)
Traceback (most recent call last):...
TypeError: Rescaling column by Rational Field element cannot be done
over Integer Ring, use change_ring or with_rescaled_col instead.
>>> from sage.all import *>>> a = matrix(ZZ, Integer(2), Integer(3), [Integer(0),Integer(1),Integer(2),␣
˓→Integer(3),Integer(4),Integer(4)]); a[0 1 2][3 4 4]>>> a.rescale_col(Integer(2), Integer(1)/Integer(2))
Traceback (most recent call last):...
TypeError: Rescaling column by Rational Field element cannot be done
over Integer Ring, use change_ring or with_rescaled_col instead.

To rescale the matrix by 1/2, you must change the base ring to the rationals:
sage: a = a.change_ring(QQ); a[0 1 2][3 4 4]sage: a.rescale_col(2,1/2); a[0 1 1][3 4 2]>>> from sage.all import *>>> a = a.change_ring(QQ); a[0 1 2][3 4 4]>>> a.rescale_col(Integer(2),Integer(1)/Integer(2)); a[0 1 1][3 4 2]

rescale_row(i, s, start_col=0)
Replace i-th row of self by s times i-th row of self.
INPUT:• i – ith row• s – scalar• start_col – only rescale entries at this column and to the right
EXAMPLES: We rescale the second row of a matrix over the rational numbers:
sage: a = matrix(QQ, 3, range(6)); a
[0 1]
[2 3]
[4 5]
sage: a.rescale_row(1, 1/2); a[ 0
1][ 1 3/2]
[ 4
5]

186

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> a = matrix(QQ, Integer(3), range(Integer(6))); a
[0 1]
[2 3]
[4 5]
>>> a.rescale_row(Integer(1), Integer(1)/Integer(2)); a[ 0
1][ 1 3/2][ 4
5]

We rescale the second row of a matrix over a polynomial ring:sage: R.<x> = QQ[]
sage: a = matrix(R, 3, [1,x,x^2,x^3,x^4,x^5]); a[ 1x][x^2 x^3][x^4 x^5]
sage: a.rescale_row(1, 1/2); a[1x][1/2*x^2 1/2*x^3]
[
x^4
x^5]
>>> from sage.all import *>>> R = QQ[ x ]; (x,) = R._first_ngens(1)>>> a = matrix(R, Integer(3), [Integer(1),x,x**Integer(2),x**Integer(3),˓→x**Integer(4),x**Integer(5)]); a[ 1x][x^2 x^3][x^4 x^5]>>> a.rescale_row(Integer(1), Integer(1)/Integer(2)); a[1x][1/2*x^2 1/2*x^3]
[
x^4
x^5]

We try and fail to rescale a matrix over the integers by a non-integer:
sage: a = matrix(ZZ, 2, 3, [0,1,2, 3,4,4]); a[0 1 2][3 4 4]sage: a.rescale_row(1, 1/2)
Traceback (most recent call last):...
TypeError: Rescaling row by Rational Field element cannot be done
over Integer Ring, use change_ring or with_rescaled_row instead.
>>> from sage.all import *>>> a = matrix(ZZ, Integer(2), Integer(3), [Integer(0),Integer(1),Integer(2),␣
˓→Integer(3),Integer(4),Integer(4)]); a[0 1 2][3 4 4]>>> a.rescale_row(Integer(1), Integer(1)/Integer(2))
Traceback (most recent call last):...
TypeError: Rescaling row by Rational Field element cannot be done
over Integer Ring, use change_ring or with_rescaled_row instead.

To rescale the matrix by 1/2, you must change the base ring to the rationals:
187

Matrices and Spaces of Matrices, Release 10.4

sage: a = a.change_ring(QQ); a[0 1 2][3 4 4]sage: a.rescale_col(1, 1/2); a[ 0 1/22][ 3
24]>>> from sage.all import *>>> a = a.change_ring(QQ); a[0 1 2][3 4 4]>>> a.rescale_col(Integer(1), Integer(1)/Integer(2)); a[ 0 1/2
2]
[ 3
2
4]

reverse_rows_and_columns()
Reverse the row order and column order of this matrix.
This method transforms a matrix 𝑚𝑖,𝑗 with 0 ≤ 𝑖 < 𝑛𝑟𝑜𝑤𝑠 and 0 ≤ 𝑗 < 𝑛𝑐𝑜𝑙𝑠 into 𝑚𝑛𝑟𝑜𝑤𝑠−𝑖−1,𝑛𝑐𝑜𝑙𝑠−𝑗−1 .
EXAMPLES:
sage: m = matrix(ZZ, 2, 2, range(4))
sage: m.reverse_rows_and_columns()
sage: m[3 2]
[1 0]
sage: m = matrix(ZZ, 2, 3, range(6), sparse=True)
sage: m.reverse_rows_and_columns()
sage: m[5 4 3][2 1 0]sage: m = matrix(ZZ, 3, 2, range(6), sparse=True)
sage: m.reverse_rows_and_columns()
sage: m
[5 4]
[3 2]
[1 0]
sage: m.reverse_rows_and_columns()
sage: m
[0 1]
[2 3]
[4 5]
sage: m = matrix(QQ, 3, 2, [1/i for i in range(1,7)])
sage: m.reverse_rows_and_columns()
sage: m[1/6 1/5][1/4 1/3][1/2
1]
sage: R.<x,y> = ZZ[ x,y ]sage: m = matrix(R, 3, 3, lambda i,j: x**i*y**j, sparse=True)
sage: m.reverse_rows_and_columns()
sage: m[x^2*y^2x^2*yx^2](continues on next page)

188

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[
[

x*y^2
y^2

x*y
y

x]
1]

>>> from sage.all import *>>> m = matrix(ZZ, Integer(2), Integer(2), range(Integer(4)))>>> m.reverse_rows_and_columns()
>>> m
[3 2]
[1 0]
>>> m = matrix(ZZ, Integer(2), Integer(3), range(Integer(6)), sparse=True)>>> m.reverse_rows_and_columns()>>> m[5 4 3][2 1 0]>>> m = matrix(ZZ, Integer(3), Integer(2), range(Integer(6)), sparse=True)>>> m.reverse_rows_and_columns()
>>> m
[5 4]
[3 2]
[1 0]
>>> m.reverse_rows_and_columns()
>>> m
[0 1]
[2 3]
[4 5]
>>> m = matrix(QQ, Integer(3), Integer(2), [Integer(1)/i for i in␣
˓→range(Integer(1),Integer(7))])>>> m.reverse_rows_and_columns()>>> m[1/6 1/5][1/4 1/3][1/2
1]>>> R = ZZ[ x,y ]; (x, y,) = R._first_ngens(2)>>> m = matrix(R, Integer(3), Integer(3), lambda i,j: x**i*y**j, sparse=True)>>> m.reverse_rows_and_columns()>>> m[x^2*y^2x^2*yx^2][ x*y^2
x*y
x]
[
y^2
y
1]

If the matrix is immutable, the method raises an error:
sage: m = matrix(ZZ, 2, [1, 3, -2, 4])
sage: m.set_immutable()sage: m.reverse_rows_and_columns()
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).
>>> from sage.all import *>>> m = matrix(ZZ, Integer(2), [Integer(1), Integer(3), -Integer(2),␣
˓→Integer(4)])(continues on next page)189

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> m.set_immutable()>>> m.reverse_rows_and_columns()
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).

set_col_to_multiple_of_col(i, j, s)
Set column i equal to s times column j.
EXAMPLES: We change the second column to -3 times the first column.
sage: a = matrix(ZZ, 2, 3, range(6)); a[0 1 2][3 4 5]sage: a.set_col_to_multiple_of_col(1, 0, -3)
sage: a[ 0 0 2][ 3 -9 5]>>> from sage.all import *>>> a = matrix(ZZ, Integer(2), Integer(3), range(Integer(6))); a[0 1 2][3 4 5]>>> a.set_col_to_multiple_of_col(Integer(1), Integer(0), -Integer(3))>>> a[ 0 0 2][ 3 -9 5]If we try to multiply a column by a rational number, we get an error message:
sage: a.set_col_to_multiple_of_col(1, 0, 1/2)
Traceback (most recent call last):...
TypeError: Multiplying column by Rational Field element cannot be done over␣
˓→Integer Ring, use change_ring or with_col_set_to_multiple_of_col instead.
>>> from sage.all import *>>> a.set_col_to_multiple_of_col(Integer(1), Integer(0), Integer(1)/˓→Integer(2))
Traceback (most recent call last):...
TypeError: Multiplying column by Rational Field element cannot be done over␣
˓→Integer Ring, use change_ring or with_col_set_to_multiple_of_col instead.

set_immutable()Call this function to set the matrix as immutable.
Matrices are always mutable by default, i.e., you can change their entries using A[i,j] = x. However,mutable matrices aren’t hashable, so can’t be used as keys in dictionaries, etc. Also, often when implementing
a class, you might compute a matrix associated to it, e.g., the matrix of a Hecke operator. If you return thismatrix to the user you’re really returning a reference and the user could then change an entry; this could be
confusing. Thus you should set such a matrix immutable.
EXAMPLES:

190

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

sage: A = Matrix(QQ, 2, 2, range(4))
sage: A.is_mutable()True
sage: A[0,0] = 10
sage: A
[10
1]
[ 2
3]
>>> from sage.all import *>>> A = Matrix(QQ, Integer(2), Integer(2), range(Integer(4)))>>> A.is_mutable()
True>>> A[Integer(0),Integer(0)] = Integer(10)
>>> A
[10
1]
[ 2
3]

Mutable matrices are not hashable, so can’t be used as keys for dictionaries:
sage: hash(A)Traceback (most recent call last):...
TypeError: mutable matrices are unhashable
sage: v = {A:1}
Traceback (most recent call last):...
TypeError: mutable matrices are unhashable>>> from sage.all import *>>> hash(A)Traceback (most recent call last):...
TypeError: mutable matrices are unhashable>>> v = {A:Integer(1)}Traceback (most recent call last):...
TypeError: mutable matrices are unhashable

If we make A immutable it suddenly is hashable.
sage: A.set_immutable()sage: A.is_mutable()False
sage: A[0,0] = 10
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).
sage: hash(A) #random
12
sage: v = {A:1}; v{[10 1][ 2 3]: 1}>>> from sage.all import *>>> A.set_immutable()(continues on next page)191

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> A.is_mutable()
False>>> A[Integer(0),Integer(0)] = Integer(10)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).
>>> hash(A) #random
12>>> v = {A:Integer(1)}; v{[10 1][ 2 3]: 1}

set_row_to_multiple_of_row(i, j, s)
Set row i equal to s times row j.
EXAMPLES: We change the second row to -3 times the first row:sage: a = matrix(ZZ, 2, 3, range(6)); a[0 1 2][3 4 5]sage: a.set_row_to_multiple_of_row(1, 0, -3)
sage: a[ 0 1 2][ 0 -3 -6]>>> from sage.all import *>>> a = matrix(ZZ, Integer(2), Integer(3), range(Integer(6))); a[0 1 2][3 4 5]>>> a.set_row_to_multiple_of_row(Integer(1), Integer(0), -Integer(3))>>> a[ 0 1 2][ 0 -3 -6]

If we try to multiply a row by a rational number, we get an error message:
sage: a.set_row_to_multiple_of_row(1, 0, 1/2)
Traceback (most recent call last):...
TypeError: Multiplying row by Rational Field element cannot be done overInteger Ring, use change_ring or with_row_set_to_multiple_of_row instead.
>>> from sage.all import *>>> a.set_row_to_multiple_of_row(Integer(1), Integer(0), Integer(1)/˓→Integer(2))
Traceback (most recent call last):...
TypeError: Multiplying row by Rational Field element cannot be done overInteger Ring, use change_ring or with_row_set_to_multiple_of_row instead.

str(rep_mapping=None, zero=None, plus_one=None, minus_one=None, unicode=False, shape=None,
character_art=False, left_border=None, right_border=None, top_border=None, bottom_border=None)
Return a nice string representation of the matrix.
INPUT:

192

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

• rep_mapping – a dictionary or callable used to override the usual representation of elements.
If rep_mapping is a dictionary then keys should be elements of the base ring and values the desired
string representation. Values sent in via the other keyword arguments will override values in the dictionary. Use of a dictionary can potentially take a very long time due to the need to hash entries of thematrix. Matrices with entries from QQbar are one example.
If rep_mapping is callable then it will be called with elements of the matrix and must return a string.
Simply call repr() on elements which should have the default representation.
• zero – string (default: None); if not None use the value of zero as the representation of the zeroelement.
• plus_one – string (default: None); if not None use the value of plus_one as the representation of
the one element.
• minus_one – string (default: None); if not None use the value of minus_one as the representationof the negative of the one element.
• unicode – boolean (default: False). Whether to use Unicode symbols instead of ASCII symbols forbrackets and subdivision lines.
• shape – one of "square" or "round" (default: None). Switches between round and square brackets. The default depends on the setting of the unicode keyword argument. For Unicode symbols, thedefault is round brackets in accordance with the TeX rendering, while the ASCII rendering defaults tosquare brackets.
• character_art – boolean (default: False); if True, the result will be of type AsciiArt orUnicodeArt which support line breaking of wide matrices that exceed the window width• left_border, right_border – sequence (default: None); if not None, call str() on the elements and use the results as labels for the rows of the matrix. The labels appear outside of the parentheses.
• top_border, bottom_border – sequence (default: None); if not None, call str() on the elements and use the results as labels for the columns of the matrix. The labels appear outside of theparentheses.
EXAMPLES:
sage: R = PolynomialRing(QQ,6, z )sage: a = matrix(2,3, R.gens())
sage: a.__repr__()[z0 z1 z2]\n[z3 z4 z5]sage: M = matrix([[1,0],[2,-1]])
sage: M.str()[ 1 0]\n[ 2 -1]
sage: M.str(plus_one= + ,minus_one= - ,zero= . )[+ .]\n[2 -]sage: M.str({1:"not this one",2:"II"},minus_one="*",plus_one="I")[ I 0]\n[II *]sage: def print_entry(x):....:if x>0:....:
return +....:elif x<0:....:
return ....:
else: return .
...
sage: M.str(print_entry)(continues on next page)193

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[+ .]\n[+ -]sage: M.str(repr)[ 1 0]\n[ 2 -1]
sage: M = matrix([[1,2,3],[4,5,6],[7,8,9]])sage: M.subdivide(None, 2)
sage: print(M.str(unicode=True))⎛1 2│3⎞⎜4 5│6⎟⎝7 8│9⎠sage: M.subdivide([0,1,1,3], [0,2,3,3])
sage: print(M.str(unicode=True, shape="square"))⎡┼───┼─┼┼⎤⎢│1 2│3││⎥⎢┼───┼─┼┼⎥⎢┼───┼─┼┼⎥⎢│4 5│6││⎥⎢│7 8│9││⎥⎣┼───┼─┼┼⎦>>> from sage.all import *>>> R = PolynomialRing(QQ,Integer(6), z )>>> a = matrix(Integer(2),Integer(3), R.gens())>>> a.__repr__()[z0 z1 z2]\n[z3 z4 z5]>>> M = matrix([[Integer(1),Integer(0)],[Integer(2),-Integer(1)]])>>> M.str()[ 1 0]\n[ 2 -1]>>> M.str(plus_one= + ,minus_one= - ,zero= . )[+ .]\n[2 -]>>> M.str({Integer(1):"not this one",Integer(2):"II"},minus_one="*",plus_one=
˓→"I")[ I 0]\n[II *]>>> def print_entry(x):...
if x>Integer(0):...
return +...
elif x<Integer(0):...
return ...
else: return .
...
>>> M.str(print_entry)[+ .]\n[+ -]>>> M.str(repr)[ 1 0]\n[ 2 -1]>>> M = matrix([[Integer(1),Integer(2),Integer(3)],[Integer(4),Integer(5),˓→Integer(6)],[Integer(7),Integer(8),Integer(9)]])>>> M.subdivide(None, Integer(2))>>> print(M.str(unicode=True))⎛1 2│3⎞⎜4 5│6⎟⎝7 8│9⎠>>> M.subdivide([Integer(0),Integer(1),Integer(1),Integer(3)], [Integer(0),˓→Integer(2),Integer(3),Integer(3)])(continues on next page)

194

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> print(M.str(unicode=True, shape="square"))⎡┼───┼─┼┼⎤⎢│1 2│3││⎥⎢┼───┼─┼┼⎥⎢┼───┼─┼┼⎥⎢│4 5│6││⎥⎢│7 8│9││⎥⎣┼───┼─┼┼⎦If character_art is set, the lines of large matrices are wrapped in a readable way:sage: set_random_seed(0)sage: matrix.random(RDF, 3, 5).str(unicode=True, character_art=True)⎛ -0.27440062056807446
0.5031965950979831 -0.001975438590219314⎜ -0.05461130074681608 -0.033673314214051286-0.9401270875197381⎝ 0.19906256610645512
0.3242250183948632
0.6026443545751128-0.9467802263760512-0.35104242112828943-0.9541798283979341

0.5056889961514748⎞
0.5084492941557279⎟-0.8948790563276592⎠>>> from sage.all import *>>> set_random_seed(Integer(0))>>> matrix.random(RDF, Integer(3), Integer(5)).str(unicode=True, character_˓→art=True)⎛ -0.27440062056807446
0.5031965950979831 -0.001975438590219314⎜ -0.05461130074681608 -0.033673314214051286-0.9401270875197381⎝ 0.19906256610645512
0.3242250183948632
0.6026443545751128<BLANKLINE>-0.9467802263760512
0.5056889961514748⎞-0.35104242112828943
0.5084492941557279⎟-0.9541798283979341-0.8948790563276592⎠

The number of floating point digits to display is controlled by matrix.options.precision and canalso be set by the IPython magic %precision. This does not affect the internal precision of the represented
data, but only the textual display of matrices:sage: matrix.options.precision = 4
sage: A = matrix(RR, [[1/3, 200/3], [-3, 1e6]]); A[ 0.3333
66.67][ -3.000 1.000E+6]
sage: unicode_art(A)⎛ 0.3333
66.67⎞⎝ -3.000 1.000E+6⎠
sage: matrix.options.precision = Nonesage: A[ 0.333333333333333
66.6666666666667][ -3.00000000000000 1.00000000000000e6]>>> from sage.all import *>>> matrix.options.precision = Integer(4)>>> A = matrix(RR, [[Integer(1)/Integer(3), Integer(200)/Integer(3)], [˓→Integer(3), RealNumber( 1e6 )]]); A[ 0.3333
66.67][ -3.000 1.000E+6]>>> unicode_art(A)(continues on next page)

195

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)⎛ 0.3333
66.67⎞⎝ -3.000 1.000E+6⎠>>> matrix.options.precision = None>>> A
[ 0.333333333333333
66.6666666666667][ -3.00000000000000 1.00000000000000e6]

Matrices with borders:sage: M = matrix([[1,2,3], [4,5,6], [7,8,9]])sage: M.subdivide(None, 2)
sage: print(M.str(unicode=True,....:
top_border=[ ab , cde , f ],....:bottom_border=[ * ,
,
],
....:
left_border=[1, 10, 100],....:right_border=[ ,< ,]))ab cde
f
1⎛ 1
2│ 3⎞
10⎜ 4
5│ 6⎟ <
100⎝ 78│ 9⎠*>>> from sage.all import *>>> M = matrix([[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),˓→Integer(6)], [Integer(7),Integer(8),Integer(9)]])>>> M.subdivide(None, Integer(2))>>> print(M.str(unicode=True,...
top_border=[ ab , cde , f ],...
bottom_border=[ * ,,],...
left_border=[Integer(1), Integer(10), Integer(100)],...
right_border=[ ,< ,]))ab cde
f
1⎛ 1
2│ 3⎞
10⎜ 4
5│ 6⎟ <
100⎝ 78│ 9⎠*swap_columns(c1, c2)
Swap columns c1 and c2 of self.
EXAMPLES: We create a rational matrix:
sage: M = MatrixSpace(QQ,3,3)
sage: A = M([1,9,-7,4/5,4,3,6,4,3])
sage: A
[ 1
9 -7]
[4/5
4
3]
[ 6
4
3]
>>> from sage.all import *>>> M = MatrixSpace(QQ,Integer(3),Integer(3))>>> A = M([Integer(1),Integer(9),-Integer(7),Integer(4)/Integer(5),Integer(4),˓→Integer(3),Integer(6),Integer(4),Integer(3)])
>>> A
[ 1
9 -7]
(continues on next page)

196

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[4/5
[ 6

4
4

3]
3]

Since the first column is numbered zero, this swaps the second and third columns:
sage: A.swap_columns(1,2); A[ 1 -7
9]
[4/5
3
4]
[ 6
3
4]
>>> from sage.all import *>>> A.swap_columns(Integer(1),Integer(2)); A[ 1 -7
9]
[4/5
3
4]
[ 6
3
4]

swap_rows(r1, r2)
Swap rows r1 and r2 of self.
EXAMPLES: We create a rational matrix:
sage: M = MatrixSpace(QQ, 3, 3)
sage: A = M([1,9,-7, 4/5,4,3, 6,4,3])
sage: A
[ 1
9 -7]
[4/5
4
3]
[ 6
4
3]
>>> from sage.all import *>>> M = MatrixSpace(QQ, Integer(3), Integer(3))>>> A = M([Integer(1),Integer(9),-Integer(7), Integer(4)/Integer(5),˓→Integer(4),Integer(3), Integer(6),Integer(4),Integer(3)])
>>> A
[ 1
9 -7]
[4/5
4
3]
[ 6
4
3]

Since the first row is numbered zero, this swaps the first and third rows:
sage: A.swap_rows(0, 2); A
[ 6
4
3]
[4/5
4
3]
[ 1
9 -7]
>>> from sage.all import *>>> A.swap_rows(Integer(0), Integer(2)); A
[ 6
4
3]
[4/5
4
3]
[ 1
9 -7]

with_added_multiple_of_column(i, j, s, start_row=0)
Add s times column j to column i, returning new matrix.
EXAMPLES: We add -1 times the third column to the second column of an integer matrix, remembering tostart numbering cols at zero:197

Matrices and Spaces of Matrices, Release 10.4

sage: a = matrix(ZZ, 2, 3, range(6)); a[0 1 2][3 4 5]sage: b = a.with_added_multiple_of_column(1, 2, -1); b[ 0 -1 2][ 3 -1 5]>>> from sage.all import *>>> a = matrix(ZZ, Integer(2), Integer(3), range(Integer(6))); a[0 1 2][3 4 5]>>> b = a.with_added_multiple_of_column(Integer(1), Integer(2), -Integer(1));␣
˓→b[ 0 -1 2][ 3 -1 5]

The original matrix is unchanged:
sage: a[0 1 2][3 4 5]>>> from sage.all import *>>> a[0 1 2][3 4 5]Adding a rational multiple is okay, and reassigning a variable is okay:
sage: a = a.with_added_multiple_of_column(0, 1, 1/3); a
[ 1/3
1
2]
[13/3
4
5]
>>> from sage.all import *>>> a = a.with_added_multiple_of_column(Integer(0), Integer(1), Integer(1)/˓→Integer(3)); a
[ 1/3
1
2]
[13/3
4
5]

with_added_multiple_of_row(i, j, s, start_col=0)
Add s times row j to row i, returning new matrix.
EXAMPLES: We add -3 times the first row to the second row of an integer matrix, remembering to start
numbering rows at zero:sage: a = matrix(ZZ,2,3,range(6)); a[0 1 2][3 4 5]sage: b = a.with_added_multiple_of_row(1,0,-3); b[ 0 1 2]
[ 3 1 -1]>>> from sage.all import *>>> a = matrix(ZZ,Integer(2),Integer(3),range(Integer(6))); a[0 1 2][3 4 5](continues on next page)

198

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> b = a.with_added_multiple_of_row(Integer(1),Integer(0),-Integer(3)); b[ 0 1 2]
[ 3 1 -1]

The original matrix is unchanged:
sage: a[0 1 2][3 4 5]>>> from sage.all import *>>> a[0 1 2][3 4 5]Adding a rational multiple is okay, and reassigning a variable is okay:
sage: a = a.with_added_multiple_of_row(0,1,1/3); a[
1 7/3 11/3][
3
4
5]>>> from sage.all import *>>> a = a.with_added_multiple_of_row(Integer(0),Integer(1),Integer(1)/˓→Integer(3)); a[
1 7/3 11/3]
[
3
4
5]

with_col_set_to_multiple_of_col(i, j, s)
Set column i equal to s times column j, returning a new matrix.
EXAMPLES: We change the second column to -3 times the first column.
sage: a = matrix(ZZ, 2, 3, range(6)); a[0 1 2][3 4 5]sage: b = a.with_col_set_to_multiple_of_col(1, 0, -3); b[ 0 0 2][ 3 -9 5]>>> from sage.all import *>>> a = matrix(ZZ, Integer(2), Integer(3), range(Integer(6))); a[0 1 2][3 4 5]>>> b = a.with_col_set_to_multiple_of_col(Integer(1), Integer(0), ˓→Integer(3)); b[ 0 0 2][ 3 -9 5]Note that the original matrix is unchanged:
sage: a[0 1 2][3 4 5]199

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> a[0 1 2][3 4 5]Adding a rational multiple is okay, and reassigning a variable is okay:
sage: a = a.with_col_set_to_multiple_of_col(1, 0, 1/2); a[ 0
02][ 3 3/2
5]>>> from sage.all import *>>> a = a.with_col_set_to_multiple_of_col(Integer(1), Integer(0), Integer(1)/˓→Integer(2)); a[ 0
02][ 3 3/2
5]

with_permuted_columns(permutation)
Return the matrix obtained from permuting the columns of self by applying the permutation group element
permutation.
As permutation group elements act on integers {1, . . . , 𝑛}, columns are considered numbered from 1 for thisoperation.
INPUT:• permutation, a PermutationGroupElement
OUTPUT:• A matrix.
EXAMPLES: We create some matrix:
sage: M = matrix(ZZ, [[1,0,0,0,0],[0,2,0,0,0],[0,0,3,0,0],[0,0,0,4,0],[0,0,0,
˓→0,5]])
sage: M
[1 0 0 0 0]
[0 2 0 0 0]
[0 0 3 0 0]
[0 0 0 4 0]
[0 0 0 0 5]>>> from sage.all import *>>> M = matrix(ZZ, [[Integer(1),Integer(0),Integer(0),Integer(0),Integer(0)],˓→[Integer(0),Integer(2),Integer(0),Integer(0),Integer(0)],[Integer(0),˓→Integer(0),Integer(3),Integer(0),Integer(0)],[Integer(0),Integer(0),˓→Integer(0),Integer(4),Integer(0)],[Integer(0),Integer(0),Integer(0),˓→Integer(0),Integer(5)]])>>> M[1 0 0 0 0]
[0 2 0 0 0]
[0 0 3 0 0]
[0 0 0 4 0]
[0 0 0 0 5]

Next of all, create a permutation group element and act on M:

200

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

sage: # needs sage.groups
sage: G = PermutationGroup([ (1,2,3)(4,5) ,sage: sigma, tau = G.gens()
sage: sigma(1,2,3)(4,5)
sage: M.with_permuted_columns(sigma)[0 0 1 0 0]
[2 0 0 0 0]
[0 3 0 0 0]
[0 0 0 0 4]
[0 0 0 5 0]>>> from sage.all import *>>> # needs sage.groups>>> G = PermutationGroup([ (1,2,3)(4,5) ,>>> sigma, tau = G.gens()>>> sigma(1,2,3)(4,5)>>> M.with_permuted_columns(sigma)[0 0 1 0 0]
[2 0 0 0 0]
[0 3 0 0 0]
[0 0 0 0 4]
[0 0 0 5 0]

(1,2,3,4,5) ])(1,2,3,4,5) ])with_permuted_rows(permutation)
Return the matrix obtained from permuting the rows of self by applying the permutation group element
permutation.
As permutation group elements act on integers {1, . . . , 𝑛}, rows are considered numbered from 1 for thisoperation.
INPUT:• permutation – a PermutationGroupElement
OUTPUT:• A matrix.
EXAMPLES: We create a matrix:
sage: M = matrix(ZZ, [[1,0,0,0,0],[0,2,0,0,0],[0,0,3,0,0],[0,0,0,4,0],[0,0,0,
˓→0,5]])
sage: M
[1 0 0 0 0]
[0 2 0 0 0]
[0 0 3 0 0]
[0 0 0 4 0]
[0 0 0 0 5]>>> from sage.all import *>>> M = matrix(ZZ, [[Integer(1),Integer(0),Integer(0),Integer(0),Integer(0)],˓→[Integer(0),Integer(2),Integer(0),Integer(0),Integer(0)],[Integer(0),˓→Integer(0),Integer(3),Integer(0),Integer(0)],[Integer(0),Integer(0),˓→Integer(0),Integer(4),Integer(0)],[Integer(0),Integer(0),Integer(0),˓→Integer(0),Integer(5)]])>>> M(continues on next page)201

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[1 0 0 0 0]
[0 2 0 0 0]
[0 0 3 0 0]
[0 0 0 4 0]
[0 0 0 0 5]

Next of all, create a permutation group element and act on M:
sage: # needs sage.groups
sage: G = PermutationGroup([ (1,2,3)(4,5) ,sage: sigma, tau = G.gens()
sage: sigma(1,2,3)(4,5)
sage: M.with_permuted_rows(sigma)[0 2 0 0 0]
[0 0 3 0 0]
[1 0 0 0 0]
[0 0 0 0 5]
[0 0 0 4 0]>>> from sage.all import *>>> # needs sage.groups>>> G = PermutationGroup([ (1,2,3)(4,5) ,>>> sigma, tau = G.gens()>>> sigma(1,2,3)(4,5)>>> M.with_permuted_rows(sigma)[0 2 0 0 0]
[0 0 3 0 0]
[1 0 0 0 0]
[0 0 0 0 5]
[0 0 0 4 0]

(1,2,3,4,5) ])(1,2,3,4,5) ])with_permuted_rows_and_columns(row_permutation, column_permutation)
Return the matrix obtained from permuting the rows and columns of self by applying the permutationgroup elements row_permutation and column_permutation.
As permutation group elements act on integers {1, . . . , 𝑛}, rows and columns are considered numbered from
1 for this operation.
INPUT:• row_permutation – a PermutationGroupElement• column_permutation – a PermutationGroupElement
OUTPUT:• A matrix.
EXAMPLES: We create a matrix:
sage: M = matrix(ZZ, [[1,0,0,0,0],[0,2,0,0,0],[0,0,3,0,0],[0,0,0,4,0],[0,0,0,
˓→0,5]])
sage: M
[1 0 0 0 0]
[0 2 0 0 0]
[0 0 3 0 0](continues on next page)

202

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 0 0 4 0]
[0 0 0 0 5]>>> from sage.all import *>>> M = matrix(ZZ, [[Integer(1),Integer(0),Integer(0),Integer(0),Integer(0)],˓→[Integer(0),Integer(2),Integer(0),Integer(0),Integer(0)],[Integer(0),˓→Integer(0),Integer(3),Integer(0),Integer(0)],[Integer(0),Integer(0),˓→Integer(0),Integer(4),Integer(0)],[Integer(0),Integer(0),Integer(0),˓→Integer(0),Integer(5)]])>>> M[1 0 0 0 0]
[0 2 0 0 0]
[0 0 3 0 0]
[0 0 0 4 0]
[0 0 0 0 5]

Next of all, create a permutation group element and act on M:
sage: # needs sage.groups
sage: G = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])sage: sigma, tau = G.gens()
sage: sigma(1,2,3)(4,5)
sage: M.with_permuted_rows_and_columns(sigma,tau)[2 0 0 0 0]
[0 3 0 0 0]
[0 0 0 0 1]
[0 0 0 5 0]
[0 0 4 0 0]>>> from sage.all import *>>> # needs sage.groups>>> G = PermutationGroup([ (1,2,3)(4,5) , (1,2,3,4,5) ])>>> sigma, tau = G.gens()>>> sigma(1,2,3)(4,5)>>> M.with_permuted_rows_and_columns(sigma,tau)[2 0 0 0 0]
[0 3 0 0 0]
[0 0 0 0 1]
[0 0 0 5 0]
[0 0 4 0 0]

with_rescaled_col(i, s, start_row=0)
Replaces i-th col of self by s times i-th col of self, returning new matrix.
EXAMPLES: We rescale the last column of a matrix over the integers:
sage: a = matrix(ZZ, 2, 3, range(6)); a[0 1 2][3 4 5]sage: b = a.with_rescaled_col(2, -2); b
[ 0
1 -4]
[ 3
4 -10]

203

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> a = matrix(ZZ, Integer(2), Integer(3), range(Integer(6))); a[0 1 2][3 4 5]>>> b = a.with_rescaled_col(Integer(2), -Integer(2)); b
[ 0
1 -4]
[ 3
4 -10]The original matrix is unchanged:
sage: a[0 1 2][3 4 5]>>> from sage.all import *>>> a[0 1 2][3 4 5]Adding a rational multiple is okay, and reassigning a variable is okay:
sage: a = a.with_rescaled_col(1, 1/3); a[ 0 1/32][ 3 4/3
5]>>> from sage.all import *>>> a = a.with_rescaled_col(Integer(1), Integer(1)/Integer(3)); a[ 0 1/32][ 3 4/3
5]

with_rescaled_row(i, s, start_col=0)
Replaces i-th row of self by s times i-th row of self, returning new matrix.
EXAMPLES: We rescale the second row of a matrix over the integers:
sage: a = matrix(ZZ, 3, 2, range(6)); a
[0 1]
[2 3]
[4 5]
sage: b = a.with_rescaled_row(1, -2); b[ 0 1][-4 -6][ 4 5]>>> from sage.all import *>>> a = matrix(ZZ, Integer(3), Integer(2), range(Integer(6))); a
[0 1]
[2 3]
[4 5]
>>> b = a.with_rescaled_row(Integer(1), -Integer(2)); b[ 0 1][-4 -6][ 4 5]The original matrix is unchanged:

204

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

sage: a
[0 1]
[2 3]
[4 5]
>>> from sage.all import *
>>> a
[0 1]
[2 3]
[4 5]

Adding a rational multiple is okay, and reassigning a variable is okay:
sage: a = a.with_rescaled_row(2, 1/3); a
[ 0
1]
[ 2
3]
[4/3 5/3]>>> from sage.all import *>>> a = a.with_rescaled_row(Integer(2), Integer(1)/Integer(3)); a
[ 0
1]
[ 2
3]
[4/3 5/3]

with_row_set_to_multiple_of_row(i, j, s)
Set row i equal to s times row j, returning a new matrix.
EXAMPLES: We change the second row to -3 times the first row:sage: a = matrix(ZZ, 2, 3, range(6)); a[0 1 2][3 4 5]sage: b = a.with_row_set_to_multiple_of_row(1, 0, -3); b[ 0 1 2][ 0 -3 -6]>>> from sage.all import *>>> a = matrix(ZZ, Integer(2), Integer(3), range(Integer(6))); a[0 1 2][3 4 5]>>> b = a.with_row_set_to_multiple_of_row(Integer(1), Integer(0), ˓→Integer(3)); b[ 0 1 2][ 0 -3 -6]

Note that the original matrix is unchanged:
sage: a[0 1 2][3 4 5]>>> from sage.all import *>>> a[0 1 2][3 4 5]Adding a rational multiple is okay, and reassigning a variable is okay:205

Matrices and Spaces of Matrices, Release 10.4

sage: a = a.with_row_set_to_multiple_of_row(1, 0, 1/2); a[ 01
2][ 0 1/2
1]>>> from sage.all import *>>> a = a.with_row_set_to_multiple_of_row(Integer(1), Integer(0), Integer(1)/˓→Integer(2)); a[ 01
2][ 0 1/2
1]

with_swapped_columns(c1, c2)
Swap columns c1 and c2 of self and return a new matrix.
INPUT:• c1, c2 – integers specifying columns of self to interchange
OUTPUT:
A new matrix, identical to self except that columns c1 and c2 are swapped.
EXAMPLES:
Remember that columns are numbered starting from zero.
sage: A = matrix(QQ, 4, range(20))
sage: A.with_swapped_columns(1, 2)[ 0 2 1 3 4]
[ 5 7 6 8 9]
[10 12 11 13 14][15 17 16 18 19]>>> from sage.all import *>>> A = matrix(QQ, Integer(4), range(Integer(20)))>>> A.with_swapped_columns(Integer(1), Integer(2))[ 0 2 1 3 4]
[ 5 7 6 8 9]
[10 12 11 13 14][15 17 16 18 19]

Trying to swap a column with itself will succeed, but still return a new matrix.
sage: A = matrix(QQ, 4, range(20))
sage: B = A.with_swapped_columns(2, 2)
sage: A == B
True
sage: A is B
False>>> from sage.all import *>>> A = matrix(QQ, Integer(4), range(Integer(20)))>>> B = A.with_swapped_columns(Integer(2), Integer(2))>>> A == B
True>>> A is B
False

The column specifications are checked.

206

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

sage: A = matrix(4, range(20))
sage: A.with_swapped_columns(-1, 2)
Traceback (most recent call last):...
IndexError: matrix column index out of range
sage: A.with_swapped_columns(2, 5)
Traceback (most recent call last):...
IndexError: matrix column index out of range>>> from sage.all import *>>> A = matrix(Integer(4), range(Integer(20)))>>> A.with_swapped_columns(-Integer(1), Integer(2))
Traceback (most recent call last):...
IndexError: matrix column index out of range>>> A.with_swapped_columns(Integer(2), Integer(5))
Traceback (most recent call last):...
IndexError: matrix column index out of range

with_swapped_rows(r1, r2)
Swap rows r1 and r2 of self and return a new matrix.
INPUT:• r1, r2 – integers specifying rows of self to interchange
OUTPUT:
A new matrix, identical to self except that rows r1 and r2 are swapped.
EXAMPLES:
Remember that rows are numbered starting from zero.
sage: A = matrix(QQ, 4, range(20))
sage: A.with_swapped_rows(1, 2)[ 0 1 2 3 4]
[10 11 12 13 14][ 5 6 7 8 9]
[15 16 17 18 19]>>> from sage.all import *>>> A = matrix(QQ, Integer(4), range(Integer(20)))>>> A.with_swapped_rows(Integer(1), Integer(2))[ 0 1 2 3 4]
[10 11 12 13 14][ 5 6 7 8 9]
[15 16 17 18 19]

Trying to swap a row with itself will succeed, but still return a new matrix.
sage: A = matrix(QQ, 4, range(20))
sage: B = A.with_swapped_rows(2, 2)
sage: A == B
(continues on next page)

207

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)True
sage: A is B
False>>> from sage.all import *>>> A = matrix(QQ, Integer(4), range(Integer(20)))>>> B = A.with_swapped_rows(Integer(2), Integer(2))>>> A == B
True>>> A is B
False

The row specifications are checked.
sage: A = matrix(4, range(20))
sage: A.with_swapped_rows(-1, 2)
Traceback (most recent call last):...
IndexError: matrix row index out of range
sage: A.with_swapped_rows(2, 5)
Traceback (most recent call last):...
IndexError: matrix row index out of range>>> from sage.all import *>>> A = matrix(Integer(4), range(Integer(20)))>>> A.with_swapped_rows(-Integer(1), Integer(2))
Traceback (most recent call last):...
IndexError: matrix row index out of range>>> A.with_swapped_rows(Integer(2), Integer(5))
Traceback (most recent call last):...
IndexError: matrix row index out of range

sage.matrix.matrix0.set_max_cols(n)Sets the global variable max_cols (which is used in deciding how to output a matrix).
EXAMPLES:
sage: from sage.matrix.matrix0 import set_max_cols
sage: set_max_cols(50)doctest:...: DeprecationWarning: set_max_cols is replaced by
˓→max_cols
See https://github.com/sagemath/sage/issues/30552 for details.
>>> from sage.all import *>>> from sage.matrix.matrix0 import set_max_cols>>> set_max_cols(Integer(50))
doctest:...: DeprecationWarning: set_max_cols is replaced by
˓→max_cols
See https://github.com/sagemath/sage/issues/30552 for details.

matrix.options.

matrix.options.

sage.matrix.matrix0.set_max_rows(n)208

Chapter 6. Base class for matrices, part 0

Matrices and Spaces of Matrices, Release 10.4

Sets the global variable max_rows (which is used in deciding how to output a matrix).
EXAMPLES:
sage: from sage.matrix.matrix0 import set_max_rows
sage: set_max_rows(20)doctest:...: DeprecationWarning: set_max_rows is replaced by
˓→max_rows
See https://github.com/sagemath/sage/issues/30552 for details.
>>> from sage.all import *>>> from sage.matrix.matrix0 import set_max_rows>>> set_max_rows(Integer(20))
doctest:...: DeprecationWarning: set_max_rows is replaced by
˓→max_rows
See https://github.com/sagemath/sage/issues/30552 for details.

matrix.options.

matrix.options.

sage.matrix.matrix0.unpickle(cls, parent, immutability, cache, data, version)
Unpickle a matrix. This is only used internally by Sage. Users should never call this function directly.
EXAMPLES: We illustrating saving and loading several different types of matrices.
OVER Z:
sage: A = matrix(ZZ, 2, range(4))
sage: loads(dumps(A)) # indirect doctest
[0 1]
[2 3]
>>> from sage.all import *>>> A = matrix(ZZ, Integer(2), range(Integer(4)))>>> loads(dumps(A)) # indirect doctest
[0 1]
[2 3]

Sparse OVER
Dense over:[𝑥, 𝑦]:

Dense over finite field.

209

Matrices and Spaces of Matrices, Release 10.4

210

Chapter 6. Base class for matrices, part 0

CHAPTERSEVEN

BASE CLASS FOR MATRICES, PART 1

For design documentation see sage.matrix.docs.
class sage.matrix.matrix1.Matrix
Bases: Matrix
augment(right, subdivide=False)
Returns a new matrix formed by appending the matrix (or vector) right on the right side of self.
INPUT:• right – a matrix, vector or free module element, whose dimensions are compatible with self.
• subdivide – (default: False); request the resulting matrix to have a new subdivision, separating
self from right.
OUTPUT:
A new matrix formed by appending right onto the right side of self. If right is a vector (or free module
element) then in this context it is appropriate to consider it as a column vector. (The code first converts a vector
to a 1-column matrix.)
If subdivide is True then any column subdivisions for the two matrices are preserved, and a new subdivision is added between self and right. If the row divisions are identical, then they are preserved,
otherwise they are discarded. When subdivide is False there is no subdivision information in the result.
Warning: If subdivide is True then unequal row subdivisions will be discarded, since it would
be ambiguous how to interpret them. If the subdivision behavior is not what you need, you can manage
subdivisions yourself with methods like get_subdivisions() and subdivide(). You might alsofind block_matrix() or block_diagonal_matrix() useful and simpler in some instances.
EXAMPLES:
Augmenting with a matrix.
sage: A = matrix(QQ, 3, range(12))
sage: B = matrix(QQ, 3, range(9))
sage: A.augment(B)[ 0 1 2 3 0 1 2]
[ 4 5 6 7 3 4 5]
[ 8 9 10 11 6 7 8]>>> from sage.all import *>>> A = matrix(QQ, Integer(3), range(Integer(12)))(continues on next page)211

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> B = matrix(QQ, Integer(3), range(Integer(9)))>>> A.augment(B)[ 0 1 2 3 0 1 2]
[ 4 5 6 7 3 4 5]
[ 8 9 10 11 6 7 8]

Augmenting with a vector.
sage: A = matrix(QQ, 2, [0, 2, 4, 6, 8, 10])sage: v = vector(QQ, 2, [100, 200])
sage: A.augment(v)[ 0
24 100][ 6
8 10 200]>>> from sage.all import *>>> A = matrix(QQ, Integer(2), [Integer(0), Integer(2), Integer(4),␣
˓→Integer(6), Integer(8), Integer(10)])>>> v = vector(QQ, Integer(2), [Integer(100), Integer(200)])>>> A.augment(v)[ 0
24 100][ 6
8 10 200]

Errors are raised if the sizes are incompatible.
sage: A = matrix(RR, [[1, 2],[3, 4]])sage: B = matrix(RR, [[10, 20], [30, 40], [50, 60]])
sage: A.augment(B)Traceback (most recent call last):...
TypeError: number of rows must be the same, 2 != 3
sage: v = vector(RR, [100, 200, 300])
sage: A.augment(v)Traceback (most recent call last):...
TypeError: number of rows must be the same, 2 != 3>>> from sage.all import *>>> A = matrix(RR, [[Integer(1), Integer(2)],[Integer(3), Integer(4)]])>>> B = matrix(RR, [[Integer(10), Integer(20)], [Integer(30), Integer(40)],␣
˓→[Integer(50), Integer(60)]])>>> A.augment(B)Traceback (most recent call last):...
TypeError: number of rows must be the same, 2 != 3>>> v = vector(RR, [Integer(100), Integer(200), Integer(300)])>>> A.augment(v)Traceback (most recent call last):...
TypeError: number of rows must be the same, 2 != 3

Setting subdivide to True will, in its simplest form, add a subdivision between self and right.
sage: A = matrix(QQ, 3, range(12))
sage: B = matrix(QQ, 3, range(15))(continues on next page)212

Chapter 7. Base class for matrices, part 1

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

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

Column subdivisions are preserved by augmentation, and enriched, if subdivisions are requested. (So multiple
augmentations can be recorded.)
sage: A = matrix(QQ, 3, range(6))
sage: A.subdivide(None, [1])sage: B = matrix(QQ, 3, range(9))
sage: B.subdivide(None, [2])sage: A.augment(B, subdivide=True)[0|1|0 1|2]
[2|3|3 4|5]
[4|5|6 7|8]>>> from sage.all import *>>> A = matrix(QQ, Integer(3), range(Integer(6)))>>> A.subdivide(None, [Integer(1)])>>> B = matrix(QQ, Integer(3), range(Integer(9)))>>> B.subdivide(None, [Integer(2)])>>> A.augment(B, subdivide=True)[0|1|0 1|2]
[2|3|3 4|5]
[4|5|6 7|8]

Row subdivisions can be preserved, but only if they are identical. Otherwise, this information is discarded
and must be managed separately.
sage: A = matrix(QQ, 3, range(6))
sage: A.subdivide([1,3], None)sage: B = matrix(QQ, 3, range(9))
sage: B.subdivide([1,3], None)sage: A.augment(B, subdivide=True)[0 1|0 1 2][---+-----][2 3|3 4 5]
[4 5|6 7 8][---+-----]
sage: A.subdivide([1,2], None)sage: A.augment(B, subdivide=True)[0 1|0 1 2]
[2 3|3 4 5]
[4 5|6 7 8]213

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = matrix(QQ, Integer(3), range(Integer(6)))>>> A.subdivide([Integer(1),Integer(3)], None)>>> B = matrix(QQ, Integer(3), range(Integer(9)))>>> B.subdivide([Integer(1),Integer(3)], None)>>> A.augment(B, subdivide=True)[0 1|0 1 2][---+-----][2 3|3 4 5]
[4 5|6 7 8][---+-----]>>> A.subdivide([Integer(1),Integer(2)], None)>>> A.augment(B, subdivide=True)[0 1|0 1 2]
[2 3|3 4 5]
[4 5|6 7 8]

The result retains the base ring of self by coercing the elements of right into the base ring of self.
sage: A = matrix(QQ, 2, [1,2])
sage: B = matrix(RR, 2, [sin(1.1), sin(2.2)])
sage: C = A.augment(B); C˓→needs sage.symbolic[
1 183017397/205358938][
2 106580492/131825561]
sage: C.parent()
˓→needs sage.symbolic
Full MatrixSpace of 2 by 2 dense matrices over Rational Field#␣#␣

sage: D = B.augment(A); D[0.89120736006... 1.00000000000000][0.80849640381... 2.00000000000000]
sage: D.parent()
Full MatrixSpace of 2 by 2 dense matrices
over Real Field with 53 bits of precision>>> from sage.all import *>>> A = matrix(QQ, Integer(2), [Integer(1),Integer(2)])>>> B = matrix(RR, Integer(2), [sin(RealNumber( 1.1 )), sin(RealNumber( 2.2
˓→ ))])>>> C = A.augment(B); C#␣˓→needs sage.symbolic[
1 183017397/205358938][
2 106580492/131825561]>>> C.parent()#␣˓→needs sage.symbolic
Full MatrixSpace of 2 by 2 dense matrices over Rational Field>>> D = B.augment(A); D[0.89120736006... 1.00000000000000][0.80849640381... 2.00000000000000]>>> D.parent()
Full MatrixSpace of 2 by 2 dense matrices
over Real Field with 53 bits of precision

Sometimes it is not possible to coerce into the base ring of self. A solution is to change the base ring ofself to a more expansive ring. Here we mix the rationals with a ring of polynomials with rational coefficients.
214

Chapter 7. Base class for matrices, part 1

Matrices and Spaces of Matrices, Release 10.4

sage: R.<y> = PolynomialRing(QQ)
sage: A = matrix(QQ, 1, [1,2])
sage: B = matrix(R, 1, [y, y^2])
sage: C = B.augment(A); C[ y y^2
1
2]
sage: C.parent()
Full MatrixSpace of 1 by 4 dense matrices over
Univariate Polynomial Ring in y over Rational Field
sage: D = A.augment(B)Traceback (most recent call last):...
TypeError: y is not a constant polynomial
sage: E = A.change_ring(R)sage: F = E.augment(B); F[ 12
y y^2]
sage: F.parent()
Full MatrixSpace of 1 by 4 dense matrices over
Univariate Polynomial Ring in y over Rational Field>>> from sage.all import *>>> R = PolynomialRing(QQ, names=( y ,)); (y,) = R._first_ngens(1)>>> A = matrix(QQ, Integer(1), [Integer(1),Integer(2)])>>> B = matrix(R, Integer(1), [y, y**Integer(2)])>>> C = B.augment(A); C[ y y^2
1
2]>>> C.parent()
Full MatrixSpace of 1 by 4 dense matrices over
Univariate Polynomial Ring in y over Rational Field>>> D = A.augment(B)Traceback (most recent call last):...
TypeError: y is not a constant polynomial>>> E = A.change_ring(R)>>> F = E.augment(B); F[ 12
y y^2]>>> F.parent()
Full MatrixSpace of 1 by 4 dense matrices over
Univariate Polynomial Ring in y over Rational Field

AUTHORS:• Naqi Jaffery (2006-01-24): examples• Rob Beezer (2010-12-07): vector argument, docstring, subdivisions
block_sum(other)
Return the block matrix that has self and other on the diagonal:[ self0 ][0 other ]EXAMPLES:

215

Matrices and Spaces of Matrices, Release 10.4

sage: A = matrix(QQ[[ t ]], 2, range(1, 5))
sage: A.block_sum(100*A)
[ 1
2
0
0]
[ 3
4
0
0]
[ 0
0 100 200]
[ 0
0 300 400]>>> from sage.all import *>>> A = matrix(QQ[[ t ]], Integer(2), range(Integer(1), Integer(5)))>>> A.block_sum(Integer(100)*A)
[ 1
2
0
0]
[ 3
4
0
0]
[ 0
0 100 200]
[ 0
0 300 400]

column(i, from_list=False)
Return the i’th column of this matrix as a vector.
This column is a dense vector if and only if the matrix is a dense matrix.
INPUT:• i – integer• from_list – bool (default: False); if true, returns the i’th element of self.columns() (seecolumns()), which may be faster, but requires building a list of all columns the first time it is called
after an entry of the matrix is changed.
EXAMPLES:
sage: a = matrix(2, 3, range(6)); a[0 1 2][3 4 5]sage: a.column(1)(1, 4)>>> from sage.all import *>>> a = matrix(Integer(2), Integer(3), range(Integer(6))); a[0 1 2][3 4 5]>>> a.column(Integer(1))(1, 4)

If the column is negative, it wraps around, just like with list indexing, e.g., -1 gives the right-most column:
sage: a.column(-1)(2, 5)>>> from sage.all import *>>> a.column(-Integer(1))(2, 5)

column_ambient_module(base_ring=None, sparse=None)
Return the free module that contains the columns of the matrix.
EXAMPLES:

216

Chapter 7. Base class for matrices, part 1

Matrices and Spaces of Matrices, Release 10.4

sage: M = matrix(Zmod(5), 2, 3)
sage: M.column_ambient_module()
Vector space of dimension 2 over Ring of integers modulo 5
sage: M.column(1).parent() == M.column_ambient_module()True
sage: M = Matrix(ZZ, 3, 4)
sage: M.column_ambient_module()
Ambient free module of rank 3 over the principal ideal domain Integer Ringsage: M.column_ambient_module(QQ)
Vector space of dimension 3 over Rational Field
sage: M = Matrix(QQ, 4, 5)
sage: M.column_ambient_module()
Vector space of dimension 4 over Rational Field
sage: M.column_ambient_module(ZZ)
Ambient free module of rank 4 over the principal ideal domain Integer Ring>>> from sage.all import *>>> M = matrix(Zmod(Integer(5)), Integer(2), Integer(3))>>> M.column_ambient_module()
Vector space of dimension 2 over Ring of integers modulo 5>>> M.column(Integer(1)).parent() == M.column_ambient_module()
True>>> M = Matrix(ZZ, Integer(3), Integer(4))>>> M.column_ambient_module()
Ambient free module of rank 3 over the principal ideal domain Integer Ring>>> M.column_ambient_module(QQ)
Vector space of dimension 3 over Rational Field>>> M = Matrix(QQ, Integer(4), Integer(5))>>> M.column_ambient_module()
Vector space of dimension 4 over Rational Field>>> M.column_ambient_module(ZZ)
Ambient free module of rank 4 over the principal ideal domain Integer Ringcolumns(copy=True)
Return a list of the columns of self.
INPUT:• copy – (default: True) if True, return a copy of the list of columns which is safe to change.
If self is a sparse matrix, columns are returned as sparse vectors, otherwise returned vectors are dense.
EXAMPLES:
sage: matrix(3, [1..9]).columns()[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
sage: matrix(RR, 2, [sqrt(2), pi, exp(1), 0]).columns()#␣˓→needs sage.symbolic[(1.41421356237310, 2.71828182845905), (3.14159265358979, 0.000000000000000)]
sage: matrix(RR, 0, 2, []).columns()[(), ()]
sage: matrix(RR, 2, 0, []).columns()[]
sage: m = matrix(RR, 3, 3, {(1,2): pi, (2, 2): -1, (0,1): sqrt(2)})#␣(continues on next page)217

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)needs sage.symbolic
sage: parent(m.columns()[0])#␣˓→needs sage.symbolicSparse vector space of dimension 3 over Real Field with 53 bits of precision˓→>>> from sage.all import *>>> matrix(Integer(3), (ellipsis_range(Integer(1),Ellipsis,Integer(9)))).
˓→columns()[(1, 4, 7), (2, 5, 8), (3, 6, 9)]>>> matrix(RR, Integer(2), [sqrt(Integer(2)), pi, exp(Integer(1)),␣
˓→Integer(0)]).columns()# needs sage.symbolic[(1.41421356237310, 2.71828182845905), (3.14159265358979, 0.000000000000000)]>>> matrix(RR, Integer(0), Integer(2), []).columns()[(), ()]>>> matrix(RR, Integer(2), Integer(0), []).columns()[]>>> m = matrix(RR, Integer(3), Integer(3), {(Integer(1),Integer(2)): pi,␣
˓→(Integer(2), Integer(2)): -Integer(1), (Integer(0),Integer(1)):␣
˓→sqrt(Integer(2))})# needs sage.symbolic>>> parent(m.columns()[Integer(0)])␣˓→# needs sage.symbolicSparse vector space of dimension 3 over Real Field with 53 bits of precision

Sparse matrices produce sparse columns.
sage: A = matrix(QQ, 2, range(4), sparse=True)
sage: v = A.columns()[0]sage: v.is_sparse()
True>>> from sage.all import *>>> A = matrix(QQ, Integer(2), range(Integer(4)), sparse=True)>>> v = A.columns()[Integer(0)]>>> v.is_sparse()
Truedelete_columns(dcols, check=True)
Return the matrix constructed from deleting the columns with indices in the dcols list.
INPUT:• dcols – list of indices of columns to be deleted from self.
• check – checks whether any index in dcols is out of range. Defaults to True.
See also:
The methods delete_rows() and matrix_from_columns() are related.
EXAMPLES:
sage: A = Matrix(3, 4, range(12)); A[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
sage: A.delete_columns([0,2])[ 1 3](continues on next page)

218

Chapter 7. Base class for matrices, part 1

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 5 7][ 9 11]>>> from sage.all import *>>> A = Matrix(Integer(3), Integer(4), range(Integer(12))); A[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]>>> A.delete_columns([Integer(0),Integer(2)])[ 1 3][ 5 7][ 9 11]dcols can be a tuple. But only the underlying set of indices matters.
sage: A.delete_columns((2,0,2))[ 1 3][ 5 7][ 9 11]>>> from sage.all import *>>> A.delete_columns((Integer(2),Integer(0),Integer(2)))[ 1 3][ 5 7][ 9 11]The default is to check whether any index in dcols is out of range.
sage: A.delete_columns([-1,2,4])
Traceback (most recent call last):...
IndexError: [-1, 4] contains invalid indicessage: A.delete_columns([-1,2,4], check=False)[ 0 1 3][ 4 5 7]
[ 8 9 11]>>> from sage.all import *>>> A.delete_columns([-Integer(1),Integer(2),Integer(4)])
Traceback (most recent call last):...
IndexError: [-1, 4] contains invalid indices>>> A.delete_columns([-Integer(1),Integer(2),Integer(4)], check=False)[ 0 1 3][ 4 5 7]
[ 8 9 11]AUTHORS:• Wai Yan Pong (2012-03-05)
delete_rows(drows, check=True)
Return the matrix constructed from deleting the rows with indices in the drows list.
INPUT:• drows – list of indices of rows to be deleted from self.
219

Matrices and Spaces of Matrices, Release 10.4

• check – (boolean, default: True); whether to check if any index in drows is out of range.
See also:
The methods delete_columns() and matrix_from_rows() are related.
EXAMPLES:
sage: A = Matrix(4, 3, range(12)); A[ 0 1 2]
[ 3 4 5]
[ 6 7 8][ 9 10 11]
sage: A.delete_rows([0,2])[ 3 4 5]
[ 9 10 11]>>> from sage.all import *>>> A = Matrix(Integer(4), Integer(3), range(Integer(12))); A[ 0 1 2]
[ 3 4 5]
[ 6 7 8][ 9 10 11]>>> A.delete_rows([Integer(0),Integer(2)])[ 3 4 5]
[ 9 10 11]

drows can be a tuple. But only the underlying set of indices matters.
sage: A.delete_rows((2,0,2))[ 3 4 5]
[ 9 10 11]>>> from sage.all import *>>> A.delete_rows((Integer(2),Integer(0),Integer(2)))[ 3 4 5]
[ 9 10 11]

The default is to check whether the any index in drows is out of range.
sage: A.delete_rows([-1,2,4])
Traceback (most recent call last):...
IndexError: [-1, 4] contains invalid indicessage: A.delete_rows([-1,2,4], check=False)[ 0 1 2]
[ 3 4 5]
[ 9 10 11]>>> from sage.all import *>>> A.delete_rows([-Integer(1),Integer(2),Integer(4)])
Traceback (most recent call last):...
IndexError: [-1, 4] contains invalid indices>>> A.delete_rows([-Integer(1),Integer(2),Integer(4)], check=False)[ 0 1 2]
[ 3 4 5]
[ 9 10 11]

220

Chapter 7. Base class for matrices, part 1

Matrices and Spaces of Matrices, Release 10.4

dense_columns(copy=True)
Return list of the dense columns of self.
INPUT:• copy – (default: True) if True, return a copy so you can modify it safely
EXAMPLES:
An example over the integers:
sage: a = matrix(3, 3, range(9)); a[0 1 2][3 4 5][6 7 8]sage: a.dense_columns()[(0, 3, 6), (1, 4, 7), (2, 5, 8)]>>> from sage.all import *>>> a = matrix(Integer(3), Integer(3), range(Integer(9))); a[0 1 2][3 4 5][6 7 8]>>> a.dense_columns()[(0, 3, 6), (1, 4, 7), (2, 5, 8)]

We do an example over a polynomial ring:sage: R.<x> = QQ[]
sage: a = matrix(R, 2, [x,x^2, 2/3*x,1+x^5]); a[xx^2][ 2/3*x x^5 + 1]
sage: a.dense_columns()[(x, 2/3*x), (x^2, x^5 + 1)]
sage: a = matrix(R, 2, [x,x^2, 2/3*x,1+x^5], sparse=True)
sage: c = a.dense_columns(); c[(x, 2/3*x), (x^2, x^5 + 1)]
sage: parent(c[1])Ambient free module of rank 2 over the principal ideal domain
Univariate Polynomial Ring in x over Rational Field>>> from sage.all import *>>> R = QQ[ x ]; (x,) = R._first_ngens(1)>>> a = matrix(R, Integer(2), [x,x**Integer(2), Integer(2)/Integer(3)*x,
˓→Integer(1)+x**Integer(5)]); a[xx^2][ 2/3*x x^5 + 1]>>> a.dense_columns()[(x, 2/3*x), (x^2, x^5 + 1)]>>> a = matrix(R, Integer(2), [x,x**Integer(2), Integer(2)/Integer(3)*x,
˓→Integer(1)+x**Integer(5)], sparse=True)>>> c = a.dense_columns(); c[(x, 2/3*x), (x^2, x^5 + 1)]>>> parent(c[Integer(1)])
Ambient free module of rank 2 over the principal ideal domain
Univariate Polynomial Ring in x over Rational Field

dense_matrix()
If this matrix is sparse, return a dense matrix with the same entries. If this matrix is dense, return this matrix
221Matrices and Spaces of Matrices, Release 10.4

(not a copy).
Note: The definition of “dense” and “sparse” in Sage have nothing to do with the number of nonzero entries.
Sparse and dense are properties of the underlying representation of the matrix.
EXAMPLES:
sage: A = MatrixSpace(QQ,2, sparse=True)([1,2,0,1])
sage: A.is_sparse()
True
sage: B = A.dense_matrix()
sage: B.is_sparse()
False
sage: A == B
True
sage: B.dense_matrix() is B
True
sage: A*B
[1 4]
[0 1]
sage: A.parent()
Full MatrixSpace of 2 by 2 sparse matrices over Rational Field
sage: B.parent()
Full MatrixSpace of 2 by 2 dense matrices over Rational Field>>> from sage.all import *>>> A = MatrixSpace(QQ,Integer(2), sparse=True)([Integer(1),Integer(2),˓→Integer(0),Integer(1)])>>> A.is_sparse()
True>>> B = A.dense_matrix()>>> B.is_sparse()
False>>> A == B
True>>> B.dense_matrix() is B
True>>> A*B[1 4][0 1]>>> A.parent()
Full MatrixSpace of 2 by 2 sparse matrices over Rational Field>>> B.parent()
Full MatrixSpace of 2 by 2 dense matrices over Rational Field

In Sage, the product of a sparse and a dense matrix is always dense:
sage: (A*B).parent()
Full MatrixSpace of 2 by 2 dense matrices over Rational Field
sage: (B*A).parent()
Full MatrixSpace of 2 by 2 dense matrices over Rational Field>>> from sage.all import *>>> (A*B).parent()
Full MatrixSpace of 2 by 2 dense matrices over Rational Field(continues on next page)

222

Chapter 7. Base class for matrices, part 1

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> (B*A).parent()
Full MatrixSpace of 2 by 2 dense matrices over Rational Field

dense_rows(copy=True)
Return list of the dense rows of self.
INPUT:• copy – (default: True) if True, return a copy so you can modify it safely (note that the individual
vectors in the copy should not be modified since they are mutable!)
EXAMPLES:
sage: m = matrix(3, range(9)); m[0 1 2][3 4 5][6 7 8]sage: v = m.dense_rows(); v[(0, 1, 2), (3, 4, 5), (6, 7, 8)]
sage: v is m.dense_rows()
False
sage: m.dense_rows(copy=False) is m.dense_rows(copy=False)
True
sage: m[0,0] = 10
sage: m.dense_rows()[(10, 1, 2), (3, 4, 5), (6, 7, 8)]>>> from sage.all import *>>> m = matrix(Integer(3), range(Integer(9))); m[0 1 2][3 4 5][6 7 8]>>> v = m.dense_rows(); v[(0, 1, 2), (3, 4, 5), (6, 7, 8)]>>> v is m.dense_rows()
False>>> m.dense_rows(copy=False) is m.dense_rows(copy=False)
True>>> m[Integer(0),Integer(0)] = Integer(10)>>> m.dense_rows()[(10, 1, 2), (3, 4, 5), (6, 7, 8)]lift()
Return lift of self to the covering ring of the base ring R, which is by definition the ring returned by calling
cover_ring() on R, or just R itself if the cover_ring method is not defined.
EXAMPLES:
sage: M = Matrix(Integers(7), 2, 2, [5, 9, 13, 15]); M
[5 2]
[6 1]
sage: M.lift()
[5 2]
[6 1]
sage: parent(M.lift())
Full MatrixSpace of 2 by 2 dense matrices over Integer Ring

223

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> M = Matrix(Integers(Integer(7)), Integer(2), Integer(2), [Integer(5),␣
˓→Integer(9), Integer(13), Integer(15)]); M
[5 2]
[6 1]
>>> M.lift()
[5 2]
[6 1]
>>> parent(M.lift())
Full MatrixSpace of 2 by 2 dense matrices over Integer Ring

The field QQ doesn’t have a cover_ring method:
sage: hasattr(QQ,
False

cover_ring )>>> from sage.all import *>>> hasattr(QQ, cover_ring )False

So lifting a matrix over QQ gives back the same exact matrix.
sage: B = matrix(QQ, 2, [1..4])
sage: B.lift()
[1 2]
[3 4]
sage: B.lift() is B
True>>> from sage.all import *>>> B = matrix(QQ, Integer(2), (ellipsis_range(Integer(1),Ellipsis,
˓→Integer(4))))>>> B.lift()
[1 2]
[3 4]
>>> B.lift() is B
True

lift_centered()
Apply the lift_centered method to every entry of self.
OUTPUT:
If self is a matrix over the Integers mod 𝑛, this method returns the unique matrix 𝑚 such that 𝑚 is congruent
to self mod 𝑛 and for every entry 𝑚[𝑖, 𝑗] we have −𝑛/2 < 𝑚[𝑖, 𝑗] ≤ 𝑛/2. If the coefficient ring does nothave a cover_ring method, return self.
EXAMPLES:
sage: M = Matrix(Integers(8), 2, 4, range(8)); M[0 1 2 3][4 5 6 7]
sage: L = M.lift_centered(); L[ 0 1 2 3]
[ 4 -3 -2 -1]
sage: parent(L)Full MatrixSpace of 2 by 4 dense matrices over Integer Ring

224

Chapter 7. Base class for matrices, part 1

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> M = Matrix(Integers(Integer(8)), Integer(2), Integer(4),␣
˓→range(Integer(8))); M[0 1 2 3][4 5 6 7]>>> L = M.lift_centered(); L[ 0 1 2 3]
[ 4 -3 -2 -1]>>> parent(L)Full MatrixSpace of 2 by 4 dense matrices over Integer Ring

The returned matrix is congruent to M modulo 8.:
sage: L.mod(8)[0 1 2 3][4 5 6 7]>>> from sage.all import *>>> L.mod(Integer(8))[0 1 2 3][4 5 6 7]

The field QQ doesn’t have a cover_ring method:
sage: hasattr(QQ,
False

cover_ring )>>> from sage.all import *>>> hasattr(QQ, cover_ring )False

So lifting a matrix over QQ gives back the same exact matrix.
sage: B = matrix(QQ, 2, [1..4])
sage: B.lift_centered()
[1 2]
[3 4]
sage: B.lift_centered() is B
True>>> from sage.all import *>>> B = matrix(QQ, Integer(2), (ellipsis_range(Integer(1),Ellipsis,
˓→Integer(4))))>>> B.lift_centered()
[1 2]
[3 4]
>>> B.lift_centered() is B
Truematrix_from_columns(columns)
Return the matrix constructed from self using columns with indices in the columns list.
EXAMPLES:
sage: M = MatrixSpace(Integers(8), 3, 3)
sage: A = M(range(9)); A(continues on next page)225

Matrices and Spaces of Matrices, Release 10.4

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

matrix_from_rows(rows)
Return the matrix constructed from self using rows with indices in the rows list.
EXAMPLES:
sage: M = MatrixSpace(Integers(8), 3, 3)
sage: A = M(range(9)); A[0 1 2][3 4 5][6 7 0]sage: A.matrix_from_rows([2,1])[6 7 0][3 4 5]>>> from sage.all import *>>> M = MatrixSpace(Integers(Integer(8)), Integer(3), Integer(3))>>> A = M(range(Integer(9))); A[0 1 2][3 4 5][6 7 0]>>> A.matrix_from_rows([Integer(2),Integer(1)])[6 7 0][3 4 5]matrix_from_rows_and_columns(rows, columns)
Return the matrix constructed from self from the given rows and columns.
EXAMPLES:
sage: M = MatrixSpace(Integers(8), 3, 3)
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])(continues on next page)

226

Chapter 7. Base class for matrices, part 1

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[4 5]
[7 0]
>>> from sage.all import *>>> M = MatrixSpace(Integers(Integer(8)), Integer(3), Integer(3))>>> 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]

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]

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]AUTHORS:• Jaap Spies (2006-02-18)• Didier Deshommes: some Pyrex speedups implemented
matrix_over_field()
Return copy of this matrix, but with entries viewed as elements of the fraction field of the base ring (assuming
it is defined).
EXAMPLES:
sage: A = MatrixSpace(IntegerRing(),2)([1,2,3,4])
sage: B = A.matrix_over_field()(continues on next page)227

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: B
[1 2]
[3 4]
sage: B.parent()
Full MatrixSpace of 2 by 2 dense matrices over Rational Field>>> from sage.all import *>>> A = MatrixSpace(IntegerRing(),Integer(2))([Integer(1),Integer(2),˓→Integer(3),Integer(4)])>>> B = A.matrix_over_field()
>>> B
[1 2]
[3 4]
>>> B.parent()
Full MatrixSpace of 2 by 2 dense matrices over Rational Field

matrix_space(nrows=None, ncols=None, sparse=None)
Return the ambient matrix space of self.
INPUT:• nrows, ncols – (optional) number of rows and columns in returned matrix space.
• sparse – whether the returned matrix space uses sparse or dense matrices.
EXAMPLES:
sage: m = matrix(3, [1..9])sage: m.matrix_space()
Full MatrixSpace of 3 by 3 dense matrices over Integer Ringsage: m.matrix_space(ncols=2)
Full MatrixSpace of 3 by 2 dense matrices over Integer Ringsage: m.matrix_space(1)Full MatrixSpace of 1 by 3 dense matrices over Integer Ringsage: m.matrix_space(1, 2, True)
Full MatrixSpace of 1 by 2 sparse matrices over Integer Ringsage: M = MatrixSpace(QQ, 3, implementation= generic )sage: m = M.an_element()
sage: m.matrix_space()
Full MatrixSpace of 3 by 3 dense matrices over Rational Field(using Matrix_generic_dense)
sage: m.matrix_space(nrows=2, ncols=12)
Full MatrixSpace of 2 by 12 dense matrices over Rational Field(using Matrix_generic_dense)
sage: m.matrix_space(nrows=2, sparse=True)
Full MatrixSpace of 2 by 3 sparse matrices over Rational Field>>> from sage.all import *>>> m = matrix(Integer(3), (ellipsis_range(Integer(1),Ellipsis,Integer(9))))>>> m.matrix_space()
Full MatrixSpace of 3 by 3 dense matrices over Integer Ring>>> m.matrix_space(ncols=Integer(2))
Full MatrixSpace of 3 by 2 dense matrices over Integer Ring>>> m.matrix_space(Integer(1))
Full MatrixSpace of 1 by 3 dense matrices over Integer Ring>>> m.matrix_space(Integer(1), Integer(2), True)(continues on next page)

228

Chapter 7. Base class for matrices, part 1

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Full MatrixSpace of 1 by 2 sparse matrices over Integer Ring>>> M = MatrixSpace(QQ, Integer(3), implementation= generic )>>> m = M.an_element()>>> m.matrix_space()
Full MatrixSpace of 3 by 3 dense matrices over Rational Field(using Matrix_generic_dense)>>> m.matrix_space(nrows=Integer(2), ncols=Integer(12))
Full MatrixSpace of 2 by 12 dense matrices over Rational Field(using Matrix_generic_dense)>>> m.matrix_space(nrows=Integer(2), sparse=True)
Full MatrixSpace of 2 by 3 sparse matrices over Rational Field

new_matrix(nrows=None, ncols=None, entries=None, coerce=True, copy=True, sparse=None)
Create a matrix in the parent of this matrix with the given number of rows, columns, etc. The default parameters are the same as for self.
INPUT:
These three variables get sent to matrix_space():• nrows, ncols – number of rows and columns in returned matrix. If not specified, defaults to Noneand will give a matrix of the same size as self.
• sparse – whether returned matrix is sparse or not. Defaults to same value as self.
The remaining three variables (coerce, entries, and copy) are used by sage.matrix.
matrix_space.MatrixSpace() to construct the new matrix.
Warning: This function called with no arguments returns the zero matrix of the same dimension andsparseness of self.
EXAMPLES:
sage: A = matrix(ZZ,2,2,[1,2,3,4]); A
[1 2]
[3 4]
sage: A.new_matrix()
[0 0]
[0 0]
sage: A.new_matrix(1,1)[0]sage: A.new_matrix(3,3).parent()
Full MatrixSpace of 3 by 3 dense matrices over Integer Ring>>> from sage.all import *>>> A = matrix(ZZ,Integer(2),Integer(2),[Integer(1),Integer(2),Integer(3),˓→Integer(4)]); A
[1 2]
[3 4]
>>> A.new_matrix()
[0 0]
[0 0]
>>> A.new_matrix(Integer(1),Integer(1))[0](continues on next page)229

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> A.new_matrix(Integer(3),Integer(3)).parent()
Full MatrixSpace of 3 by 3 dense matrices over Integer Ringsage: A = matrix(RR,2,3,[1.1,2.2,3.3,4.4,5.5,6.6]); A[1.10000000000000 2.20000000000000 3.30000000000000][4.40000000000000 5.50000000000000 6.60000000000000]
sage: A.new_matrix()[0.000000000000000 0.000000000000000 0.000000000000000][0.000000000000000 0.000000000000000 0.000000000000000]
sage: A.new_matrix().parent()
Full MatrixSpace of 2 by 3 dense matrices
over Real Field with 53 bits of precision>>> from sage.all import *>>> A = matrix(RR,Integer(2),Integer(3),[RealNumber( 1.1 ),RealNumber( 2.2 ),˓→RealNumber( 3.3 ),RealNumber( 4.4 ),RealNumber( 5.5 ),RealNumber( 6.6 )]); A[1.10000000000000 2.20000000000000 3.30000000000000][4.40000000000000 5.50000000000000 6.60000000000000]>>> A.new_matrix()[0.000000000000000 0.000000000000000 0.000000000000000][0.000000000000000 0.000000000000000 0.000000000000000]>>> A.new_matrix().parent()
Full MatrixSpace of 2 by 3 dense matrices
over Real Field with 53 bits of precision
sage: M = MatrixSpace(ZZ, 2, 3, implementation= generic )sage: m = M.an_element()
sage: m.new_matrix().parent()
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring
(using Matrix_generic_dense)
sage: m.new_matrix(3,3).parent()
Full MatrixSpace of 3 by 3 dense matrices over Integer Ring
(using Matrix_generic_dense)
sage: m.new_matrix(3,3, sparse=True).parent()
Full MatrixSpace of 3 by 3 sparse matrices over Integer Ring>>> from sage.all import *>>> M = MatrixSpace(ZZ, Integer(2), Integer(3), implementation= generic )>>> m = M.an_element()>>> m.new_matrix().parent()
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring
(using Matrix_generic_dense)>>> m.new_matrix(Integer(3),Integer(3)).parent()
Full MatrixSpace of 3 by 3 dense matrices over Integer Ring
(using Matrix_generic_dense)>>> m.new_matrix(Integer(3),Integer(3), sparse=True).parent()
Full MatrixSpace of 3 by 3 sparse matrices over Integer Ring

numpy(dtype=None)
Return the Numpy matrix associated to this matrix.
INPUT:• dtype – The desired data-type for the array. If not given, then the type will be determined as theminimum type required to hold the objects in the sequence.
EXAMPLES:
230

Chapter 7. Base class for matrices, part 1

Matrices and Spaces of Matrices, Release 10.4

sage: # needs numpy
sage: a = matrix(3, range(12))
sage: a.numpy()
array([[ 0, 1, 2, 3],[ 4, 5, 6, 7],[ 8, 9, 10, 11]])sage: a.numpy( f )array([[ 0.,
1.,
2.,
3.],
[ 4.,
5.,
6.,
7.],
[ 8.,
9., 10., 11.]], dtype=float32)
sage: a.numpy( d )array([[ 0.,
1.,
2.,
3.],
[ 4.,
5.,
6.,
7.],
[ 8.,
9., 10., 11.]])
sage: a.numpy( B )array([[ 0, 1, 2, 3],[ 4, 5, 6, 7],[ 8, 9, 10, 11]], dtype=uint8)>>> from sage.all import *>>> # needs numpy>>> a = matrix(Integer(3), range(Integer(12)))>>> a.numpy()
array([[ 0, 1, 2, 3],[ 4, 5, 6, 7],[ 8, 9, 10, 11]])>>> a.numpy( f )array([[ 0.,
1.,
2.,
3.],
[ 4.,
5.,
6.,
7.],
[ 8.,
9., 10., 11.]], dtype=float32)>>> a.numpy( d )array([[ 0.,
1.,
2.,
3.],
[ 4.,
5.,
6.,
7.],
[ 8.,
9., 10., 11.]])>>> a.numpy( B )array([[ 0, 1, 2, 3],[ 4, 5, 6, 7],[ 8, 9, 10, 11]], dtype=uint8)

Type numpy.typecodes for a list of the possible typecodes:
sage: import numpy
˓→needs numpy
sage: sorted(numpy.typecodes.items())
˓→needs numpy[( All , ?bhilqpBHILQPefdgFDGSUVOMm ), ( AllFloat , efdgFDG ),( AllInteger , bBhHiIlLqQpP ), ( Character , c ), ( Complex ,( Datetime , Mm ), ( Float , efdg ), ( Integer , bhilqp ),( UnsignedInteger , BHILQP )]>>> from sage.all import *>>> import numpy
˓→needs numpy>>> sorted(numpy.typecodes.items())
˓→needs numpy[( All , ?bhilqpBHILQPefdgFDGSUVOMm ), ( AllFloat , efdgFDG ),( AllInteger , bBhHiIlLqQpP ), ( Character , c ), ( Complex ,#␣#␣FDG ),#␣#␣FDG ),(continues on next page)231

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)( Datetime , Mm ), ( Float , efdg ), ( Integer ,( UnsignedInteger , BHILQP )]bhilqp ),Alternatively, numpy automatically calls this function (via the magic __array__() method) to convert
Sage matrices to numpy arrays:
sage: # needs numpy
sage: import numpy
sage: b = numpy.array(a); b
array([[ 0, 1, 2, 3],[ 4, 5, 6, 7],[ 8, 9, 10, 11]])sage: b.dtype
dtype( int32 ) # 32-bit
dtype( int64 ) # 64-bit
sage: b.shape(3, 4)>>> from sage.all import *>>> # needs numpy>>> import numpy>>> b = numpy.array(a); b
array([[ 0, 1, 2, 3],[ 4, 5, 6, 7],[ 8, 9, 10, 11]])>>> b.dtype
dtype( int32 ) # 32-bit
dtype( int64 ) # 64-bit>>> b.shape(3, 4)

row(i, from_list=False)
Return the i’th row of this matrix as a vector.
This row is a dense vector if and only if the matrix is a dense matrix.
INPUT:• i – integer• from_list – bool (default: False); if true, returns the i’th element of self.rows() (seerows()), which may be faster, but requires building a list of all rows the first time it is called afteran entry of the matrix is changed.
EXAMPLES:
sage: a = matrix(2, 3, range(6)); a[0 1 2][3 4 5]sage: a.row(0)(0, 1, 2)
sage: a.row(1)(3, 4, 5)
sage: a.row(-1) # last row(3, 4, 5)232

Chapter 7. Base class for matrices, part 1

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> a = matrix(Integer(2), Integer(3), range(Integer(6))); a[0 1 2][3 4 5]>>> a.row(Integer(0))(0, 1, 2)>>> a.row(Integer(1))(3, 4, 5)>>> a.row(-Integer(1)) # last row(3, 4, 5)

row_ambient_module(base_ring=None, sparse=None)
Return the free module that contains the rows of the matrix.
EXAMPLES:
sage: M = matrix(Zmod(5), 2, 3)
sage: M.row_ambient_module()
Vector space of dimension 3 over Ring of integers modulo 5
sage: M.row(1).parent() == M.row_ambient_module()True
sage: M = Matrix(ZZ, 3, 4)
sage: M.row_ambient_module()
Ambient free module of rank 4 over the principal ideal domain Integer Ringsage: M.row_ambient_module(QQ)
Vector space of dimension 4 over Rational Field
sage: M = Matrix(QQ, 4, 5)
sage: M.row_ambient_module()
Vector space of dimension 5 over Rational Field
sage: M.row_ambient_module(ZZ)
Ambient free module of rank 5 over the principal ideal domain Integer Ring>>> from sage.all import *>>> M = matrix(Zmod(Integer(5)), Integer(2), Integer(3))>>> M.row_ambient_module()
Vector space of dimension 3 over Ring of integers modulo 5>>> M.row(Integer(1)).parent() == M.row_ambient_module()
True>>> M = Matrix(ZZ, Integer(3), Integer(4))>>> M.row_ambient_module()
Ambient free module of rank 4 over the principal ideal domain Integer Ring>>> M.row_ambient_module(QQ)
Vector space of dimension 4 over Rational Field>>> M = Matrix(QQ, Integer(4), Integer(5))>>> M.row_ambient_module()
Vector space of dimension 5 over Rational Field>>> M.row_ambient_module(ZZ)
Ambient free module of rank 5 over the principal ideal domain Integer Ringrows(copy=True)
Return a list of the rows of self.
INPUT:

233

Matrices and Spaces of Matrices, Release 10.4

• copy – (default: True) if True, return a copy of the list of rows which is safe to change.
If self is a sparse matrix, rows are returned as sparse vectors, otherwise returned vectors are dense.
EXAMPLES:
sage: matrix(3, [1..9]).rows()[(1, 2, 3), (4, 5, 6), (7, 8, 9)]
sage: matrix(RR, 2, [sqrt(2), pi, exp(1), 0]).rows()#␣˓→needs sage.symbolic[(1.41421356237310, 3.14159265358979), (2.71828182845905, 0.000000000000000)]
sage: matrix(RR, 0, 2, []).rows()[]
sage: matrix(RR, 2, 0, []).rows()[(), ()]
sage: m = matrix(RR, 3, 3, {(1,2): pi, (2, 2): -1, (0,1): sqrt(2)})#␣˓→needs sage.symbolic
sage: parent(m.rows()[0])#␣˓→needs sage.symbolicSparse vector space of dimension 3 over Real Field with 53 bits of precision>>> from sage.all import *>>> matrix(Integer(3), (ellipsis_range(Integer(1),Ellipsis,Integer(9)))).
˓→rows()[(1, 2, 3), (4, 5, 6), (7, 8, 9)]>>> matrix(RR, Integer(2), [sqrt(Integer(2)), pi, exp(Integer(1)),␣
˓→Integer(0)]).rows()# needs sage.symbolic[(1.41421356237310, 3.14159265358979), (2.71828182845905, 0.000000000000000)]>>> matrix(RR, Integer(0), Integer(2), []).rows()[]>>> matrix(RR, Integer(2), Integer(0), []).rows()[(), ()]>>> m = matrix(RR, Integer(3), Integer(3), {(Integer(1),Integer(2)): pi,␣
˓→(Integer(2), Integer(2)): -Integer(1), (Integer(0),Integer(1)):␣
˓→sqrt(Integer(2))})# needs sage.symbolic>>> parent(m.rows()[Integer(0)])␣˓→# needs sage.symbolicSparse vector space of dimension 3 over Real Field with 53 bits of precision

Sparse matrices produce sparse rows.
sage: A = matrix(QQ, 2, range(4), sparse=True)
sage: v = A.rows()[0]sage: v.is_sparse()
True>>> from sage.all import *>>> A = matrix(QQ, Integer(2), range(Integer(4)), sparse=True)>>> v = A.rows()[Integer(0)]>>> v.is_sparse()
True

set_column(col, v)
Sets the entries of column col to the entries of v.
INPUT:• col – index of column to be set.
• v – a list or vector of the new entries.
234

Chapter 7. Base class for matrices, part 1

Matrices and Spaces of Matrices, Release 10.4

OUTPUT:
Changes the matrix in-place, so there is no output.
EXAMPLES:
New entries may be contained in a vector.:sage: A = matrix(QQ, 5, range(25))
sage: u = vector(QQ, [0, -1, -2, -3, -4])
sage: A.set_column(2, u)
sage: A[ 0 1 0 3 4]
[ 5 6 -1 8 9]
[10 11 -2 13 14][15 16 -3 18 19][20 21 -4 23 24]>>> from sage.all import *>>> A = matrix(QQ, Integer(5), range(Integer(25)))>>> u = vector(QQ, [Integer(0), -Integer(1), -Integer(2), -Integer(3), ˓→Integer(4)])>>> A.set_column(Integer(2), u)>>> A[ 0 1 0 3 4]
[ 5 6 -1 8 9]
[10 11 -2 13 14][15 16 -3 18 19][20 21 -4 23 24]

New entries may be in any sort of list.:
sage: A = matrix([[1, 2], [3, 4]]); A
[1 2]
[3 4]
sage: A.set_column(0, [0, 0]); A
[0 2]
[0 4]
sage: A.set_column(1, (0, 0)); A
[0 0]
[0 0]
>>> from sage.all import *>>> A = matrix([[Integer(1), Integer(2)], [Integer(3), Integer(4)]]); A
[1 2]
[3 4]
>>> A.set_column(Integer(0), [Integer(0), Integer(0)]); A
[0 2]
[0 4]
>>> A.set_column(Integer(1), (Integer(0), Integer(0))); A
[0 0]
[0 0]

set_row(row, v)
Sets the entries of row row to the entries of v.
INPUT:• row – index of row to be set.

235

Matrices and Spaces of Matrices, Release 10.4

• v – a list or vector of the new entries.
OUTPUT:
Changes the matrix in-place, so there is no output.
EXAMPLES:
New entries may be contained in a vector.:sage: A = matrix(QQ, 5, range(25))
sage: u = vector(QQ, [0, -1, -2, -3, -4])
sage: A.set_row(2, u)
sage: A[ 0 1 2 3 4]
[ 5 6 7 8 9]
[ 0 -1 -2 -3 -4][15 16 17 18 19][20 21 22 23 24]>>> from sage.all import *>>> A = matrix(QQ, Integer(5), range(Integer(25)))>>> u = vector(QQ, [Integer(0), -Integer(1), -Integer(2), -Integer(3), ˓→Integer(4)])>>> A.set_row(Integer(2), u)>>> A[ 0 1 2 3 4]
[ 5 6 7 8 9]
[ 0 -1 -2 -3 -4][15 16 17 18 19][20 21 22 23 24]

New entries may be in any sort of list.:
sage: A = matrix([[1, 2], [3, 4]]); A
[1 2]
[3 4]
sage: A.set_row(0, [0, 0]); A
[0 0]
[3 4]
sage: A.set_row(1, (0, 0)); A
[0 0]
[0 0]
>>> from sage.all import *>>> A = matrix([[Integer(1), Integer(2)], [Integer(3), Integer(4)]]); A
[1 2]
[3 4]
>>> A.set_row(Integer(0), [Integer(0), Integer(0)]); A
[0 0]
[3 4]
>>> A.set_row(Integer(1), (Integer(0), Integer(0))); A
[0 0]
[0 0]

sparse_columns(copy=True)
Return a list of the columns of self as sparse vectors (or free module elements).
INPUT:

236

Chapter 7. Base class for matrices, part 1

Matrices and Spaces of Matrices, Release 10.4

• copy – (default: True) if True, return a copy so you can
modify it safely
EXAMPLES:
sage: a = matrix(2, 3, range(6)); a[0 1 2][3 4 5]sage: v = a.sparse_columns(); v[(0, 3), (1, 4), (2, 5)]
sage: v[1].is_sparse()
True>>> from sage.all import *>>> a = matrix(Integer(2), Integer(3), range(Integer(6))); a[0 1 2][3 4 5]>>> v = a.sparse_columns(); v[(0, 3), (1, 4), (2, 5)]>>> v[Integer(1)].is_sparse()
Truesparse_matrix()
If this matrix is dense, return a sparse matrix with the same entries. If this matrix is sparse, return this matrix(not a copy).
Note: The definition of “dense” and “sparse” in Sage have nothing to do with the number of nonzero entries.
Sparse and dense are properties of the underlying representation of the matrix.
EXAMPLES:
sage: A = MatrixSpace(QQ,2, sparse=False)([1,2,0,1])
sage: A.is_sparse()
False
sage: B = A.sparse_matrix()
sage: B.is_sparse()
True
sage: A == B
True
sage: B.sparse_matrix() is B
True
sage: A*B
[1 4]
[0 1]
sage: A.parent()
Full MatrixSpace of 2 by 2 dense matrices over Rational Field
sage: B.parent()
Full MatrixSpace of 2 by 2 sparse matrices over Rational Field
sage: (A*B).parent()
Full MatrixSpace of 2 by 2 dense matrices over Rational Field
sage: (B*A).parent()
Full MatrixSpace of 2 by 2 dense matrices over Rational Field>>> from sage.all import *>>> A = MatrixSpace(QQ,Integer(2), sparse=False)([Integer(1),Integer(2),˓→Integer(0),Integer(1)])(continues on next page)237

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> A.is_sparse()
False>>> B = A.sparse_matrix()>>> B.is_sparse()
True>>> A == B
True>>> B.sparse_matrix() is B
True>>> A*B[1 4][0 1]>>> A.parent()
Full MatrixSpace of 2 by 2 dense matrices over Rational Field>>> B.parent()
Full MatrixSpace of 2 by 2 sparse matrices over Rational Field>>> (A*B).parent()
Full MatrixSpace of 2 by 2 dense matrices over Rational Field>>> (B*A).parent()
Full MatrixSpace of 2 by 2 dense matrices over Rational Field

sparse_rows(copy=True)
Return a list of the rows of self as sparse vectors (or free module elements).
INPUT:• copy – (default: True) if True, return a copy so you can
modify it safely
EXAMPLES:
sage: m = Mat(ZZ, 3, 3, sparse=True)(range(9)); m[0 1 2][3 4 5][6 7 8]sage: v = m.sparse_rows(); v[(0, 1, 2), (3, 4, 5), (6, 7, 8)]
sage: m.sparse_rows(copy=False) is m.sparse_rows(copy=False)
True
sage: v[1].is_sparse()
True
sage: m[0,0] = 10
sage: m.sparse_rows()[(10, 1, 2), (3, 4, 5), (6, 7, 8)]>>> from sage.all import *>>> m = Mat(ZZ, Integer(3), Integer(3), sparse=True)(range(Integer(9))); m[0 1 2][3 4 5][6 7 8]>>> v = m.sparse_rows(); v[(0, 1, 2), (3, 4, 5), (6, 7, 8)]>>> m.sparse_rows(copy=False) is m.sparse_rows(copy=False)
True>>> v[Integer(1)].is_sparse()
True>>> m[Integer(0),Integer(0)] = Integer(10)(continues on next page)

238

Chapter 7. Base class for matrices, part 1

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> m.sparse_rows()[(10, 1, 2), (3, 4, 5), (6, 7, 8)]

stack(bottom, subdivide=False)
Return a new matrix formed by appending the matrix (or vector) bottom below self:[ self ][ bottom ]INPUT:• bottom – a matrix, vector or free module element, whose dimensions are compatible with self.
• subdivide – (default: False); request the resulting matrix to have a new subdivision, separating
self from bottom.
OUTPUT:
A new matrix formed by appending bottom beneath self. If bottom is a vector (or free module element)
then in this context it is appropriate to consider it as a row vector. (The code first converts a vector to a 1-row
matrix.)If subdivide is True then any row subdivisions for the two matrices are preserved, and a new subdivision
is added between self and bottom. If the column divisions are identical, then they are preserved, otherwise
they are discarded. When subdivide is False there is no subdivision information in the result.
Warning: If subdivide is True then unequal column subdivisions will be discarded, since it would
be ambiguous how to interpret them. If the subdivision behavior is not what you need, you can manage
subdivisions yourself with methods like subdivisions() and subdivide(). You might also findblock_matrix() or block_diagonal_matrix() useful and simpler in some instances.
EXAMPLES:
Stacking with a matrix.
sage: A = matrix(QQ, 4, 3, range(12))
sage: B = matrix(QQ, 3, 3, range(9))
sage: A.stack(B)[ 0 1 2]
[ 3 4 5]
[ 6 7 8][ 9 10 11][ 0 1 2]
[ 3 4 5]
[ 6 7 8]>>> from sage.all import *>>> A = matrix(QQ, Integer(4), Integer(3), range(Integer(12)))>>> B = matrix(QQ, Integer(3), Integer(3), range(Integer(9)))>>> A.stack(B)[ 0 1 2]
[ 3 4 5]
[ 6 7 8][ 9 10 11][ 0 1 2]
(continues on next page)239

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[ 3
[ 6

4
7

5]
8]

Stacking with a vector.
sage: A = matrix(QQ, 3, 2, [0, 2, 4, 6, 8, 10])sage: v = vector(QQ, 2, [100, 200])
sage: A.stack(v)
[ 0
2]
[ 4
6]
[ 8 10][100 200]>>> from sage.all import *>>> A = matrix(QQ, Integer(3), Integer(2), [Integer(0), Integer(2),␣
˓→Integer(4), Integer(6), Integer(8), Integer(10)])>>> v = vector(QQ, Integer(2), [Integer(100), Integer(200)])>>> A.stack(v)
[ 0
2]
[ 4
6]
[ 8 10][100 200]

Errors are raised if the sizes are incompatible.
sage: A = matrix(RR, [[1, 2],[3, 4]])sage: B = matrix(RR, [[10, 20, 30], [40, 50, 60]])
sage: A.stack(B)Traceback (most recent call last):...
TypeError: number of columns must be the same, not 2 and 3
sage: v = vector(RR, [100, 200, 300])
sage: A.stack(v)Traceback (most recent call last):...
TypeError: number of columns must be the same, not 2 and 3>>> from sage.all import *>>> A = matrix(RR, [[Integer(1), Integer(2)],[Integer(3), Integer(4)]])>>> B = matrix(RR, [[Integer(10), Integer(20), Integer(30)], [Integer(40),␣
˓→Integer(50), Integer(60)]])>>> A.stack(B)Traceback (most recent call last):...
TypeError: number of columns must be the same, not 2 and 3>>> v = vector(RR, [Integer(100), Integer(200), Integer(300)])>>> A.stack(v)Traceback (most recent call last):...
TypeError: number of columns must be the same, not 2 and 3

Setting subdivide to True will, in its simplest form, add a subdivision between self and bottom.

240

Chapter 7. Base class for matrices, part 1

Matrices and Spaces of Matrices, Release 10.4

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

Row subdivisions are preserved by stacking, and enriched, if subdivisions are requested. (So multiple stackings can be recorded.)
sage: A = matrix(QQ, 2, 4, range(8))
sage: A.subdivide([1], None)sage: B = matrix(QQ, 3, 4, range(12))
sage: B.subdivide([2], None)sage: A.stack(B, subdivide=True)[ 0 1 2 3][-----------][ 4 5 6 7][-----------][ 0 1 2 3]
[ 4 5 6 7][-----------][ 8 9 10 11]>>> from sage.all import *>>> A = matrix(QQ, Integer(2), Integer(4), range(Integer(8)))>>> A.subdivide([Integer(1)], None)>>> B = matrix(QQ, Integer(3), Integer(4), range(Integer(12)))>>> B.subdivide([Integer(2)], None)>>> A.stack(B, subdivide=True)[ 0 1 2 3][-----------][ 4 5 6 7][-----------][ 0 1 2 3]
[ 4 5 6 7][-----------][ 8 9 10 11]

Column subdivisions can be preserved, but only if they are identical. Otherwise, this information is discarded
and must be managed separately.

241

Matrices and Spaces of Matrices, Release 10.4

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

The base ring of the result is the common parent for the base rings of self and bottom. In particular, theparent for A.stack(B) and B.stack(A) should be equal:
sage: A = matrix(QQ, 1, 2, [1,2])
sage: B = matrix(RR, 1, 2, [sin(1.1), sin(2.2)])
sage: C = A.stack(B); C[ 1.00000000000000 2.00000000000000][0.891207360061435 0.808496403819590]
sage: C.parent()
Full MatrixSpace of 2 by 2 dense matrices
over Real Field with 53 bits of precision
sage: D = B.stack(A); D[0.891207360061435 0.808496403819590](continues on next page)242

Chapter 7. Base class for matrices, part 1

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 1.00000000000000 2.00000000000000]
sage: D.parent()
Full MatrixSpace of 2 by 2 dense matrices
over Real Field with 53 bits of precision>>> from sage.all import *>>> A = matrix(QQ, Integer(1), Integer(2), [Integer(1),Integer(2)])>>> B = matrix(RR, Integer(1), Integer(2), [sin(RealNumber( 1.1 )),␣
˓→sin(RealNumber( 2.2 ))])>>> C = A.stack(B); C[ 1.00000000000000 2.00000000000000][0.891207360061435 0.808496403819590]>>> C.parent()
Full MatrixSpace of 2 by 2 dense matrices
over Real Field with 53 bits of precision>>> D = B.stack(A); D[0.891207360061435 0.808496403819590][ 1.00000000000000 2.00000000000000]>>> D.parent()
Full MatrixSpace of 2 by 2 dense matrices
over Real Field with 53 bits of precision
sage: R.<y> = PolynomialRing(ZZ)
sage: A = matrix(QQ, 1, 2, [1, 2/3])
sage: B = matrix(R, 1, 2, [y, y^2])
sage: C = A.stack(B); C[ 1 2/3][ y y^2]sage: C.parent()
Full MatrixSpace of 2 by 2 dense matrices over
Univariate Polynomial Ring in y over Rational Field>>> from sage.all import *>>> R = PolynomialRing(ZZ, names=( y ,)); (y,) = R._first_ngens(1)>>> A = matrix(QQ, Integer(1), Integer(2), [Integer(1), Integer(2)/˓→Integer(3)])>>> B = matrix(R, Integer(1), Integer(2), [y, y**Integer(2)])>>> C = A.stack(B); C[ 1 2/3][ y y^2]>>> C.parent()
Full MatrixSpace of 2 by 2 dense matrices over
Univariate Polynomial Ring in y over Rational Field

Stacking a dense matrix atop a sparse one returns a sparse matrix:
sage: M = Matrix(ZZ, 2, 3, range(6), sparse=False)
sage: N = diagonal_matrix([10,11,12], sparse=True)
sage: P = M.stack(N); P[ 0 1 2]
[ 3 4 5]
[10 0 0][ 0 11 0](continues on next page)243

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 0 0 12]sage: P.is_sparse()
True
sage: P = N.stack(M); P[10 0 0][ 0 11 0][ 0 0 12][ 0 1 2]
[ 3 4 5]sage: P.is_sparse()
True>>> from sage.all import *>>> M = Matrix(ZZ, Integer(2), Integer(3), range(Integer(6)), sparse=False)>>> N = diagonal_matrix([Integer(10),Integer(11),Integer(12)], sparse=True)>>> P = M.stack(N); P[ 0 1 2]
[ 3 4 5]
[10 0 0][ 0 11 0][ 0 0 12]>>> P.is_sparse()
True>>> P = N.stack(M); P[10 0 0][ 0 11 0][ 0 0 12][ 0 1 2]
[ 3 4 5]>>> P.is_sparse()
True

One can stack matrices over different rings (Issue #16399).
sage: M = Matrix(ZZ, 2, 3, range(6))
sage: N = Matrix(QQ, 1, 3, [10,11,12])
sage: M.stack(N)[ 0 1 2]
[ 3 4 5]
[10 11 12]
sage: N.stack(M)[10 11 12][ 0 1 2]
[ 3 4 5]>>> from sage.all import *>>> M = Matrix(ZZ, Integer(2), Integer(3), range(Integer(6)))>>> N = Matrix(QQ, Integer(1), Integer(3), [Integer(10),Integer(11),
˓→Integer(12)])>>> M.stack(N)[ 0 1 2]
[ 3 4 5]
[10 11 12]>>> N.stack(M)[10 11 12][ 0 1 2]
(continues on next page)244

Chapter 7. Base class for matrices, part 1

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[ 3

4

5]

AUTHORS:• Rob Beezer (2011-03-19): rewritten to mirror code for augment()• Jeroen Demeyer (2015-01-06): refactor, see Issue #16399. Put all boilerplate in one place (here) andput the actual type-dependent implementation in _stack_impl.
submatrix(row=0, col=0, nrows=-1, ncols=-1)
Return the matrix constructed from self using the specified range of rows and columns.
INPUT:• row, col – index of the starting row and column. Indices start at zero.
• nrows, ncols – (optional) number of rows and columns to take. If not provided, take all rows below
and all columns to the right of the starting entry.
See also:Thefunctionsmatrix_from_rows(),
matrix_from_columns(),andmatrix_from_rows_and_columns() allow one to select arbitrary subsets of rows and/or columns.
EXAMPLES:
Take the 3 × 3 submatrix starting from entry (1,1) in a 4 × 4 matrix:
sage: m = matrix(4, [1..16])
sage: m.submatrix(1, 1)[ 6 7 8][10 11 12][14 15 16]>>> from sage.all import *>>> m = matrix(Integer(4), (ellipsis_range(Integer(1),Ellipsis,Integer(16))))>>> m.submatrix(Integer(1), Integer(1))[ 6 7 8][10 11 12][14 15 16]Same thing, except take only two rows:
sage: m.submatrix(1, 1, 2)[ 6 7 8][10 11 12]>>> from sage.all import *>>> m.submatrix(Integer(1), Integer(1), Integer(2))[ 6 7 8][10 11 12]

And now take only one column:
sage: m.submatrix(1, 1, 2, 1)
[ 6]
[10]

245

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> m.submatrix(Integer(1), Integer(1), Integer(2), Integer(1))
[ 6]
[10]

You can take zero rows or columns if you want:sage: m.submatrix(1, 1, 0)[]
sage: parent(m.submatrix(1, 1, 0))
Full MatrixSpace of 0 by 3 dense matrices over Integer Ring>>> from sage.all import *>>> m.submatrix(Integer(1), Integer(1), Integer(0))[]>>> parent(m.submatrix(Integer(1), Integer(1), Integer(0)))
Full MatrixSpace of 0 by 3 dense matrices over Integer Ring

zero_pattern_matrix(ring=None)
Return a matrix that contains one for corresponding zero entries.
All other entries are zero.
INPUT:• ring – (optional); base ring of the output; default is ZZ
OUTPUT:
A new dense matrix with same dimensions as self and with base ring ring.
EXAMPLES:
sage: M = Matrix(ZZ, 2, [1,2,-2,0])
sage: M.zero_pattern_matrix()
[0 0]
[0 1]
sage: M = Matrix(QQ, 2, [1,2/3,-2,0])
sage: M.zero_pattern_matrix()
[0 0]
[0 1]
>>> from sage.all import *>>> M = Matrix(ZZ, Integer(2), [Integer(1),Integer(2),-Integer(2),Integer(0)])>>> M.zero_pattern_matrix()
[0 0]
[0 1]
>>> M = Matrix(QQ, Integer(2), [Integer(1),Integer(2)/Integer(3),-Integer(2),˓→Integer(0)])>>> M.zero_pattern_matrix()
[0 0]
[0 1]

Default base ring for the output is ZZ:
sage: M.zero_pattern_matrix().base_ring()
Integer Ring

246

Chapter 7. Base class for matrices, part 1

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> M.zero_pattern_matrix().base_ring()
Integer Ring

Specify a different base ring for the output:
sage: M.zero_pattern_matrix(GF(2)).base_ring()
Finite Field of size 2>>> from sage.all import *>>> M.zero_pattern_matrix(GF(Integer(2))).base_ring()
Finite Field of size 2

Examples for different base rings for self:
sage: M = Matrix(Zmod(8), 3, 2, [2, 3, 9, 8, 1, 0]); M
[2 3]
[1 0]
[1 0]
sage: M.zero_pattern_matrix()
[0 0]
[0 1]
[0 1]
>>> from sage.all import *>>> M = Matrix(Zmod(Integer(8)), Integer(3), Integer(2), [Integer(2),␣
˓→Integer(3), Integer(9), Integer(8), Integer(1), Integer(0)]); M
[2 3]
[1 0]
[1 0]
>>> M.zero_pattern_matrix()
[0 0]
[0 1]
[0 1]
sage: W.<a> = CyclotomicField(100)˓→needs sage.rings.number_fieldsage: M = Matrix(2, 3, [a, a/2, 0, a^2, a^100-1, a^2 - a]); M˓→needs sage.rings.number_field
[
a
1/2*a
0]
[
a^2
0 a^2 - a]sage: M.zero_pattern_matrix()
˓→needs sage.rings.number_field[0 0 1][0 1 0]#␣#␣#␣>>> from sage.all import *>>> W = CyclotomicField(Integer(100), names=( a ,)); (a,) = W._first_ngens(1)˓→# needs sage.rings.number_field>>> M = Matrix(Integer(2), Integer(3), [a, a/Integer(2), Integer(0),␣
˓→a**Integer(2), a**Integer(100)-Integer(1), a**Integer(2) - a]); M␣˓→# needs sage.rings.number_field
[
a
1/2*a
0]
[
a^2
0 a^2 - a]>>> M.zero_pattern_matrix()#␣˓→needs sage.rings.number_field(continues on next page)247

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 0 1][0 1 0]sage: # needs sage.rings.finite_rings
sage: K.<a> = GF(2^4)
sage: l = [a^2 + 1, a^3 + 1, 0, 0, a, a^3 + a + 1, a + 1,....:
a + 1, a^2, a^3 + a + 1, a^3 + a, a^3 + a]
sage: M = Matrix(K, 3, 4, l); M[a^2 + 1a^3 + 100][
a a^3 + a + 1
a + 1
a + 1][a^2 a^3 + a + 1
a^3 + aa^3 + a]sage: M.zero_pattern_matrix()[0 0 1 1][0 0 0 0][0 0 0 0]>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> K = GF(Integer(2)**Integer(4), names=( a ,)); (a,) = K._first_ngens(1)>>> l = [a**Integer(2) + Integer(1), a**Integer(3) + Integer(1), Integer(0),␣
˓→Integer(0), a, a**Integer(3) + a + Integer(1), a + Integer(1),...
a + Integer(1), a**Integer(2), a**Integer(3) + a + Integer(1),␣
˓→a**Integer(3) + a, a**Integer(3) + a]>>> M = Matrix(K, Integer(3), Integer(4), l); M[a^2 + 1a^3 + 100][
a a^3 + a + 1
a + 1
a + 1][a^2 a^3 + a + 1
a^3 + aa^3 + a]>>> M.zero_pattern_matrix()[0 0 1 1][0 0 0 0][0 0 0 0]
sage: # needs sage.rings.finite_rings
sage: K.<a> = GF(25)sage: M = Matrix(K, 2, 3, [0, 2, 3, 5, a, a^2])
sage: M
[
0
2
3]
[
0
a a + 3]sage: M.zero_pattern_matrix()[1 0 0][1 0 0]>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> K = GF(Integer(25), names=( a ,)); (a,) = K._first_ngens(1)>>> M = Matrix(K, Integer(2), Integer(3), [Integer(0), Integer(2), Integer(3),˓→ Integer(5), a, a**Integer(2)])
>>> M
[
0
2
3]
[
0
a a + 3]>>> M.zero_pattern_matrix()[1 0 0][1 0 0]248

Chapter 7. Base class for matrices, part 1

Matrices and Spaces of Matrices, Release 10.4

Note: This method can be optimized by improving get_is_zero_unsafe() for derived matrix classes.

249

Matrices and Spaces of Matrices, Release 10.4

250

Chapter 7. Base class for matrices, part 1

CHAPTER

EIGHTBASE CLASS FOR MATRICES, PART 2

For design documentation see matrix/docs.py.
AUTHORS:• William Stein: initial version• Jaap Spies (2006-02-24): added prod_of_row_sums, permanent, permanental_minor, rook_vector methods• Robert Bradshaw (2007-06-14): added subdivide method• Jaap Spies (2007-11-14): implemented _binomial, _choose auxiliary functions• William Stein (2007-11-18): added _gram_schmidt_noscale method• David Loeffler (2008-12-05): added smith_form method• David Loeffler (2009-06-01): added _echelon_form_PID method• Sebastian Pancratz (2009-06-25): implemented adjoint and charpoly methods; fixed adjoint reflecting
the change that _adjoint is now implemented in Matrix; used the division-free algorithm for charpoly• Rob Beezer (2009-07-13): added elementwise_product method• Miguel Marco (2010-06-19):
tend=False

modified eigenvalues and eigenvectors functions to allow the option ex-• Thierry Monteil (2010-10-05): bugfix for Issue #10063, so that the determinant is computed even for rings forwhich the is_field method is not implemented.
• Rob Beezer (2010-12-13): added conjugate_transpose method• Rob Beezer (2011-02-05): refactored all of the matrix kernel routines; added extended_echelon_form,right_kernel_matrix, QR, _gram_schmidt_noscale, is_similar methods• Moritz Minzlaff (2011-03-17): corrected _echelon_form_PID method for matrices of one row, fixed in Issue#9053• Rob Beezer (2011-06-09): added is_normal, is_diagonalizable, LU, cyclic_subspace,zigzag_form, rational_form methods• Rob Beezer (2012-05-27):
cholesky methods

added indefinite_factorization,

is_positive_definite,• Darij Grinberg (2013-10-01): added first (slow) pfaffian implementation• Mario Pernici (2014-07-01): modified rook_vector method• Rob Beezer (2015-05-25): modified is_similar method251

Matrices and Spaces of Matrices, Release 10.4

• Samuel Lelièvre (2020-09-18): improved method LLL_gram based on a patch by William Stein posted at Issue#5178, moving the method from its initial location in sage.matrix.integer_matrix_dense• Michael Jung (2020-10-02): added Bär-Faddeev-LeVerrier algorithm for the Pfaffian• Moritz Firsching(2020-10-05): added quantum_determinant• Dima Pasechnik (2022-11-08): fixed echelonize for inexact matrices
class sage.matrix.matrix2.Matrix
Bases: Matrix
Base class for matrices, part 2
C
Returns the conjugate matrix.
EXAMPLES:
sage: A = matrix(QQbar, [[-3, 5 - 3*I, 7 - 4*I],
˓→needs sage.rings.number_field....:[7 + 3*I, -1 + 6*I, 3 + 5*I],....:[3 + 3*I, -3 + 6*I, 5 +I]])
sage: A.C
˓→needs sage.rings.number_field[-3 5 + 3*I 7 + 4*I]
[ 7 - 3*I -1 - 6*I 3 - 5*I]
[ 3 - 3*I -3 - 6*I 5 - 1*I]#␣#␣>>> from sage.all import *>>> A = matrix(QQbar, [[-Integer(3), Integer(5) - Integer(3)*I,␣
˓→Integer(7) - Integer(4)*I],# needs sage.rings.number_
˓→field...
[Integer(7) + Integer(3)*I, -Integer(1) + Integer(6)*I,˓→ Integer(3) + Integer(5)*I],...
[Integer(3) + Integer(3)*I, -Integer(3) + Integer(6)*I,˓→ Integer(5) +I]])>>> A.C#␣˓→needs sage.rings.number_field[-3 5 + 3*I 7 + 4*I]
[ 7 - 3*I -1 - 6*I 3 - 5*I]
[ 3 - 3*I -3 - 6*I 5 - 1*I]

H
Returns the conjugate-transpose (Hermitian) matrix.
EXAMPLES:
sage: A = matrix(QQbar, [[-3, 5 - 3*I, 7 - 4*I],
˓→needs sage.rings.number_field....:[7 + 3*I, -1 + 6*I, 3 + 5*I],....:[3 + 3*I, -3 + 6*I, 5 +I]])
sage: A.H
˓→needs sage.rings.number_field[-3 7 - 3*I 3 - 3*I]
[ 5 + 3*I -1 - 6*I -3 - 6*I]
[ 7 + 4*I 3 - 5*I 5 - 1*I]

252

#␣

#␣

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = matrix(QQbar, [[-Integer(3), Integer(5) - Integer(3)*I,␣
˓→Integer(7) - Integer(4)*I],# needs sage.rings.number_
˓→field...
[Integer(7) + Integer(3)*I, -Integer(1) + Integer(6)*I,˓→ Integer(3) + Integer(5)*I],...
[Integer(3) + Integer(3)*I, -Integer(3) + Integer(6)*I,˓→ Integer(5) +I]])>>> A.H#␣˓→needs sage.rings.number_field[-3 7 - 3*I 3 - 3*I]
[ 5 + 3*I -1 - 6*I -3 - 6*I]
[ 7 + 4*I 3 - 5*I 5 - 1*I]

LLL_gram(flag=0)
Return the LLL transformation matrix for this Gram matrix.
That is, the transformation matrix U over ZZ of determinant 1 that transforms the lattice with this matrix as
Gram matrix to a lattice that is LLL-reduced.
Always works when self is positive definite, might work in some semidefinite and indefinite cases.
INPUT:• self – the Gram matrix of a quadratic form or of a lattice equipped with a bilinear form
• flag – an optional flag passed to qflllgram. According to pari:qflllgram’s documentation the optionsare:– 0 – (default), assume that self has either exact (integral or rational) or real floating point entries.
The matrix is rescaled, converted to integers and the behavior is then as in flag=1.
– 1 – assume that G is integral. Computations involving Gram-Schmidt vectors are approximate, with
precision varying as needed.
OUTPUT:A dense matrix U over the integers with determinant 1 such that U.T * M * U is LLL-reduced.
ALGORITHM:
Calls PARI’s pari:qflllgram.
EXAMPLES:
Create a Gram matrix and LLL-reduce it:sage: M = Matrix(ZZ, 2, 2, [5, 3, 3, 2])
sage: U = M.LLL_gram()
˓→needs sage.libs.pari
sage: MM = U.transpose() * M * U
˓→needs sage.libs.pari
sage: M, U, MM
˓→needs sage.libs.pari([5 3] [-1 1] [1 0][3 2], [ 1 -2], [0 1]
)

#␣
#␣
#␣

>>> from sage.all import *>>> M = Matrix(ZZ, Integer(2), Integer(2), [Integer(5), Integer(3),␣
(continues on next page)253

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Integer(3), Integer(2)])>>> U = M.LLL_gram()
˓→needs sage.libs.pari>>> MM = U.transpose() * M * U
˓→needs sage.libs.pari>>> M, U, MM
˓→needs sage.libs.pari([5 3] [-1 1] [1 0][3 2], [ 1 -2], [0 1]
)
˓→

#␣
#␣
#␣

For a Gram matrix over RR with a length one first vector and a very short second vector, the LLL-reduced
basis is obtained by swapping the two basis vectors (and changing sign to preserve orientation).
sage: M = Matrix(RDF, 2, 2, [1, 0, 0, 1e-5])
sage: M.LLL_gram()
˓→needs sage.libs.pari[ 0 -1][ 1 0]#␣>>> from sage.all import *>>> M = Matrix(RDF, Integer(2), Integer(2), [Integer(1), Integer(0),␣
˓→Integer(0), RealNumber( 1e-5 )])>>> M.LLL_gram()
˓→needs sage.libs.pari[ 0 -1][ 1 0]#␣The algorithm might work for some semidefinite and indefinite forms:
sage: Matrix(ZZ, 2, 2, [2, 6, 6, 3]).LLL_gram()
˓→needs sage.libs.pari[-3 -1][ 1 0]
sage: Matrix(ZZ, 2, 2, [1, 0, 0, -1]).LLL_gram()
˓→needs sage.libs.pari[ 0 -1][ 1 0]#␣#␣>>> from sage.all import *>>> Matrix(ZZ, Integer(2), Integer(2), [Integer(2), Integer(6), Integer(6),␣
˓→Integer(3)]).LLL_gram()# needs sage.libs.pari[-3 -1][ 1 0]>>> Matrix(ZZ, Integer(2), Integer(2), [Integer(1), Integer(0), Integer(0), ˓→Integer(1)]).LLL_gram()# needs sage.libs.pari[ 0 -1][ 1 0]

However, it might fail for others, either raising a ValueError:
sage: Matrix(ZZ, 1, 1, [0]).LLL_gram()
˓→needs sage.libs.pari
Traceback (most recent call last):...

#␣(continues on next page)

254

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

ValueError: qflllgram did not return a square matrix,
perhaps the matrix is not positive definite
sage: Matrix(ZZ, 2, 2, [0, 1, 1, 0]).LLL_gram()
˓→needs sage.libs.pari
Traceback (most recent call last):...
ValueError: qflllgram did not return a square matrix,
perhaps the matrix is not positive definite#␣>>> from sage.all import *>>> Matrix(ZZ, Integer(1), Integer(1), [Integer(0)]).LLL_gram()˓→# needs sage.libs.pari
Traceback (most recent call last):...
ValueError: qflllgram did not return a square matrix,
perhaps the matrix is not positive definite␣>>> Matrix(ZZ, Integer(2), Integer(2), [Integer(0), Integer(1), Integer(1),␣
˓→Integer(0)]).LLL_gram()# needs sage.libs.pari
Traceback (most recent call last):...
ValueError: qflllgram did not return a square matrix,
perhaps the matrix is not positive definite

or running forever:sage: Matrix(ZZ, 2, 2, [-5, -1, -1, -5]).LLL_gram()
˓→needs sage.libs.pari
Traceback (most recent call last):...
RuntimeError: infinite loop while calling qflllgram# not tested,␣

>>> from sage.all import *>>> Matrix(ZZ, Integer(2), Integer(2), [-Integer(5), -Integer(1), -Integer(1),˓→ -Integer(5)]).LLL_gram()# not tested, needs sage.libs.pari
Traceback (most recent call last):...
RuntimeError: infinite loop while calling qflllgram

Nonreal input leads to a value error:
sage: Matrix(2, 2, [CDF(1, 1), 0, 0, 1]).LLL_gram()˓→# needs sage.libs.pari
Traceback (most recent call last):...
ValueError: qflllgram failed, perhaps the matrix is not positive definite>>> from sage.all import *>>> Matrix(Integer(2), Integer(2), [CDF(Integer(1), Integer(1)), Integer(0),␣
˓→Integer(0), Integer(1)]).LLL_gram()# needs sage.
˓→libs.pari
Traceback (most recent call last):...
ValueError: qflllgram failed, perhaps the matrix is not positive definite

255

Matrices and Spaces of Matrices, Release 10.4

LU(pivot=None, format='plu')
Finds a decomposition into a lower-triangular matrix and an upper-triangular matrix.
INPUT:• pivot – pivoting strategy– ‘auto’ (default) – see if the matrix entries are ordered (i.e. if they have an absolute value method),and if so, use a the partial pivoting strategy. Otherwise, fall back to the nonzero strategy. This is thebest choice for general routines that may call this for matrix entries of a variety of types.
– ‘partial’ – each column is examined for the element with the largest absolute value and the row
containing this element is swapped into place.
– ‘nonzero’ – the first nonzero element in a column is located and the row with this element is used.
• format – contents of output, see more discussion below about output.
– ‘plu’ (default) – a triple; matrices P, L and U such that A = P*L*U.
– ‘compact’ – a pair; row permutation as a tuple, and the matrices L and U combined into one matrix.
OUTPUT:
Suppose that 𝐴 is an 𝑚 × 𝑛 matrix, then an LU decomposition is a lower-triangular 𝑚 × 𝑚 matrix 𝐿 withevery diagonal element equal to 1, and an upper-triangular 𝑚 × 𝑛 matrix, 𝑈 such that the product 𝐿𝑈 , after
a permutation of the rows, is then equal to 𝐴. For the ‘plu’ format the permutation is returned as an 𝑚 × 𝑚
permutation matrix 𝑃 such that𝐴 = 𝑃 𝐿𝑈
It is more common to place the permutation matrix just to the left of 𝐴. If you desire this version, then use
the inverse of 𝑃 which is computed most efficiently as its transpose.
If the ‘partial’ pivoting strategy is used, then the non-diagonal entries of 𝐿 will be less than or equal to 1 inabsolute value. The ‘nonzero’ pivot strategy may be faster, but the growth of data structures for elements ofthe decomposition might counteract the advantage.
By necessity, returned matrices have a base ring equal to the fraction field of the base ring of the original
matrix.
In the ‘compact’ format, the first returned value is a tuple that is a permutation of the rows of 𝐿𝑈 that yields
𝐴. See the doctest for how you might employ this permutation. Then the matrices 𝐿 and 𝑈 are merged into
one matrix – remove the diagonal of ones in 𝐿 and the remaining nonzero entries can replace the entries of𝑈 beneath the diagonal.
The results are cached, only in the compact format, separately for each pivot strategy called. Repeated requests
for the ‘plu’ format will require just a small amount of overhead in each call to bust out the compact format
to the three matrices. Since only the compact format is cached, the components of the compact format are
immutable, while the components of the ‘plu’ format are regenerated, and hence are mutable.
Notice that while 𝑈 is similar to row-echelon form and the rows of 𝑈 span the row space of 𝐴, the rows of 𝑈
are not generally linearly independent. Nor are the pivot columns (or rank) immediately obvious. However
for rings without specialized echelon form routines, this method is about twice as fast as the generic echelon
form routine since it only acts “below the diagonal”, as would be predicted from a theoretical analysis of thealgorithms.
Note: This is an exact computation, so limited to exact rings. If you need numerical results, convert the basering to the field of real double numbers, RDF or the field of complex double numbers, CDF, which will use afaster routine that is careful about numerical subtleties.

256

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

ALGORITHM:“Gaussian Elimination with Partial Pivoting,” Algorithm 21.1 of [TB1997].
EXAMPLES:
Notice the difference in the 𝐿 matrix as a result of different pivoting strategies. With partial pivoting, every
entry of 𝐿 has absolute value 1 or less.
sage: A = matrix(QQ, [[1, -1, 0, 2, 4, 7, -1],....:
[2, -1, 0, 6, 4, 8, -2],....:
[2, 0, 1, 4, 2, 6, 0],....:[1, 0, -1, 8, -1, -1, -3],....:
[1, 1, 2, -2, -1, 1, 3]])sage: P, L, U = A.LU(pivot= partial )sage: P[0 0 0 0 1]
[1 0 0 0 0]
[0 0 0 1 0]
[0 0 1 0 0]
[0 1 0 0 0]
sage: L
[
1
0
0
0
0]
[ 1/2
1
0
0
0]
[ 1/2 1/3
10
0][
1 2/3 1/5
10]
[ 1/2 -1/3 -2/5
0
1]
sage: U
[
2
-1
0
6
4
8
-2]
[
0
3/2
2
-5
-3
-3
4]
[
0
0 -5/3 20/3
-2
-4 -10/3]
[
0
0
0
0
2/5
4/5
0]
[
0
0
0
0
1/5
2/5
0]
sage: A == P*L*U
True
sage: P, L, U = A.LU(pivot= nonzero )sage: P
[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]
sage: L[ 1 0 0 0 0]
[ 2 1 0 0 0]
[ 2 2 1 0 0]
[ 1 1 -1 1 0]
[ 1 2 2 0 1]
sage: U[ 1 -1 0 2 4 7 -1][ 0 1 0 2 -4 -6 0][ 0 0 1 -4 2 4 2]
[ 0 0 0 0 1 2 0]
[ 0 0 0 0 -1 -2 0]
sage: A == P*L*U
True>>> from sage.all import *>>> A = matrix(QQ, [[Integer(1), -Integer(1),Integer(0),Integer(2), ␣(continues on next page)257

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Integer(4), Integer(7), -Integer(1)],...
[Integer(2), -Integer(1), Integer(0), Integer(6), ␣
˓→Integer(4),Integer(8), -Integer(2)],...
[Integer(2), Integer(0), Integer(1), Integer(4), ␣
˓→Integer(2),Integer(6), Integer(0)],...
[Integer(1), Integer(0), -Integer(1), Integer(8), ˓→Integer(1), -Integer(1), -Integer(3)],...
[Integer(1), Integer(1), Integer(2), -Integer(2), ˓→Integer(1),Integer(1), Integer(3)]])>>> P, L, U = A.LU(pivot= partial )>>> P[0 0 0 0 1]
[1 0 0 0 0]
[0 0 0 1 0]
[0 0 1 0 0]
[0 1 0 0 0]
>>> L
[
1
0
0
0
0]
[ 1/2
1
0
0
0]
[ 1/2 1/3
10
0][
1 2/3 1/5
10]
[ 1/2 -1/3 -2/5
0
1]
>>> U
[
2
-1
0
6
4
8
-2]
[
0
3/2
2
-5
-3
-3
4]
[
0
0 -5/3 20/3
-2
-4 -10/3]
[
0
0
0
0
2/5
4/5
0]
[
0
0
0
0
1/5
2/5
0]
>>> A == P*L*U
True>>> P, L, U = A.LU(pivot= nonzero )>>> P[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]>>> L
[ 1 0 0 0 0]
[ 2 1 0 0 0]
[ 2 2 1 0 0]
[ 1 1 -1 1 0]
[ 1 2 2 0 1]>>> U
[ 1 -1 0 2 4 7 -1][ 0 1 0 2 -4 -6 0][ 0 0 1 -4 2 4 2]
[ 0 0 0 0 1 2 0]
[ 0 0 0 0 -1 -2 0]>>> A == P*L*U
True
˓→An example of the compact format.
sage: B = matrix(QQ, [[ 1, 3, 5, 5],....:[ 1, 4, 7, 8],....:[-1, -4, -6, -6],
(continues on next page)

258

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)....:[ 0, -2, -5, -8],....:[-2, -6, -6, -2]])
sage: perm, M = B.LU(format= compact )sage: perm
(4, 3, 0, 1, 2)
sage: M
[ -2
-6
-6
-2]
[
0
-2
-5
-8]
[-1/2
0
2
4]
[-1/2 -1/2 3/4
0][ 1/2 1/2 -1/4
0]>>> from sage.all import *>>> B = matrix(QQ, [[ Integer(1), Integer(3), Integer(5), Integer(5)],...
[ Integer(1), Integer(4), Integer(7), Integer(8)],...
[-Integer(1), -Integer(4), -Integer(6), -Integer(6)],...
[ Integer(0), -Integer(2), -Integer(5), -Integer(8)],...
[-Integer(2), -Integer(6), -Integer(6), -Integer(2)]])>>> perm, M = B.LU(format= compact )>>> perm(4, 3, 0, 1, 2)
>>> M
[ -2
-6
-6
-2]
[
0
-2
-5
-8]
[-1/2
0
2
4]
[-1/2 -1/2 3/4
0][ 1/2 1/2 -1/4
0]

We can easily illustrate the relationships between the two formats with a square matrix.
sage: C = matrix(QQ, [[-2, 3, -2, -5],....:
[ 1, -2, 1, 3],....:[-4, 7, -3, -8],....:[-3, 8, -1, -5]])sage: P, L, U = C.LU(format= plu )sage: perm, M = C.LU(format= compact )sage: (L - identity_matrix(4)) + U == M
True
sage: p = [perm[i]+1 for i in range(len(perm))]
sage: PP = Permutation(p).to_matrix()
sage: PP == P
True>>> from sage.all import *>>> C = matrix(QQ, [[-Integer(2), Integer(3), -Integer(2), -Integer(5)],...
[ Integer(1), -Integer(2), Integer(1), Integer(3)],...
[-Integer(4), Integer(7), -Integer(3), -Integer(8)],...
[-Integer(3), Integer(8), -Integer(1), -Integer(5)]])>>> P, L, U = C.LU(format= plu )>>> perm, M = C.LU(format= compact )>>> (L - identity_matrix(Integer(4))) + U == M
True>>> p = [perm[i]+Integer(1) for i in range(len(perm))]>>> PP = Permutation(p).to_matrix()>>> PP == P
True

259

Matrices and Spaces of Matrices, Release 10.4

For a nonsingular matrix, and the ‘nonzero’ pivot strategy there is no need to permute rows, so the permutation matrix will be the identity. Furthermore, it can be shown that then the 𝐿 and 𝑈 matrices are uniquelydetermined by requiring 𝐿 to have ones on the diagonal.
sage: D = matrix(QQ, [[ 1, 0, 2, 0, -2, -1],....:
[ 3, -2, 3, -1, 0, 6],....:[-4, 2, -3, 1, -1, -8],....:[-2, 2, -3, 2, 1, 0],....:[ 0, -1, -1, 0, 2, 5],....:[-1, 2, -4, -1, 5, -3]])
sage: P, L, U = D.LU(pivot= nonzero )sage: P
[1 0 0 0 0 0]
[0 1 0 0 0 0]
[0 0 1 0 0 0]
[0 0 0 1 0 0]
[0 0 0 0 1 0]
[0 0 0 0 0 1]
sage: L
[
1
0
0
0
0
0]
[
3
1
0
0
0
0]
[ -4
-1
1
0
0
0]
[ -2
-1
-1
1
0
0]
[
0 1/2 1/4 1/2
1
0]
[ -1
-1 -5/2-2-6
1]
sage: U
[
1
0
2
0
-2
-1]
[
0
-2
-3
-1
6
9]
[
0
0
2
0
-3
-3]
[
0
0
0
1
0
4]
[
0
0
0
0 -1/4 -3/4]
[
0
0
0
0
0
1]
sage: D == L*U
True>>> from sage.all import *>>> D = matrix(QQ, [[ Integer(1), Integer(0), Integer(2), Integer(0), ˓→Integer(2), -Integer(1)],...
[ Integer(3), -Integer(2), Integer(3), -Integer(1), ␣
˓→Integer(0),Integer(6)],...
[-Integer(4), Integer(2), -Integer(3), Integer(1), ˓→Integer(1), -Integer(8)],...
[-Integer(2), Integer(2), -Integer(3), Integer(2), ␣
˓→Integer(1),Integer(0)],...
[ Integer(0), -Integer(1), -Integer(1), Integer(0), ␣
˓→Integer(2),Integer(5)],...
[-Integer(1), Integer(2), -Integer(4), -Integer(1), ␣
˓→Integer(5), -Integer(3)]])>>> P, L, U = D.LU(pivot= nonzero )>>> P[1 0 0 0 0 0]
[0 1 0 0 0 0]
[0 0 1 0 0 0]
[0 0 0 1 0 0]
[0 0 0 0 1 0]
[0 0 0 0 0 1]>>> L
(continues on next page)

260

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[
1
0
0
[
3
1
0
[ -4
-1
1
[ -2
-1
-1
[
0 1/2 1/4
[ -1
-1 -5/2
>>> U
[
1
0
2
[
0
-2
-3
[
0
0
2
[
0
0
0
[
0
0
0
[
0
0
0
>>> D == L*U
True

0
0
0
1
1/2
-2

0
0
0
0
1
-6

0]
0]
0]
0]
0]
1]

0
-2
-1]
-1
6
9]
0
-3
-3]
1
0
4]
0 -1/4 -3/4]
00
1]

The base ring of the matrix may be any field, or a ring which has a fraction field implemented in Sage. The
ring needs to be exact (there is a numerical LU decomposition for matrices over RDF and CDF). Matrices
returned are over the original field, or the fraction field of the ring. If the field is not ordered (i.e. the absolutevalue function is not implemented), then the pivot strategy needs to be ‘nonzero’.
sage: A = matrix(RealField(100), 3, 3, range(9))
sage: P, L, U = A.LU()
Traceback (most recent call last):...
TypeError: base ring of the matrix must be exact,
not Real Field with 100 bits of precision
sage: A = matrix(Integers(6), 3, 2, range(6))
sage: A.LU()
Traceback (most recent call last):...
TypeError: base ring of the matrix needs a field of fractions,
not Ring of integers modulo 6
sage: R.<y> = PolynomialRing(QQ, y )sage: B = matrix(R, [[y+1, y^2+y], [y^2, y^3]])sage: P, L, U = B.LU(pivot= partial )Traceback (most recent call last):...
TypeError: cannot take absolute value of matrix entries, try pivot=nonzero
sage: P, L, U = B.LU(pivot= nonzero )sage: P[1 0]
[0 1]
sage: L[10][y^2/(y + 1)
1]
sage: U[ y + 1 y^2 + y][00]
sage: L.base_ring()
Fraction Field of Univariate Polynomial Ring in y over Rational Field
sage: B == P*L*U
True(continues on next page)261

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: # needs sage.rings.finite_rings
sage: F.<a> = FiniteField(5^2)
sage: C = matrix(F, [[a + 3, 4*a + 4, 2, 4*a + 2],....:[3, 2*a + 4, 2*a + 4, 2*a + 1],....:[3*a + 1, a + 3, 2*a + 4, 4*a + 3],....:[a, 3, 3*a + 1, a]])sage: P, L, U = C.LU(pivot= nonzero )sage: P
[1 0 0 0][0 1 0 0][0 0 1 0][0 0 0 1]
sage: L˓→needs sage.combinat
[
1
0
0
0]
[3*a + 3
1
00][
2*a 4*a + 2
1
0][2*a + 3
2 2*a + 4
1]
sage: U˓→needs sage.combinat[ a + 3 4*a + 4
2 4*a + 2]
[
0
a + 1
a + 3 2*a + 4][00
1 4*a + 2]
[
0
0
0
0]
sage: L.base_ring()
˓→needs sage.combinat
Finite Field in a of size 5^2sage: C == P*L*U
˓→needs sage.combinat
True

#␣

#␣

#␣

#␣

>>> from sage.all import *>>> A = matrix(RealField(Integer(100)), Integer(3), Integer(3),␣
˓→range(Integer(9)))>>> P, L, U = A.LU()
Traceback (most recent call last):...
TypeError: base ring of the matrix must be exact,
not Real Field with 100 bits of precision>>> A = matrix(Integers(Integer(6)), Integer(3), Integer(2),␣
˓→range(Integer(6)))>>> A.LU()
Traceback (most recent call last):...
TypeError: base ring of the matrix needs a field of fractions,
not Ring of integers modulo 6>>> R = PolynomialRing(QQ, y , names=( y ,)); (y,) = R._first_ngens(1)>>> B = matrix(R, [[y+Integer(1), y**Integer(2)+y], [y**Integer(2),␣
˓→y**Integer(3)]])>>> P, L, U = B.LU(pivot= partial )Traceback (most recent call last):...
TypeError: cannot take absolute value of matrix entries, try pivot=nonzero>>> P, L, U = B.LU(pivot= nonzero )(continues on next page)

262

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

>>> P
[1 0]
[0 1]
>>> L
[
1
0]
[y^2/(y + 1)
1]>>> U
[ y + 1 y^2 + y][00]>>> L.base_ring()
Fraction Field of Univariate Polynomial Ring in y over Rational Field>>> B == P*L*U
True>>> # needs sage.rings.finite_rings>>> F = FiniteField(Integer(5)**Integer(2), names=( a ,)); (a,) = F._first_
˓→ngens(1)>>> C = matrix(F, [[a + Integer(3), Integer(4)*a + Integer(4), Integer(2),␣
˓→Integer(4)*a + Integer(2)],...
[Integer(3), Integer(2)*a + Integer(4), Integer(2)*a +␣˓→Integer(4), Integer(2)*a + Integer(1)],...
[Integer(3)*a + Integer(1), a + Integer(3), Integer(2)*a +␣˓→Integer(4), Integer(4)*a + Integer(3)],...
[a, Integer(3), Integer(3)*a + Integer(1), a]])>>> P, L, U = C.LU(pivot= nonzero )>>> P[1 0 0 0][0 1 0 0][0 0 1 0][0 0 0 1]>>> L#␣˓→needs sage.combinat
[
1
0
0
0]
[3*a + 3
1
00][
2*a 4*a + 2
1
0][2*a + 3
2 2*a + 4
1]
>>> U
#␣
˓→needs sage.combinat[ a + 3 4*a + 4
2 4*a + 2]
[
0
a + 1
a + 3 2*a + 4][00
1 4*a + 2]
[
0
0
0
0]
>>> L.base_ring()#␣˓→needs sage.combinat
Finite Field in a of size 5^2>>> C == P*L*U#␣˓→needs sage.combinat
True

With no pivoting strategy given (i.e. pivot=None) the routine will try to use partial pivoting, but then fallback to the nonzero strategy. For the nonsingular matrix below, we see evidence of pivoting when viewed
over the rationals, and no pivoting over the integers mod 29.
sage: entries = [3, 20, 11, 7, 16, 28, 5, 15, 21, 23, 22, 18, 8, 23, 15, 2]
sage: A = matrix(Integers(29), 4, 4, entries)
sage: perm, _ = A.LU(format= compact ); perm
(continues on next page)263

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)(0, 1, 2, 3)
sage: B = matrix(QQ, 4, 4, entries)
sage: perm, _ = B.LU(format= compact ); perm
(2, 0, 1, 3)>>> from sage.all import *>>> entries = [Integer(3), Integer(20), Integer(11), Integer(7), Integer(16),␣
˓→Integer(28), Integer(5), Integer(15), Integer(21), Integer(23), Integer(22),˓→ Integer(18), Integer(8), Integer(23), Integer(15), Integer(2)]>>> A = matrix(Integers(Integer(29)), Integer(4), Integer(4), entries)>>> perm, _ = A.LU(format= compact ); perm
(0, 1, 2, 3)>>> B = matrix(QQ, Integer(4), Integer(4), entries)>>> perm, _ = B.LU(format= compact ); perm
(2, 0, 1, 3)

The 𝑈 matrix is only guaranteed to be upper-triangular. The rows are not necessarily linearly independent,
nor are the pivots columns or rank in evidence.
sage: A = matrix(QQ, [[ 1, -4, 1, 0, -2, 1, 3, 3, 2],....:[-1, 4, 0, -4, 0, -4, 5, -7, -7],....:
[ 0, 0, 1, -4, -1, -3, 6, -5, -6],....:[-2, 8, -1, -4, 2, -4, 1, -8, -7],....:
[ 1, -4, 2, -4, -3, 2, 5, 6, 4]])sage: P, L, U = A.LU()
sage: U
[
-2
8
-1
-4
2
-4
1
-8
-7]
[
0
0
1/2
-2
-1
-2
9/2
-3 -7/2]
[
0
0
3/2
-6
-2
0 11/2
2
1/2]
[
0
0
0
0 -1/3-1
5/3 -5/3 -5/3]
[
0
0
0
0
1/3
-3
7/3 -19/3 -19/3]
sage: A.rref()[ 1 -4 0 4 0 0 -1 -1 -1][ 0 0 1 -4 0 0 1 0 -1][ 0 0 0 0 1 0 -2 -1 -1][ 0 0 0 0 0 1 -1 2 2]
[ 0 0 0 0 0 0 0 0 0]
sage: A.pivots()(0, 2, 4, 5)>>> from sage.all import *>>> A = matrix(QQ, [[ Integer(1), -Integer(4), Integer(1), Integer(0), ˓→Integer(2),Integer(1), Integer(3), Integer(3), Integer(2)],...
[-Integer(1), Integer(4), Integer(0), -Integer(4), ␣
˓→Integer(0), -Integer(4), Integer(5), -Integer(7), -Integer(7)],...
[ Integer(0), Integer(0), Integer(1), -Integer(4), ˓→Integer(1), -Integer(3), Integer(6), -Integer(5), -Integer(6)],...
[-Integer(2), Integer(8), -Integer(1), -Integer(4), ␣
˓→Integer(2), -Integer(4), Integer(1), -Integer(8), -Integer(7)],...
[ Integer(1), -Integer(4), Integer(2), -Integer(4), ˓→Integer(3),Integer(2), Integer(5), Integer(6), Integer(4)]])>>> P, L, U = A.LU()
>>> U
[
-2
8
-1
-4
2
-4
1
-8
-7]
[
0
0
1/2
-2
-1
-2
9/2
-3 -7/2]
[
0
0
3/2
-6
-2
0 11/22
1/2](continues on next page)264

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[
0
0
[
0
0
>>> A.rref()[ 1 -4 0 4 0[ 0 0 1 -4 0
[ 0 0 0 0 1[ 0 0 0 0 0[ 0 0 0 0 0>>> A.pivots()(0, 2, 4, 5)

0
0

0
0

-1/3
1/3

-1
-3

5/3 -5/3 -5/3]
7/3 -19/3 -19/3]

0 -1 -1 -1]
0 1 0 -1]
0 -2 -1 -1]
1 -1 2 2]0 0 0 0]QR(full=True)
Returns a factorization of self as a unitary matrix and an upper-triangular matrix.
INPUT:• full – (default: True); if True then the returned matrices have dimensions as described below. If
False the R matrix has no zero rows and the columns of Q are a basis for the column space of self.
OUTPUT:
If self is an 𝑚 × 𝑛 matrix and full=True then this method returns a pair of matrices: 𝑄 is an 𝑚 × 𝑚
unitary matrix (meaning its inverse is its conjugate-transpose) and 𝑅 is an 𝑚 × 𝑛 upper-triangular matrix
with non-negative entries on the diagonal. For a matrix of full rank this factorization is unique (due to therestriction to positive entries on the diagonal).
If full=False then 𝑄 has 𝑚 rows and the columns form an orthonormal basis for the column space ofself. So, in particular, the conjugate-transpose of 𝑄 times 𝑄 will be an identity matrix. The matrix 𝑅 will
still be upper-triangular but will also have full rank, in particular it will lack the zero rows present in a full
factorization of a rank-deficient matrix.
The results obtained when full=True are cached, hence 𝑄 and 𝑅 are immutable matrices in this case.
Note: This is an exact computation, so limited to exact rings. Also the base ring needs to have a fraction field
implemented in Sage and this field must contain square roots. One example is the field of algebraic numbers,
QQbar, as used in the examples below. If you need numerical results, convert the base ring to the field ofcomplex double numbers, CDF, which will use a faster routine that is careful about numerical subtleties.
ALGORITHM:“Modified Gram-Schmidt,” Algorithm 8.1 of [TB1997].
EXAMPLES:
For a nonsingular matrix, the QR decomposition is unique.
sage: # needs sage.rings.number_fieldsage: A = matrix(QQbar, [[-2, 0, -4, -1, -1],....:[-2, 1, -6, -3, -1],....:
[1, 1, 7, 4, 5],....:[3, 0, 8, 3, 3],....:[-1, 1, -6, -6, 5]])sage: Q, R = A.QR()
sage: Q[ -0.4588314677411235? -0.1260506983326509?
0.3812120831224489?
˓→394573711338418?
-0.687440062597?][ -0.4588314677411235?
0.4726901187474409? -0.05198346588033394?

-0.
0.

(continues on next page)265

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)717294125164660?
-0.220962877263?][ 0.2294157338705618?
0.6617661662464172?
0.6619227988762521?
-0.
˓→180872093737548?
0.1964114464561?][ 0.6882472016116853?
0.1890760474989764? -0.2044682991293135?
0.
˓→096630296654307?
-0.662888631790?][ -0.2294157338705618?
0.5357154679137663?
-0.609939332995919?
-0.
˓→536422031427112?
0.0245514308070?]
sage: R[ 4.358898943540674? -0.4588314677411235?
13.07669683062202?
6.
˓→194224814505168?
2.982404540317303?][
01.670171752907625? 0.5987408170800917? -1.
˓→292019657909672?
6.207996892883057?][005.444401659866974?
5.
˓→468660610611130?
-0.682716185228386?]
[
0
0
0
1.
˓→027626039419836?
-3.61930014968662?]
[
0
0
0
␣
˓→
0
0.02455143080702?]
sage: Q.conjugate_transpose()*Q[1.000000000000000?
0.?e-18
0.?e-170.?e-15 ␣˓→
0.?e-12][0.?e-18 1.000000000000000?
0.?e-160.?e-15 ␣˓→
0.?e-12][0.?e-170.?e-16 1.000000000000000?
0.?e-15 ␣˓→
0.?e-12][0.?e-150.?e-150.?e-15 1.000000000000000? ␣˓→
0.?e-12][0.?e-120.?e-120.?e-120.?e-12 ␣
˓→1.000000000000?]
sage: Q * R == ATrue˓→>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQbar, [[-Integer(2), Integer(0), -Integer(4), -Integer(1), ˓→Integer(1)],...
[-Integer(2), Integer(1), -Integer(6), -Integer(3), ˓→Integer(1)],...
[Integer(1), Integer(1), Integer(7), Integer(4),␣
˓→Integer(5)],...
[Integer(3), Integer(0), Integer(8), Integer(3),␣
˓→Integer(3)],...
[-Integer(1), Integer(1), -Integer(6), -Integer(6),␣
˓→Integer(5)]])>>> Q, R = A.QR()>>> Q[ -0.4588314677411235? -0.1260506983326509?
0.3812120831224489?
-0.
˓→394573711338418?
-0.687440062597?][ -0.4588314677411235?
0.4726901187474409? -0.05198346588033394?
0.
˓→717294125164660?
-0.220962877263?][ 0.2294157338705618?
0.6617661662464172?
0.6619227988762521?
-0.
˓→180872093737548?
0.1964114464561?][ 0.6882472016116853?
0.1890760474989764? -0.2044682991293135?
0.
˓→096630296654307?
-0.662888631790?][ -0.2294157338705618?
0.5357154679137663?
-0.609939332995919?
-0.
˓→536422031427112?
0.0245514308070?](continues on next page)

266

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> R[ 4.358898943540674? -0.4588314677411235?
13.07669683062202?
6.
˓→194224814505168?
2.982404540317303?][
01.670171752907625? 0.5987408170800917? -1.
˓→292019657909672?
6.207996892883057?][005.444401659866974?
5.
˓→468660610611130?
-0.682716185228386?]
[
0
0
0
1.
˓→027626039419836?
-3.61930014968662?]
[
0
0
0
␣
˓→
0
0.02455143080702?]>>> Q.conjugate_transpose()*Q[1.000000000000000?
0.?e-18
0.?e-170.?e-15 ␣˓→
0.?e-12][0.?e-18 1.000000000000000?
0.?e-160.?e-15 ␣˓→
0.?e-12][0.?e-170.?e-16 1.000000000000000?
0.?e-15 ␣˓→
0.?e-12][0.?e-150.?e-150.?e-15 1.000000000000000? ␣˓→
0.?e-12][0.?e-120.?e-120.?e-120.?e-12 ␣
˓→1.000000000000?]>>> Q * R == ATrue

An example with complex numbers in QQbar, the field of algebraic numbers.
sage: # needs sage.rings.number_fieldsage: A = matrix(QQbar, [[-8, 4*I + 1, -I + 2, 2*I + 1],....:[1, -2*I - 1, -I + 3, -I + 1],....:[I + 7, 2*I + 1, -2*I + 7, -I + 1],....:[I + 2, 0, I + 12, -1]])
sage: Q, R = A.QR()
sage: Q[
-0.7302967433402215?
0.2070566455055649? + 0.
˓→5383472783144687?*I
0.2463049809998642? - 0.0764456358723292?*I
0.
˓→2381617683194332? - 0.1036596032779695?*I][
0.0912870929175277?
-0.2070566455055649? - 0.
˓→3778783780476559?*I
0.3786559533863032? - 0.1952221495524667?*I
0.
˓→701244450214469? - 0.364371165098660?*I][
0.6390096504226938? + 0.0912870929175277?*I
0.1708217325420910? + 0.
˓→6677576817554466?*I -0.03411475806452072? + 0.04090198741767143?*I0.
˓→3140171085506763? - 0.0825191718705412?*I][
0.1825741858350554? + 0.0912870929175277?*I -0.03623491296347385? + 0.
˓→0724698259269477?*I
0.8632284069415110? + 0.06322839976356195?*I-0.
˓→4499694867611521? - 0.0116119181208918?*I]
sage: R[
10.95445115010333?
0.?e-18 - 1.
˓→917028951268082?*I
5.385938482134133? - 2.190890230020665?*I -0.
˓→2738612787525831? - 2.190890230020665?*I][
0
4.829596256417300?
˓→ + 0.?e-17*I-0.869637911123373? - 5.864879483945125?*I0.
˓→993871898426712? - 0.3054085521207082?*I]
[
0
␣
˓→
0
12.00160760935814? + 0.?e-16*I -0.
˓→2709533402297273? + 0.4420629644486323?*I][0␣
(continues on next page)267

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)00
1.
˓→942963944258992? + 0.?e-16*I]
sage: Q.conjugate_transpose()*Q[1.000000000000000? + 0.?e-19*I
0.?e-18 + 0.?e-17*I0.?
˓→e-17 + 0.?e-17*I
0.?e-16 + 0.?e-16*I][
0.?e-18 + 0.?e-17*I 1.000000000000000? + 0.?e-17*I0.?
˓→e-17 + 0.?e-17*I
0.?e-16 + 0.?e-16*I][
0.?e-17 + 0.?e-17*I
0.?e-17 + 0.?e-17*I 1.
˓→000000000000000? + 0.?e-16*I
0.?e-16 + 0.?e-16*I][
0.?e-16 + 0.?e-16*I
0.?e-16 + 0.?e-16*I0.?
˓→e-16 + 0.?e-16*I 1.000000000000000? + 0.?e-15*I]
sage: Q*R - A[
0.?e-17 0.?e-17 + 0.?e-17*I 0.?e-16 + 0.?e-16*I 0.?e-16 + 0.?e˓→16*I][
0.?e-18 0.?e-17 + 0.?e-17*I 0.?e-16 + 0.?e-16*I 0.?e-15 + 0.?e˓→15*I][0.?e-17 + 0.?e-18*I 0.?e-17 + 0.?e-17*I 0.?e-16 + 0.?e-16*I 0.?e-16 + 0.?e˓→16*I][0.?e-18 + 0.?e-18*I 0.?e-18 + 0.?e-17*I 0.?e-16 + 0.?e-16*I 0.?e-15 + 0.?e˓→16*I]˓→>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQbar, [[-Integer(8), Integer(4)*I + Integer(1), -I +␣˓→Integer(2), Integer(2)*I + Integer(1)],...
[Integer(1), -Integer(2)*I - Integer(1), -I +␣˓→Integer(3), -I + Integer(1)],...
[I + Integer(7), Integer(2)*I + Integer(1), ˓→Integer(2)*I + Integer(7), -I + Integer(1)],...
[I + Integer(2), Integer(0), I + Integer(12), ˓→Integer(1)]])>>> Q, R = A.QR()>>> Q[-0.7302967433402215?
0.2070566455055649? + 0.
˓→5383472783144687?*I
0.2463049809998642? - 0.0764456358723292?*I
0.
˓→2381617683194332? - 0.1036596032779695?*I][
0.0912870929175277?
-0.2070566455055649? - 0.
˓→3778783780476559?*I
0.3786559533863032? - 0.1952221495524667?*I
0.
˓→701244450214469? - 0.364371165098660?*I][
0.6390096504226938? + 0.0912870929175277?*I
0.1708217325420910? + 0.
˓→6677576817554466?*I -0.03411475806452072? + 0.04090198741767143?*I0.
˓→3140171085506763? - 0.0825191718705412?*I][
0.1825741858350554? + 0.0912870929175277?*I -0.03623491296347385? + 0.
˓→0724698259269477?*I
0.8632284069415110? + 0.06322839976356195?*I-0.
˓→4499694867611521? - 0.0116119181208918?*I]>>> R[
10.95445115010333?
0.?e-18 - 1.
˓→917028951268082?*I
5.385938482134133? - 2.190890230020665?*I -0.
˓→2738612787525831? - 2.190890230020665?*I][
0
4.829596256417300?
˓→ + 0.?e-17*I-0.869637911123373? - 5.864879483945125?*I0.
˓→993871898426712? - 0.3054085521207082?*I]
[
0
␣
˓→
0
12.00160760935814? + 0.?e-16*I -0.
˓→2709533402297273? + 0.4420629644486323?*I][0␣
(continues on next page)

268

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)00
1.
˓→942963944258992? + 0.?e-16*I]>>> Q.conjugate_transpose()*Q[1.000000000000000? + 0.?e-19*I
0.?e-18 + 0.?e-17*I0.?
˓→e-17 + 0.?e-17*I
0.?e-16 + 0.?e-16*I][
0.?e-18 + 0.?e-17*I 1.000000000000000? + 0.?e-17*I0.?
˓→e-17 + 0.?e-17*I
0.?e-16 + 0.?e-16*I][
0.?e-17 + 0.?e-17*I
0.?e-17 + 0.?e-17*I 1.
˓→000000000000000? + 0.?e-16*I
0.?e-16 + 0.?e-16*I][
0.?e-16 + 0.?e-16*I
0.?e-16 + 0.?e-16*I0.?
˓→e-16 + 0.?e-16*I 1.000000000000000? + 0.?e-15*I]>>> Q*R - A[
0.?e-17 0.?e-17 + 0.?e-17*I 0.?e-16 + 0.?e-16*I 0.?e-16 + 0.?e˓→16*I][
0.?e-18 0.?e-17 + 0.?e-17*I 0.?e-16 + 0.?e-16*I 0.?e-15 + 0.?e˓→15*I][0.?e-17 + 0.?e-18*I 0.?e-17 + 0.?e-17*I 0.?e-16 + 0.?e-16*I 0.?e-16 + 0.?e˓→16*I][0.?e-18 + 0.?e-18*I 0.?e-18 + 0.?e-17*I 0.?e-16 + 0.?e-16*I 0.?e-15 + 0.?e˓→16*I]˓→

A rank-deficient rectangular matrix, with both values of the full keyword.
sage: # needs sage.rings.number_fieldsage: A = matrix(QQbar, [[2, -3, 3],....:[-1, 1, -1],....:[-1, 3, -3],....:[-5, 1, -1]])
sage: Q, R = A.QR()
sage: Q
[ 0.3592106040535498? -0.5693261797050169?
0.7239227659930268?
0.
˓→1509015305256380?][ -0.1796053020267749?
0.1445907757980996?
00.
˓→9730546968377341?][ -0.1796053020267749?
0.7048800320157352?
0.672213996993525? -0.
˓→1378927778941174?][ -0.8980265101338745? -0.3976246334447737?
0.1551263069985058? -0.
˓→10667177157846818?]
sage: R[ 5.567764362830022? -2.694079530401624? 2.694079530401624?][
0 3.569584777515583? -3.569584777515583?]
[
0
0
0]
[
0
0
0]
sage: Q.conjugate_transpose() * Q[
10.?e-18
0.?e-18
0.?e-18][
0.?e-18
10.?e-18
0.?e-18][
0.?e-18
0.?e-18 1.000000000000000?
0.?e-18][
0.?e-18
0.?e-18
0.?e-18 1.000000000000000?]
sage: # needs sage.rings.number_fieldsage: Q, R = A.QR(full=False)
sage: Q
[ 0.3592106040535498? -0.5693261797050169?][-0.1796053020267749? 0.1445907757980996?][-0.1796053020267749? 0.7048800320157352?][-0.8980265101338745? -0.3976246334447737?]
sage: R
(continues on next page)269

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 5.567764362830022? -2.694079530401624? 2.694079530401624?][
0 3.569584777515583? -3.569584777515583?]
sage: Q.conjugate_transpose()*Q[
1 0.?e-18][0.?e-18
1]>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQbar, [[Integer(2), -Integer(3), Integer(3)],...
[-Integer(1), Integer(1), -Integer(1)],...
[-Integer(1), Integer(3), -Integer(3)],...
[-Integer(5), Integer(1), -Integer(1)]])>>> Q, R = A.QR()>>> Q[ 0.3592106040535498? -0.5693261797050169?
0.7239227659930268?
0.
˓→1509015305256380?][ -0.1796053020267749?
0.1445907757980996?
00.
˓→9730546968377341?][ -0.1796053020267749?
0.7048800320157352?
0.672213996993525? -0.
˓→1378927778941174?][ -0.8980265101338745? -0.3976246334447737?
0.1551263069985058? -0.
˓→10667177157846818?]>>> R[ 5.567764362830022? -2.694079530401624? 2.694079530401624?][
0 3.569584777515583? -3.569584777515583?]
[
0
0
0]
[
0
0
0]
>>> Q.conjugate_transpose() * Q[
10.?e-18
0.?e-18
0.?e-18][
0.?e-18
10.?e-18
0.?e-18][
0.?e-18
0.?e-18 1.000000000000000?
0.?e-18][
0.?e-18
0.?e-18
0.?e-18 1.000000000000000?]>>> # needs sage.rings.number_field>>> Q, R = A.QR(full=False)>>> Q[ 0.3592106040535498? -0.5693261797050169?][-0.1796053020267749? 0.1445907757980996?][-0.1796053020267749? 0.7048800320157352?][-0.8980265101338745? -0.3976246334447737?]>>> R[ 5.567764362830022? -2.694079530401624? 2.694079530401624?][
0 3.569584777515583? -3.569584777515583?]>>> Q.conjugate_transpose()*Q[
1 0.?e-18][0.?e-18
1]

Another rank-deficient rectangular matrix, with complex entries, as a reduced decomposition.
sage: # needs sage.rings.number_fieldsage: A = matrix(QQbar, [[-3*I - 3, I - 3, -12*I + 1, -2],....:[-I - 1, -2, 5*I - 1, -I - 2],....:[-4*I - 4, I - 5, -7*I, -I - 4]])sage: Q, R = A.QR(full=False)
sage: Q[ -0.4160251471689219? - 0.4160251471689219?*I
0.5370861555295747? + 0.
(continues on next page)

270

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

1790287185098583?*I][ -0.1386750490563073? - 0.1386750490563073?*I -0.7519206177414046? - 0.
˓→2506402059138015?*I][ -0.5547001962252291? - 0.5547001962252291?*I -0.2148344622118299? - 0.
˓→07161148740394329?*I]
sage: R[7.211102550927979? 3.328201177351375? - 5.
˓→269651864139676?*I
7.904477796209515? + 8.45917799243475?*I 4.
˓→021576422632911? - 2.634825932069838?*I][
0
1.
˓→074172311059150?
-1.611258466588724? - 9.13046464400277?*I 1.
˓→611258466588724? + 0.5370861555295747?*I]
sage: Q.conjugate_transpose()*Q
[1 0]
[0 1]
sage: Q*R - A[0 0 0 0][0 0 0 0][0 0 0 0]
˓→>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQbar, [[-Integer(3)*I - Integer(3), I - Integer(3), ˓→Integer(12)*I + Integer(1), -Integer(2)],...
[-I - Integer(1), -Integer(2), Integer(5)*I -␣˓→Integer(1), -I - Integer(2)],...
[-Integer(4)*I - Integer(4), I - Integer(5), ˓→Integer(7)*I, -I - Integer(4)]])>>> Q, R = A.QR(full=False)>>> Q[ -0.4160251471689219? - 0.4160251471689219?*I
0.5370861555295747? + 0.
˓→1790287185098583?*I][ -0.1386750490563073? - 0.1386750490563073?*I -0.7519206177414046? - 0.
˓→2506402059138015?*I][ -0.5547001962252291? - 0.5547001962252291?*I -0.2148344622118299? - 0.
˓→07161148740394329?*I]>>> R[
7.211102550927979? 3.328201177351375? - 5.
˓→269651864139676?*I
7.904477796209515? + 8.45917799243475?*I 4.
˓→021576422632911? - 2.634825932069838?*I][
0
1.
˓→074172311059150?
-1.611258466588724? - 9.13046464400277?*I 1.
˓→611258466588724? + 0.5370861555295747?*I]>>> Q.conjugate_transpose()*Q
[1 0]
[0 1]
>>> Q*R - A[0 0 0 0][0 0 0 0][0 0 0 0]

Results of full decompositions are cached and thus returned immutable.
sage: # needs sage.rings.number_fieldsage: A = random_matrix(QQbar, 2, 2)
sage: Q, R = A.QR()(continues on next page)271

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: Q.is_mutable()False
sage: R.is_mutable()
False>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = random_matrix(QQbar, Integer(2), Integer(2))>>> Q, R = A.QR()>>> Q.is_mutable()
False>>> R.is_mutable()
False

Trivial cases return trivial results of the correct size, and we check 𝑄 itself in one case.
sage: # needs sage.rings.number_fieldsage: A = zero_matrix(QQbar, 0, 10)
sage: Q, R = A.QR()
sage: Q.nrows(), Q.ncols()(0, 0)
sage: R.nrows(), R.ncols()(0, 10)sage: A = zero_matrix(QQbar, 3, 0)
sage: Q, R = A.QR()
sage: Q.nrows(), Q.ncols()(3, 3)
sage: R.nrows(), R.ncols()(3, 0)
sage: Q
[1 0 0][0 1 0][0 0 1]>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = zero_matrix(QQbar, Integer(0), Integer(10))>>> Q, R = A.QR()>>> Q.nrows(), Q.ncols()(0, 0)>>> R.nrows(), R.ncols()(0, 10)>>> A = zero_matrix(QQbar, Integer(3), Integer(0))>>> Q, R = A.QR()>>> Q.nrows(), Q.ncols()(3, 3)>>> R.nrows(), R.ncols()(3, 0)>>> Q[1 0 0][0 1 0][0 0 1]T
Returns the transpose of a matrix.
EXAMPLES:
272

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

sage: A = matrix(QQ, 5, range(25))
sage: A.T
[ 0 5 10 15 20][ 1 6 11 16 21][ 2 7 12 17 22][ 3 8 13 18 23][ 4 9 14 19 24]>>> from sage.all import *>>> A = matrix(QQ, Integer(5), range(Integer(25)))>>> A.T[ 0 5 10 15 20][ 1 6 11 16 21][ 2 7 12 17 22][ 3 8 13 18 23][ 4 9 14 19 24]

adjoint(*args, **kwds)
Deprecated: Use adjugate() instead. See Issue #10501 for details.
adjoint_classical()
Return the adjugate matrix of self (that is, the transpose of the matrix of cofactors).
Let 𝑀 be an 𝑛 × 𝑛-matrix. The adjugate matrix of 𝑀 is the 𝑛 × 𝑛-matrix 𝑁 whose (𝑖, 𝑗)-th entry is(−1)𝑖+𝑗 det(𝑀𝑗,𝑖 ), where 𝑀𝑗,𝑖 is the matrix 𝑀 with its 𝑗-th row and 𝑖-th column removed. It is known tosatisfy 𝑁 𝑀 = 𝑀 𝑁 = det(𝑀 )𝐼.
EXAMPLES:
sage: M = Matrix(ZZ,2,2,[5,2,3,4]); M
[5 2]
[3 4]
sage: N = M.adjugate(); N[ 4 -2][-3 5]
sage: M * N[14 0][ 0 14]sage: N * M[14 0][ 0 14]sage: M = Matrix(QQ, 2, 2, [5/3,2/56, 33/13,41/10]); M[ 5/3 1/28][33/13 41/10]
sage: N = M.adjugate(); N˓→needs sage.libs.pari[ 41/10 -1/28][-33/13
5/3]
sage: M * N
˓→needs sage.libs.pari[7363/1092
0][0 7363/1092]#␣#␣>>> from sage.all import *>>> M = Matrix(ZZ,Integer(2),Integer(2),[Integer(5),Integer(2),Integer(3),˓→Integer(4)]); M[5 2](continues on next page)273

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[3 4]>>> N = M.adjugate(); N[ 4 -2][-3 5]>>> M * N
[14 0][ 0 14]>>> N * M
[14 0][ 0 14]>>> M = Matrix(QQ, Integer(2), Integer(2), [Integer(5)/Integer(3),Integer(2)/˓→Integer(56), Integer(33)/Integer(13),Integer(41)/Integer(10)]); M[ 5/3 1/28][33/13 41/10]>>> N = M.adjugate(); N#␣˓→needs sage.libs.pari[ 41/10 -1/28][-33/13
5/3]>>> M * N#␣˓→needs sage.libs.pari[7363/1092
0][0 7363/1092]

An alias is adjoint_classical(), which replaces the deprecated adjoint() method:
sage: M.adjoint()#␣˓→needs sage.libs.pari...: DeprecationWarning: adjoint is deprecated. Please use adjugate instead.
See https://github.com/sagemath/sage/issues/10501 for details.
[ 41/10 -1/28][-33/13
5/3]
sage: M.adjoint_classical()#␣˓→needs sage.libs.pari[ 41/10 -1/28][-33/13
5/3]>>> from sage.all import *>>> M.adjoint()#␣˓→needs sage.libs.pari...: DeprecationWarning: adjoint is deprecated. Please use adjugate instead.
See https://github.com/sagemath/sage/issues/10501 for details.
[ 41/10 -1/28][-33/13
5/3]>>> M.adjoint_classical()#␣˓→needs sage.libs.pari[ 41/10 -1/28][-33/13
5/3]

ALGORITHM:
Use PARI whenever the method self._adjugate is included to do so in an inheriting class. Otherwise,
use a generic division-free algorithm that computes the adjugate matrix from the characteristic polynomial.
The result is cached.
adjugate()
Return the adjugate matrix of self (that is, the transpose of the matrix of cofactors).

274

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

Let 𝑀 be an 𝑛 × 𝑛-matrix. The adjugate matrix of 𝑀 is the 𝑛 × 𝑛-matrix 𝑁 whose (𝑖, 𝑗)-th entry is(−1)𝑖+𝑗 det(𝑀𝑗,𝑖 ), where 𝑀𝑗,𝑖 is the matrix 𝑀 with its 𝑗-th row and 𝑖-th column removed. It is known tosatisfy 𝑁 𝑀 = 𝑀 𝑁 = det(𝑀 )𝐼.
EXAMPLES:
sage: M = Matrix(ZZ,2,2,[5,2,3,4]); M
[5 2]
[3 4]
sage: N = M.adjugate(); N[ 4 -2][-3 5]
sage: M * N[14 0][ 0 14]sage: N * M[14 0][ 0 14]sage: M = Matrix(QQ, 2, 2, [5/3,2/56, 33/13,41/10]); M[ 5/3 1/28][33/13 41/10]
sage: N = M.adjugate(); N˓→needs sage.libs.pari[ 41/10 -1/28][-33/13
5/3]
sage: M * N
˓→needs sage.libs.pari[7363/1092
0][0 7363/1092]#␣#␣>>> from sage.all import *>>> M = Matrix(ZZ,Integer(2),Integer(2),[Integer(5),Integer(2),Integer(3),˓→Integer(4)]); M
[5 2]
[3 4]
>>> N = M.adjugate(); N[ 4 -2][-3 5]>>> M * N
[14 0][ 0 14]>>> N * M
[14 0][ 0 14]>>> M = Matrix(QQ, Integer(2), Integer(2), [Integer(5)/Integer(3),Integer(2)/˓→Integer(56), Integer(33)/Integer(13),Integer(41)/Integer(10)]); M[ 5/3 1/28][33/13 41/10]>>> N = M.adjugate(); N#␣˓→needs sage.libs.pari[ 41/10 -1/28][-33/13
5/3]>>> M * N#␣˓→needs sage.libs.pari[7363/1092
0][0 7363/1092]

An alias is adjoint_classical(), which replaces the deprecated adjoint() method:275

Matrices and Spaces of Matrices, Release 10.4

sage: M.adjoint()#␣˓→needs sage.libs.pari...: DeprecationWarning: adjoint is deprecated. Please use adjugate instead.
See https://github.com/sagemath/sage/issues/10501 for details.
[ 41/10 -1/28][-33/13
5/3]
sage: M.adjoint_classical()#␣˓→needs sage.libs.pari[ 41/10 -1/28][-33/13
5/3]>>> from sage.all import *>>> M.adjoint()#␣˓→needs sage.libs.pari...: DeprecationWarning: adjoint is deprecated. Please use adjugate instead.
See https://github.com/sagemath/sage/issues/10501 for details.
[ 41/10 -1/28][-33/13
5/3]>>> M.adjoint_classical()#␣˓→needs sage.libs.pari[ 41/10 -1/28][-33/13
5/3]

ALGORITHM:
Use PARI whenever the method self._adjugate is included to do so in an inheriting class. Otherwise,
use a generic division-free algorithm that computes the adjugate matrix from the characteristic polynomial.
The result is cached.
apply_map(phi, R=None, sparse=None)
Apply the given map phi (an arbitrary Python function or callable object) to this dense matrix. If R is not
given, automatically determine the base ring of the resulting matrix.
INPUT:• sparse – True to make the output a sparse matrix; default: False• phi – arbitrary Python function or callable object• R – (optional) ring
OUTPUT: a matrix over R
EXAMPLES:
sage: m = matrix(ZZ, 3, 3, range(9))
sage: k.<a> = GF(9)˓→needs sage.rings.finite_rings
sage: f = lambda x: k(x)sage: n = m.apply_map(f); n˓→needs sage.rings.finite_rings[0 1 2][0 1 2][0 1 2]sage: n.parent()
˓→needs sage.rings.finite_rings
Full MatrixSpace of 3 by 3 dense matrices
over Finite Field in a of size 3^2

276

#␣

#␣

#␣

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> m = matrix(ZZ, Integer(3), Integer(3), range(Integer(9)))>>> k = GF(Integer(9), names=( a ,)); (a,) = k._first_ngens(1)# needs sage.
˓→rings.finite_rings>>> f = lambda x: k(x)>>> n = m.apply_map(f); n#␣˓→needs sage.rings.finite_rings[0 1 2][0 1 2][0 1 2]>>> n.parent()#␣˓→needs sage.rings.finite_rings
Full MatrixSpace of 3 by 3 dense matrices
over Finite Field in a of size 3^2

In this example, we explicitly specify the codomain.
sage: s = GF(3)sage: f = lambda x: s(x)sage: n = m.apply_map(f, k); n˓→needs sage.rings.finite_rings[0 1 2][0 1 2][0 1 2]sage: n.parent()
˓→needs sage.rings.finite_rings
Full MatrixSpace of 3 by 3 dense matrices
over Finite Field in a of size 3^2>>> from sage.all import *>>> s = GF(Integer(3))>>> f = lambda x: s(x)>>> n = m.apply_map(f, k); n˓→needs sage.rings.finite_rings[0 1 2][0 1 2][0 1 2]>>> n.parent()
˓→needs sage.rings.finite_rings
Full MatrixSpace of 3 by 3 dense matrices
over Finite Field in a of size 3^2

#␣

#␣

#␣

#␣

If self is subdivided, the result will be as well:sage: m = matrix(2, 2, srange(4))
sage: m.subdivide(None, 1); m
[0|1]
[2|3]
sage: m.apply_map(lambda x: x*x)
[0|1]
[4|9]
>>> from sage.all import *>>> m = matrix(Integer(2), Integer(2), srange(Integer(4)))>>> m.subdivide(None, Integer(1)); m
[0|1]
[2|3]
(continues on next page)277

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> m.apply_map(lambda x: x*x)
[0|1]
[4|9]

If the matrix is sparse, the result will be as well:sage: m = matrix(ZZ,100,100,sparse=True)
sage: m[18,32] = -6
sage: m[1,83] = 19
sage: n = m.apply_map(abs, R=ZZ)
sage: n.dict(){(1, 83): 19, (18, 32): 6}
sage: n.is_sparse()
True>>> from sage.all import *>>> m = matrix(ZZ,Integer(100),Integer(100),sparse=True)>>> m[Integer(18),Integer(32)] = -Integer(6)>>> m[Integer(1),Integer(83)] = Integer(19)>>> n = m.apply_map(abs, R=ZZ)>>> n.dict(){(1, 83): 19, (18, 32): 6}>>> n.is_sparse()
True

If the map sends most of the matrix to zero, then it may be useful to get the result as a sparse matrix.
sage: m = matrix(ZZ, 3, 3, range(1, 10))sage: n = m.apply_map(lambda x: 1//x, sparse=True); n[1 0 0][0 0 0][0 0 0]sage: n.parent()
Full MatrixSpace of 3 by 3 sparse matrices over Integer Ring>>> from sage.all import *>>> m = matrix(ZZ, Integer(3), Integer(3), range(Integer(1), Integer(10)))>>> n = m.apply_map(lambda x: Integer(1)//x, sparse=True); n[1 0 0][0 0 0][0 0 0]>>> n.parent()
Full MatrixSpace of 3 by 3 sparse matrices over Integer Ring

apply_morphism(phi)Apply the morphism phi to the coefficients of this dense 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:

278

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

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

We apply a morphism to a matrix over a polynomial ring:sage: R.<x,y> = QQ[]
sage: m = matrix(2, [x,x^2 + y, 2/3*y^2-x, x]); m[xx^2 + y][2/3*y^2 - x
x]
sage: phi = R.hom([y,x])
sage: m.apply_morphism(phi)[yy^2 + x][2/3*x^2 - yy]>>> from sage.all import *>>> R = QQ[ x, y ]; (x, y,) = R._first_ngens(2)>>> m = matrix(Integer(2), [x,x**Integer(2) + y, Integer(2)/˓→Integer(3)*y**Integer(2)-x, x]); m[xx^2 + y][2/3*y^2 - x
x]>>> phi = R.hom([y,x])>>> m.apply_morphism(phi)[yy^2 + x][2/3*x^2 - yy]as_bipartite_graph()
Construct a bipartite graph B representing the matrix uniquely.
Vertices are labeled 1 to nrows on the left and nrows + 1 to nrows + ncols on the right, representing
rows and columns correspondingly. Each row is connected to each column with an edge weighted by the valueof the corresponding matrix entry.
This graph is a helper for calculating automorphisms of a matrix under row and column permutations. See
automorphisms_of_rows_and_columns().
OUTPUT:• A bipartite graph.
EXAMPLES:

279

Matrices and Spaces of Matrices, Release 10.4

sage: M = matrix(QQ, [[1/3, 7], [6, 1/4], [8, -5]])sage: M
[1/3
7]
[ 6 1/4][ 8 -5]sage: # needs sage.graphs
sage: B = M.as_bipartite_graph(); B
Bipartite graph on 5 vertices
sage: B.edges(sort=True)[(1, 4, 1/3), (1, 5, 7), (2, 4, 6), (2, 5, 1/4), (3, 4, 8), (3, 5, -5)]sage: len(B.left) == M.nrows()
Truesage: len(B.right) == M.ncols()
True>>> from sage.all import *>>> M = matrix(QQ, [[Integer(1)/Integer(3), Integer(7)], [Integer(6),␣
˓→Integer(1)/Integer(4)], [Integer(8), -Integer(5)]])
>>> M
[1/3
7]
[ 6 1/4][ 8 -5]>>> # needs sage.graphs>>> B = M.as_bipartite_graph(); B
Bipartite graph on 5 vertices>>> B.edges(sort=True)[(1, 4, 1/3), (1, 5, 7), (2, 4, 6), (2, 5, 1/4), (3, 4, 8), (3, 5, -5)]>>> len(B.left) == M.nrows()
True>>> len(B.right) == M.ncols()
Trueas_sum_of_permutations()
Returns the current matrix as a sum of permutation matrices
According to the Birkhoff-von Neumann Theorem, any bistochastic matrix can be written as a positive sumof permutation matrices, which also means that the polytope of bistochastic matrices is integer.
As a non-bistochastic matrix can obviously not be written as a sum of permutations, this theorem is an equivalence.
This function, given a bistochastic matrix, returns the corresponding decomposition.
See also:• bistochastic_as_sum_of_permutations – for more information on this method.
• Birkhoff_polytope()
EXAMPLES:
We create a bistochastic matrix from a convex sum of permutations, then try to deduce the decomposition
from the matrix
sage: L = []sage: L.append((9, Permutation([4, 1, 3, 5, 2])))(continues on next page)

280

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: L.append((6, Permutation([5, 3, 4, 1, 2])))sage: L.append((3, Permutation([3, 1, 4, 2, 5])))sage: L.append((2, Permutation([1, 4, 2, 3, 5])))sage: M = sum([c * p.to_matrix() for c, p in L])
sage: from sage.combinat.permutation import bistochastic_as_sum_of_
˓→permutations
sage: decomp = bistochastic_as_sum_of_permutations(M)#␣˓→needs sage.combinat sage.graphs
sage: print(decomp)#␣˓→needs sage.combinat sage.graphs
2*B[[1, 4, 2, 3, 5]] + 3*B[[3, 1, 4, 2, 5]] + 9*B[[4, 1, 3, 5, 2]] + 6*B[[5,␣˓→3, 4, 1, 2]]>>> from sage.all import *>>> L = []>>> L.append((Integer(9), Permutation([Integer(4), Integer(1), Integer(3),␣
˓→Integer(5), Integer(2)])))>>> L.append((Integer(6), Permutation([Integer(5), Integer(3), Integer(4),␣
˓→Integer(1), Integer(2)])))>>> L.append((Integer(3), Permutation([Integer(3), Integer(1), Integer(4),␣
˓→Integer(2), Integer(5)])))>>> L.append((Integer(2), Permutation([Integer(1), Integer(4), Integer(2),␣
˓→Integer(3), Integer(5)])))>>> M = sum([c * p.to_matrix() for c, p in L])>>> from sage.combinat.permutation import bistochastic_as_sum_of_permutations>>> decomp = bistochastic_as_sum_of_permutations(M)#␣˓→needs sage.combinat sage.graphs>>> print(decomp)#␣˓→needs sage.combinat sage.graphs
2*B[[1, 4, 2, 3, 5]] + 3*B[[3, 1, 4, 2, 5]] + 9*B[[4, 1, 3, 5, 2]] + 6*B[[5,␣˓→3, 4, 1, 2]]

An exception is raised when the matrix is not bistochastic:
sage: M = Matrix([[2,3],[2,2]])
sage: decomp = bistochastic_as_sum_of_permutations(M)˓→needs sage.graphs
Traceback (most recent call last):...
ValueError: The matrix is not bistochastic>>> from sage.all import *>>> M = Matrix([[Integer(2),Integer(3)],[Integer(2),Integer(2)]])>>> decomp = bistochastic_as_sum_of_permutations(M)˓→needs sage.graphs
Traceback (most recent call last):...
ValueError: The matrix is not bistochastic#␣#␣

automorphisms_of_rows_and_columns()
Return the automorphisms of self under permutations of rows and columns as a list of pairs of PermutationGroupElement objects.
EXAMPLES:

281

Matrices and Spaces of Matrices, Release 10.4

sage: # needs sage.graphs sage.groups
sage: M = matrix(ZZ,[[1,0],[1,0],[0,1]]); M
[1 0]
[1 0]
[0 1]
sage: A = M.automorphisms_of_rows_and_columns(); A[((), ()), ((1,2), ())]
sage: M = matrix(ZZ, [[1,1,1,1],[1,1,1,1]])
sage: A = M.automorphisms_of_rows_and_columns()
sage: len(A)48>>> from sage.all import *>>> # needs sage.graphs sage.groups>>> M = matrix(ZZ,[[Integer(1),Integer(0)],[Integer(1),Integer(0)],˓→[Integer(0),Integer(1)]]); M
[1 0]
[1 0]
[0 1]
>>> A = M.automorphisms_of_rows_and_columns(); A[((), ()), ((1,2), ())]>>> M = matrix(ZZ, [[Integer(1),Integer(1),Integer(1),Integer(1)],[Integer(1),˓→Integer(1),Integer(1),Integer(1)]])>>> A = M.automorphisms_of_rows_and_columns()>>> len(A)48

One can now apply these automorphisms to M to show that it leaves it invariant:sage: all(M.with_permuted_rows_and_columns(*i) == M for i in A)
˓→needs sage.graphs sage.groups
True>>> from sage.all import *>>> all(M.with_permuted_rows_and_columns(*i) == M for i in A)
˓→needs sage.graphs sage.groups
True

#␣

#␣

Check that Issue #25426 is fixed:
sage: j = matrix([(3, 2, 1, 0, 0),....:(2, 2, 0, 1, 0),....:(1, 0, 3, 0, 2),....:(0, 1, 0, 2, 1),....:(0, 0, 2, 1, 2)])sage: j.automorphisms_of_rows_and_columns()
˓→needs sage.graphs sage.groups[((), ()), ((1,3)(2,5), (1,3)(2,5))]#␣>>> from sage.all import *>>> j = matrix([(Integer(3), Integer(2), Integer(1), Integer(0), Integer(0)),...
(Integer(2), Integer(2), Integer(0), Integer(1), Integer(0)),...
(Integer(1), Integer(0), Integer(3), Integer(0), Integer(2)),...
(Integer(0), Integer(1), Integer(0), Integer(2), Integer(1)),...
(Integer(0), Integer(0), Integer(2), Integer(1), Integer(2))])>>> j.automorphisms_of_rows_and_columns()#␣(continues on next page)282

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)needs sage.graphs sage.groups[((), ()), ((1,3)(2,5), (1,3)(2,5))]˓→

block_ldlt(classical=False)
Compute a block-𝐿𝐷𝐿𝑇 factorization of a Hermitian matrix.
The standard 𝐿𝐷𝐿𝑇 factorization of a positive-definite matrix 𝐴 factors it as 𝐴 = 𝐿𝐷𝐿𝑇 where 𝐿 isunit-lower-triangular and 𝐷 is diagonal. If one allows row/column swaps via a permutation matrix 𝑃 , then thisfactorization can be extended to many positive-semidefinite matrices 𝐴 via the factorization 𝑃 𝑇 𝐴𝑃 = 𝐿𝐷𝐿𝑇
that places the zeros at the bottom of 𝐷 to avoid division by zero. These factorizations extend easily to complex Hermitian matrices when one replaces the transpose by the conjugate-transpose.
However, we can go one step further. If, in addition, we allow 𝐷 to potentially contain 2 × 2 blocks on its
diagonal, then every real or complex Hermitian matrix 𝐴 can be factored as 𝐴 = 𝑃 𝐿𝐷𝐿* 𝑃 𝑇 . When therow/column swaps are made intelligently, this process is numerically stable over inexact rings like RDF. Bunch
and Kaufman describe such a “pivot” scheme that is suitable for the solution of Hermitian systems, and thatis how we choose our row and column swaps.
INPUT:• classical – (default: False) whether or not to attempt a classical non-block 𝐿𝐷𝐿𝑇 factorization
with no row/column swaps.
Warning: Not all matrices have a classical 𝐿𝐷𝐿𝑇 factorization. Set classical=True at yourown risk, preferably after verifying that your matrix is positive-definite and (over inexact rings) not
ill-conditioned.
OUTPUT:
If the input matrix is not Hermitian, the output from this function is undefined. Otherwise, we return a triple(𝑃, 𝐿, 𝐷) such that 𝐴 = 𝑃 𝐿𝐷𝐿* 𝑃 𝑇 and• 𝑃 is a permutation matrix,• 𝐿 is unit lower-triangular,• 𝐷 is a block-diagonal matrix whose blocks are of size one or two.
With classical=True, the permutation matrix 𝑃 is always an identity matrix and the diagonal blocks
are always one-by-one. A ValueError is raised if the matrix has no classical 𝐿𝐷𝐿𝑇 factorization.
ALGORITHM:
We essentially follow “Algorithm A” in the paper by Bunch and Kaufman [BK1977] that describes the stablepivoting strategy. The same scheme is described by Higham [Hig2002].
See also:
indefinite_factorization()
REFERENCES:• [BK1977]• [Hig2002]
EXAMPLES:This three-by-three real symmetric matrix has one positive, one negative, and one zero eigenvalue – so it is
not any flavor of (semi)definite, yet we can still factor it:283

Matrices and Spaces of Matrices, Release 10.4

sage: A = matrix(QQ, [[0, 1, 0],....:[1, 1, 2],....:[0, 2, 0]])sage: P,L,D = A.block_ldlt()
sage: P[0 0 1][1 0 0][0 1 0]sage: L
[ 1
0
0]
[ 2
1
0]
[ 1 1/2
1]
sage: D
[ 1| 0| 0][--+--+--][ 0|-4| 0][--+--+--][ 0| 0| 0]
sage: P.transpose()*A*P == L*D*L.transpose()True>>> from sage.all import *>>> A = matrix(QQ, [[Integer(0), Integer(1), Integer(0)],...
[Integer(1), Integer(1), Integer(2)],...
[Integer(0), Integer(2), Integer(0)]])>>> P,L,D = A.block_ldlt()>>> P[0 0 1][1 0 0][0 1 0]
>>> L
[ 1
0
0]
[ 2
1
0]
[ 1 1/2
1]>>> D[ 1| 0| 0][--+--+--][ 0|-4| 0][--+--+--][ 0| 0| 0]>>> P.transpose()*A*P == L*D*L.transpose()
True

This two-by-two matrix has no classical factorization, but it constitutes its own block-factorization:
sage: A = matrix(QQ, [ [0,1],....:[1,0] ])
sage: A.block_ldlt(classical=True)
Traceback (most recent call last):...
ValueError: matrix has no classical LDL^T factorization
sage: A.block_ldlt()([1 0] [1 0] [0 1][0 1], [0 1], [1 0])284

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = matrix(QQ, [ [Integer(0),Integer(1)],...
[Integer(1),Integer(0)] ])>>> A.block_ldlt(classical=True)
Traceback (most recent call last):...
ValueError: matrix has no classical LDL^T factorization>>> A.block_ldlt()([1 0] [1 0] [0 1][0 1], [0 1], [1 0])

The same is true of the following complex Hermitian matrix:
sage: # needs sage.rings.number_fieldsage: A = matrix(QQbar, [ [ 0,I],....:[-I,0] ])sage: A.block_ldlt(classical=True)
Traceback (most recent call last):...
ValueError: matrix has no classical LDL^T factorization
sage: A.block_ldlt()([1 0] [1 0] [ 0 I]
[0 1], [0 1], [-I 0])>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQbar, [ [ Integer(0),I],...
[-I,Integer(0)] ])>>> A.block_ldlt(classical=True)
Traceback (most recent call last):...
ValueError: matrix has no classical LDL^T factorization>>> A.block_ldlt()([1 0] [1 0] [ 0 I]
[0 1], [0 1], [-I 0])

Complete diagonal pivoting could cause problems for the following matrix, since the diagonal entries are small
compared to the off-diagonals that must be zeroed; however, the block algorithm refuses to factor it:
sage: A = matrix(RDF, 2, 2, [ [1e-10, 1
],
....:
[1
, 2e-10] ])sage: _,L,D = A.block_ldlt(classical=True)
sage: L*D*L.T[1e-10
1.0]
[ 1.0
0.0]
sage: A.block_ldlt()
˓→needs scipy([1.0 0.0] [1.0 0.0] [1e-10
1.0][0.0 1.0], [0.0 1.0], [ 1.0 2e-10]
)

#␣

285

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = matrix(RDF, Integer(2), Integer(2), [ [RealNumber( 1e-10 ),␣
˓→Integer(1)],...
[Integer(1), RealNumber( 2e-10 )] ])>>> _,L,D = A.block_ldlt(classical=True)>>> L*D*L.T[1e-10
1.0]
[ 1.0
0.0]
>>> A.block_ldlt()
˓→needs scipy([1.0 0.0] [1.0 0.0] [1e-10
1.0][0.0 1.0], [0.0 1.0], [ 1.0 2e-10])#␣The factorization over an inexact ring is necessarily inexact, but 𝑃 𝑇 𝐴𝑃 will ideally be close to 𝐿𝐷𝐿* in themetric induced by the norm:
sage: # needs scipy sage.rings.complex_double sage.symbolic
sage: A = matrix(CDF, 2, 2, [ [-1.1933, -0.3185 - 1.3553*I],....:[-0.3185 + 1.3553*I, 1.5729 ] ])sage: P,L,D = A.block_ldlt()
sage: P.T*A*P == L*D*L.H
False
sage: (P.T*A*P - L*D*L.H).norm() < 1e-10
True>>> from sage.all import *>>> # needs scipy sage.rings.complex_double sage.symbolic>>> A = matrix(CDF, Integer(2), Integer(2), [ [-RealNumber( 1.1933 ), ˓→RealNumber( 0.3185 ) - RealNumber( 1.3553 )*I],...
[-RealNumber( 0.3185 ) + RealNumber( 1.3553 )*I,␣
˓→RealNumber( 1.5729 ) ] ])>>> P,L,D = A.block_ldlt()>>> P.T*A*P == L*D*L.H
False>>> (P.T*A*P - L*D*L.H).norm() < RealNumber( 1e-10 )TrueThis matrix has a singular three-by-three leading principal submatrix, and therefore has no classical factorization:
sage: A = matrix(QQ, [[21, 15, 12, -2],....:
[15, 12, 9, 6],....:[12, 9, 7, 3],....:[-2, 6, 3, 8]])sage: A[0:3,0:3].det() == 0
True
sage: A.block_ldlt(classical=True)
Traceback (most recent call last):...
ValueError: matrix has no classical LDL^T factorization
sage: A.block_ldlt()([1 0 0 0] [10
0
0]
[0 0 1 0] [ -2/21
10
0][0 0 0 1] [5/7 39/41
10](continues on next page)

286

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 1 0 0], [4/7 87/164

48/79

1],

[
21|
0|
0|
0]
[-------+-------+-------+-------][
0| 164/21|
0|0][-------+-------+-------+-------][
0|0|-237/41|
0][-------+-------+-------+-------][
0|0|
0| 25/316])>>> from sage.all import *>>> A = matrix(QQ, [[Integer(21), Integer(15), Integer(12), -Integer(2)],...
[Integer(15), Integer(12), Integer(9), Integer(6)],...
[Integer(12), Integer(9), Integer(7), Integer(3)],...
[-Integer(2), Integer(6), Integer(3), Integer(8)]])>>> A[Integer(0):Integer(3),Integer(0):Integer(3)].det() == Integer(0)True>>> A.block_ldlt(classical=True)
Traceback (most recent call last):...
ValueError: matrix has no classical LDL^T factorization>>> A.block_ldlt()([1 0 0 0] [10
0
0]
[0 0 1 0] [ -2/21
10
0][0 0 0 1] [5/7 39/41
1
0][0 1 0 0], [4/7 87/164 48/79
1],<BLANKLINE>
[
21|
0|
0|
0]
[-------+-------+-------+-------][
0| 164/21|
0|0][-------+-------+-------+-------][
0|0|-237/41|
0][-------+-------+-------+-------][
0|0|
0| 25/316])

An indefinite symmetric matrix that happens to have a classical factorization:
sage: A = matrix(QQ, [[ 3, -6,
9,
6, -9],....:[-6, 11, -16, -11, 17],....:
[ 9, -16, 28, 16, -40],....:[ 6, -11, 16,
9, -19],....:[-9, 17, -40, -19, 68]])
sage: A.block_ldlt(classical=True)[1:]([ 3| 0| 0| 0| 0][--+--+--+--+--][ 0|-1| 0| 0| 0][--+--+--+--+--][ 1 0 0 0 0] [ 0| 0| 5| 0| 0][-2 1 0 0 0] [--+--+--+--+--][ 3 -2 1 0 0] [ 0| 0| 0|-2| 0][ 2 -1 0 1 0] [--+--+--+--+--][-3 1 -3 1 1], [ 0| 0| 0| 0|-1])287

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = matrix(QQ, [[ Integer(3), -Integer(6),Integer(9),Integer(6), ˓→Integer(9)],...
[-Integer(6), Integer(11), -Integer(16), -Integer(11), ␣
˓→Integer(17)],...
[ Integer(9), -Integer(16), Integer(28), Integer(16), ˓→Integer(40)],...
[ Integer(6), -Integer(11), Integer(16),Integer(9), ˓→Integer(19)],...
[-Integer(9), Integer(17), -Integer(40), -Integer(19), ␣
˓→Integer(68)]])>>> A.block_ldlt(classical=True)[Integer(1):]([ 3| 0| 0| 0| 0][--+--+--+--+--][ 0|-1| 0| 0| 0][--+--+--+--+--][ 1 0 0 0 0] [ 0| 0| 5| 0| 0][-2 1 0 0 0] [--+--+--+--+--][ 3 -2 1 0 0] [ 0| 0| 0|-2| 0][ 2 -1 0 1 0] [--+--+--+--+--][-3 1 -3 1 1], [ 0| 0| 0| 0|-1])

An indefinite Hermitian matrix that happens to have a classical factorization:
sage: F.<I> = QuadraticField(-1)˓→needs sage.rings.number_fieldsage: A = matrix(F, [[2, 4 - 2*I, 2 + 2*I],
˓→needs sage.rings.number_field....:[4 + 2*I,
8,
10*I],....:[2 - 2*I,-10*I,-3]])sage: A.block_ldlt(classical=True)[1:]˓→needs sage.rings.number_field([ 2| 0| 0][--+--+--][
100] [ 0|-2| 0][ I + 2
10] [--+--+--][ -I + 1 2*I + 1
1], [ 0| 0| 3]
)

#␣
#␣

#␣

>>> from sage.all import *>>> F = QuadraticField(-Integer(1), names=( I ,)); (I,) = F._first_ngens(1)#␣
˓→needs sage.rings.number_field>>> A = matrix(F, [[Integer(2), Integer(4) - Integer(2)*I, Integer(2) +␣˓→Integer(2)*I],# needs sage.rings.number_field...
[Integer(4) + Integer(2)*I,
Integer(8),␣˓→Integer(10)*I],...
[Integer(2) - Integer(2)*I,-Integer(10)*I,
˓→Integer(3)]])>>> A.block_ldlt(classical=True)[Integer(1):]␣˓→# needs sage.rings.number_field([ 2| 0| 0][--+--+--][
100] [ 0|-2| 0](continues on next page)

288

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ I + 2
1
[ -I + 1 2*I + 1)

0] [--+--+--]
1], [ 0| 0| 3]

characteristic_polynomial(*args, **kwds)
Synonym for self.charpoly(…).
EXAMPLES:
sage: a = matrix(QQ, 2,2, [1,2,3,4]); a
[1 2]
[3 4]
sage: a.characteristic_polynomial( T )˓→needs sage.libs.pariT^2 - 5*T - 2#␣>>> from sage.all import *>>> a = matrix(QQ, Integer(2),Integer(2), [Integer(1),Integer(2),Integer(3),˓→Integer(4)]); a
[1 2]
[3 4]
>>> a.characteristic_polynomial( T )#␣˓→needs sage.libs.pariT^2 - 5*T - 2

charpoly(var='x', algorithm=None)
Returns the characteristic polynomial of self, as a polynomial over the base ring.
ALGORITHM:
If the base ring has a method 𝑚 𝑎𝑡𝑟𝑖𝑥𝑐 ℎ𝑎𝑟𝑝𝑜𝑙𝑦, we use it.
In the generic case of matrices over a ring (commutative and with unity), there is a division-free algorithm,
which can be accessed using "df", with complexity 𝑂(𝑛4 ). Alternatively, by specifying "hessenberg",
this method computes the Hessenberg form of the matrix and then reads off the characteristic polynomial.
Moreover, for matrices over number fields, this method can use PARI’s charpoly implementation instead.
The method’s logic is as follows: If no algorithm is specified, first check if the base ring is a number field (andthen use PARI), otherwise check if the base ring is the ring of integers modulo n (in which case computethe characteristic polynomial of a lift of the matrix to the integers, and then coerce back to the base), next
check if the base ring is an exact field (and then use the Hessenberg form), or otherwise, use the generic
division-free algorithm. If an algorithm is specified explicitly, if algorithm == "hessenberg", use
the Hessenberg form, or otherwise use the generic division-free algorithm.
The result is cached.
INPUT:• var – a variable name (default: ‘x’)
• algorithm – string:– "df" – Generic 𝑂(𝑛4 ) division-free algorithm– "hessenberg" – Use the Hessenberg form of the matrix
EXAMPLES:First a matrix over Z:

289

Matrices and Spaces of Matrices, Release 10.4

sage: A = MatrixSpace(ZZ,2)( [1,2, 3,4] )sage: f = A.charpoly( x )sage: fx^2 - 5*x - 2
sage: f.parent()
Univariate Polynomial Ring in x over Integer Ringsage: f(A)
[0 0]
[0 0]
>>> from sage.all import *>>> A = MatrixSpace(ZZ,Integer(2))( [Integer(1),Integer(2),˓→Integer(4)] )>>> f = A.charpoly( x )>>> fx^2 - 5*x - 2>>> f.parent()
Univariate Polynomial Ring in x over Integer Ring>>> f(A)
[0 0]
[0 0]

An example overInteger(3),:sage: A = MatrixSpace(QQ, 3)(range(9))
sage: A.charpoly( x )˓→needs sage.libs.parix^3 - 12*x^2 - 18*x
sage: A.trace()12sage: A.determinant()0#␣>>> from sage.all import *>>> A = MatrixSpace(QQ, Integer(3))(range(Integer(9)))>>> A.charpoly( x )˓→needs sage.libs.parix^3 - 12*x^2 - 18*x>>> A.trace()
12>>> A.determinant()0#␣

We compute the characteristic polynomial of a matrix over the polynomial ring Z[𝑎]:sage: R.<a> = PolynomialRing(ZZ)
sage: M = MatrixSpace(R, 2)([a,1, a,a+1]); M[a1][a a + 1]
sage: f = M.charpoly( x ); fx^2 + (-2*a - 1)*x + a^2
sage: f.parent()
Univariate Polynomial Ring in x
over Univariate Polynomial Ring in a over Integer Ringsage: M.trace()
2*a + 1
(continues on next page)

290

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: M.determinant()a^2>>> from sage.all import *>>> R = PolynomialRing(ZZ, names=( a ,)); (a,) = R._first_ngens(1)>>> M = MatrixSpace(R, Integer(2))([a,Integer(1), a,a+Integer(1)]); M[a1][a a + 1]>>> f = M.charpoly( x ); fx^2 + (-2*a - 1)*x + a^2>>> f.parent()
Univariate Polynomial Ring in x
over Univariate Polynomial Ring in a over Integer Ring>>> M.trace()
2*a + 1>>> M.determinant()a^2

We compute the characteristic polynomial of a matrix over the multi-variate polynomial ring Z[𝑥, 𝑦]:sage: R.<x,y> = PolynomialRing(ZZ,2)
sage: A = MatrixSpace(R, 2)([x, y, x^2, y^2])
sage: f = A.charpoly( x ); fx^2 + (-y^2 - x)*x - x^2*y + x*y^2>>> from sage.all import *>>> R = PolynomialRing(ZZ,Integer(2), names=( x , y ,)); (x, y,) = R._first_
˓→ngens(2)>>> A = MatrixSpace(R, Integer(2))([x, y, x**Integer(2), y**Integer(2)])>>> f = A.charpoly( x ); fx^2 + (-y^2 - x)*x - x^2*y + x*y^2

It’s a little difficult to distinguish the variables. To fix this, we temporarily view the indeterminate as 𝑍:
sage: with localvars(f.parent(), Z ): print(f)Z^2 + (-y^2 - x)*Z - x^2*y + x*y^2>>> from sage.all import *>>> with localvars(f.parent(), Z ): print(f)Z^2 + (-y^2 - x)*Z - x^2*y + x*y^2

We could also compute f in terms of Z from the start:
sage: A.charpoly( Z )Z^2 + (-y^2 - x)*Z - x^2*y + x*y^2>>> from sage.all import *>>> A.charpoly( Z )Z^2 + (-y^2 - x)*Z - x^2*y + x*y^2

Here is an example over a number field:
sage: # needs sage.rings.number_fieldsage: x = QQ[ x ].gen()sage: K.<a> = NumberField(x^2 - 2)
(continues on next page)291

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: m = matrix(K, [[a-1, 2], [a, a+1]])
sage: m.charpoly( Z )Z^2 - 2*a*Z - 2*a + 1
sage: m.charpoly( a )(m) == 0
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> x = QQ[ x ].gen()>>> K = NumberField(x**Integer(2) - Integer(2), names=( a ,)); (a,) = K._
˓→first_ngens(1)>>> m = matrix(K, [[a-Integer(1), Integer(2)], [a, a+Integer(1)]])>>> m.charpoly( Z )Z^2 - 2*a*Z - 2*a + 1>>> m.charpoly( a )(m) == Integer(0)TrueOver integers modulo 𝑛 with composite 𝑛:sage: A = Mat(Integers(6), 3, 3)(range(9))
sage: A.charpoly()x^3>>> from sage.all import *>>> A = Mat(Integers(Integer(6)), Integer(3), Integer(3))(range(Integer(9)))>>> A.charpoly()x^3Here is an example over a general commutative ring, that is to say, as of version 4.0.2, Sage does not evenpositively determine that S in the following example is an integral domain. But the computation of thecharacteristic polynomial succeeds as follows:
sage: # needs sage.libs.singularsage: R.<a,b> = QQ[]
sage: S.<x,y> = R.quo((b^3))
sage: A = matrix(S, [[x*y^2, 2*x], [2, x^10*y]]); A[ x*y^2
2*x][
2 x^10*y]
sage: A.charpoly( T )T^2 + (-x^10*y - x*y^2)*T - 4*x>>> from sage.all import *>>> # needs sage.libs.singular>>> R = QQ[ a, b ]; (a, b,) = R._first_ngens(2)>>> S = R.quo((b**Integer(3)), names=( x , y ,)); (x, y,) = S._first_ngens(2)>>> A = matrix(S, [[x*y**Integer(2), Integer(2)*x], [Integer(2),␣
˓→x**Integer(10)*y]]); A[ x*y^2
2*x][
2 x^10*y]>>> A.charpoly( T )T^2 + (-x^10*y - x*y^2)*T - 4*xcholesky()
Returns the Cholesky decomposition of a Hermitian matrix.
INPUT:
292

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

A positive-definite matrix. Generally, the base ring for the entries of the matrix needs to be a subfield of
the algebraic numbers (QQbar). Examples include the rational numbers (QQ), some number fields, andreal algebraic numbers and the algebraic numbers themselves. Symbolic matrices can also occasionally befactored.
OUTPUT:For a matrix 𝐴 the routine returns a lower triangular matrix 𝐿 such that,
𝐴 = 𝐿𝐿*
where 𝐿* is the conjugate-transpose. If the matrix is not positive-definite (for example, if it is not Hermitian)then a ValueError results.
If possible, the output matrix will be over the fraction field of the base ring of the input matrix. If that fraction
field is missing the requisite square roots but if no imaginaries are encountered, then the algebraic-reals will
be used. Otherwise, the algebraic closure of the fraction field (typically QQbar) will be used.
ALGORITHM:First we ensure that the matrix 𝐴 is_hermitian(). Afterwards, we attempt to compute a classical block_ldlt() factorization, 𝐴 = 𝐿𝐷𝐿* , of the matrix. If that fails, then √the matrix was not
positive-definite and an error is raised. Otherwise we take the entrywise square-root 𝐷 of the diagonal
matrix 𝐷 (whose
entries
positive eigenvalues of the original matrix) to obtain the Cholesky factoriza(︁ √ )︁(︁ √are)︁the*tion 𝐴 = 𝐿 𝐷 𝐿 𝐷 . If the necessary square roots cannot be taken in the fraction field of original
base ring, then we move to either its algebraic closure or the algebraic reals, depending on whether or not
imaginary numbers are required.
EXAMPLES:This simple example has a result with entries that remain in the field of rational numbers:
sage: A = matrix(QQ, [[ 4, -2, 4, 2],....:[-2, 10, -2, -7],....:
[ 4, -2, 8, 4],....:[ 2, -7, 4, 7]])sage: A.is_symmetric()True
sage: L = A.cholesky(); L[ 2 0 0 0][-1 3 0 0]
[ 2 0 2 0]
[ 1 -2 1 1]
sage: L.parent()
Full MatrixSpace of 4 by 4 dense matrices over Rational Field
sage: L*L.transpose() == A
True>>> from sage.all import *>>> A = matrix(QQ, [[ Integer(4), -Integer(2), Integer(4), Integer(2)],...
[-Integer(2), Integer(10), -Integer(2), -Integer(7)],...
[ Integer(4), -Integer(2), Integer(8), Integer(4)],...
[ Integer(2), -Integer(7), Integer(4), Integer(7)]])>>> A.is_symmetric()
True>>> L = A.cholesky(); L[ 2 0 0 0][-1 3 0 0]
[ 2 0 2 0](continues on next page)

293

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 1 -2 1 1]>>> L.parent()
Full MatrixSpace of 4 by 4 dense matrices over Rational Field>>> L*L.transpose() == A
True

This seemingly simple example requires first moving to the rational numbers for field operations, and thensquare roots necessitate that the result has entries in the field of algebraic numbers:
sage: A = matrix(ZZ, [[ 78, -30, -37, -2],....:[-30, 102, 179, -18],....:[-37, 179, 326, -38],....:[ -2, -18, -38, 15]])
sage: A.is_symmetric()True
sage: L = A.cholesky(); L˓→needs sage.rings.number_field[
8.83176086632785?
0
0
˓→
0]
[ -3.396831102433787?
9.51112708681461?
0˓→0][ -4.189425026335004?
17.32383862241232?
2.886751345948129?
˓→0][-0.2264554068289192? -1.973397116652010? -1.649572197684645?
2.
˓→886751345948129?]
sage: L.parent()
˓→needs sage.rings.number_field
Full MatrixSpace of 4 by 4 dense matrices over Algebraic Real Field
sage: L*L.transpose() == A˓→needs sage.rings.number_field
True

#␣
␣
␣
␣

#␣

#␣

>>> from sage.all import *>>> A = matrix(ZZ, [[ Integer(78), -Integer(30), -Integer(37), -Integer(2)],...
[-Integer(30), Integer(102), Integer(179), -Integer(18)],...
[-Integer(37), Integer(179), Integer(326), -Integer(38)],...
[ -Integer(2), -Integer(18), -Integer(38), Integer(15)]])>>> A.is_symmetric()
True>>> L = A.cholesky(); L#␣˓→needs sage.rings.number_field[
8.83176086632785?
0
0
␣
˓→
0]
[ -3.396831102433787?
9.51112708681461?
0
␣
˓→
0]
[ -4.189425026335004?
17.32383862241232?
2.886751345948129?
␣˓→
0][-0.2264554068289192? -1.973397116652010? -1.649572197684645?
2.
˓→886751345948129?]>>> L.parent()#␣˓→needs sage.rings.number_field
Full MatrixSpace of 4 by 4 dense matrices over Algebraic Real Field>>> L*L.transpose() == A#␣˓→needs sage.rings.number_field
True

Some subfields of the complex numbers, such as this number field of complex numbers with rational real and294

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

imaginary parts, allow for this computation:
sage: # needs sage.rings.number_fieldsage: C.<I> = QuadraticField(-1)
sage: A = matrix(C, [[23, 17*I + 3, 24*I + 25,
21*I],....:[ -17*I + 3,
38, -69*I + 89, 7*I + 15],....:[-24*I + 25, 69*I + 89,
976, 24*I + 6],....:[-21*I, -7*I + 15, -24*I + 6,28]])
sage: A.is_hermitian()True
sage: L = A.cholesky(); L[
4.79...?
0
0 ␣
˓→
0]
[
0.62...? - 3.54...?*I
5.00...?
0 ␣
˓→
0]
[
5.21...? - 5.00...?*I
13.58...? + 10.72...?*I
24.98...? ␣˓→
0][-4.37...?*I-0.10...? - 0.85...?*I -0.21...? + 0.37...?*I 2.
˓→81...?]
sage: L.parent()
Full MatrixSpace of 4 by 4 dense matrices over Algebraic Field
sage: (L*L.conjugate_transpose() - A.change_ring(QQbar)).norm() < 10^-10
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> C = QuadraticField(-Integer(1), names=( I ,)); (I,) = C._first_ngens(1)>>> A = matrix(C, [[Integer(23), Integer(17)*I + Integer(3), ␣
˓→Integer(24)*I + Integer(25),Integer(21)*I],...
[ -Integer(17)*I + Integer(3),Integer(38), ˓→Integer(69)*I + Integer(89), Integer(7)*I + Integer(15)],...
[-Integer(24)*I + Integer(25), Integer(69)*I + Integer(89),˓→Integer(976), Integer(24)*I + Integer(6)],...
[-Integer(21)*I, -Integer(7)*I + Integer(15), ˓→Integer(24)*I + Integer(6),Integer(28)]])>>> A.is_hermitian()
True>>> L = A.cholesky(); L[
4.79...?
0
0 ␣
˓→
0]
[
0.62...? - 3.54...?*I
5.00...?
0 ␣
˓→
0]
[
5.21...? - 5.00...?*I
13.58...? + 10.72...?*I
24.98...? ␣˓→
0][-4.37...?*I-0.10...? - 0.85...?*I -0.21...? + 0.37...?*I 2.
˓→81...?]>>> L.parent()
Full MatrixSpace of 4 by 4 dense matrices over Algebraic Field>>> (L*L.conjugate_transpose() - A.change_ring(QQbar)).norm() < Integer(10)**˓→Integer(10)True

The field of algebraic numbers is an ideal setting for this computation:
sage: # needs sage.rings.number_fieldsage: A = matrix(QQbar, [[2,
4 + 2*I,
6 - 4*I],....:[ -2*I + 4,
11, 10 - 12*I],....:[ 4*I + 6, 10 + 12*I,
37]])(continues on next page)295

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: A.is_hermitian()True
sage: L = A.cholesky()
sage: L[1.414213562373095?
00][2.828427124746190? - 1.414213562373095?*I
1
0][4.242640687119285? + 2.828427124746190?*I-2*I + 2
1.732050807568878?]
sage: L.parent()
Full MatrixSpace of 3 by 3 dense matrices over Algebraic Field
sage: L*L.conjugate_transpose() == A
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQbar, [[Integer(2),Integer(4) + Integer(2)*I, ␣
˓→Integer(6) - Integer(4)*I],...
[ -Integer(2)*I + Integer(4),Integer(11),␣
˓→Integer(10) - Integer(12)*I],...
[ Integer(4)*I + Integer(6), Integer(10) +␣˓→Integer(12)*I,
Integer(37)]])>>> A.is_hermitian()
True>>> L = A.cholesky()>>> L[
1.414213562373095?
00][2.828427124746190? - 1.414213562373095?*I
1
0][4.242640687119285? + 2.828427124746190?*I-2*I + 2
1.732050807568878?]>>> L.parent()
Full MatrixSpace of 3 by 3 dense matrices over Algebraic Field>>> L*L.conjugate_transpose() == A
True

Results are cached, hence immutable. Use the copy function if you need to make a change:
sage: A = matrix(QQ, [[ 4, -2, 4, 2],....:[-2, 10, -2, -7],....:
[ 4, -2, 8, 4],....:[ 2, -7, 4, 7]])sage: L = A.cholesky()
sage: L.is_immutable()True
sage: from copy import copy
sage: LC = copy(L)sage: LC[0,0] = 1000
sage: LC
[1000
0
0
0]
[ -1
3
0
0]
[
2
0
2
0]
[
1
-2
1
1]
>>> from sage.all import *>>> A = matrix(QQ, [[ Integer(4), -Integer(2), Integer(4), Integer(2)],...
[-Integer(2), Integer(10), -Integer(2), -Integer(7)],...
[ Integer(4), -Integer(2), Integer(8), Integer(4)],...
[ Integer(2), -Integer(7), Integer(4), Integer(7)]])>>> L = A.cholesky()(continues on next page)

296

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> L.is_immutable()True>>> from copy import copy>>> LC = copy(L)>>> LC[Integer(0),Integer(0)] = Integer(1000)>>> LC
[1000
0
0
0]
[ -1
3
0
0]
[
2
0
2
0]
[
1
-2
1
1]

The base ring need not be exact, although you should expect the result to be inexact (correct only in the norm)
as well in that case:sage: F = RealField(100)sage: A = A = matrix(F, [[1.0, 2.0], [2.0, 6.0]])
sage: L = A.cholesky(); L[ 1.000... 0.000...][ 2.000... 1.414...]sage: (L*L.transpose() - A).norm() < 1e-10
˓→needs scipy
True

#␣

>>> from sage.all import *>>> F = RealField(Integer(100))>>> A = A = matrix(F, [[RealNumber( 1.0 ), RealNumber( 2.0 )], [RealNumber( 2.
˓→0 ), RealNumber( 6.0 )]])>>> L = A.cholesky(); L[ 1.000... 0.000...][ 2.000... 1.414...]>>> (L*L.transpose() - A).norm() < RealNumber( 1e-10 )␣˓→# needs scipy
True

Even symbolic matrices can sometimes be factored:sage: A = matrix(SR, [[pi,0], [0,pi]])˓→needs sage.symbolic
sage: A.cholesky()˓→needs sage.symbolic[sqrt(pi)0][0 sqrt(pi)]>>> from sage.all import *>>> A = matrix(SR, [[pi,Integer(0)], [Integer(0),pi]])˓→# needs sage.symbolic>>> A.cholesky()˓→needs sage.symbolic[sqrt(pi)0][0 sqrt(pi)]

#␣
#␣

␣
#␣

There are a variety of situations which will prevent the computation of a Cholesky decomposition.
The base ring may not be able to be viewed as a subset of the complex numbers, implying that “Hermitian”
is meaningless:297

Matrices and Spaces of Matrices, Release 10.4

sage: A = matrix(Integers(6), [[2, 0], [0, 4]])sage: A.cholesky()Traceback (most recent call last):...
AttributeError: sage.rings.finite_rings.integer_mod.IntegerMod_int
object has no attribute conjugate>>> from sage.all import *>>> A = matrix(Integers(Integer(6)), [[Integer(2), Integer(0)], [Integer(0),␣
˓→Integer(4)]])>>> A.cholesky()Traceback (most recent call last):...
AttributeError: sage.rings.finite_rings.integer_mod.IntegerMod_int
object has no attribute conjugate

The matrix may not be Hermitian:sage: F.<a> = FiniteField(5^4)˓→needs sage.rings.finite_rings
sage: A = matrix(F, [[2+a^3, 3], [3, 3]])
˓→needs sage.rings.finite_rings
sage: A.cholesky()˓→needs sage.rings.finite_rings
Traceback (most recent call last):...
ValueError: matrix is not Hermitian

#␣
#␣
#␣

>>> from sage.all import *>>> F = FiniteField(Integer(5)**Integer(4), names=( a ,)); (a,) = F._first_
˓→ngens(1)# needs sage.rings.finite_rings>>> A = matrix(F, [[Integer(2)+a**Integer(3), Integer(3)], [Integer(3),␣
˓→Integer(3)]])# needs sage.rings.finite_
˓→rings>>> A.cholesky()#␣˓→needs sage.rings.finite_rings
Traceback (most recent call last):...
ValueError: matrix is not Hermitian

The matrix may not be positive-definite:sage: # needs sage.rings.number_fieldsage: C.<I> = QuadraticField(-1)
sage: B = matrix(C, [[2, 4 - 2*I, 2 + 2*I],....:[4 + 2*I,
8,
10*I],....:[2 - 2*I,-10*I,-3]])sage: B.is_positive_definite()
False
sage: B.cholesky()Traceback (most recent call last):...
ValueError: matrix is not positive definite>>> from sage.all import *>>> # needs sage.rings.number_field(continues on next page)

298

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> C = QuadraticField(-Integer(1), names=( I ,)); (I,) = C._first_ngens(1)>>> B = matrix(C, [[Integer(2), Integer(4) - Integer(2)*I, Integer(2) +␣˓→Integer(2)*I],...
[Integer(4) + Integer(2)*I,
Integer(8),␣˓→Integer(10)*I],...
[Integer(2) - Integer(2)*I,-Integer(10)*I,
˓→Integer(3)]])>>> B.is_positive_definite()
False>>> B.cholesky()Traceback (most recent call last):...
ValueError: matrix is not positive definite
sage: A = matrix(QQ, [[21, 15, 12, -3],....:
[15, 12, 9, 12],....:
[12, 9, 7, 3],....:[-3, 12, 3, 8]])sage: A.is_positive_definite()
False
sage: A.cholesky()Traceback (most recent call last):...
ValueError: matrix is not positive definite>>> from sage.all import *>>> A = matrix(QQ, [[Integer(21), Integer(15), Integer(12), -Integer(3)],...
[Integer(15), Integer(12), Integer(9), Integer(12)],...
[Integer(12), Integer(9), Integer(7), Integer(3)],...
[-Integer(3), Integer(12), Integer(3), Integer(8)]])>>> A.is_positive_definite()
False>>> A.cholesky()Traceback (most recent call last):...
ValueError: matrix is not positive definite

column_module()
Return the free module over the base ring spanned by the columns of this matrix.
EXAMPLES:
sage: t = matrix(QQ, 3, 3, range(9)); t[0 1 2][3 4 5][6 7 8]sage: t.column_module()
Vector space of degree 3 and dimension 2 over Rational Field
Basis matrix:[ 1 0 -1]
[ 0 1 2]>>> from sage.all import *>>> t = matrix(QQ, Integer(3), Integer(3), range(Integer(9))); t[0 1 2][3 4 5](continues on next page)299

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[6 7 8]>>> t.column_module()
Vector space of degree 3 and dimension 2 over Rational Field
Basis matrix:[ 1 0 -1]
[ 0 1 2]column_space()
Return the vector space over the base ring spanned by the columns of this matrix.
EXAMPLES:
sage: M = MatrixSpace(QQ, 3, 3)
sage: A = M([1,9,-7, 4/5,4,3, 6,4,3])
sage: A.column_space()
Vector space of degree 3 and dimension 3 over Rational Field
Basis matrix:[1 0 0][0 1 0][0 0 1]
sage: # needs sage.rings.real_mpfr sage.symbolic
sage: W = MatrixSpace(CC, 2, 2)
sage: B = W([1, 2 + 3*I, 4 + 5*I, 9]); B[
1.00000000000000 2.00000000000000 + 3.00000000000000*I][4.00000000000000 + 5.00000000000000*I
9.00000000000000]
sage: B.column_space()
Vector space of degree 2 and dimension 2over Complex Field with 53 bits of precision
Basis matrix:[ 1.00000000000000 0.000000000000000][0.000000000000000 1.00000000000000]>>> from sage.all import *>>> M = MatrixSpace(QQ, Integer(3), Integer(3))>>> A = M([Integer(1),Integer(9),-Integer(7), Integer(4)/Integer(5),˓→Integer(4),Integer(3), Integer(6),Integer(4),Integer(3)])>>> A.column_space()
Vector space of degree 3 and dimension 3 over Rational Field
Basis matrix:[1 0 0][0 1 0][0 0 1]>>> # needs sage.rings.real_mpfr sage.symbolic>>> W = MatrixSpace(CC, Integer(2), Integer(2))>>> B = W([Integer(1), Integer(2) + Integer(3)*I, Integer(4) + Integer(5)*I,␣
˓→Integer(9)]); B[
1.00000000000000 2.00000000000000 + 3.00000000000000*I][4.00000000000000 + 5.00000000000000*I
9.00000000000000]>>> B.column_space()
Vector space of degree 2 and dimension 2over Complex Field with 53 bits of precision
Basis matrix:[ 1.00000000000000 0.000000000000000][0.000000000000000 1.00000000000000]

300

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

conjugate()
Return the conjugate of self, i.e. the matrix whose entries are the conjugates of the entries of self.
EXAMPLES:
sage: # needs sage.rings.complex_double sage.symbolic
sage: A = matrix(CDF, [[1+I,1],[0,2*I]])sage: A.conjugate()[1.0 - 1.0*I
1.0]
[
0.0
-2.0*I]>>> from sage.all import *>>> # needs sage.rings.complex_double sage.symbolic>>> A = matrix(CDF, [[Integer(1)+I,Integer(1)],[Integer(0),Integer(2)*I]])>>> A.conjugate()[1.0 - 1.0*I
1.0]
[
0.0
-2.0*I]

A matrix over a not-totally-real number field:
sage: x = polygen(ZZ, x )sage: K.<j> = NumberField(x^2 + 5)
˓→needs sage.rings.number_fieldsage: M = matrix(K, [[1+j,1], [0,2*j]])˓→needs sage.rings.number_fieldsage: M.conjugate()
˓→needs sage.rings.number_field[-j + 1
1]
[
0
-2*j]

#␣
#␣
#␣

>>> from sage.all import *>>> x = polygen(ZZ, x )>>> K = NumberField(x**Integer(2) + Integer(5), names=( j ,)); (j,) = K._
˓→first_ngens(1)# needs sage.rings.number_field>>> M = matrix(K, [[Integer(1)+j,Integer(1)], [Integer(0),Integer(2)*j]])␣˓→# needs sage.rings.number_field>>> M.conjugate()#␣˓→needs sage.rings.number_field[-j + 1
1]
[
0
-2*j]

There is a shortcut for the conjugate:
sage: M.C
˓→needs sage.rings.number_field[-j + 1
1]
[
0
-2*j]
>>> from sage.all import *>>> M.C
˓→needs sage.rings.number_field[-j + 1
1]
[
0
-2*j]

#␣

#␣

There is also a shortcut for the conjugate transpose, or “Hermitian transpose”:

301

Matrices and Spaces of Matrices, Release 10.4

sage: M.H
˓→needs sage.rings.number_field[-j + 1
0]
[
1
-2*j]

#␣

>>> from sage.all import *>>> M.H
˓→needs sage.rings.number_field[-j + 1
0]
[
1
-2*j]

#␣

Conjugates work (trivially) for matrices over rings that embed canonically into the real numbers:
sage: M = random_matrix(ZZ, 2)
sage: M == M.conjugate()Truesage: M = random_matrix(QQ, 3)
sage: M == M.conjugate()Truesage: M = random_matrix(RR, 2)
sage: M == M.conjugate()
True>>> from sage.all import *>>> M = random_matrix(ZZ, Integer(2))>>> M == M.conjugate()
True>>> M = random_matrix(QQ, Integer(3))>>> M == M.conjugate()
True>>> M = random_matrix(RR, Integer(2))>>> M == M.conjugate()
True

conjugate_transpose()
Return the transpose of self after each entry has been converted to its complex conjugate.
Note: This function is sometimes known as the “adjoint” of a matrix, though there is substantial variationand some confusion with the use of that term.
OUTPUT:
A matrix formed by taking the complex conjugate of every entry of self and then transposing the resulting
matrix.
Complex conjugation is implemented for many subfields of the complex numbers. See the examples below,
or more at conjugate().
EXAMPLES:
sage: M = matrix(SR, 2, 2, [[2-I, 3+4*I], [9-6*I, 5*I]])˓→needs sage.symbolic
sage: M.base_ring()
˓→needs sage.symbolic
Symbolic Ring#␣#␣(continues on next page)302

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: M.conjugate_transpose()
˓→needs sage.symbolic[I + 2 6*I + 9][-4*I + 3
-5*I]

#␣

sage: # needs sage.rings.real_mpfr sage.symbolic
sage: P = matrix(CC, 3, 2, [0.95-0.63*I, 0.84+0.13*I,....:
0.94+0.23*I, 0.23+0.59*I,....:
0.52-0.41*I, -0.50+0.90*I])
sage: P.base_ring()
Complex Field with 53 bits of precision
sage: P.conjugate_transpose()[ 0.950... + 0.630...*I 0.940... - 0.230...*I 0.520... + 0.410...*I][ 0.840... - 0.130...*I 0.230... - 0.590...*I -0.500... - 0.900...*I]>>> from sage.all import *>>> M = matrix(SR, Integer(2), Integer(2), [[Integer(2)-I,␣
˓→Integer(3)+Integer(4)*I], [Integer(9)-Integer(6)*I, Integer(5)*I]])˓→# needs sage.symbolic>>> M.base_ring()
˓→needs sage.symbolic
Symbolic Ring>>> M.conjugate_transpose()
˓→needs sage.symbolic[I + 2 6*I + 9][-4*I + 3
-5*I]

␣
#␣

#␣

>>> # needs sage.rings.real_mpfr sage.symbolic>>> P = matrix(CC, Integer(3), Integer(2), [RealNumber( 0.95 )-RealNumber( 0.
˓→63 )*I, RealNumber( 0.84 )+RealNumber( 0.13 )*I,...
RealNumber( 0.94 )+RealNumber( 0.23 )*I, RealNumber(
˓→ 0.23 )+RealNumber( 0.59 )*I,...
RealNumber( 0.52 )-RealNumber( 0.41 )*I, ˓→RealNumber( 0.50 )+RealNumber( 0.90 )*I])>>> P.base_ring()
Complex Field with 53 bits of precision>>> P.conjugate_transpose()[ 0.950... + 0.630...*I 0.940... - 0.230...*I 0.520... + 0.410...*I][ 0.840... - 0.130...*I 0.230... - 0.590...*I -0.500... - 0.900...*I]

There is also a shortcut for the conjugate transpose, or “Hermitian transpose”:
sage: M.H
˓→needs sage.symbolic[I + 2 6*I + 9][-4*I + 3
-5*I]>>> from sage.all import *>>> M.H
˓→needs sage.symbolic[I + 2 6*I + 9][-4*I + 3
-5*I]

#␣

#␣

Matrices over base rings that can be embedded in the real numbers will behave as expected.

303

Matrices and Spaces of Matrices, Release 10.4

sage: P = random_matrix(QQ, 3, 4)
sage: P.conjugate_transpose() == P.transpose()True>>> from sage.all import *>>> P = random_matrix(QQ, Integer(3), Integer(4))>>> P.conjugate_transpose() == P.transpose()
True

The conjugate of a matrix is formed by taking conjugates of all the entries. Some specialized subfields of thecomplex numbers are implemented in Sage and complex conjugation can be applied. (Matrices over quadratic
number fields are another class of examples.)sage: # needs sage.rings.number_fieldsage: C = CyclotomicField(5)sage: a = C.gen(); azeta5
sage: CC(a)0.309016994374947 + 0.951056516295154*I
sage: M = matrix(C, 1, 2, [a^2, a+a^3])
sage: M.conjugate_transpose()[zeta5^3][-zeta5^3 - zeta5 - 1]>>> from sage.all import *>>> # needs sage.rings.number_field>>> C = CyclotomicField(Integer(5))>>> a = C.gen(); azeta5>>> CC(a)0.309016994374947 + 0.951056516295154*I>>> M = matrix(C, Integer(1), Integer(2), [a**Integer(2), a+a**Integer(3)])>>> M.conjugate_transpose()[zeta5^3][-zeta5^3 - zeta5 - 1]

Furthermore, this method can be applied to matrices over quadratic extensions of finite fields:
sage: F.<a> = GF(9, a )˓→needs sage.rings.finite_rings
sage: N = matrix(F, 2, [0,a,-a,1]); N
˓→needs sage.rings.finite_rings
[ 0
a]
[2*a
1]
sage: N.conjugate_transpose()
˓→needs sage.rings.finite_rings[0
a + 2][2*a + 1
1]

#␣
#␣

#␣

>>> from sage.all import *>>> F = GF(Integer(9), a , names=( a ,)); (a,) = F._first_ngens(1)# needs␣
˓→sage.rings.finite_rings>>> N = matrix(F, Integer(2), [Integer(0),a,-a,Integer(1)]); N˓→# needs sage.rings.finite_rings
[ 0
a]
[2*a
1]

␣

(continues on next page)

304

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> N.conjugate_transpose()
˓→needs sage.rings.finite_rings[0
a + 2][2*a + 1
1]#␣Conjugation does not make sense over rings not containing complex numbers or finite fields which are not aquadratic extension:
sage: N = matrix(GF(5), 2, [0,1,2,3])
sage: N.conjugate_transpose()
Traceback (most recent call last):...
AttributeError: sage.rings.finite_rings.integer_mod.IntegerMod_int
has no attribute conjugate ...

object>>> from sage.all import *>>> N = matrix(GF(Integer(5)), Integer(2), [Integer(0),Integer(1),Integer(2),˓→Integer(3)])>>> N.conjugate_transpose()
Traceback (most recent call last):...
AttributeError: sage.rings.finite_rings.integer_mod.IntegerMod_int object
has no attribute conjugate ...

cyclic_subspace(v, var=None, basis='echelon')
Create a cyclic subspace for a vector, and optionally, a minimal polynomial for the iterated powers.
These subspaces are also known as Krylov subspaces. They are spanned by the vectors{𝑣, 𝐴𝑣, 𝐴2 𝑣, 𝐴3 𝑣, . . . }INPUT:• self – a square matrix with entries from a field.
• v – a vector with a degree equal to the size of the matrix and entries compatible with the entries of thematrix.
• var – (default: None); if specified as a string or a generator of a polynomial ring, then this will be
used to construct a polynomial reflecting a relation of linear dependence on the powers 𝐴𝑖 𝑣 and this willcause the polynomial to be returned along with the subspace. A generator must create polynomials withcoefficients from the same field as the matrix entries.
• basis – (default: echelon); the basis for the subspace is “echelonized” by default, but the keyword ‘iterates’ will return a subspace with a user basis equal to the largest linearly independent set{𝑣, 𝐴𝑣, 𝐴2 𝑣, 𝐴3 𝑣, . . . , 𝐴𝑘−1 𝑣}.
OUTPUT:
Suppose 𝑘 is the smallest power such that {𝑣, 𝐴𝑣, 𝐴2 𝑣, 𝐴3 𝑣, . . . , 𝐴𝑘 𝑣} is linearly dependent. Then thesubspace returned will have dimension 𝑘 and be spanned by the powers 0 through 𝑘 − 1.
If a polynomial is requested through the use of the var keyword, then a pair is returned, with the polynomial
first and the subspace second. The polynomial is the unique monic polynomial whose coefficients provide a
relation of linear dependence on the first 𝑘 powers.
For less convenient, but more flexible output, see the helper method “_cyclic_subspace” in this module.
EXAMPLES:305

Matrices and Spaces of Matrices, Release 10.4

sage: A = matrix(QQ, [[5,4,2,1],[0,1,-1,-1],[-1,-1,3,0],[1,1,-1,2]])
sage: v = vector(QQ, [0,1,0,0])
sage: E = A.cyclic_subspace(v); E
Vector space of degree 4 and dimension 3 over Rational Field
Basis matrix:[ 1 0 0 0]
[ 0 1 0 0]
[ 0 0 1 -1]
sage: F = A.cyclic_subspace(v, basis= iterates ); F
Vector space of degree 4 and dimension 3 over Rational Field
User basis matrix:[ 0 1 0 0]
[ 4 1 -1 1][23 1 -8 8]sage: E == F
True
sage: p, S = A.cyclic_subspace(v, var= T ); p
T^3 - 9*T^2 + 24*T - 16sage: p.degree() == E.dimension()
True>>> from sage.all import *>>> A = matrix(QQ, [[Integer(5),Integer(4),Integer(2),Integer(1)],[Integer(0),˓→Integer(1),-Integer(1),-Integer(1)],[-Integer(1),-Integer(1),Integer(3),˓→Integer(0)],[Integer(1),Integer(1),-Integer(1),Integer(2)]])>>> v = vector(QQ, [Integer(0),Integer(1),Integer(0),Integer(0)])>>> E = A.cyclic_subspace(v); E
Vector space of degree 4 and dimension 3 over Rational Field
Basis matrix:[ 1 0 0 0]
[ 0 1 0 0]
[ 0 0 1 -1]>>> F = A.cyclic_subspace(v, basis= iterates ); F
Vector space of degree 4 and dimension 3 over Rational Field
User basis matrix:[ 0 1 0 0]
[ 4 1 -1 1][23 1 -8 8]>>> E == F
True>>> p, S = A.cyclic_subspace(v, var= T ); p
T^3 - 9*T^2 + 24*T - 16>>> p.degree() == E.dimension()
True

The polynomial has coefficients that yield a non-trivial relation of linear dependence on the iterates. Or,
equivalently, evaluating the polynomial with the matrix will create a matrix that annihilates the vector.
sage: A = matrix(QQ, [[15, 37/3, -16, -104/3, -29, -7/3, 35, 2/3, -29/3, -1/
˓→3],
....:
[ 2, 9, -1, -6, -6, 0, 7, 0, -2, 0],....:[24, 74/3, -29, -208/3, -58, -14/3, 70, 4/3, -58/3, -2/
˓→3],
....:
[-6, -19, 3, 21, 19, 0, -21, 0, 6, 0],....:[2, 6, -1, -6, -3, 0, 7, 0, -2, 0],....:[-96, -296/3, 128, 832/3, 232, 65/3, -279, -16/3, 232/3,
˓→ 8/3],(continues on next page)

306

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)....:[0, 0, 0, 0, 0, 0, 3, 0, 0, 0],....:[20, 26/3, -30, -199/3, -42, -14/3, 70, 13/3, -55/3, -2/
˓→3],
....:
[18, 57, -9, -54, -57, 0, 63, 0, -15, 0],....:[0, 0, 0, 0, 0, 0, 0, 0, 0, 3]])sage: u = zero_vector(QQ, 10); u[0] = 1
sage: p, S = A.cyclic_subspace(u, var= t , basis= iterates )sage: S
Vector space of degree 10 and dimension 3 over Rational Field
User basis matrix:
[
1
0
0
0
0
0
0
0
0
0]
[ 15
2
24
-6
2 -96
0
20
18
0]
[ 79
12 140 -36
12 -560
0 116 1080]
sage: pt^3 - 9*t^2 + 27*t - 27sage: k = p.degree()sage: coeffs = p.list()
sage: iterates = S.basis() + [A^k*u]
sage: sum(coeffs[i]*iterates[i] for i in range(k+1))(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
sage: u in p(A).right_kernel()True>>> from sage.all import *>>> A = matrix(QQ, [[Integer(15), Integer(37)/Integer(3), -Integer(16), ˓→Integer(104)/Integer(3), -Integer(29), -Integer(7)/Integer(3), Integer(35),␣
˓→Integer(2)/Integer(3), -Integer(29)/Integer(3), -Integer(1)/Integer(3)],...
[ Integer(2), Integer(9), -Integer(1), -Integer(6), ˓→Integer(6), Integer(0), Integer(7), Integer(0), -Integer(2), Integer(0)],...
[Integer(24), Integer(74)/Integer(3), -Integer(29), ˓→Integer(208)/Integer(3), -Integer(58), -Integer(14)/Integer(3), Integer(70),
˓→ Integer(4)/Integer(3), -Integer(58)/Integer(3), -Integer(2)/Integer(3)],...
[-Integer(6), -Integer(19), Integer(3), Integer(21),␣
˓→Integer(19), Integer(0), -Integer(21), Integer(0), Integer(6), Integer(0)],...
[Integer(2), Integer(6), -Integer(1), -Integer(6), ˓→Integer(3), Integer(0), Integer(7), Integer(0), -Integer(2), Integer(0)],...
[-Integer(96), -Integer(296)/Integer(3), Integer(128),␣
˓→Integer(832)/Integer(3), Integer(232), Integer(65)/Integer(3), ˓→Integer(279), -Integer(16)/Integer(3), Integer(232)/Integer(3), Integer(8)/˓→Integer(3)],...
[Integer(0), Integer(0), Integer(0), Integer(0),␣
˓→Integer(0), Integer(0), Integer(3), Integer(0), Integer(0), Integer(0)],...
[Integer(20), Integer(26)/Integer(3), -Integer(30), ˓→Integer(199)/Integer(3), -Integer(42), -Integer(14)/Integer(3), Integer(70),
˓→ Integer(13)/Integer(3), -Integer(55)/Integer(3), -Integer(2)/Integer(3)],...
[Integer(18), Integer(57), -Integer(9), -Integer(54), ˓→Integer(57), Integer(0), Integer(63), Integer(0), -Integer(15), Integer(0)],...
[Integer(0), Integer(0), Integer(0), Integer(0),␣
˓→Integer(0), Integer(0), Integer(0), Integer(0), Integer(0), Integer(3)]])>>> u = zero_vector(QQ, Integer(10)); u[Integer(0)] = Integer(1)>>> p, S = A.cyclic_subspace(u, var= t , basis= iterates )>>> SVector space of degree 10 and dimension 3 over Rational Field
User basis matrix:
[
1
0
0
0
0
0
0
0
0
0]
[ 15
2
24
-6
2 -96
0
20
18
0]
(continues on next page)307

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 79
12 140 -36
12 -560
0 116 1080]>>> p
t^3 - 9*t^2 + 27*t - 27>>> k = p.degree()>>> coeffs = p.list()>>> iterates = S.basis() + [A**k*u]>>> sum(coeffs[i]*iterates[i] for i in range(k+Integer(1)))(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)>>> u in p(A).right_kernel()Truedecomposition(algorithm='spin', is_diagonalizable=False, dual=False)
Returns the decomposition of the free module on which this matrix A acts from the right (i.e., the action is x
goes to x A), along with whether this matrix acts irreducibly on each factor. The factors are guaranteed to besorted in the same way as the corresponding factors of the characteristic polynomial.
Let A be the matrix acting from the on the vector space V of column vectors. Assume that A is square.
This function computes maximal subspaces W_1, …, W_n corresponding to Galois conjugacy classes of
eigenvalues of A. More precisely, let 𝑓 (𝑋) be the characteristic polynomial of A. This function computes thesubspace 𝑊𝑖 = 𝑘𝑒𝑟(𝑔( 𝐴)𝑛 ), where 𝑔𝑖 (𝑋) is an irreducible factor of 𝑓 (𝑋) and 𝑔𝑖 (𝑋) exactly divides 𝑓 (𝑋).
If the optional parameter is_diagonalizable is True, then we let 𝑊𝑖 = 𝑘𝑒𝑟(𝑔(𝐴)), since then we know that𝑘𝑒𝑟(𝑔(𝐴)) = 𝑘𝑒𝑟(𝑔(𝐴)𝑛 ).
INPUT:• self – a matrix• algorithm – ‘spin’ (default): algorithm involves iterating the action of self on a vector. ‘kernel’: naively
just compute 𝑘𝑒𝑟(𝑓𝑖 (𝐴)) for each factor 𝑓𝑖 .
• dual – bool (default: False): If True, also returns the corresponding decomposition of V under theaction of the transpose of A. The factors are guaranteed to correspond.
• is_diagonalizable – if the matrix is known to be diagonalizable, set this to True, which might
speed up the algorithm in some cases.
Note: If the base ring is not a field, the kernel algorithm is used.
OUTPUT:• Sequence – list of pairs (V,t), where V is a vector spaces and t is a bool, and t is True exactly when
the charpoly of self on V is irreducible.
• (optional) list – list of pairs (W,t), where W is a vector space and t is a bool, and t is True exactly when
the charpoly of the transpose of self on W is irreducible.
EXAMPLES:
sage: A = matrix(ZZ, 4, [3,4,5,6, 7,3,8,10, 14,5,6,7, 2,2,10,9])
sage: B = matrix(QQ, 6, 6, range(36))
sage: B*11
[ 0 11 22 33 44 55][ 66 77 88 99 110 121]
[132 143 154 165 176 187]
[198 209 220 231 242 253]
[264 275 286 297 308 319]
[330 341 352 363 374 385]
(continues on next page)

308

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: A.decomposition()
˓→needs sage.libs.pari[ (Ambient free module of rank 4over the principal ideal domain Integer Ring,
True) ]
sage: B.decomposition()
˓→needs sage.libs.pari[ (Vector space of degree 6 and dimension 2 over Rational Field
Basis matrix:[ 1 0 -1 -2 -3 -4][ 0 1 2 3 4 5],True),(Vector space of degree 6 and dimension 4 over Rational Field
Basis matrix:[ 1 0 0 0 -5 4][ 0 1 0 0 -4 3][ 0 0 1 0 -3 2][ 0 0 0 1 -2 1],
False) ]#␣#␣>>> from sage.all import *>>> A = matrix(ZZ, Integer(4), [Integer(3),Integer(4),Integer(5),Integer(6),␣
˓→Integer(7),Integer(3),Integer(8),Integer(10), Integer(14),Integer(5),˓→Integer(6),Integer(7), Integer(2),Integer(2),Integer(10),Integer(9)])>>> B = matrix(QQ, Integer(6), Integer(6), range(Integer(36)))>>> B*Integer(11)[ 0 11 22 33 44 55][ 66 77 88 99 110 121]
[132 143 154 165 176 187]
[198 209 220 231 242 253]
[264 275 286 297 308 319]
[330 341 352 363 374 385]>>> A.decomposition()#␣˓→needs sage.libs.pari[ (Ambient free module of rank 4over the principal ideal domain Integer Ring,
True) ]>>> B.decomposition()#␣˓→needs sage.libs.pari[ (Vector space of degree 6 and dimension 2 over Rational Field
Basis matrix:[ 1 0 -1 -2 -3 -4][ 0 1 2 3 4 5],True),(Vector space of degree 6 and dimension 4 over Rational Field
Basis matrix:[ 1 0 0 0 -5 4][ 0 1 0 0 -4 3][ 0 0 1 0 -3 2][ 0 0 0 1 -2 1],
False) ]decomposition_of_subspace(M, check_restrict=True, **kwds)
Suppose the right action of self on M leaves M invariant. Return the decomposition of M as a list of pairs(W, is_irred) where is_irred is True if the charpoly of self acting on the factor W is irreducible.
Additional inputs besides M are passed onto the decomposition command.
309

Matrices and Spaces of Matrices, Release 10.4

INPUT:• 𝑀 – A subspace of the free module self acts on.
• check_restrict – A boolean (default: True); Call restrict
with or without check.
• kwds – Keywords that will be forwarded to decomposition().
EXAMPLES:
sage: # needs sage.libs.pari
sage: t = matrix(QQ, 3, [3, 0, -2, 0, -2, 0, 0, 0, 0]); t[ 3 0 -2]
[ 0 -2 0][ 0 0 0]sage: t.fcp( X )# factored charpoly(X - 3) * X * (X + 2)
sage: v = kernel(t*(t+2)); v# an invariant subspace
Vector space of degree 3 and dimension 2 over Rational Field
Basis matrix:[0 1 0][0 0 1]
sage: D = t.decomposition_of_subspace(v); D[ (Vector space of degree 3 and dimension 1 over Rational Field
Basis matrix: [0 0 1],
True),(Vector space of degree 3 and dimension 1 over Rational Field
Basis matrix: [0 1 0],True) ]
sage: t.restrict(D[0][0])[0]sage: t.restrict(D[1][0])[-2]>>> from sage.all import *>>> # needs sage.libs.pari>>> t = matrix(QQ, Integer(3), [Integer(3), Integer(0), -Integer(2),␣
˓→Integer(0), -Integer(2), Integer(0), Integer(0), Integer(0), Integer(0)]); t[ 3 0 -2]
[ 0 -2 0][ 0 0 0]>>> t.fcp( X )# factored charpoly(X - 3) * X * (X + 2)>>> v = kernel(t*(t+Integer(2))); v# an invariant subspace
Vector space of degree 3 and dimension 2 over Rational Field
Basis matrix:[0 1 0][0 0 1]>>> D = t.decomposition_of_subspace(v); D[ (Vector space of degree 3 and dimension 1 over Rational Field
Basis matrix: [0 0 1],
True),(Vector space of degree 3 and dimension 1 over Rational Field
Basis matrix: [0 1 0],True) ]>>> t.restrict(D[Integer(0)][Integer(0)])[0]>>> t.restrict(D[Integer(1)][Integer(0)])(continues on next page)

310

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[-2]

We do a decomposition over ZZ:
sage: a = matrix(ZZ, 6, [0, 0, -2, 0, 2, 0,....:
2, -4, -2, 0, 2, 0,....:
0, 0, -2, -2, 0, 0,....:
2, 0, -2, -4, 2, -2,....:
0, 2, 0, -2, -2, 0,....:
0, 2, 0, -2, 0, 0])
sage: a.decomposition_of_subspace(ZZ^6)
˓→needs sage.libs.pari[ (Free module of degree 6 and rank 2 over Integer Ring
Echelon basis matrix:[ 1 0 1 -1 1 -1][ 0 1 0 -1 2 -1],
False),(Free module of degree 6 and rank 4 over Integer Ring
Echelon basis matrix:[ 1 0 -1 0 1 0]
[ 0 1 0 0 0 0]
[ 0 0 0 1 0 0]
[ 0 0 0 0 0 1],
False) ]>>> from sage.all import *>>> a = matrix(ZZ, Integer(6), [Integer(0), Integer(0), -Integer(2),␣
˓→Integer(0), Integer(2), Integer(0),...
Integer(2), -Integer(4), -Integer(2), Integer(0),␣
˓→Integer(2), Integer(0),...
Integer(0), Integer(0), -Integer(2), -Integer(2),␣
˓→Integer(0), Integer(0),...
Integer(2), Integer(0), -Integer(2), -Integer(4),␣
˓→Integer(2), -Integer(2),...
Integer(0), Integer(2), Integer(0), -Integer(2), ˓→Integer(2), Integer(0),...
Integer(0), Integer(2), Integer(0), -Integer(2),␣
˓→Integer(0), Integer(0)])>>> a.decomposition_of_subspace(ZZ**Integer(6))˓→# needs sage.libs.pari[ (Free module of degree 6 and rank 2 over Integer Ring
Echelon basis matrix:[ 1 0 1 -1 1 -1][ 0 1 0 -1 2 -1],
False),(Free module of degree 6 and rank 4 over Integer Ring
Echelon basis matrix:[ 1 0 -1 0 1 0]
[ 0 1 0 0 0 0]
[ 0 0 0 1 0 0]
[ 0 0 0 0 0 1],
False) ]#␣␣denominator()
Return the least common multiple of the denominators of the elements of self.
If there is no denominator function for the base field, or no LCM function for the denominators, raise a
311

Matrices and Spaces of Matrices, Release 10.4

TypeError.
EXAMPLES:
sage: A = MatrixSpace(QQ, 2)([1/2, 1/3, 1/5, 1/7])
sage: A.denominator()
210>>> from sage.all import *>>> A = MatrixSpace(QQ, Integer(2))([Integer(1)/Integer(2), Integer(1)/˓→Integer(3), Integer(1)/Integer(5), Integer(1)/Integer(7)])>>> A.denominator()
210

A trivial example:
sage: A = matrix(QQ, 0,2)
sage: A.denominator()
1>>> from sage.all import *>>> A = matrix(QQ, Integer(0),Integer(2))>>> A.denominator()
1

Denominators are not defined for real numbers:
sage: A = MatrixSpace(RealField(),2)([1,2,3,4])
sage: A.denominator()
Traceback (most recent call last):...
TypeError: denominator not defined for elements of the base ring>>> from sage.all import *>>> A = MatrixSpace(RealField(),Integer(2))([Integer(1),Integer(2),Integer(3),˓→Integer(4)])>>> A.denominator()
Traceback (most recent call last):...
TypeError: denominator not defined for elements of the base ring

We can even compute the denominator of matrix over the fraction field of Z[𝑥].
sage: K.<x> = Frac(ZZ[ x ])sage: A = MatrixSpace(K,2)([1/x, 2/(x+1), 1, 5/(x^3)])sage: A.denominator()x^4 + x^3>>> from sage.all import *>>> K = Frac(ZZ[ x ], names=( x ,)); (x,) = K._first_ngens(1)>>> A = MatrixSpace(K,Integer(2))([Integer(1)/x, Integer(2)/(x+Integer(1)),␣
˓→Integer(1), Integer(5)/(x**Integer(3))])>>> A.denominator()x^4 + x^3

Here’s an example involving a cyclotomic field:

312

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

sage: # needs sage.rings.number_fieldsage: K.<z> = CyclotomicField(3)sage: M = MatrixSpace(K, 3, sparse=True)
sage: A = M([(1+z)/3, (2+z)/3, z/3, 1, 1+z, -2, 1, 5, -1+z])
sage: print(A)[1/3*z + 1/3 1/3*z + 2/3
1/3*z]
[
1
z + 1
-2]
[
1
5
z - 1]
sage: print(A.denominator())
3>>> from sage.all import *>>> # needs sage.rings.number_field>>> K = CyclotomicField(Integer(3), names=( z ,)); (z,) = K._first_ngens(1)>>> M = MatrixSpace(K, Integer(3), sparse=True)>>> A = M([(Integer(1)+z)/Integer(3), (Integer(2)+z)/Integer(3), z/Integer(3),˓→ Integer(1), Integer(1)+z, -Integer(2), Integer(1), Integer(5), ˓→Integer(1)+z])>>> print(A)[1/3*z + 1/3 1/3*z + 2/3
1/3*z]
[
1
z + 1
-2]
[
1
5
z - 1]>>> print(A.denominator())
3

density()
Return the density of the matrix.
By density we understand the ratio of the number of nonzero positions and the self.nrows() * self.ncols(), i.e.
the number of possible nonzero positions.
EXAMPLES:First, note that the density parameter does not ensure the density of a matrix, it is only an upper bound.
sage: A = random_matrix(GF(127), 200, 200, density=0.3)
sage: A.density() <= 0.3
True>>> from sage.all import *>>> A = random_matrix(GF(Integer(127)), Integer(200), Integer(200),␣
˓→density=RealNumber( 0.3 ))>>> A.density() <= RealNumber( 0.3 )True
sage: A = matrix(QQ, 3,3, [0,1,2,3,0,0,6,7,8])
sage: A.density()
2/3>>> from sage.all import *>>> A = matrix(QQ, Integer(3),Integer(3), [Integer(0),Integer(1),Integer(2),˓→Integer(3),Integer(0),Integer(0),Integer(6),Integer(7),Integer(8)])>>> A.density()
2/3

313

Matrices and Spaces of Matrices, Release 10.4

sage: a = matrix([[],[],[],[]])
sage: a.density()0>>> from sage.all import *>>> a = matrix([[],[],[],[]])>>> a.density()0

derivative(*args)
Derivative with respect to variables supplied in args.
Multiple variables and iteration counts may be supplied; see documentation for the global derivative() function
for more details.
EXAMPLES:
sage: # needs sage.symbolic
sage: v = vector([1,x,x^2])
sage: v.derivative(x)(0, 1, 2*x)
sage: type(v.derivative(x)) == type(v)True
sage: v = vector([1,x,x^2], sparse=True)
sage: v.derivative(x)(0, 1, 2*x)
sage: type(v.derivative(x)) == type(v)True
sage: v.derivative(x,x)(0, 0, 2)>>> from sage.all import *>>> # needs sage.symbolic>>> v = vector([Integer(1),x,x**Integer(2)])>>> v.derivative(x)(0, 1, 2*x)>>> type(v.derivative(x)) == type(v)True>>> v = vector([Integer(1),x,x**Integer(2)], sparse=True)>>> v.derivative(x)(0, 1, 2*x)>>> type(v.derivative(x)) == type(v)True>>> v.derivative(x,x)(0, 0, 2)det(*args, **kwds)
Synonym for self.determinant(…).
EXAMPLES:
sage: A = MatrixSpace(Integers(8), 3)([1,7,3, 1,1,1, 3,4,5])
sage: A.det()
6>>> from sage.all import *>>> A = MatrixSpace(Integers(Integer(8)), Integer(3))([Integer(1),Integer(7),(continues on next page)

314

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Integer(3), Integer(1),Integer(1),Integer(1), Integer(3),Integer(4),˓→Integer(5)])>>> A.det()
6˓→determinant(algorithm=None)
Return the determinant of self.
ALGORITHM:
If the base ring has a method _matrix_determinant(), we call it.
Otherwise, for small matrices (n less than 4), this is computed using the naive formula. In the specific caseof matrices over the integers modulo a non-prime, the determinant of a lift is computed over the integers.
In general, the characteristic polynomial is computed either using the Hessenberg form (specified by "hessenberg") or the generic division-free algorithm (specified by "df"). When the base ring is an exact field,
the default choice is "hessenberg", otherwise it is "df". Note that for matrices over most rings, moresophisticated algorithms can be used. (Type A.determinant? to see what is done for a specific matrix
A.)
INPUT:• algorithm – string:– "df" – Generic O(n^4) division-free algorithm– "hessenberg" – Use the Hessenberg form of the matrix
EXAMPLES:
sage: A = MatrixSpace(Integers(8), 3)([1,7,3, 1,1,1, 3,4,5])
sage: A.determinant()
6
sage: A.determinant() is A.determinant()
True
sage: A[0,0] = 10
sage: A.determinant()
7>>> from sage.all import *>>> A = MatrixSpace(Integers(Integer(8)), Integer(3))([Integer(1),Integer(7),˓→Integer(3), Integer(1),Integer(1),Integer(1), Integer(3),Integer(4),˓→Integer(5)])>>> A.determinant()
6>>> A.determinant() is A.determinant()
True>>> A[Integer(0),Integer(0)] = Integer(10)>>> A.determinant()
7

We compute the determinant of the arbitrary 3x3 matrix:
sage: R = PolynomialRing(QQ, 9, x )sage: A = matrix(R, 3, R.gens())
sage: A[x0 x1 x2][x3 x4 x5](continues on next page)315

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[x6 x7 x8]
sage: A.determinant()-x2*x4*x6 + x1*x5*x6 + x2*x3*x7 - x0*x5*x7 - x1*x3*x8 + x0*x4*x8>>> from sage.all import *>>> R = PolynomialRing(QQ, Integer(9), x )>>> A = matrix(R, Integer(3), R.gens())>>> A[x0 x1 x2][x3 x4 x5][x6 x7 x8]>>> A.determinant()-x2*x4*x6 + x1*x5*x6 + x2*x3*x7 - x0*x5*x7 - x1*x3*x8 + x0*x4*x8

We create a matrix over Z[𝑥, 𝑦] and compute its determinant.
sage: R.<x,y> = PolynomialRing(IntegerRing(), 2)
sage: A = MatrixSpace(R,2)([x, y, x**2, y**2])
sage: A.determinant()-x^2*y + x*y^2>>> from sage.all import *>>> R = PolynomialRing(IntegerRing(), Integer(2), names=( x , y ,)); (x, y,)␣˓→= R._first_ngens(2)>>> A = MatrixSpace(R,Integer(2))([x, y, x**Integer(2), y**Integer(2)])>>> A.determinant()-x^2*y + x*y^2

A matrix over a non-domain:
sage: m = matrix(Integers(4), 2, [1,2,2,3])
sage: m.determinant()
3>>> from sage.all import *>>> m = matrix(Integers(Integer(4)), Integer(2), [Integer(1),Integer(2),˓→Integer(2),Integer(3)])>>> m.determinant()
3

diagonal()
Return the diagonal entries of self.
OUTPUT:
A list containing the entries of the matrix that have equal row and column indices, in order of the indices.
Behavior is not limited to square matrices.
EXAMPLES:
sage: A = matrix([[2,5], [3,7]]); A
[2 5]
[3 7]
sage: A.diagonal()[2, 7]

316

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = matrix([[Integer(2),Integer(5)], [Integer(3),Integer(7)]]); A
[2 5]
[3 7]
>>> A.diagonal()[2, 7]

Two rectangular matrices.
sage: B = matrix(3, 7, range(21)); B[ 0 1 2 3 4 5 6]
[ 7 8 9 10 11 12 13][14 15 16 17 18 19 20]
sage: B.diagonal()[0, 8, 16]
sage: C = matrix(3, 2, range(6)); C
[0 1]
[2 3]
[4 5]
sage: C.diagonal()[0, 3]>>> from sage.all import *>>> B = matrix(Integer(3), Integer(7), range(Integer(21))); B[ 0 1 2 3 4 5 6]
[ 7 8 9 10 11 12 13][14 15 16 17 18 19 20]>>> B.diagonal()[0, 8, 16]>>> C = matrix(Integer(3), Integer(2), range(Integer(6))); C
[0 1]
[2 3]
[4 5]
>>> C.diagonal()[0, 3]

Empty matrices behave properly.
sage: E = matrix(0, 5, []); E[]
sage: E.diagonal()[]>>> from sage.all import *>>> E = matrix(Integer(0), Integer(5), []); E[]>>> E.diagonal()[]

diagonalization(base_field=None)
Return a diagonal matrix similar to self along with the transformation matrix.
INPUT:• base_field – if given, self is regarded as a matrix over it

317

Matrices and Spaces of Matrices, Release 10.4

OUTPUT: a diagonal matrix 𝐷 and an invertible matrix 𝑃 such that 𝑃 −1 𝐴𝑃 = 𝐷, if self is a diagonalizable matrix 𝐴.
EXAMPLES:
sage: # needs sage.libs.pari
sage: A = matrix(QQ, 4, [-4, 6, 3, 3, -3, 5, 3, 3, 3, -6, -4, -3, -3, 6, 3,␣˓→2])
sage: A[-4 6 3 3][-3 5 3 3]
[ 3 -6 -4 -3][-3 6 3 2]
sage: A.is_diagonalizable()True
sage: A.diagonalization()([ 2 0 0 0] [ 1 1 0 0]
[ 0 -1 0 0] [ 1 0 1 0]
[ 0 0 -1 0] [-1 0 0 1]
[ 0 0 0 -1], [ 1 1 -2 -1])
sage: D, P = A.diagonalization()sage: P^-1*A*P == D
True
sage: # needs sage.libs.pari
sage: A = matrix(QQ, 2, [0, 2, 1, 0])
sage: A.is_diagonalizable()False
sage: A.is_diagonalizable(QQbar)
˓→needs sage.rings.number_fieldTrue
sage: D, P = A.diagonalization(QQbar)
˓→needs sage.rings.number_fieldsage: P^-1*A*P == D˓→needs sage.rings.number_field
True

#␣

#␣
#␣

>>> from sage.all import *>>> # needs sage.libs.pari>>> A = matrix(QQ, Integer(4), [-Integer(4), Integer(6), Integer(3),␣
˓→Integer(3), -Integer(3), Integer(5), Integer(3), Integer(3), Integer(3), ˓→Integer(6), -Integer(4), -Integer(3), -Integer(3), Integer(6), Integer(3),␣
˓→Integer(2)])>>> A[-4 6 3 3][-3 5 3 3]
[ 3 -6 -4 -3][-3 6 3 2]>>> A.is_diagonalizable()
True>>> A.diagonalization()([ 2 0 0 0] [ 1 1 0 0]
[ 0 -1 0 0] [ 1 0 1 0]
[ 0 0 -1 0] [-1 0 0 1]
[ 0 0 0 -1], [ 1 1 -2 -1](continues on next page)

318

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page))>>> D, P = A.diagonalization()>>> P**-Integer(1)*A*P == D
True>>> # needs sage.libs.pari>>> A = matrix(QQ, Integer(2), [Integer(0), Integer(2), Integer(1),␣
˓→Integer(0)])>>> A.is_diagonalizable()
False>>> A.is_diagonalizable(QQbar)
˓→needs sage.rings.number_field
True>>> D, P = A.diagonalization(QQbar)
˓→needs sage.rings.number_field>>> P**-Integer(1)*A*P == D˓→# needs sage.rings.number_field
True

#␣

#␣
␣

Matrices may fail to be diagonalizable for various reasons:sage: A = matrix(QQ, 2, [1,2,3, 4,5,6]); A[1 2 3][4 5 6]sage: A.diagonalization()
Traceback (most recent call last):...
TypeError: not a square matrix
sage: B = matrix(ZZ, 2, [1, 2, 3, 4]); B
[1 2]
[3 4]
sage: B.diagonalization()
Traceback (most recent call last):...
ValueError: matrix entries must be from a fieldsage: C = matrix(RR, 2, [1., 2., 3., 4.]); C[1.00000000000000 2.00000000000000][3.00000000000000 4.00000000000000]
sage: C.diagonalization()
Traceback (most recent call last):...
ValueError: base field must be exact,
but Real Field with 53 bits of precision is not
sage: D = matrix(QQ, 2, [0, 2, 1, 0]); D
[0 2]
[1 0]
sage: D.diagonalization()
˓→needs sage.libs.pari
Traceback (most recent call last):...
ValueError: not diagonalizable over Rational Field#␣

sage: E = matrix(QQ, 2, [3, 1, 0, 3]); E[3 1](continues on next page)319

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 3]
sage: E.diagonalization()
˓→needs sage.libs.pari
Traceback (most recent call last):...
ValueError: not diagonalizablesage: E.jordan_form()
˓→needs sage.combinat sage.libs.pari
[3 1]
[0 3]

#␣

#␣

>>> from sage.all import *>>> A = matrix(QQ, Integer(2), [Integer(1),Integer(2),Integer(3), Integer(4),˓→Integer(5),Integer(6)]); A[1 2 3][4 5 6]>>> A.diagonalization()
Traceback (most recent call last):...
TypeError: not a square matrix>>> B = matrix(ZZ, Integer(2), [Integer(1), Integer(2), Integer(3),␣
˓→Integer(4)]); B
[1 2]
[3 4]
>>> B.diagonalization()
Traceback (most recent call last):...
ValueError: matrix entries must be from a field>>> C = matrix(RR, Integer(2), [RealNumber( 1. ), RealNumber( 2. ),␣˓→RealNumber( 3. ), RealNumber( 4. )]); C[1.00000000000000 2.00000000000000][3.00000000000000 4.00000000000000]>>> C.diagonalization()
Traceback (most recent call last):...
ValueError: base field must be exact,
but Real Field with 53 bits of precision is not>>> D = matrix(QQ, Integer(2), [Integer(0), Integer(2), Integer(1),␣
˓→Integer(0)]); D
[0 2]
[1 0]
>>> D.diagonalization()
˓→needs sage.libs.pari
Traceback (most recent call last):...
ValueError: not diagonalizable over Rational Field>>> E = matrix(QQ, Integer(2), [Integer(3), Integer(1), Integer(0),␣
˓→Integer(3)]); E
[3 1]
[0 3]
>>> E.diagonalization()
˓→needs sage.libs.pari#␣#␣(continues on next page)

320

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Traceback (most recent call last):...
ValueError: not diagonalizable>>> E.jordan_form()
˓→needs sage.combinat sage.libs.pari
[3 1]
[0 3]

#␣

echelon_form(algorithm='default', cutoff=0, **kwds)
Return the echelon form of self.
Note: This row reduction does not use division if the matrix is not over a field (e.g., if the matrix is over the
integers). If you want to calculate the echelon form using division, then use rref(), which assumes that thematrix entries are in a field (specifically, the field of fractions of the base ring of the matrix).
INPUT:• algorithm – string. Which algorithm to use. Choices are–default : Let Sage choose an algorithm (default).

–classical : Gauss elimination.

–

partial_pivoting : Gauss elimination, using partial pivoting (if base ring has absolutevalue)–

scaled_partial_pivoting : Gauss elimination, using scaled partial pivoting (if base ringhas absolute value)–

scaled_partial_pivoting_valuation : Gauss elimination, using scaled partial pivoting (if base ring has valuation)–strassen : use a Strassen divide and conquer algorithm (if available)• cutoff – integer. Only used if the Strassen algorithm is selected.
• transformation – boolean. Whether to also return the transformation matrix. Some matrix backends do not provide this information, in which case this option is ignored.
OUTPUT:The reduced row echelon form of self, as an immutable matrix. Note that self is not changed by thiscommand. Use echelonize() to change self in place.
If the optional parameter transformation=True is specified, the output consists of a pair (𝐸, 𝑇 ) of
matrices where 𝐸 is the echelon form of self and 𝑇 is the transformation matrix.
EXAMPLES:
sage: MS = MatrixSpace(GF(19), 2, 3)
sage: C = MS.matrix([1,2,3,4,5,6])
sage: C.rank()
2sage: C.nullity()0sage: C.echelon_form()[ 1 0 18]
[ 0 1 2]321

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> MS = MatrixSpace(GF(Integer(19)), Integer(2), Integer(3))>>> C = MS.matrix([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5),˓→Integer(6)])>>> C.rank()
2>>> C.nullity()0>>> C.echelon_form()[ 1 0 18]
[ 0 1 2]The matrix library used for Z/𝑝-matrices does not return the transformation matrix, so the transformation option is ignored:sage: C.echelon_form(transformation=True)[ 1 0 18]
[ 0 1 2]sage: D = matrix(ZZ, 2, 3, [1,2,3,4,5,6])
sage: D.echelon_form(transformation=True)([1 2 3] [ 1 0]
[0 3 6], [ 4 -1])
sage: E, T = D.echelon_form(transformation=True)
sage: T*D == E
True>>> from sage.all import *>>> C.echelon_form(transformation=True)[ 1 0 18]
[ 0 1 2]>>> D = matrix(ZZ, Integer(2), Integer(3), [Integer(1),Integer(2),Integer(3),˓→Integer(4),Integer(5),Integer(6)])>>> D.echelon_form(transformation=True)([1 2 3] [ 1 0]
[0 3 6], [ 4 -1])>>> E, T = D.echelon_form(transformation=True)>>> T*D == E
Trueechelonize(algorithm='default', cutoff=0, **kwds)
Transform self into a matrix in echelon form over the same base ring as self.
Note: This row reduction does not use division if the matrix is not over a field (e.g., if the matrix is over the
integers). If you want to calculate the echelon form using division, then use rref(), which assumes that thematrix entries are in a field (specifically, the field of fractions of the base ring of the matrix).
INPUT:• algorithm – string. Which algorithm to use. Choices are

322

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4–

default : Let Sage choose an algorithm (default).

–classical : Gauss elimination.

–

partial_pivoting : Gauss elimination, using partial pivoting (if base ring has absolutevalue)–

scaled_partial_pivoting : Gauss elimination, using scaled partial pivoting (if base ringhas absolute value)–

scaled_partial_pivoting_valuation : Gauss elimination, using scaled partial pivoting (if base ring has valuation)–strassen : use a Strassen divide and conquer algorithm (if available)• cutoff – integer. Only used if the Strassen algorithm is selected.
• transformation – boolean. Whether to also return the transformation matrix. Some matrix backends do not provide this information, in which case this option is ignored.
OUTPUT:
The matrix self is put into echelon form. Nothing is returned unless the keyword option transformation=True is specified, in which case the transformation matrix is returned.
EXAMPLES:
sage: a = matrix(QQ, 3,3, range(9)); a[0 1 2][3 4 5][6 7 8]sage: a.echelonize()
sage: a[ 1 0 -1]
[ 0 1 2][ 0 0 0]>>> from sage.all import *>>> a = matrix(QQ, Integer(3),Integer(3), range(Integer(9))); a[0 1 2][3 4 5][6 7 8]>>> a.echelonize()>>> a[ 1 0 -1]
[ 0 1 2][ 0 0 0]

An immutable matrix cannot be transformed into echelon form. Use self.echelon_form() instead:sage: a = matrix(QQ, 3,3, range(9)); a.set_immutable()sage: a.echelonize()
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).
sage: a.echelon_form()[ 1 0 -1]
[ 0 1 2][ 0 0 0]323

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> a = matrix(QQ, Integer(3),Integer(3), range(Integer(9))); a.set_
˓→immutable()>>> a.echelonize()
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).
>>> a.echelon_form()[ 1 0 -1]
[ 0 1 2][ 0 0 0]Echelon form over the integers is what is also classically often known as Hermite normal form:
sage: a = matrix(ZZ, 3,3, range(9))
sage: a.echelonize(); a[ 3 0 -3]
[ 0 1 2][ 0 0 0]>>> from sage.all import *>>> a = matrix(ZZ, Integer(3),Integer(3), range(Integer(9)))>>> a.echelonize(); a[ 3 0 -3]
[ 0 1 2][ 0 0 0]We compute an echelon form both over a domain and fraction field:
sage: R.<x,y> = QQ[]
sage: a = matrix(R, 2, [x,y, x,y])
sage: a.echelon_form()# not very useful? -- why two copies of␣˓→the same row?
# needs sage.rings.function_field
[x y]
[x y]
>>> from sage.all import *>>> R = QQ[ x, y ]; (x, y,) = R._first_ngens(2)>>> a = matrix(R, Integer(2), [x,y, x,y])>>> a.echelon_form()# not very useful? -- why two copies of␣˓→the same row?
# needs sage.rings.function_field
[x y]
[x y]
sage: b = a.change_ring(R.fraction_field())
sage: b.echelon_form()# potentially useful[ 1 y/x][ 00]>>> from sage.all import *>>> b = a.change_ring(R.fraction_field())>>> b.echelon_form()# potentially useful[ 1 y/x][ 0
0]

We check that the echelon form works for matrices over p-adics. See Issue #17272:
324

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

sage: # needs sage.rings.padics
sage: R = ZpCA(5,5,print_mode= val-unit )sage: A = matrix(R, 3,3, [250,2369,1147, 106,927,362, 90,398,2483])
sage: A
[5^3 * 2 + O(5^5)
2369 + O(5^5)
1147 + O(5^5)][
106 + O(5^5)
927 + O(5^5)
362 + O(5^5)][ 5 * 18 + O(5^5)
398 + O(5^5)
2483 + O(5^5)]sage: K = R.fraction_field()sage: A.change_ring(K).augment(identity_matrix(K,3)).echelon_form()[
1 + O(5^5)
O(5^5)
O(5^5) 5 * 212 + O(5^5)
3031␣
˓→+ O(5^5)
2201 + O(5^5)][O(5^5)
1 + O(5^5)
O(5^5)
1348 + O(5^5) 5 * 306␣˓→+ O(5^5)
2648 + O(5^5)][O(5^5)
O(5^5)
1 + O(5^5)
1987 + O(5^5) 5 * 263␣˓→+ O(5^5)
154 + O(5^5)]>>> from sage.all import *>>> # needs sage.rings.padics>>> R = ZpCA(Integer(5),Integer(5),print_mode= val-unit )>>> A = matrix(R, Integer(3),Integer(3), [Integer(250),Integer(2369),
˓→Integer(1147), Integer(106),Integer(927),Integer(362), Integer(90),
˓→Integer(398),Integer(2483)])>>> A[5^3 * 2 + O(5^5)
2369 + O(5^5)
1147 + O(5^5)][
106 + O(5^5)
927 + O(5^5)
362 + O(5^5)][ 5 * 18 + O(5^5)
398 + O(5^5)
2483 + O(5^5)]>>> K = R.fraction_field()>>> A.change_ring(K).augment(identity_matrix(K,Integer(3))).echelon_form()[
1 + O(5^5)
O(5^5)
O(5^5) 5 * 212 + O(5^5)
3031␣
˓→+ O(5^5)
2201 + O(5^5)][O(5^5)
1 + O(5^5)
O(5^5)
1348 + O(5^5) 5 * 306␣˓→+ O(5^5)
2648 + O(5^5)][O(5^5)
O(5^5)
1 + O(5^5)
1987 + O(5^5) 5 * 263␣˓→+ O(5^5)
154 + O(5^5)]Echelon form is not defined over arbitrary rings:
sage: a = matrix(Integers(9), 3,3, range(9))
sage: a.echelon_form()
Traceback (most recent call last):...
NotImplementedError: Echelon form not implemented over˓→modulo 9 .

Ring of integers␣

>>> from sage.all import *>>> a = matrix(Integers(Integer(9)), Integer(3),Integer(3), range(Integer(9)))>>> a.echelon_form()
Traceback (most recent call last):...
NotImplementedError: Echelon form not implemented over Ring of integers␣
˓→modulo 9 .

Involving a sparse matrix:
sage: m = matrix(3,[1, 1, 1, 1, 0, 2, 1, 2, 0], sparse=True); m[1 1 1][1 0 2](continues on next page)325

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[1 2 0]sage: m.echelon_form()[ 1 0 2][ 0 1 -1]
[ 0 0 0]sage: m.echelonize(); m[ 1 0 2][ 0 1 -1]
[ 0 0 0]>>> from sage.all import *>>> m = matrix(Integer(3),[Integer(1), Integer(1), Integer(1), Integer(1),␣
˓→Integer(0), Integer(2), Integer(1), Integer(2), Integer(0)], sparse=True); m[1 1 1][1 0 2][1 2 0]>>> m.echelon_form()[ 1 0 2][ 0 1 -1]
[ 0 0 0]>>> m.echelonize(); m[ 1 0 2][ 0 1 -1]
[ 0 0 0]

The transformation matrix is optionally returned:
sage: m_original = m
sage: transformation_matrix = m.echelonize(transformation=True)
sage: m == transformation_matrix * m_originalTrue>>> from sage.all import *>>> m_original = m>>> transformation_matrix = m.echelonize(transformation=True)>>> m == transformation_matrix * m_original
True

eigenmatrix_left(other=None)
Return matrices 𝐷 and 𝑃 , where 𝐷 is a diagonal matrix of eigenvalues and the rows of 𝑃 are corresponding
eigenvectors (or zero vectors).
INPUT:• other – a square matrix 𝐵 (default: None) in a generalized eigenvalue problem; if None, an ordinary
eigenvalue problem is solved
OUTPUT:
If self is a square matrix 𝐴, then the output is a diagonal matrix 𝐷 and a matrix 𝑃 such that𝑃 𝐴 = 𝐷𝑃,
where the rows of 𝑃 are eigenvectors of 𝐴 and the diagonal entries of 𝐷 are the corresponding eigenvalues.
If a matrix 𝐵 is passed as optional argument, the output is a solution to the generalized eigenvalue problem
such that𝑃 𝐴 = 𝐷𝑃 𝐵.
326

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

The ordinary eigenvalue problem is equivalent to the generalized one if 𝐵 is the identity matrix.
The generalized eigenvector decomposition is currently only implemented for matrices over RDF and CDF.
EXAMPLES:
sage: # needs sage.rings.number_fieldsage: A = matrix(QQ, 3, 3, range(9)); A[0 1 2][3 4 5][6 7 8]sage: D, P = A.eigenmatrix_left()
sage: D[00
0][
0 -1.348469228349535?
0][0
0 13.34846922834954?]
sage: P[
1-2
1][
1 0.3101020514433644? -0.3797958971132713?][
1
1.289897948556636?
1.579795897113272?]
sage: P*A == D*P
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQ, Integer(3), Integer(3), range(Integer(9))); A[0 1 2][3 4 5][6 7 8]>>> D, P = A.eigenmatrix_left()
>>> D
[
0
0
0]
[
0 -1.348469228349535?
0][0
0 13.34846922834954?]
>>> P
[
1
-2
1]
[
1 0.3101020514433644? -0.3797958971132713?][
1
1.289897948556636?
1.579795897113272?]>>> P*A == D*P
True

Because 𝑃 is invertible, 𝐴 is diagonalizable.
sage: A == (~P)*D*P
˓→needs sage.rings.number_field
True>>> from sage.all import *>>> A == (~P)*D*P
˓→needs sage.rings.number_field
True

#␣

#␣

The matrix 𝑃 may contain zero rows corresponding to eigenvalues for which the algebraic multiplicity isgreater than the geometric multiplicity. In these cases, the matrix is not diagonalizable.
sage: # needs sage.rings.number_fieldsage: A = jordan_block(2, 3); A[2 1 0](continues on next page)327

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 2 1][0 0 2]sage: D, P = A.eigenmatrix_left()
sage: D
[2 0 0][0 2 0][0 0 2]sage: P[0 0 1][0 0 0][0 0 0]sage: P*A == D*P
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = jordan_block(Integer(2), Integer(3)); A[2 1 0][0 2 1][0 0 2]>>> D, P = A.eigenmatrix_left()>>> D[2 0 0][0 2 0][0 0 2]>>> P[0 0 1][0 0 0][0 0 0]>>> P*A == D*P
True

A generalized eigenvector decomposition:
sage: # needs scipy
sage: A = matrix(RDF, [[1, -2], [3, 4]])sage: B = matrix(RDF, [[0, 7], [2, -3]])
sage: D, P = A.eigenmatrix_left(B)sage: (P * A - D * P * B).norm() < 1e-14
True>>> from sage.all import *>>> # needs scipy>>> A = matrix(RDF, [[Integer(1), -Integer(2)], [Integer(3), Integer(4)]])>>> B = matrix(RDF, [[Integer(0), Integer(7)], [Integer(2), -Integer(3)]])>>> D, P = A.eigenmatrix_left(B)>>> (P * A - D * P * B).norm() < RealNumber( 1e-14 )True

The matrix 𝐵 in a generalized eigenvalue problem may be singular:
sage: # needs scipy sage.rings.complex_double sage.symbolic
sage: A = matrix.identity(CDF, 2)
sage: B = matrix(CDF, [[2, 1+I], [4, 2+2*I]])sage: D, P = A.eigenmatrix_left(B)sage: D.diagonal() # tol 1e-14(continues on next page)

328

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0.2 - 0.1*I, +infinity]>>> from sage.all import *>>> # needs scipy sage.rings.complex_double sage.symbolic>>> A = matrix.identity(CDF, Integer(2))>>> B = matrix(CDF, [[Integer(2), Integer(1)+I], [Integer(4),␣
˓→Integer(2)+Integer(2)*I]])>>> D, P = A.eigenmatrix_left(B)>>> D.diagonal() # tol 1e-14[0.2 - 0.1*I, +infinity]

In this case, we can still verify the eigenvector equation for the first eigenvalue and first eigenvector:
sage: # needs scipy sage.rings.complex_double sage.symbolic
sage: l = D[0, 0]
sage: v = P[0, :]sage: (v * A - l * v * B).norm() < 1e-14
True>>> from sage.all import *>>> # needs scipy sage.rings.complex_double sage.symbolic>>> l = D[Integer(0), Integer(0)]>>> v = P[Integer(0), :]>>> (v * A - l * v * B).norm() < RealNumber( 1e-14 )True

The second eigenvector is contained in the left kernel of 𝐵:
sage: (P[1, :] * B).norm() < 1e-14
˓→needs scipy sage.rings.complex_double sage.symbolic
True

#␣

>>> from sage.all import *>>> (P[Integer(1), :] * B).norm() < RealNumber( 1e-14 )˓→# needs scipy sage.rings.complex_double sage.symbolicTrue␣

See also:
eigenvalues(),
eigenvectors_left(),eigenvectors_left(), eigenmatrix_right().

Matrix_double_dense.

eigenmatrix_right(other=None)
Return matrices 𝐷 and 𝑃 , where 𝐷 is a diagonal matrix of eigenvalues and the columns of 𝑃 are corresponding eigenvectors (or zero vectors).
INPUT:• other – a square matrix 𝐵 (default: None) in a generalized eigenvalue problem; if None, an ordinary
eigenvalue problem is solved
OUTPUT:
If self is a square matrix 𝐴, then the output is a diagonal matrix 𝐷 and a matrix 𝑃 such that𝐴𝑃 = 𝑃 𝐷,
where the columns of 𝑃 are eigenvectors of 𝐴 and the diagonal entries of 𝐷 are the corresponding eigenvalues.
329

Matrices and Spaces of Matrices, Release 10.4

If a matrix 𝐵 is passed as optional argument, the output is a solution to the generalized eigenvalue problem
such that𝐴𝑃 = 𝐵𝑃 𝐷.
The ordinary eigenvalue problem is equivalent to the generalized one if 𝐵 is the identity matrix.
The generalized eigenvector decomposition is currently only implemented for matrices over RDF and CDF.
EXAMPLES:
sage: # needs sage.rings.number_fieldsage: A = matrix(QQ, 3, 3, range(9)); A[0 1 2][3 4 5][6 7 8]sage: D, P = A.eigenmatrix_right()
sage: D[00
0][
0 -1.348469228349535?
0][0
0 13.34846922834954?]
sage: P[1
1
1][
-2 0.1303061543300932?
3.069693845669907?][
1 -0.7393876913398137?
5.139387691339814?]
sage: A*P == P*D
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQ, Integer(3), Integer(3), range(Integer(9))); A[0 1 2][3 4 5][6 7 8]>>> D, P = A.eigenmatrix_right()
>>> D
[
0
0
0]
[
0 -1.348469228349535?
0][0
0 13.34846922834954?]
>>> P
[
1
1
1]
[
-2 0.1303061543300932?
3.069693845669907?][
1 -0.7393876913398137?
5.139387691339814?]>>> A*P == P*D
True

Because 𝑃 is invertible, 𝐴 is diagonalizable.
sage: A == P*D*(~P)˓→needs sage.rings.number_field
True>>> from sage.all import *>>> A == P*D*(~P)˓→needs sage.rings.number_field
True

#␣

#␣

The matrix 𝑃 may contain zero columns corresponding to eigenvalues for which the algebraic multiplicity isgreater than the geometric multiplicity. In these cases, the matrix is not diagonalizable.
330

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

sage: # needs sage.rings.number_fieldsage: A = jordan_block(2, 3); A[2 1 0][0 2 1][0 0 2]sage: D, P = A.eigenmatrix_right()
sage: D
[2 0 0][0 2 0][0 0 2]sage: P
[1 0 0][0 0 0][0 0 0]sage: A*P == P*D
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = jordan_block(Integer(2), Integer(3)); A[2 1 0][0 2 1][0 0 2]>>> D, P = A.eigenmatrix_right()>>> D[2 0 0][0 2 0][0 0 2]>>> P[1 0 0][0 0 0][0 0 0]>>> A*P == P*DTrue

A generalized eigenvector decomposition:
sage: # needs scipy
sage: A = matrix(RDF, [[1, -2], [3, 4]])sage: B = matrix(RDF, [[0, 7], [2, -3]])
sage: D, P = A.eigenmatrix_right(B)sage: (A * P - B * P * D).norm() < 1e-14
True>>> from sage.all import *>>> # needs scipy>>> A = matrix(RDF, [[Integer(1), -Integer(2)], [Integer(3), Integer(4)]])>>> B = matrix(RDF, [[Integer(0), Integer(7)], [Integer(2), -Integer(3)]])>>> D, P = A.eigenmatrix_right(B)>>> (A * P - B * P * D).norm() < RealNumber( 1e-14 )True

The matrix 𝐵 in a generalized eigenvalue problem may be singular:
sage: # needs scipy
sage: A = matrix.identity(RDF, 2)
sage: B = matrix(RDF, [[3, 5], [6, 10]])(continues on next page)331

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: D, P = A.eigenmatrix_right(B); D# tol 1e-14[0.07692307692307694
0.0]
[
0.0
+infinity]>>> from sage.all import *>>> # needs scipy>>> A = matrix.identity(RDF, Integer(2))>>> B = matrix(RDF, [[Integer(3), Integer(5)], [Integer(6), Integer(10)]])>>> D, P = A.eigenmatrix_right(B); D# tol 1e-14[0.07692307692307694
0.0]
[
0.0
+infinity]

In this case, we can still verify the eigenvector equation for the first eigenvalue and first eigenvector:
sage: # needs scipy
sage: l = D[0, 0]
sage: v = P[:, 0]
sage: (A * v - B * v * l).norm() < 1e-14
True>>> from sage.all import *>>> # needs scipy>>> l = D[Integer(0), Integer(0)]>>> v = P[:, Integer(0)]>>> (A * v - B * v * l).norm() < RealNumber( 1e-14 )True

The second eigenvector is contained in the right kernel of 𝐵:
sage: (B * P[:, 1]).norm() < 1e-14
˓→needs scipy
True

#␣

>>> from sage.all import *>>> (B * P[:, Integer(1)]).norm() < RealNumber( 1e-14 )˓→# needs scipy
True␣

See also:
eigenvalues(),
eigenvectors_right(),
eigenvectors_right(), eigenmatrix_left().

Matrix_double_dense.

eigenspaces_left(format='all', var='a', algebraic_multiplicity=False)
Compute the left eigenspaces of a matrix.
Note that eigenspaces_left() and left_eigenspaces() are identical methods. Here “left”
refers to the eigenvectors being placed to the left of the matrix.
INPUT:• self – a square matrix over an exact field. For inexact matrices consult the numerical or symbolic
matrix classes.
• format – one of:–332

all – Attempts to create every eigenspace. This will always be possible for matrices with rational
entries.
Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4–

galois – For each irreducible factor of the characteristic polynomial, a single eigenspace will
be output for a single root/eigenvalue for the irreducible factor.

– None (default) – Uses the all format if the base ring is contained in an algebraically closed
field which is implemented. Otherwise, uses the galois format.
• var – string (default: a ); variable name used to represent elements of the root field of each irreducible
factor of the characteristic polynomial. If var= a , then the root fields will be in terms of a0, a1,
a2, ..., where the numbering runs across all the irreducible factors of the characteristic polynomial,
even for linear factors.
• algebraic_multiplicity – (boolean, default: False); whether to include the algebraic multiplicity of each eigenvalue in the output. See the discussion below.
OUTPUT:
If algebraic_multiplicity=False, return a list of pairs (𝑒, 𝑉 ) where 𝑒 is an eigenvalue of thematrix, and 𝑉 is the corresponding left eigenspace. For Galois conjugates of eigenvalues, there may be justone representative eigenspace, depending on the format keyword.
If algebraic_multiplicity=True, return a list of triples (𝑒, 𝑉, 𝑛) where 𝑒 and 𝑉 are as above and𝑛 is the algebraic multiplicity of the eigenvalue.
Warning: Uses a somewhat naive algorithm (simply factors the characteristic polynomial and computes
kernels directly over the extension field).
EXAMPLES:
We compute the left eigenspaces of a 3 × 3 rational matrix. First, we request all of the eigenvalues, so
the results are in the field of algebraic numbers, QQbar. Then we request just one eigenspace per irreducible
factor of the characteristic polynomial with format= galois .
sage: A = matrix(QQ, 3, 3, range(9)); A[0 1 2][3 4 5][6 7 8]sage: es = A.eigenspaces_left(format= all ); es
˓→needs sage.rings.number_field[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]),(-1.348469228349535?,
Vector space of degree 3 and dimension 1 over Algebraic Field
User basis matrix:[
1 0.3101020514433644? -0.3797958971132713?]),(13.34846922834954?,
Vector space of degree 3 and dimension 1 over Algebraic Field
User basis matrix:[
1 1.289897948556636? 1.579795897113272?]) ]#␣sage: # needs sage.rings.number_fieldsage: es = A.eigenspaces_left(format= galois ); es[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]),(a1,(continues on next page)333

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/15*a1 + 2/5 2/15*a1 - 1/5]) ]sage: es = A.eigenspaces_left(format= galois ,....:algebraic_multiplicity=True); es[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1],1),(a1,
Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/15*a1 + 2/5 2/15*a1 - 1/5],1) ]sage: e, v, n = es[0]; v = v.basis()[0]sage: delta = e*v - v*A
sage: abs(abs(delta)) < 1e-10
True>>> from sage.all import *>>> A = matrix(QQ, Integer(3), Integer(3), range(Integer(9))); A[0 1 2][3 4 5][6 7 8]>>> es = A.eigenspaces_left(format= all ); es
˓→needs sage.rings.number_field[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]),(-1.348469228349535?,
Vector space of degree 3 and dimension 1 over Algebraic Field
User basis matrix:[
1 0.3101020514433644? -0.3797958971132713?]),(13.34846922834954?,
Vector space of degree 3 and dimension 1 over Algebraic Field
User basis matrix:[
1 1.289897948556636? 1.579795897113272?]) ]#␣>>> # needs sage.rings.number_field>>> es = A.eigenspaces_left(format= galois ); es[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]),(a1,
Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/15*a1 + 2/5 2/15*a1 - 1/5]) ]>>> es = A.eigenspaces_left(format= galois ,...
algebraic_multiplicity=True); es[ (0,(continues on next page)

334

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1],1),(a1,
Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/15*a1 + 2/5 2/15*a1 - 1/5],
1) ]>>> e, v, n = es[Integer(0)]; v = v.basis()[Integer(0)]>>> delta = e*v - v*A>>> abs(abs(delta)) < RealNumber( 1e-10 )True

The same computation, but with implicit base change to a field.
sage: A = matrix(ZZ, 3, 3, range(9)); A[0 1 2][3 4 5][6 7 8]sage: A.eigenspaces_left(format= galois )˓→needs sage.rings.number_field[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]),(a1,
Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/15*a1 + 2/5 2/15*a1 - 1/5]) ]>>> from sage.all import *>>> A = matrix(ZZ, Integer(3), Integer(3), range(Integer(9))); A[0 1 2][3 4 5][6 7 8]>>> A.eigenspaces_left(format= galois )˓→needs sage.rings.number_field[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]),(a1,
Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/15*a1 + 2/5 2/15*a1 - 1/5]) ]#␣#␣We compute the left eigenspaces of the matrix of the Hecke operator 𝑇2 on level 43 modular symbols, bothwith all eigenvalues (the default) and with one subspace per factor.
sage: # needs sage.modular
sage: A = ModularSymbols(43).T(2).matrix(); A[ 3 0 0 0 0 0 -1](continues on next page)335

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 0 -2 1 0 0 0 0]
[ 0 -1 1 1 0 -1 0][ 0 -1 0 -1 2 -1 1][ 0 -1 0 1 1 -1 1][ 0 0 -2 0 2 -2 1][ 0 0 -1 0 1 0 -1]
sage: A.base_ring()
Rational Field
sage: f = A.charpoly(); fx^7 + x^6 - 12*x^5 - 16*x^4 + 36*x^3 + 52*x^2 - 32*x - 48
sage: factor(f)(x - 3) * (x + 2)^2 * (x^2 - 2)^2
sage: A.eigenspaces_left(algebraic_multiplicity=True)[ (3,Vector space of degree 7 and dimension 1 over Rational Field
User basis matrix:
[
1
0 1/7
0 -1/7
0 -2/7],1),(-2,Vector space of degree 7 and dimension 2 over Rational Field
User basis matrix:[ 0 1 0 1 -1 1 -1][ 0 0 1 0 -1 2 -1],
2),(-1.414213562373095?,
Vector space of degree 7 and dimension 2 over Algebraic Field
User basis matrix:
[
0
1
0
␣
˓→
-1 0.4142135623730951?
1
-1]
[
0
0
1
␣
˓→
0
-1
0 2.414213562373095?],2),(1.414213562373095?,
Vector space of degree 7 and dimension 2 over Algebraic Field
User basis matrix:
[
0
1
0
␣
˓→
-1 -2.414213562373095?
1
-1]
[
0
0
1
␣
˓→
0
-1
0 -0.4142135623730951?],2) ]sage: A.eigenspaces_left(format= galois , algebraic_multiplicity=True)[ (3,Vector space of degree 7 and dimension 1 over Rational Field
User basis matrix:
[
1
0 1/7
0 -1/7
0 -2/7],1),(-2,Vector space of degree 7 and dimension 2 over Rational Field
User basis matrix:[ 0 1 0 1 -1 1 -1][ 0 0 1 0 -1 2 -1],2),(a2,Vector space of degree 7 and dimension 2over Number Field in a2 with defining polynomial x^2 - 2
User basis matrix:[0
1
0-1 -a2 - 1
1-1](continues on next page)

336

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[
2) ]

0

0

1

0

-1

0 -a2 + 1],>>> from sage.all import *>>> # needs sage.modular>>> A = ModularSymbols(Integer(43)).T(Integer(2)).matrix(); A[ 3 0 0 0 0 0 -1][ 0 -2 1 0 0 0 0]
[ 0 -1 1 1 0 -1 0][ 0 -1 0 -1 2 -1 1][ 0 -1 0 1 1 -1 1][ 0 0 -2 0 2 -2 1][ 0 0 -1 0 1 0 -1]>>> A.base_ring()
Rational Field>>> f = A.charpoly(); fx^7 + x^6 - 12*x^5 - 16*x^4 + 36*x^3 + 52*x^2 - 32*x - 48>>> factor(f)(x - 3) * (x + 2)^2 * (x^2 - 2)^2>>> A.eigenspaces_left(algebraic_multiplicity=True)[ (3,Vector space of degree 7 and dimension 1 over Rational Field
User basis matrix:
[
1
0 1/7
0 -1/7
0 -2/7],1),(-2,Vector space of degree 7 and dimension 2 over Rational Field
User basis matrix:[ 0 1 0 1 -1 1 -1][ 0 0 1 0 -1 2 -1],
2),(-1.414213562373095?,
Vector space of degree 7 and dimension 2 over Algebraic Field
User basis matrix:
[
0
1
0
␣
˓→
-1 0.4142135623730951?
1
-1]
[
0
0
1
␣
˓→
0
-1
0 2.414213562373095?],2),(1.414213562373095?,
Vector space of degree 7 and dimension 2 over Algebraic Field
User basis matrix:
[
0
1
0
␣
˓→
-1 -2.414213562373095?
1
-1]
[
0
0
1
␣
˓→
0
-1
0 -0.4142135623730951?],
2) ]>>> A.eigenspaces_left(format= galois , algebraic_multiplicity=True)[ (3,Vector space of degree 7 and dimension 1 over Rational Field
User basis matrix:
[
1
0 1/7
0 -1/7
0 -2/7],1),(-2,Vector space of degree 7 and dimension 2 over Rational Field
User basis matrix:(continues on next page)337

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 0 1 0 1 -1 1 -1][ 0 0 1 0 -1 2 -1],2),(a2,Vector space of degree 7 and dimension 2over Number Field in a2 with defining polynomial x^2 - 2
User basis matrix:[0
1
0-1 -a2 - 1
1
-1]
[
0
0
1
0
-1
0 -a2 + 1],
2) ]Next we compute the left eigenspaces over the finite field of order 11.
sage: # needs sage.modular sage.rings.finite_rings
sage: A = ModularSymbols(43, base_ring=GF(11), sign=1).T(2).matrix(); A[ 3 0 9 0]
[ 0 9 0 10][ 0 0 10 1][ 0 0 1 1]
sage: A.base_ring()
Finite Field of size 11
sage: A.charpoly()x^4 + 10*x^3 + 3*x^2 + 2*x + 1
sage: A.eigenspaces_left(format= galois , var= beta )[ (9,Vector space of degree 4 and dimension 1 over Finite Field of size 11
User basis matrix: [0 1 5 6]),(3, Vector space of degree 4 and dimension 1 over Finite Field of size 11
User basis matrix: [1 0 1 6]),(beta2, Vector space of degree 4 and dimension 1
over Univariate Quotient Polynomial Ring in beta2
over Finite Field of size 11 with modulus x^2 + 9
User basis matrix: [00
1 beta2 + 1])]>>> from sage.all import *>>> # needs sage.modular sage.rings.finite_rings>>> A = ModularSymbols(Integer(43), base_ring=GF(Integer(11)),␣
˓→sign=Integer(1)).T(Integer(2)).matrix(); A[ 3 0 9 0]
[ 0 9 0 10][ 0 0 10 1][ 0 0 1 1]>>> A.base_ring()
Finite Field of size 11>>> A.charpoly()x^4 + 10*x^3 + 3*x^2 + 2*x + 1>>> A.eigenspaces_left(format= galois , var= beta )[ (9,Vector space of degree 4 and dimension 1 over Finite Field of size 11
User basis matrix: [0 1 5 6]),(3, Vector space of degree 4 and dimension 1 over Finite Field of size 11
User basis matrix: [1 0 1 6]),(beta2, Vector space of degree 4 and dimension 1
over Univariate Quotient Polynomial Ring in beta2
over Finite Field of size 11 with modulus x^2 + 9(continues on next page)

338

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

User basis matrix: [00

1 beta2 + 1])]

This method is only applicable to exact matrices. The “eigenmatrix” routines for matrices withdouble-precision floating-point entries (RDF, CDF) are the best alternative. (Since some platforms return
eigenvectors that are the negatives of those given here, this one example is not tested here.) There are also
“eigenmatrix” routines for matrices with symbolic entries.
sage: A = matrix(QQ, 3, 3, range(9))
sage: A.change_ring(RR).eigenspaces_left()
Traceback (most recent call last):...
NotImplementedError: eigenspaces cannot be computed reliably
for inexact rings such as Real Field with 53 bits of precision,
consult numerical or symbolic matrix classes for other options
sage: # needs scipy
sage: em = A.change_ring(RDF).eigenmatrix_left()
sage: eigenvalues = em[0]; eigenvalues.dense_matrix()[13.348469228349522
0.0[
0.0 -1.348469228349534
[
0.0
0.0
sage: eigenvectors = em[1]; eigenvectors # not tested[ 0.440242867... 0.567868371... 0.695493875...][ 0.897878732... 0.278434036... -0.341010658...][ 0.408248290... -0.816496580... 0.408248290...]# abs tol 1e-13
0.0]
0.0]
0.0]

sage: # needs sage.symbolic
sage: x, y = var( x y )sage: S = matrix([[x, y], [y, 3*x^2]])sage: em = S.eigenmatrix_left()
sage: eigenvalues = em[0]; eigenvalues[3/2*x^2 + 1/2*x - 1/2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2)
␣
˓→
0]
[
0 3/2*x^2 + 1/2*x + 1/
˓→2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2)]
sage: eigenvectors = em[1]; eigenvectors[
1 1/2*(3*x^2 - x -␣˓→sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y][
1 1/2*(3*x^2 - x +␣˓→sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y]>>> from sage.all import *>>> A = matrix(QQ, Integer(3), Integer(3), range(Integer(9)))>>> A.change_ring(RR).eigenspaces_left()
Traceback (most recent call last):...
NotImplementedError: eigenspaces cannot be computed reliably
for inexact rings such as Real Field with 53 bits of precision,
consult numerical or symbolic matrix classes for other options>>> # needs scipy>>> em = A.change_ring(RDF).eigenmatrix_left()>>> eigenvalues = em[Integer(0)]; eigenvalues.dense_matrix()[13.348469228349522
0.0
0.0]
[
0.0 -1.348469228349534
0.0]# abs tol 1e-13(continues on next page)339

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[
0.0
0.0
0.0]
>>> eigenvectors = em[Integer(1)]; eigenvectors # not tested[ 0.440242867... 0.567868371... 0.695493875...][ 0.897878732... 0.278434036... -0.341010658...][ 0.408248290... -0.816496580... 0.408248290...]>>> # needs sage.symbolic>>> x, y = var( x y )>>> S = matrix([[x, y], [y, Integer(3)*x**Integer(2)]])>>> em = S.eigenmatrix_left()>>> eigenvalues = em[Integer(0)]; eigenvalues[3/2*x^2 + 1/2*x - 1/2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2)
␣
˓→
0]
[
0 3/2*x^2 + 1/2*x + 1/
˓→2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2)]>>> eigenvectors = em[Integer(1)]; eigenvectors[
1 1/2*(3*x^2 - x -␣˓→sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y][
1 1/2*(3*x^2 - x +␣˓→sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y]

A request for all the eigenvalues, when it is not possible, will raise an error. Using the galois
format option is more likely to be successful.
sage: # needs sage.rings.finite_rings
sage: F.<b> = FiniteField(11^2)sage: A = matrix(F, [[b + 1, b + 1], [10*b + 4, 5*b + 4]])sage: A.eigenspaces_left(format= all )#␣˓→needs sage.rings.number_field
Traceback (most recent call last):...
NotImplementedError: unable to construct eigenspaces for eigenvalues outside␣˓→the base field,
try the keyword option: format= galois
sage: A.eigenspaces_left(format= galois )#␣˓→needs sage.rings.number_field[ (a0,
Vector space of degree 2 and dimension 1 over
Univariate Quotient Polynomial Ring in a0 over
Finite Field in b of size 11^2
with modulus x^2 + (5*b + 6)*x + 8*b + 10
User basis matrix:[
1 6*b*a0 + 3*b + 1]) ]>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> F = FiniteField(Integer(11)**Integer(2), names=( b ,)); (b,) = F._first_
˓→ngens(1)>>> A = matrix(F, [[b + Integer(1), b + Integer(1)], [Integer(10)*b +␣
˓→Integer(4), Integer(5)*b + Integer(4)]])>>> A.eigenspaces_left(format= all )#␣˓→needs sage.rings.number_field
Traceback (most recent call last):...
NotImplementedError: unable to construct eigenspaces for eigenvalues outside␣˓→the base field,(continues on next page)

340

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

try the keyword option: format= galois>>> A.eigenspaces_left(format= galois )˓→needs sage.rings.number_field[ (a0,
Vector space of degree 2 and dimension 1 over
Univariate Quotient Polynomial Ring in a0 over
Finite Field in b of size 11^2
with modulus x^2 + (5*b + 6)*x + 8*b + 10
User basis matrix:[
1 6*b*a0 + 3*b + 1]) ]#␣eigenspaces_right(format='all', var='a', algebraic_multiplicity=False)
Compute the right eigenspaces of a matrix.
Note that eigenspaces_right() and right_eigenspaces() are identical methods. Here “right”
refers to the eigenvectors being placed to the right of the matrix.
INPUT:• self – a square matrix over an exact field. For inexact matrices consult the numerical or symbolic
matrix classes.
• format – default: None–

all – attempts to create every eigenspace. This will always be possible for matrices with rational
entries.

–

galois – for each irreducible factor of the characteristic polynomial, a single eigenspace will
be output for a single root/eigenvalue for the irreducible factor.

– None – Uses the ‘all’ format if the base ring is contained in an algebraically closed field which is
implemented. Otherwise, uses the ‘galois’ format.
• var – (default: ‘a’); variable name used to represent elements of the root field of each irreducible factorof the characteristic polynomial. If var=’a’, then the root fields will be in terms of a0, a1, a2, …., where
the numbering runs across all the irreducible factors of the characteristic polynomial, even for linear
factors.
• algebraic_multiplicity – (default: False); whether or not to include the algebraic multiplicity of each eigenvalue in the output. See the discussion below.
OUTPUT:
If algebraic_multiplicity=False, return a list of pairs (e, V) where e is an eigenvalue of the matrix, and V isthe corresponding left eigenspace. For Galois conjugates of eigenvalues, there may be just one representative
eigenspace, depending on the format keyword.
If algebraic_multiplicity=True, return a list of triples (e, V, n) where e and V are as above and n is the algebraic
multiplicity of the eigenvalue.
Warning: Uses a somewhat naive algorithm (simply factors the characteristic polynomial and computes
kernels directly over the extension field).
EXAMPLES:
Right eigenspaces are computed from the left eigenspaces of the transpose of the matrix. As such, there is agreater collection of illustrative examples at the eigenspaces_left().
We compute the right eigenspaces of a 3 × 3 rational matrix.
341

Matrices and Spaces of Matrices, Release 10.4

sage: # needs sage.rings.number_fieldsage: A = matrix(QQ, 3, 3, range(9)); A[0 1 2][3 4 5][6 7 8]sage: A.eigenspaces_right()[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]),(-1.348469228349535?,
Vector space of degree 3 and dimension 1 over Algebraic Field
User basis matrix:[
1 0.1303061543300932? -0.7393876913398137?]),(13.34846922834954?,
Vector space of degree 3 and dimension 1 over Algebraic Field
User basis matrix:[
1 3.069693845669907? 5.139387691339814?]) ]sage: es = A.eigenspaces_right(format= galois ); es[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]),(a1,
Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/5*a1 + 2/5 2/5*a1 - 1/5]) ]sage: es = A.eigenspaces_right(format= galois ,....:algebraic_multiplicity=True); es[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1],1),(a1,
Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/5*a1 + 2/5 2/5*a1 - 1/5],1) ]sage: e, v, n = es[0]; v = v.basis()[0]sage: delta = v*e - A*v
sage: abs(abs(delta)) < 1e-10
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQ, Integer(3), Integer(3), range(Integer(9))); A[0 1 2][3 4 5][6 7 8]>>> A.eigenspaces_right()[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]),
(continues on next page)

342

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)(-1.348469228349535?,
Vector space of degree 3 and dimension 1 over Algebraic Field
User basis matrix:[
1 0.1303061543300932? -0.7393876913398137?]),(13.34846922834954?,
Vector space of degree 3 and dimension 1 over Algebraic Field
User basis matrix:[
1 3.069693845669907? 5.139387691339814?]) ]>>> es = A.eigenspaces_right(format= galois ); es[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]),(a1,
Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/5*a1 + 2/5 2/5*a1 - 1/5]) ]>>> es = A.eigenspaces_right(format= galois ,...
algebraic_multiplicity=True); es[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1],1),(a1,
Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/5*a1 + 2/5 2/5*a1 - 1/5],
1) ]>>> e, v, n = es[Integer(0)]; v = v.basis()[Integer(0)]>>> delta = v*e - A*v>>> abs(abs(delta)) < RealNumber( 1e-10 )True

The same computation, but with implicit base change to a field:
sage: A = matrix(ZZ, 3, range(9)); A[0 1 2][3 4 5][6 7 8]sage: A.eigenspaces_right(format= galois )˓→needs sage.rings.number_field[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]),(a1,
Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/5*a1 + 2/5 2/5*a1 - 1/5]) ]#␣>>> from sage.all import *>>> A = matrix(ZZ, Integer(3), range(Integer(9))); A(continues on next page)343

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 1 2][3 4 5][6 7 8]>>> A.eigenspaces_right(format= galois )˓→needs sage.rings.number_field[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]),(a1,
Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/5*a1 + 2/5 2/5*a1 - 1/5]) ]#␣This method is only applicable to exact matrices. The “eigenmatrix” routines for matrices withdouble-precision floating-point entries (RDF, CDF) are the best alternative. (Since some platforms return
eigenvectors that are the negatives of those given here, this one example is not tested here.) There are also
“eigenmatrix” routines for matrices with symbolic entries.
sage: B = matrix(RR, 3, 3, range(9))
sage: B.eigenspaces_right()
Traceback (most recent call last):...
NotImplementedError: eigenspaces cannot be computed reliably
for inexact rings such as Real Field with 53 bits of precision,
consult numerical or symbolic matrix classes for other options
sage: # needs scipy
sage: em = B.change_ring(RDF).eigenmatrix_right()
sage: eigenvalues = em[0]; eigenvalues.dense_matrix() # abs tol 1e-13[13.348469228349522
0.0
0.0]
[
0.0 -1.348469228349534
0.0]
[
0.0
0.0
0.0]
sage: eigenvectors = em[1]; eigenvectors # not tested[ 0.164763817... 0.799699663... 0.408248290...][ 0.505774475... 0.104205787... -0.816496580...][ 0.846785134... -0.591288087... 0.408248290...]sage: # needs sage.symbolic
sage: x, y = var( x y )sage: S = matrix([[x, y], [y, 3*x^2]])sage: em = S.eigenmatrix_right()
sage: eigenvalues = em[0]; eigenvalues[3/2*x^2 + 1/2*x - 1/2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2)
␣
˓→
0]
[
0 3/2*x^2 + 1/2*x + 1/
˓→2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2)]
sage: eigenvectors = em[1]; eigenvectors
[
1
␣
˓→
1]
[1/2*(3*x^2 - x - sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y 1/2*(3*x^2 - x +␣˓→sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y]>>> from sage.all import *>>> B = matrix(RR, Integer(3), Integer(3), range(Integer(9)))(continues on next page)

344

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> B.eigenspaces_right()
Traceback (most recent call last):...
NotImplementedError: eigenspaces cannot be computed reliably
for inexact rings such as Real Field with 53 bits of precision,
consult numerical or symbolic matrix classes for other options>>> # needs scipy>>> em = B.change_ring(RDF).eigenmatrix_right()>>> eigenvalues = em[Integer(0)]; eigenvalues.dense_matrix()[13.348469228349522
0.0
0.0]
[
0.0 -1.348469228349534
0.0]
[
0.0
0.0
0.0]
>>> eigenvectors = em[Integer(1)]; eigenvectors # not tested[ 0.164763817... 0.799699663... 0.408248290...][ 0.505774475... 0.104205787... -0.816496580...][ 0.846785134... -0.591288087... 0.408248290...]# abs tol 1e-13>>> # needs sage.symbolic>>> x, y = var( x y )>>> S = matrix([[x, y], [y, Integer(3)*x**Integer(2)]])>>> em = S.eigenmatrix_right()>>> eigenvalues = em[Integer(0)]; eigenvalues[3/2*x^2 + 1/2*x - 1/2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2)
␣
˓→
0]
[
0 3/2*x^2 + 1/2*x + 1/
˓→2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2)]>>> eigenvectors = em[Integer(1)]; eigenvectors
[
1
␣
˓→
1]
[1/2*(3*x^2 - x - sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y 1/2*(3*x^2 - x +␣˓→sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y]

eigenvalue_multiplicity(s)Return the multiplicity of s as a generalized eigenvalue of the matrix.
EXAMPLES:
sage: M = Matrix(QQ, [[0,1],[0,0]])
sage: M.eigenvalue_multiplicity(0)2sage: M.eigenvalue_multiplicity(1)0sage: M = posets.DiamondPoset(5).coxeter_transformation()
˓→needs sage.graphs sage.libs.flint
sage: [M.eigenvalue_multiplicity(x) for x in [-1, 1]]
˓→needs sage.graphs sage.libs.flint[3, 2]#␣#␣>>> from sage.all import *>>> M = Matrix(QQ, [[Integer(0),Integer(1)],[Integer(0),Integer(0)]])>>> M.eigenvalue_multiplicity(Integer(0))
2>>> M.eigenvalue_multiplicity(Integer(1))
0(continues on next page)345

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> M = posets.DiamondPoset(Integer(5)).coxeter_transformation()˓→# needs sage.graphs sage.libs.flint>>> [M.eigenvalue_multiplicity(x) for x in [-Integer(1), Integer(1)]]˓→# needs sage.graphs sage.libs.flint[3, 2]

␣␣eigenvalues(extend=True)
Return a sequence of the eigenvalues of a matrix, with multiplicity. If the eigenvalues are roots of polynomials
in QQ, then QQbar elements are returned that represent each separate root.
If the option extend is set to False, only eigenvalues in the base ring are considered.
EXAMPLES:
sage: a = matrix(ZZ, 4, range(16)); a[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11][12 13 14 15]
sage: sorted(a.eigenvalues(), reverse=True)
˓→needs sage.rings.number_field[32.46424919657298?, 0, 0, -2.464249196572981?]>>> from sage.all import *>>> a = matrix(ZZ, Integer(4), range(Integer(16))); a[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11][12 13 14 15]>>> sorted(a.eigenvalues(), reverse=True)
˓→needs sage.rings.number_field[32.46424919657298?, 0, 0, -2.464249196572981?]#␣#␣

sage: a = matrix([(1, 9, -1, -1),....:(-2, 0, -10, 2),....:(-1, 0, 15, -2),....:
(0, 1, 0, -1)])
sage: a.eigenvalues()
˓→needs sage.rings.number_field[-0.9386318578049146?,
15.50655435353258?,
0.2160387521361705? - 4.713151979747493?*I,
0.2160387521361705? + 4.713151979747493?*I]>>> from sage.all import *>>> a = matrix([(Integer(1), Integer(9), -Integer(1), -Integer(1)),...
(-Integer(2), Integer(0), -Integer(10), Integer(2)),...
(-Integer(1), Integer(0), Integer(15), -Integer(2)),...
(Integer(0), Integer(1), Integer(0), -Integer(1))])>>> a.eigenvalues()
˓→needs sage.rings.number_field[-0.9386318578049146?,
15.50655435353258?,
0.2160387521361705? - 4.713151979747493?*I,
0.2160387521361705? + 4.713151979747493?*I]

346

#␣

#␣

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

A symmetric matrix a + a.transpose() should have real eigenvalues
sage: b = a + a.transpose()sage: ev = b.eigenvalues(); ev
˓→needs sage.rings.number_field[-8.35066086057957?, -1.107247901349379?,
5.718651326708515?, 33.73925743522043?]>>> from sage.all import *>>> b = a + a.transpose()>>> ev = b.eigenvalues(); ev
˓→needs sage.rings.number_field[-8.35066086057957?, -1.107247901349379?,
5.718651326708515?, 33.73925743522043?]#␣#␣

The eigenvalues are elements of QQbar, so they really represent exact roots of polynomials, not just approximations.
sage: e = ev[0]; e˓→needs sage.rings.number_field-8.35066086057957?
sage: p = e.minpoly(); p˓→needs sage.rings.number_fieldx^4 - 30*x^3 - 171*x^2 + 1460*x + 1784
sage: p(e) == 0
˓→needs sage.rings.number_field
True>>> from sage.all import *>>> e = ev[Integer(0)]; e˓→# needs sage.rings.number_field-8.35066086057957?
>>> p = e.minpoly(); p˓→needs sage.rings.number_fieldx^4 - 30*x^3 - 171*x^2 + 1460*x + 1784>>> p(e) == Integer(0)˓→# needs sage.rings.number_field
True

#␣

#␣

#␣

␣

#␣

␣

To perform computations on the eigenvalue as an element of a number field, you can always convert back to
a number field element.
sage: e.as_number_field_element()#␣˓→needs sage.rings.number_field(Number Field in awith defining polynomial y^4 - 2*y^3 - 507*y^2 - 3972*y - 4264,
a + 7,
Ring morphism:
From: Number Field in a with defining polynomial y^4 - 2*y^3 - 507*y^2 -␣
˓→3972*y - 4264
To:
Algebraic Real Field
Defn: a |--> -15.35066086057957?)>>> from sage.all import *>>> e.as_number_field_element()
˓→needs sage.rings.number_field(Number Field in a#␣(continues on next page)347

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

with defining polynomial y^4 - 2*y^3 - 507*y^2 - 3972*y - 4264,
a + 7,
Ring morphism:
From: Number Field in a with defining polynomial y^4 - 2*y^3 - 507*y^2 -␣
˓→3972*y - 4264
To:
Algebraic Real Field
Defn: a |--> -15.35066086057957?)

Notice the effect of the extend option.
sage: M = matrix(QQ, [[0,-1,0], [1,0,0], [0,0,2]])
sage: M.eigenvalues()
˓→needs sage.rings.number_field[2, -1*I, 1*I]
sage: M.eigenvalues(extend=False)
˓→needs sage.libs.pari
[2]

#␣

#␣

>>> from sage.all import *>>> M = matrix(QQ, [[Integer(0),-Integer(1),Integer(0)], [Integer(1),˓→Integer(0),Integer(0)], [Integer(0),Integer(0),Integer(2)]])>>> M.eigenvalues()
˓→needs sage.rings.number_field[2, -1*I, 1*I]>>> M.eigenvalues(extend=False)
˓→needs sage.libs.pari
[2]

#␣

#␣

The method also works for matrices over finite fields:
sage: M = matrix(GF(3), [[0,1,1], [1,2,0], [2,0,1]])
sage: ev = sorted(M.eigenvalues()); ev
˓→needs sage.rings.finite_rings[2*z3, 2*z3 + 1, 2*z3 + 2]

#␣>>> from sage.all import *>>> M = matrix(GF(Integer(3)), [[Integer(0),Integer(1),Integer(1)],␣
˓→[Integer(1),Integer(2),Integer(0)], [Integer(2),Integer(0),Integer(1)]])>>> ev = sorted(M.eigenvalues()); ev#␣˓→needs sage.rings.finite_rings[2*z3, 2*z3 + 1, 2*z3 + 2]

Similarly as in the case of QQbar, the eigenvalues belong to some algebraic closure but they can be converted
to elements of a finite field:
sage: e = ev[0]˓→needs sage.rings.finite_rings
sage: e.parent()
˓→needs sage.rings.finite_rings
Algebraic closure of Finite Field of size 3
sage: e.as_finite_field_element()
˓→needs sage.rings.finite_rings(Finite Field in z3 of size 3^3,
2*z3,
Ring morphism:
From: Finite Field in z3 of size 3^3

#␣
#␣

#␣

(continues on next page)

348

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)To:
Algebraic closure of Finite Field of size 3
Defn: z3 |--> z3)>>> from sage.all import *>>> e = ev[Integer(0)]˓→# needs sage.rings.finite_rings>>> e.parent()
˓→needs sage.rings.finite_rings
Algebraic closure of Finite Field of size 3>>> e.as_finite_field_element()
˓→needs sage.rings.finite_rings(Finite Field in z3 of size 3^3,
2*z3,
Ring morphism:
From: Finite Field in z3 of size 3^3
To:
Algebraic closure of Finite Field of size 3
Defn: z3 |--> z3)

␣
#␣

#␣

eigenvectors_left(other=None, extend=True)
Compute the left eigenvectors of a matrix.
INPUT:• other – a square matrix 𝐵 (default: None) in a generalized eigenvalue problem; if None, an ordinary
eigenvalue problem is solved (currently supported only if the base ring of self is RDF or CDF)
• extend – boolean (default: True)OUTPUT:For each distinct eigenvalue, returns a list of the form (e,V,n) where e is the eigenvalue, V is a list of eigenvectors forming a basis for the corresponding left eigenspace, and n is the algebraic multiplicity of the eigenvalue.
If the option extend is set to False, then only the eigenvalues that live in the base ring are considered.
EXAMPLES:
We compute the left eigenvectors of a 3 × 3 rational matrix.
sage: # needs sage.rings.number_fieldsage: A = matrix(QQ, 3, 3, range(9)); A[0 1 2][3 4 5][6 7 8]sage: es = A.eigenvectors_left(); es[(0, [ (1, -2, 1) ], 1),(-1.348469228349535?, [(1, 0.3101020514433644?, -0.3797958971132713?)], 1),(13.34846922834954?, [(1, 1.289897948556636?, 1.579795897113272?)], 1)]
sage: eval, [evec], mult = es[0]sage: delta = eval*evec - evec*A
sage: abs(abs(delta)) < 1e-10
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQ, Integer(3), Integer(3), range(Integer(9))); A[0 1 2][3 4 5](continues on next page)349

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[6 7 8]>>> es = A.eigenvectors_left(); es[(0, [ (1, -2, 1) ], 1),(-1.348469228349535?, [(1, 0.3101020514433644?, -0.3797958971132713?)], 1),(13.34846922834954?, [(1, 1.289897948556636?, 1.579795897113272?)], 1)]>>> eval, [evec], mult = es[Integer(0)]>>> delta = eval*evec - evec*A>>> abs(abs(delta)) < RealNumber( 1e-10 )True

Notice the difference between considering ring extensions or not.
sage: M = matrix(QQ, [[0,-1,0], [1,0,0], [0,0,2]])
sage: M.eigenvectors_left()
˓→needs sage.rings.number_field[(2,[ (0, 0, 1) ], 1),(-1*I, [(1, -1*I, 0)], 1),(1*I, [(1, 1*I, 0)], 1)]
sage: M.eigenvectors_left(extend=False)
˓→needs sage.rings.number_field[(2,[ (0, 0, 1) ], 1)]#␣#␣>>> from sage.all import *>>> M = matrix(QQ, [[Integer(0),-Integer(1),Integer(0)], [Integer(1),˓→Integer(0),Integer(0)], [Integer(0),Integer(0),Integer(2)]])>>> M.eigenvectors_left()
˓→needs sage.rings.number_field[(2,[ (0, 0, 1) ], 1),(-1*I, [(1, -1*I, 0)], 1),(1*I, [(1, 1*I, 0)], 1)]>>> M.eigenvectors_left(extend=False)
˓→needs sage.rings.number_field[(2,[ (0, 0, 1) ], 1)]#␣#␣eigenvectors_right(other=None, extend=True)
Compute the right eigenvectors of a matrix.
INPUT:• other – a square matrix 𝐵 (default: None) in a generalized eigenvalue problem; if None, an ordinary
eigenvalue problem is solved (currently supported only if the base ring of self is RDF or CDF)
• extend – boolean (default: True)OUTPUT:For each distinct eigenvalue, returns a list of the form (e,V,n) where e is the eigenvalue, V is a list of eigenvectors forming a basis for the corresponding right eigenspace, and n is the algebraic multiplicity of theeigenvalue. If extend = True (the default), this will return eigenspaces over the algebraic closure of thebase field where this is implemented; otherwise it will restrict to eigenvalues in the base field.
EXAMPLES:
We compute the right eigenvectors of a 3 × 3 rational matrix.
sage: # needs sage.rings.number_fieldsage: A = matrix(QQ, 3, 3, range(9)); A[0 1 2](continues on next page)

350

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[3 4 5][6 7 8]sage: es = A.eigenvectors_right(); es[(0, [ (1, -2, 1) ], 1),(-1.348469228349535?, [(1, 0.1303061543300932?, -0.7393876913398137?)], 1),(13.34846922834954?, [(1, 3.069693845669907?, 5.139387691339814?)], 1)]
sage: A.eigenvectors_right(extend=False)[(0, [ (1, -2, 1) ], 1)]
sage: eval, [evec], mult = es[0]sage: delta = eval*evec - A*evec
sage: abs(abs(delta)) < 1e-10
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQ, Integer(3), Integer(3), range(Integer(9))); A[0 1 2][3 4 5][6 7 8]>>> es = A.eigenvectors_right(); es[(0, [ (1, -2, 1) ], 1),(-1.348469228349535?, [(1, 0.1303061543300932?, -0.7393876913398137?)], 1),(13.34846922834954?, [(1, 3.069693845669907?, 5.139387691339814?)], 1)]>>> A.eigenvectors_right(extend=False)[(0, [ (1, -2, 1) ], 1)]>>> eval, [evec], mult = es[Integer(0)]>>> delta = eval*evec - A*evec>>> abs(abs(delta)) < RealNumber( 1e-10 )Trueelementary_divisors(algorithm=None)
If self is a matrix over a principal ideal domain 𝑅, return elements 𝑑𝑖 for 1 ≤ 𝑖 ≤ 𝑘 = min(𝑟, 𝑠) where 𝑟
and 𝑠 are the number of rows and columns of self, such that the cokernel of self is isomorphic to𝑅/(𝑑1 ) ⊕ 𝑅/(𝑑2 ) ⊕ 𝑅/(𝑑𝑘 )with 𝑑𝑖 | 𝑑𝑖+1 for all 𝑖. These are the diagonal entries of the Smith form of self (see smith_form()).
INPUT:• algorithm – ignored
EXAMPLES:
sage: x = polygen(ZZ, x )sage: OE.<w> = EquationOrder(x^2 - x + 2)
˓→needs sage.rings.number_fieldsage: m = Matrix([[1, w], [w, 7]])˓→needs sage.rings.number_fieldsage: m.elementary_divisors()
˓→needs sage.rings.number_field[1, -w + 9]

#␣
#␣
#␣

>>> from sage.all import *>>> x = polygen(ZZ, x )>>> OE = EquationOrder(x**Integer(2) - x + Integer(2), names=( w ,)); (w,) =␣
(continues on next page)351

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)OE._first_ngens(1)# needs sage.rings.number_field>>> m = Matrix([[Integer(1), w], [w, Integer(7)]])˓→# needs sage.rings.number_field>>> m.elementary_divisors()
˓→needs sage.rings.number_field[1, -w + 9]
˓→

␣
#␣

See also:smith_form()
elementwise_product(right)
Returns the elementwise product of two matrices of the same size (also known as the Hadamard product).
INPUT:• right – the right operand of the product. A matrix of the same size as self such that multiplication ofelements of the base rings of self and right is defined, once Sage’s coercion model is applied. If thematrices have different sizes, or if multiplication of individual entries cannot be achieved, a TypeError
will result.
OUTPUT:
A matrix of the same size as self and right. The entry in location (𝑖, 𝑗) of the output is the product of
the two entries in location (𝑖, 𝑗) of self and right (in that order).
The parent of the result is determined by Sage’s coercion model. If the base rings are identical, then the result
is dense or sparse according to this property for the left operand. If the base rings must be adjusted for one,or both, matrices then the result will be sparse only if both operands are sparse. No subdivisions are present
in the result.
If the type of the result is not to your liking, or the ring could be “tighter,” adjust the operands withchange_ring(). Adjust sparse versus dense inputs with the methods sparse_matrix() anddense_matrix().
EXAMPLES:
sage: A = matrix(ZZ, 2, 3, range(6))
sage: B = matrix(QQ, 2, 3, [5, 1/3, 2/7, 11/2, -3/2, 8])
sage: C = A.elementwise_product(B)sage: C[
0 1/3 4/7]
[33/2
-6
40]
sage: C.parent()
Full MatrixSpace of 2 by 3 dense matrices over Rational Field>>> from sage.all import *>>> A = matrix(ZZ, Integer(2), Integer(3), range(Integer(6)))>>> B = matrix(QQ, Integer(2), Integer(3), [Integer(5), Integer(1)/Integer(3),˓→ Integer(2)/Integer(7), Integer(11)/Integer(2), -Integer(3)/Integer(2),␣
˓→Integer(8)])>>> C = A.elementwise_product(B)>>> C[
0 1/3 4/7]
[33/2
-6
40]
>>> C.parent()
Full MatrixSpace of 2 by 3 dense matrices over Rational Field

Notice the base ring of the results in the next two examples.
352

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

sage: x = polygen(ZZ, x )sage: D = matrix(ZZ[ x ],2,[1+x^2,2,3,4-x])
sage: E = matrix(QQ,2,[1,2,3,4])
sage: F = D.elementwise_product(E)sage: F[ x^2 + 14][
9 -4*x + 16]
sage: F.parent()
Full MatrixSpace of 2 by 2 dense matrices
over Univariate Polynomial Ring in x over Rational Field>>> from sage.all import *>>> x = polygen(ZZ, x )>>> D = matrix(ZZ[ x ],Integer(2),[Integer(1)+x**Integer(2),Integer(2),˓→Integer(3),Integer(4)-x])>>> E = matrix(QQ,Integer(2),[Integer(1),Integer(2),Integer(3),Integer(4)])>>> F = D.elementwise_product(E)>>> F[ x^2 + 14][
9 -4*x + 16]>>> F.parent()
Full MatrixSpace of 2 by 2 dense matrices
over Univariate Polynomial Ring in x over Rational Field
sage: G = matrix(GF(3), 2, [0, 1, 2, 2])
sage: H = matrix(ZZ, 2, [1, 2, 3, 4])
sage: J = G.elementwise_product(H)sage: J[0 2]
[0 2]
sage: J.parent()
Full MatrixSpace of 2 by 2 dense matrices
over Finite Field of size 3>>> from sage.all import *>>> G = matrix(GF(Integer(3)), Integer(2), [Integer(0), Integer(1),␣
˓→Integer(2), Integer(2)])>>> H = matrix(ZZ, Integer(2), [Integer(1), Integer(2), Integer(3),␣
˓→Integer(4)])>>> J = G.elementwise_product(H)
>>> J
[0 2]
[0 2]
>>> J.parent()
Full MatrixSpace of 2 by 2 dense matrices
over Finite Field of size 3

Non-commutative rings behave as expected. These are the usual quaternions.
sage: # needs sage.combinat
sage: R.<i,j,k> = QuaternionAlgebra(-1, -1)
sage: A = matrix(R, 2, [1,i,j,k])
sage: B = matrix(R, 2, [i,i,i,i])
sage: A.elementwise_product(B)[ i -1][-k j](continues on next page)353

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: B.elementwise_product(A)[ i -1][ k -j]>>> from sage.all import *>>> # needs sage.combinat>>> R = QuaternionAlgebra(-Integer(1), -Integer(1), names=( i ,˓→(i, j, k,) = R._first_ngens(3)>>> A = matrix(R, Integer(2), [Integer(1),i,j,k])>>> B = matrix(R, Integer(2), [i,i,i,i])>>> A.elementwise_product(B)[ i -1][-k j]>>> B.elementwise_product(A)[ i -1][ k -j]j ,k ,));␣

Input that is not a matrix will raise an error.
sage: A = random_matrix(ZZ, 5, 10, x=20)
sage: A.elementwise_product(vector(ZZ, [1,2,3,4]))Traceback (most recent call last):...
TypeError: no common canonical parent for objects with parents:
Full MatrixSpace of 5 by 10 dense matrices over Integer Ring andAmbient free module of rank 4 over the principal ideal domain Integer Ringsage: A = matrix(2, 2, range(4))
sage: A.elementwise_product(polygen(parent(A)))
Traceback (most recent call last):...
TypeError: elementwise_product() argument should be a matrix
or coercible to a matrix>>> from sage.all import *>>> A = random_matrix(ZZ, Integer(5), Integer(10), x=Integer(20))>>> A.elementwise_product(vector(ZZ, [Integer(1),Integer(2),Integer(3),˓→Integer(4)]))
Traceback (most recent call last):...
TypeError: no common canonical parent for objects with parents:
Full MatrixSpace of 5 by 10 dense matrices over Integer Ring andAmbient free module of rank 4 over the principal ideal domain Integer Ring>>> A = matrix(Integer(2), Integer(2), range(Integer(4)))>>> A.elementwise_product(polygen(parent(A)))
Traceback (most recent call last):...
TypeError: elementwise_product() argument should be a matrix
or coercible to a matrix

Matrices of different sizes for operands will raise an error.
sage: A = random_matrix(ZZ, 5, 10, x=20)
sage: B = random_matrix(ZZ, 10, 5, x=40)
sage: A.elementwise_product(B)(continues on next page)354

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Traceback (most recent call last):...
TypeError: no common canonical parent for objects with parents:
Full MatrixSpace of 5 by 10 dense matrices over Integer Ring andFull MatrixSpace of 10 by 5 dense matrices over Integer Ring>>> from sage.all import *>>> A = random_matrix(ZZ, Integer(5), Integer(10), x=Integer(20))>>> B = random_matrix(ZZ, Integer(10), Integer(5), x=Integer(40))>>> A.elementwise_product(B)Traceback (most recent call last):...
TypeError: no common canonical parent for objects with parents:
Full MatrixSpace of 5 by 10 dense matrices over Integer Ring andFull MatrixSpace of 10 by 5 dense matrices over Integer Ring

Some pairs of rings do not have a common parent where multiplication makes sense. This will raise an error.
sage: A = matrix(QQ, 3, 2, range(6))
sage: B = matrix(GF(3), 3, [2]*6)
sage: A.elementwise_product(B)Traceback (most recent call last):...
TypeError: no common canonical parent for objects with parents:
Full MatrixSpace of 3 by 2 dense matrices over Rational Field andFull MatrixSpace of 3 by 2 dense matrices over Finite Field of size 3>>> from sage.all import *>>> A = matrix(QQ, Integer(3), Integer(2), range(Integer(6)))>>> B = matrix(GF(Integer(3)), Integer(3), [Integer(2)]*Integer(6))>>> A.elementwise_product(B)Traceback (most recent call last):...
TypeError: no common canonical parent for objects with parents:
Full MatrixSpace of 3 by 2 dense matrices over Rational Field andFull MatrixSpace of 3 by 2 dense matrices over Finite Field of size 3

We illustrate various combinations of sparse and dense matrices. The usual coercion rules apply:
sage: A = matrix(ZZ, 5, 6, range(30), sparse=False)
sage: B = matrix(ZZ, 5, 6, range(30), sparse=True)
sage: C = matrix(QQ, 5, 6, range(30), sparse=True)
sage: A.elementwise_product(C).is_sparse()
True
sage: B.elementwise_product(C).is_sparse()
True
sage: A.elementwise_product(B).is_dense()
True
sage: B.elementwise_product(A).is_dense()
True>>> from sage.all import *>>> A = matrix(ZZ, Integer(5), Integer(6), range(Integer(30)), sparse=False)>>> B = matrix(ZZ, Integer(5), Integer(6), range(Integer(30)), sparse=True)>>> C = matrix(QQ, Integer(5), Integer(6), range(Integer(30)), sparse=True)(continues on next page)355

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> A.elementwise_product(C).is_sparse()
True>>> B.elementwise_product(C).is_sparse()
True>>> A.elementwise_product(B).is_dense()
True>>> B.elementwise_product(A).is_dense()
True

exp()
Calculate the exponential of this matrix X, which is the matrix
𝑒𝑋 =

∞
∑︁
𝑋𝑘
𝑘=0

𝑘!

.

This function depends on maxima’s matrix exponentiation function, which does not deal well with floating
point numbers. If the matrix has floating point numbers, they will be rounded automatically to rational numbers during the computation. If you want approximations to the exponential that are calculated numerically,
you may get better results by first converting your matrix to RDF or CDF, as shown in the last example.
EXAMPLES:
sage: # needs sage.symbolic
sage: a = matrix([[1,2], [3,4]])
sage: a.exp()[-1/22*((sqrt(33) - 11)*e^sqrt(33) - sqrt(33) - 11)*e^(-1/2*sqrt(33) + 5/2) ␣˓→
2/33*(sqrt(33)*e^sqrt(33) - sqrt(33))*e^(-1/2*sqrt(33) + 5/2)][
1/11*(sqrt(33)*e^sqrt(33) - sqrt(33))*e^(-1/2*sqrt(33) + 5/2) ␣˓→1/22*((sqrt(33) + 11)*e^sqrt(33) - sqrt(33) + 11)*e^(-1/2*sqrt(33) + 5/2)]
sage: type(a.exp())
˓→needs sage.symbolic<class sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense >#␣sage: a = matrix([[1/2,2/3], [3/4,4/5]])
sage: a.exp()#␣˓→needs sage.symbolic[-1/418*((3*sqrt(209) - 209)*e^(1/10*sqrt(209)) - 3*sqrt(209) - 209)*e^(-1/
˓→20*sqrt(209) + 13/20)
20/627*(sqrt(209)*e^(1/
˓→10*sqrt(209)) - sqrt(209))*e^(-1/20*sqrt(209) + 13/20)][
15/418*(sqrt(209)*e^(1/10*sqrt(209)) - sqrt(209))*e^(-1/
˓→20*sqrt(209) + 13/20)
1/418*((3*sqrt(209) + 209)*e^(1/10*sqrt(209)) -␣
˓→3*sqrt(209) + 209)*e^(-1/20*sqrt(209) + 13/20)]
sage: a = matrix(RR, [[1,pi.n()], [1e2,1e-2]])#␣˓→needs sage.symbolic
sage: a.exp()#␣˓→needs sage.symbolic[ 1/11882424341266*((11*sqrt(227345670387496707609) + 5941212170633)*e^(3/
˓→1275529100*sqrt(227345670387496707609)) - 11*sqrt(227345670387496707609) +␣˓→5941212170633)*e^(-3/2551058200*sqrt(227345670387496707609) + 101/200)
␣˓→445243650/
˓→75781890129165569203*(sqrt(227345670387496707609)*e^(3/
˓→1275529100*sqrt(227345670387496707609)) - sqrt(227345670387496707609))*e^(˓→3/2551058200*sqrt(227345670387496707609) + 101/200)][
10000/(continues on next page)

356

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)53470909535697*(sqrt(227345670387496707609)*e^(3/
˓→1275529100*sqrt(227345670387496707609)) - sqrt(227345670387496707609))*e^(˓→3/2551058200*sqrt(227345670387496707609) + 101/200) -1/
˓→11882424341266*((11*sqrt(227345670387496707609) - 5941212170633)*e^(3/
˓→1275529100*sqrt(227345670387496707609)) - 11*sqrt(227345670387496707609) -␣˓→5941212170633)*e^(-3/2551058200*sqrt(227345670387496707609) + 101/200)]
sage: a.change_ring(RDF).exp() # rel tol 1e-14#␣˓→needs sage.symbolic[42748127.31532951 7368259.244159399][234538976.1381042 40426191.45156228]
˓→>>> from sage.all import *>>> # needs sage.symbolic>>> a = matrix([[Integer(1),Integer(2)], [Integer(3),Integer(4)]])>>> a.exp()[-1/22*((sqrt(33) - 11)*e^sqrt(33) - sqrt(33) - 11)*e^(-1/2*sqrt(33) + 5/2) ␣˓→
2/33*(sqrt(33)*e^sqrt(33) - sqrt(33))*e^(-1/2*sqrt(33) + 5/2)][
1/11*(sqrt(33)*e^sqrt(33) - sqrt(33))*e^(-1/2*sqrt(33) + 5/2) ␣˓→1/22*((sqrt(33) + 11)*e^sqrt(33) - sqrt(33) + 11)*e^(-1/2*sqrt(33) + 5/2)]>>> type(a.exp())
˓→needs sage.symbolic<class sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense >#␣>>> a = matrix([[Integer(1)/Integer(2),Integer(2)/Integer(3)], [Integer(3)/˓→Integer(4),Integer(4)/Integer(5)]])>>> a.exp()#␣˓→needs sage.symbolic[-1/418*((3*sqrt(209) - 209)*e^(1/10*sqrt(209)) - 3*sqrt(209) - 209)*e^(-1/
˓→20*sqrt(209) + 13/20)
20/627*(sqrt(209)*e^(1/
˓→10*sqrt(209)) - sqrt(209))*e^(-1/20*sqrt(209) + 13/20)][
15/418*(sqrt(209)*e^(1/10*sqrt(209)) - sqrt(209))*e^(-1/
˓→20*sqrt(209) + 13/20)
1/418*((3*sqrt(209) + 209)*e^(1/10*sqrt(209)) -␣
˓→3*sqrt(209) + 209)*e^(-1/20*sqrt(209) + 13/20)]>>> a = matrix(RR, [[Integer(1),pi.n()], [RealNumber( 1e2 ),RealNumber( 1e-2˓→ )]])# needs sage.symbolic>>> a.exp()#␣˓→needs sage.symbolic[ 1/11882424341266*((11*sqrt(227345670387496707609) + 5941212170633)*e^(3/
˓→1275529100*sqrt(227345670387496707609)) - 11*sqrt(227345670387496707609) +␣˓→5941212170633)*e^(-3/2551058200*sqrt(227345670387496707609) + 101/200)
␣˓→445243650/
˓→75781890129165569203*(sqrt(227345670387496707609)*e^(3/
˓→1275529100*sqrt(227345670387496707609)) - sqrt(227345670387496707609))*e^(˓→3/2551058200*sqrt(227345670387496707609) + 101/200)][
10000/
˓→53470909535697*(sqrt(227345670387496707609)*e^(3/
˓→1275529100*sqrt(227345670387496707609)) - sqrt(227345670387496707609))*e^(˓→3/2551058200*sqrt(227345670387496707609) + 101/200) -1/
˓→11882424341266*((11*sqrt(227345670387496707609) - 5941212170633)*e^(3/
˓→1275529100*sqrt(227345670387496707609)) - 11*sqrt(227345670387496707609) -␣˓→5941212170633)*e^(-3/2551058200*sqrt(227345670387496707609) + 101/200)]>>> a.change_ring(RDF).exp() # rel tol 1e-14#␣˓→needs sage.symbolic[42748127.31532951 7368259.244159399][234538976.1381042 40426191.45156228]

357

Matrices and Spaces of Matrices, Release 10.4

extended_echelon_form(subdivide=False, **kwds)
Return the echelon form of self augmented with an identity matrix.
INPUT:• subdivide – (boolean, default: False) whether to subdivide the returned matrix. See the descriptionof the (output) below for details.
• kwds – additional keywords that can be passed to the method that computes the echelon form.
OUTPUT:
If 𝐴 is an 𝑚 × 𝑛 matrix, add the 𝑚 columns of an 𝑚 × 𝑚 identity matrix to the right of self. Thenrow-reduce this 𝑚 × (𝑛 + 𝑚) matrix. This matrix is returned as an immutable matrix.
If subdivide is True then the returned matrix has a single division among the columns and a single
division among the rows. The column subdivision has 𝑛 columns to the left and 𝑚 columns to the right. The
row division separates the non-zero rows from the zero rows, when restricted to the first 𝑛 columns.
For a nonsingular matrix the final 𝑚 columns of the extended echelon form are the inverse of self. Fora matrix of any size, the final 𝑚 columns provide a matrix that transforms self to echelon form when
it multiplies self from the left. When the base ring is a field, the uniqueness of reduced row-echelon
form implies that this transformation matrix can be taken as the coefficients giving a canonical set of linear
combinations of the rows of self that yield reduced row-echelon form.
When subdivided as described above, and again over a field, the parts of the subdivision in the upper-leftcorner and lower-right corner satisfy several interesting relationships with the row space, column space, left
kernel and right kernel of self. See the examples below.
Note: This method returns an echelon form. If the base ring is not a field, no attempt is made to move tothe fraction field. See an example below where the base ring is changed manually.
EXAMPLES:
The four relationships at the end of this example hold in general.
sage: A = matrix(QQ, [[2, -1, 7, -1, 0, -3],....:[-1, 1, -5, 3, 4, 4],....:[2, -1, 7, 0, 2, -2],....:
[2, 0, 4, 3, 6, 1],....:[2, -1, 7, 0, 2, -2]])
sage: E = A.extended_echelon_form(subdivide=True); E
[
1
0
2
0
0
-1|
0
-1
0
1
-1]
[
0
1
-3
0
-2
0|
0
-2
0
2
-3]
[
0
0
0
1
2
1|
0 2/3
0 -1/3 2/3][-----------------------------+------------------------]
[
0
0
0
0
0
0|
1 2/3
0 -1/3 -1/3]
[
0
0
0
0
0
0|
0
0
1
0
-1]
sage: J = E.matrix_from_columns(range(6,11)); J
[
0
-1
0
1
-1]
[
0
-2
0
2
-3]
[
0 2/3
0 -1/3 2/3][
1 2/3
0 -1/3 -1/3]
[
0
0
1
0
-1]
sage: J*A == A.rref()Truesage: C = E.subdivision(0,0); C[ 1 0 2 0 0 -1](continues on next page)

358

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 0 1 -3 0 -2 0][ 0 0 0 1 2 1]
sage: L = E.subdivision(1,1); L[
1 2/3
0 -1/3 -1/3]
[
0
0
1
0
-1]
sage: A.right_kernel() == C.right_kernel()True
sage: A.row_space() == C.row_space()
True
sage: A.column_space() == L.right_kernel()True
sage: A.left_kernel() == L.row_space()
True>>> from sage.all import *>>> A = matrix(QQ, [[Integer(2), -Integer(1), Integer(7), -Integer(1),␣
˓→Integer(0), -Integer(3)],...
[-Integer(1), Integer(1), -Integer(5), Integer(3),␣
˓→Integer(4), Integer(4)],...
[Integer(2), -Integer(1), Integer(7), Integer(0),␣
˓→Integer(2), -Integer(2)],...
[Integer(2), Integer(0), Integer(4), Integer(3),␣
˓→Integer(6), Integer(1)],...
[Integer(2), -Integer(1), Integer(7), Integer(0),␣
˓→Integer(2), -Integer(2)]])>>> E = A.extended_echelon_form(subdivide=True); E
[
1
0
2
0
0
-1|
0
-1
0
1
-1]
[
0
1
-3
0
-2
0|
0
-2
0
2
-3]
[
0
0
0
1
2
1|
0 2/3
0 -1/3 2/3][-----------------------------+------------------------]
[
0
0
0
0
0
0|
1 2/3
0 -1/3 -1/3]
[
0
0
0
0
0
0|
0
0
1
0
-1]
>>> J = E.matrix_from_columns(range(Integer(6),Integer(11))); J
[
0
-1
0
1
-1]
[
0
-2
0
2
-3]
[
0 2/3
0 -1/3 2/3][
1 2/3
0 -1/3 -1/3]
[
0
0
1
0
-1]
>>> J*A == A.rref()True>>> C = E.subdivision(Integer(0),Integer(0)); C[ 1 0 2 0 0 -1][ 0 1 -3 0 -2 0][ 0 0 0 1 2 1]>>> L = E.subdivision(Integer(1),Integer(1)); L[
1 2/3
0 -1/3 -1/3]
[
0
0
1
0
-1]
>>> A.right_kernel() == C.right_kernel()True>>> A.row_space() == C.row_space()
True>>> A.column_space() == L.right_kernel()True>>> A.left_kernel() == L.row_space()
True

For a nonsingular matrix, the right half of the extended echelon form is the inverse matrix.
359

Matrices and Spaces of Matrices, Release 10.4

sage: B = matrix(QQ, [[1,3,4], [1,4,4], [0,-2,-1]])
sage: E = B.extended_echelon_form()
sage: J = E.matrix_from_columns(range(3,6)); J[-4 5 4][-1 1 0][ 2 -2 -1]
sage: J == B.inverse()
True>>> from sage.all import *>>> B = matrix(QQ, [[Integer(1),Integer(3),Integer(4)], [Integer(1),˓→Integer(4),Integer(4)], [Integer(0),-Integer(2),-Integer(1)]])>>> E = B.extended_echelon_form()>>> J = E.matrix_from_columns(range(Integer(3),Integer(6))); J[-4 5 4][-1 1 0][ 2 -2 -1]>>> J == B.inverse()
True

The result is in echelon form, so if the base ring is not a field, the leading entry of each row may not be 1.
But you can easily change to the fraction field if necessary.
sage: A = matrix(ZZ, [[16, 20, 4, 5, -4, 13, 5],....:[10, 13, 3, -3, 7, 11, 6],....:[-12, -15, -3, -3, 2, -10, -4],....:
[10, 13, 3, 3, -1, 9, 4],....:[4, 5, 1, 8, -10, 1, -1]])
sage: E = A.extended_echelon_form(subdivide=True); E[ 2 0 -2 2 -9 -3 -4| 0 4 -3 -9 4][ 0 1 1 2 0 1 1| 0 1 2 1 1]
[ 0 0 0 3 -4 -1 -1| 0 3 1 -3 3][--------------------+--------------][ 0 0 0 0 0 0 0| 1 6 3 -6 5][ 0 0 0 0 0 0 0| 0 7 2 -7 6]
sage: J = E.matrix_from_columns(range(7,12)); J[ 0 4 -3 -9 4][ 0 1 2 1 1]
[ 0 3 1 -3 3][ 1 6 3 -6 5][ 0 7 2 -7 6]
sage: J*A == A.echelon_form()True
sage: B = A.change_ring(QQ)
sage: B.extended_echelon_form(subdivide=True)[
10-1
0 -19/6
-7/6
-5/3|
0
0 -89/42
-5/2␣
˓→
1/7]
[
0
1
1
0
8/3
5/3
5/3|
0
0 34/21
2␣
˓→
-1/7]
[
0
0
0
1
-4/3
-1/3
-1/3|
0
0
1/21
0␣
˓→
1/7]
[------------------------------------------------+---------------------------˓→------]
[
0
0
0
0
0
0
0|
1
0
9/7
0␣
˓→
-1/7]
[
0
0
0
0
0
0
0|
0
1
2/7
-1␣
˓→
6/7]

360

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = matrix(ZZ, [[Integer(16), Integer(20), Integer(4), Integer(5), ˓→Integer(4), Integer(13), Integer(5)],...
[Integer(10), Integer(13), Integer(3), -Integer(3),␣
˓→Integer(7), Integer(11), Integer(6)],...
[-Integer(12), -Integer(15), -Integer(3), -Integer(3),␣
˓→Integer(2), -Integer(10), -Integer(4)],...
[Integer(10), Integer(13), Integer(3), Integer(3), ˓→Integer(1), Integer(9), Integer(4)],...
[Integer(4), Integer(5), Integer(1), Integer(8), ˓→Integer(10), Integer(1), -Integer(1)]])>>> E = A.extended_echelon_form(subdivide=True); E[ 2 0 -2 2 -9 -3 -4| 0 4 -3 -9 4][ 0 1 1 2 0 1 1| 0 1 2 1 1]
[ 0 0 0 3 -4 -1 -1| 0 3 1 -3 3][--------------------+--------------][ 0 0 0 0 0 0 0| 1 6 3 -6 5][ 0 0 0 0 0 0 0| 0 7 2 -7 6]>>> J = E.matrix_from_columns(range(Integer(7),Integer(12))); J[ 0 4 -3 -9 4][ 0 1 2 1 1]
[ 0 3 1 -3 3][ 1 6 3 -6 5][ 0 7 2 -7 6]>>> J*A == A.echelon_form()
True>>> B = A.change_ring(QQ)>>> B.extended_echelon_form(subdivide=True)[
10-1
0 -19/6
-7/6
-5/3|
0
0 -89/42
-5/2␣
˓→
1/7]
[
0
1
1
0
8/3
5/3
5/3|
0
0 34/21
2␣
˓→
-1/7]
[
0
0
0
1
-4/3
-1/3
-1/3|
0
0
1/21
0␣
˓→
1/7]
[------------------------------------------------+---------------------------˓→------]
[
0
0
0
0
0
0
0|
1
0
9/7
0␣
˓→
-1/7]
[
0
0
0
0
0
0
0|
0
1
2/7
-1␣
˓→
6/7]

Subdivided, or not, the result is immutable, so make a copy if you want to make changes.
sage: A = matrix(FiniteField(7), [[2,0,3], [5,5,3], [5,6,5]])
sage: E = A.extended_echelon_form()
sage: E.is_mutable()False
sage: F = A.extended_echelon_form(subdivide=True)
sage: F
[1 0 0|0 4 6]
[0 1 0|4 2 2]
[0 0 1|5 2 3][-----+-----]
sage: F.is_mutable()False
sage: G = copy(F)sage: G.subdivide([], []); G(continues on next page)361

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[1 0 0 0 4 6]
[0 1 0 4 2 2]
[0 0 1 5 2 3]>>> from sage.all import *>>> A = matrix(FiniteField(Integer(7)), [[Integer(2),Integer(0),Integer(3)],␣
˓→[Integer(5),Integer(5),Integer(3)], [Integer(5),Integer(6),Integer(5)]])>>> E = A.extended_echelon_form()>>> E.is_mutable()
False>>> F = A.extended_echelon_form(subdivide=True)>>> F[1 0 0|0 4 6]
[0 1 0|4 2 2]
[0 0 1|5 2 3][-----+-----]>>> F.is_mutable()
False>>> G = copy(F)>>> G.subdivide([], []); G[1 0 0 0 4 6]
[0 1 0 4 2 2]
[0 0 1 5 2 3]

If you want to determine exactly which algorithm is used to compute the echelon form, you can add additional
keywords to pass on to the echelon_form() routine employed on the augmented matrix. Sending theflag include_zero_rows is a bit silly, since the extended echelon form will never have any zero rows.
sage: A = matrix(ZZ, [[1,2], [5,0], [5,9]])sage: E = A.extended_echelon_form(algorithm= padic , include_zero_rows=False)
sage: E
[ 1
0 36
1 -8]
[ 0
1
5
0 -1]
[ 0
0 45
1 -10]>>> from sage.all import *>>> A = matrix(ZZ, [[Integer(1),Integer(2)], [Integer(5),Integer(0)],␣
˓→[Integer(5),Integer(9)]])>>> E = A.extended_echelon_form(algorithm= padic , include_zero_rows=False)
>>> E
[ 1
0 36
1 -8]
[ 0
1
5
0 -1]
[ 0
0 45
1 -10]

fcp(var='x')
Return the factorization of the characteristic polynomial of self.
INPUT:• var – (default: ‘x’) name of variable of charpoly
EXAMPLES:
sage: M = MatrixSpace(QQ, 3, 3)
sage: A = M([1,9,-7, 4/5,4,3, 6,4,3])
sage: A.fcp()#␣(continues on next page)362

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)needs sage.libs.parix^3 - 8*x^2 + 209/5*x - 286
sage: A = M([3, 0, -2, 0, -2, 0, 0, 0, 0])
sage: A.fcp( T )˓→needs sage.libs.pari(T - 3) * T * (T + 2)
˓→#␣>>> from sage.all import *>>> M = MatrixSpace(QQ, Integer(3), Integer(3))>>> A = M([Integer(1),Integer(9),-Integer(7), Integer(4)/Integer(5),˓→Integer(4),Integer(3), Integer(6),Integer(4),Integer(3)])>>> A.fcp()#␣˓→needs sage.libs.parix^3 - 8*x^2 + 209/5*x - 286>>> A = M([Integer(3), Integer(0), -Integer(2), Integer(0), -Integer(2),␣
˓→Integer(0), Integer(0), Integer(0), Integer(0)])>>> A.fcp( T )#␣˓→needs sage.libs.pari(T - 3) * T * (T + 2)

find(f, indices=False)
Find elements in this matrix satisfying the constraints in the function 𝑓 . The function is evaluated on eachelement of the matrix .
INPUT:• f – a function that is evaluated on each element of this matrix.
• indices – whether or not to return the indices and elements of this matrix that satisfy the function.
OUTPUT: If indices is not specified, return a matrix with 1 where 𝑓 is satisfied and 0 where it is not. If
indices is specified, return a dictionary containing the elements of this matrix satisfying 𝑓 .
EXAMPLES:
sage: M = matrix(4,3,[1, -1/2, -1, 1, -1, -1/2, -1, 0, 0, 2, 0, 1])
sage: M.find(lambda entry: entry == 0)[0 0 0][0 0 0][0 1 1][0 1 0]>>> from sage.all import *>>> M = matrix(Integer(4),Integer(3),[Integer(1), -Integer(1)/Integer(2), ˓→Integer(1), Integer(1), -Integer(1), -Integer(1)/Integer(2), -Integer(1),␣
˓→Integer(0), Integer(0), Integer(2), Integer(0), Integer(1)])>>> M.find(lambda entry: entry == Integer(0))[0 0 0][0 0 0][0 1 1][0 1 0]sage: M.find(lambda u: u < 0)
[0 1 1][0 1 1][1 0 0][0 0 0]363

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> M.find(lambda u: u < Integer(0))[0 1 1][0 1 1][1 0 0][0 0 0]sage: M = matrix(4,3,[1, -1/2, -1, 1, -1, -1/2, -1, 0, 0, 2, 0, 1])
sage: len(M.find(lambda u:u<1 and u>-1,indices=True))5>>> from sage.all import *>>> M = matrix(Integer(4),Integer(3),[Integer(1), -Integer(1)/Integer(2), ˓→Integer(1), Integer(1), -Integer(1), -Integer(1)/Integer(2), -Integer(1),␣
˓→Integer(0), Integer(0), Integer(2), Integer(0), Integer(1)])>>> len(M.find(lambda u:u<Integer(1) and u>-Integer(1),indices=True))5
sage: M.find(lambda u: u != 1/2)
[1 1 1][1 1 1][1 1 1][1 1 1]>>> from sage.all import *>>> M.find(lambda u: u != Integer(1)/Integer(2))[1 1 1][1 1 1][1 1 1][1 1 1]
sage: M.find(lambda u: u > 1.2)
[0 0 0][0 0 0][0 0 0][1 0 0]>>> from sage.all import *>>> M.find(lambda u: u > RealNumber( 1.2 ))[0 0 0][0 0 0][0 0 0][1 0 0]sage: sorted(M.find(lambda u: u != 0, indices=True).keys()) == M.nonzero_
˓→positions()
True>>> from sage.all import *>>> sorted(M.find(lambda u: u != Integer(0), indices=True).keys()) == M.
˓→nonzero_positions()
True

fitting_ideal(i)Return the 𝑖-th Fitting ideal of the matrix. This is the ideal generated by the 𝑛 − 𝑖 minors, where 𝑛 is the364

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

number of columns.
INPUT:• i – an integer
OUTPUT:
An ideal on the base ring.
EXAMPLES:
sage: R.<x,y,z> = QQ[]
sage: M = matrix(R, [[2*x-z, 0, y-z^2, 1], [0, z - y, z - x, 0],[z - y, x^2 -␣
˓→y, 0, 0]])sage: M[ 2*x - z
0 -z^2 + y
1][0-y + z-x + z0][ -y + z x^2 - y00]
sage: [R.ideal(M.minors(i)) == M.fitting_ideal(4-i) for i in range(5)][True, True, True, True, True]
sage: M.fitting_ideal(0)Ideal (0) of Multivariate Polynomial Ring in x, y, z over Rational Field
sage: M.fitting_ideal(1)Ideal (2*x^4 - 3*x^3*z + x^2*z^2 + y^2*z^2 - 2*y*z^3 + z^4 - 2*x^2*y - y^3 +␣
˓→3*x*y*z + 2*y^2*z - 2*y*z^2, -x^3 + x^2*z + x*y - y*z, y^2 - 2*y*z + z^2,␣˓→x*y - x*z - y*z + z^2) of Multivariate Polynomial Ring in x, y, z over␣˓→Rational Field
sage: M.fitting_ideal(3)Ideal (2*x - z, -z^2 + y, 1, -y + z, -x + z, -y + z, x^2 - y) of Multivariate␣˓→Polynomial Ring in x, y, z over Rational Field
sage: M.fitting_ideal(4)Ideal (1) of Multivariate Polynomial Ring in x, y, z over Rational Field>>> from sage.all import *>>> R = QQ[ x, y, z ]; (x, y, z,) = R._first_ngens(3)>>> M = matrix(R, [[Integer(2)*x-z, Integer(0), y-z**Integer(2), Integer(1)],␣
˓→[Integer(0), z - y, z - x, Integer(0)],[z - y, x**Integer(2) - y,␣˓→Integer(0), Integer(0)]])>>> M[ 2*x - z
0 -z^2 + y
1][0-y + z-x + z0][ -y + z x^2 - y
00]>>> [R.ideal(M.minors(i)) == M.fitting_ideal(Integer(4)-i) for i in␣
˓→range(Integer(5))][True, True, True, True, True]>>> M.fitting_ideal(Integer(0))
Ideal (0) of Multivariate Polynomial Ring in x, y, z over Rational Field>>> M.fitting_ideal(Integer(1))
Ideal (2*x^4 - 3*x^3*z + x^2*z^2 + y^2*z^2 - 2*y*z^3 + z^4 - 2*x^2*y - y^3 +␣
˓→3*x*y*z + 2*y^2*z - 2*y*z^2, -x^3 + x^2*z + x*y - y*z, y^2 - 2*y*z + z^2,␣˓→x*y - x*z - y*z + z^2) of Multivariate Polynomial Ring in x, y, z over␣˓→Rational Field>>> M.fitting_ideal(Integer(3))
Ideal (2*x - z, -z^2 + y, 1, -y + z, -x + z, -y + z, x^2 - y) of Multivariate␣˓→Polynomial Ring in x, y, z over Rational Field>>> M.fitting_ideal(Integer(4))
Ideal (1) of Multivariate Polynomial Ring in x, y, z over Rational Field

If the base ring is a field, the Fitting ideals are zero under the corank:
365

Matrices and Spaces of Matrices, Release 10.4

sage: M = matrix(QQ, [[2,1,3,5],[4,2,6,6],[0,3,2,0]])
sage: M
[2 1 3 5][4 2 6 6][0 3 2 0]
sage: M.fitting_ideal(0)Principal ideal (0) of Rational Field
sage: M.fitting_ideal(1)Principal ideal (1) of Rational Field
sage: M.fitting_ideal(2)Principal ideal (1) of Rational Field
sage: M.fitting_ideal(3)Principal ideal (1) of Rational Field
sage: M.fitting_ideal(4)Principal ideal (1) of Rational Field>>> from sage.all import *>>> M = matrix(QQ, [[Integer(2),Integer(1),Integer(3),Integer(5)],[Integer(4),˓→Integer(2),Integer(6),Integer(6)],[Integer(0),Integer(3),Integer(2),˓→Integer(0)]])>>> M[2 1 3 5][4 2 6 6][0 3 2 0]>>> M.fitting_ideal(Integer(0))
Principal ideal (0) of Rational Field>>> M.fitting_ideal(Integer(1))
Principal ideal (1) of Rational Field>>> M.fitting_ideal(Integer(2))
Principal ideal (1) of Rational Field>>> M.fitting_ideal(Integer(3))
Principal ideal (1) of Rational Field>>> M.fitting_ideal(Integer(4))
Principal ideal (1) of Rational Field

In the case of principal ideal domains, it is given by the elementary divisors:
sage: M = matrix([[2,1,3,5],[4,2,6,6],[0,3,2,0]])
sage: M
[2 1 3 5][4 2 6 6][0 3 2 0]
sage: M.fitting_ideal(0)Principal ideal (0) of Integer Ringsage: M.fitting_ideal(1)Principal ideal (4) of Integer Ringsage: M.fitting_ideal(2)Principal ideal (1) of Integer Ringsage: M.fitting_ideal(3)Principal ideal (1) of Integer Ringsage: M.fitting_ideal(4)Principal ideal (1) of Integer Ringsage: M.elementary_divisors()[1, 1, 4]>>> from sage.all import *>>> M = matrix([[Integer(2),Integer(1),Integer(3),Integer(5)],[Integer(4),(continues on next page)

366

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Integer(2),Integer(6),Integer(6)],[Integer(0),Integer(3),Integer(2),˓→Integer(0)]])>>> M[2 1 3 5][4 2 6 6][0 3 2 0]>>> M.fitting_ideal(Integer(0))
Principal ideal (0) of Integer Ring>>> M.fitting_ideal(Integer(1))
Principal ideal (4) of Integer Ring>>> M.fitting_ideal(Integer(2))
Principal ideal (1) of Integer Ring>>> M.fitting_ideal(Integer(3))
Principal ideal (1) of Integer Ring>>> M.fitting_ideal(Integer(4))
Principal ideal (1) of Integer Ring>>> M.elementary_divisors()[1, 1, 4]˓→This is also true for univariate polynomials over a field:
sage: R.<x> = QQ[]
sage: M = matrix(R,[[x^2-2*x+1, x-1,x^2-1],[0,x+1,1]])
sage: M.fitting_ideal(0)Principal ideal (0) of Univariate Polynomial Ring in x over Rational Field
sage: M.fitting_ideal(1)Principal ideal (x - 1) of Univariate Polynomial Ring in x over Rational Field
sage: M.fitting_ideal(2)Principal ideal (1) of Univariate Polynomial Ring in x over Rational Field
sage: M.smith_form()[0]
[
1
0
0]
[
0 x - 10]>>> from sage.all import *>>> R = QQ[ x ]; (x,) = R._first_ngens(1)>>> M = matrix(R,[[x**Integer(2)-Integer(2)*x+Integer(1), x-Integer(1),˓→x**Integer(2)-Integer(1)],[Integer(0),x+Integer(1),Integer(1)]])>>> M.fitting_ideal(Integer(0))
Principal ideal (0) of Univariate Polynomial Ring in x over Rational Field>>> M.fitting_ideal(Integer(1))
Principal ideal (x - 1) of Univariate Polynomial Ring in x over Rational Field>>> M.fitting_ideal(Integer(2))
Principal ideal (1) of Univariate Polynomial Ring in x over Rational Field>>> M.smith_form()[Integer(0)]
[
1
0
0]
[
0 x - 10]

get_subdivisions()
Returns the current subdivision of self.
EXAMPLES:
sage: M = matrix(5, 5, range(25))
sage: M.subdivisions()([], [])
sage: M.subdivide(2,3)(continues on next page)367

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: M.subdivisions()([2], [3])sage: N = M.parent()(1)
sage: N.subdivide(M.subdivisions()); N[1 0 0|0 0][0 1 0|0 0][-----+---][0 0 1|0 0][0 0 0|1 0][0 0 0|0 1]>>> from sage.all import *>>> M = matrix(Integer(5), Integer(5), range(Integer(25)))>>> M.subdivisions()([], [])>>> M.subdivide(Integer(2),Integer(3))>>> M.subdivisions()([2], [3])>>> N = M.parent()(Integer(1))>>> N.subdivide(M.subdivisions()); N[1 0 0|0 0][0 1 0|0 0][-----+---][0 0 1|0 0][0 0 0|1 0][0 0 0|0 1]

gram_schmidt(orthonormal=False)
Performs Gram-Schmidt orthogonalization on the rows of the matrix, returning a new matrix and a matrix
accomplishing the transformation.
INPUT:• self – a matrix whose rows are to be orthogonalized.
• orthonormal – (default: False); if True the returned orthogonal vectors are unit vectors. This
keyword is ignored if the matrix is over RDF or CDF and the results are always orthonormal.
OUTPUT:
A pair of matrices, G and M such that if A represents self, where the parenthetical properties occur whenorthonormal = True:• A = M*G• The rows of G are an orthogonal (resp. orthonormal) set of vectors.
• G times the conjugate-transpose of G is a diagonal (resp. identity) matrix.
• The row space of G equals the row space of A.
• M is a full-rank matrix with zeros above the diagonal.
For exact rings, any zero vectors produced (when the original vectors are linearly dependent) are not output,
thus the orthonormal set is linearly independent, and thus a basis for the row space of the original matrix.
Any notion of a Gram-Schmidt procedure requires that the base ring of the matrix has a fraction field implemented. In order to arrive at an orthonormal set, it must be possible to construct square roots of the elementsof the base field. In Sage, your best option is the field of algebraic numbers, QQbar, which properly contains
the rationals and number fields.

368

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

If you have an approximate numerical matrix, then this routine requires that your base field be the real andcomplex double-precision floating point numbers, RDF and CDF. In this case, the matrix is treated as having
full rank, as no attempt is made to recognize linear dependence with approximate calculations.
EXAMPLES:
Inexact Rings, Numerical Matrices:First, the inexact rings, CDF and RDF.
sage: # needs scipy sage.rings.complex_double sage.symbolic
sage: A = matrix(CDF, [[ 0.6454 + 0.7491*I, -0.8662 + 0.1489*I, 0.7656 - 0.
˓→00344*I],....:[-0.2913 + 0.8057*I, 0.8321 + 0.8170*I, -0.6744 + 0.
˓→9248*I],....:[ 0.2554 + 0.3517*I, -0.4454 - 0.1715*I, 0.8325 - 0.
˓→6282*I]])sage: G, M = A.gram_schmidt()
sage: G.round(6) # random signs[-0.422243 - 0.490087*I 0.566698 - 0.097416*I -0.500882 + 0.002251*I][-0.057002 - 0.495035*I -0.35059 - 0.625323*I 0.255514 - 0.415284*I][ 0.394105 - 0.421778*I -0.392266 - 0.039345*I -0.352905 + 0.62195*I]
sage: M.round(6) # random[-1.528503
0.0
0.0][ 0.459974 - 0.40061*I-1.741233
0.0][-0.934304 + 0.148868*I
0.54833 + 0.073202*I-0.550725]
sage: (A - M*G).zero_at(10^-12)[0.0 0.0 0.0]
[0.0 0.0 0.0]
[0.0 0.0 0.0]
sage: (G*G.conjugate_transpose()) # random[0.9999999999999999
0.0
0.0]
[
0.0 0.9999999999999997
0.0]
[
0.0
0.0
1.0]
>>> from sage.all import *>>> # needs scipy sage.rings.complex_double sage.symbolic>>> A = matrix(CDF, [[ RealNumber( 0.6454 ) + RealNumber( 0.7491 )*I, ˓→RealNumber( 0.8662 ) + RealNumber( 0.1489 )*I,
RealNumber( 0.7656 ) -␣˓→RealNumber( 0.00344 )*I],...
[-RealNumber( 0.2913 ) + RealNumber( 0.8057 )*I, ␣
˓→RealNumber( 0.8321 ) + RealNumber( 0.8170 )*I, -RealNumber( 0.6744 ) +␣˓→RealNumber( 0.9248 )*I],...
[ RealNumber( 0.2554 ) + RealNumber( 0.3517 )*I, ˓→RealNumber( 0.4454 ) - RealNumber( 0.1715 )*I,
RealNumber( 0.8325 ) -␣˓→RealNumber( 0.6282 )*I]])>>> G, M = A.gram_schmidt()>>> G.round(Integer(6)) # random signs[-0.422243 - 0.490087*I 0.566698 - 0.097416*I -0.500882 + 0.002251*I][-0.057002 - 0.495035*I -0.35059 - 0.625323*I 0.255514 - 0.415284*I][ 0.394105 - 0.421778*I -0.392266 - 0.039345*I -0.352905 + 0.62195*I]>>> M.round(Integer(6)) # random[-1.528503
0.0
0.0][ 0.459974 - 0.40061*I-1.741233
0.0][-0.934304 + 0.148868*I
0.54833 + 0.073202*I-0.550725]>>> (A - M*G).zero_at(Integer(10)**-Integer(12))[0.0 0.0 0.0]
[0.0 0.0 0.0]
[0.0 0.0 0.0]
(continues on next page)369

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> (G*G.conjugate_transpose()) # random[0.9999999999999999
0.0[
0.0 0.9999999999999997
[
0.0
0.0

0.0]
0.0]
1.0]

A rectangular matrix. Note that the orthonormal keyword is ignored in these cases.
sage: # needs scipy
sage: A = matrix(RDF, [[-0.978325, -0.751994, 0.925305, -0.200512, 0.420458],....:[-0.474877, -0.983403, 0.089836, 0.132218, 0.672965]])
sage: G, M = A.gram_schmidt(orthonormal=False)
sage: G.round(6).zero_at(10^-6)[-0.607223 -0.466745 0.574315 -0.124453 0.260968][ 0.123203 -0.617909 -0.530578 0.289773 0.487368]
sage: M.round(6).zero_at(10^-6)[1.611147
0.0][0.958116 0.867778]
sage: (A - M*G).zero_at(10^-12)[0.0 0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0 0.0]
sage: (G*G.transpose()).round(6).zero_at(10^-6)[1.0 0.0][0.0 1.0]>>> from sage.all import *>>> # needs scipy>>> A = matrix(RDF, [[-RealNumber( 0.978325 ), -RealNumber( 0.751994 ),␣
˓→RealNumber( 0.925305 ), -RealNumber( 0.200512 ), RealNumber( 0.420458 )],...
[-RealNumber( 0.474877 ), -RealNumber( 0.983403 ),␣
˓→RealNumber( 0.089836 ),RealNumber( 0.132218 ), RealNumber( 0.672965 )]])>>> G, M = A.gram_schmidt(orthonormal=False)>>> G.round(Integer(6)).zero_at(Integer(10)**-Integer(6))[-0.607223 -0.466745 0.574315 -0.124453 0.260968][ 0.123203 -0.617909 -0.530578 0.289773 0.487368]>>> M.round(Integer(6)).zero_at(Integer(10)**-Integer(6))[1.611147
0.0][0.958116 0.867778]>>> (A - M*G).zero_at(Integer(10)**-Integer(12))[0.0 0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0 0.0]>>> (G*G.transpose()).round(Integer(6)).zero_at(Integer(10)**-Integer(6))[1.0 0.0][0.0 1.0]

Even though a set of vectors may be linearly dependent, no effort is made to decide when a zero vector isreally the result of a relation of linear dependence. So in this regard, input matrices are treated as being offull rank. Try one of the base rings that provide exact results if you need exact results.
sage: # needs scipy
sage: entries = [[1,1,2], [2,1,3], [3,1,4]]
sage: A = matrix(QQ, entries)
sage: A.rank()
2sage: B = matrix(RDF, entries)
sage: G, M = B.gram_schmidt()
sage: G.round(6) # random signs(continues on next page)

370

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[-0.408248 -0.408248 -0.816497][ 0.707107 -0.707107-0.0][ -0.57735 -0.57735
0.57735]
sage: M.round(10) # random[-2.4494897428
0.0
0.0][-3.6742346142 0.7071067812
0.0][-4.8989794856 1.4142135624
0.0]
sage: (A - M*G).zero_at(1e-14)[0.0 0.0 0.0]
[0.0 0.0 0.0]
[0.0 0.0 0.0]
sage: (G*G.transpose()) # abs tol 1e-14[0.9999999999999997
0.0[
0.0 0.9999999999999998
[
0.0
0.0

0.0]
0.0]
1.0]

>>> from sage.all import *>>> # needs scipy>>> entries = [[Integer(1),Integer(1),Integer(2)], [Integer(2),Integer(1),˓→Integer(3)], [Integer(3),Integer(1),Integer(4)]]>>> A = matrix(QQ, entries)>>> A.rank()
2>>> B = matrix(RDF, entries)>>> G, M = B.gram_schmidt()>>> G.round(Integer(6)) # random signs[-0.408248 -0.408248 -0.816497][ 0.707107 -0.707107-0.0][ -0.57735 -0.57735
0.57735]>>> M.round(Integer(10)) # random[-2.4494897428
0.0
0.0][-3.6742346142 0.7071067812
0.0][-4.8989794856 1.4142135624
0.0]>>> (A - M*G).zero_at(RealNumber( 1e-14 ))[0.0 0.0 0.0]
[0.0 0.0 0.0]
[0.0 0.0 0.0]>>> (G*G.transpose()) # abs tol 1e-14[0.9999999999999997
0.0
0.0]
[
0.0 0.9999999999999998
0.0]
[
0.0
0.0
1.0]

Exact Rings, Orthonormalization:
To scale a vector to unit length requires taking a square root, which often takes us outside the base ring. For
the integers and the rationals, the field of algebraic numbers (QQbar) is big enough to contain what we need,but the price is that the computations are very slow, hence mostly of value for small cases or instruction. Now
we need to use the orthonormal keyword.
sage: # needs sage.rings.number_fieldsage: A = matrix(QQbar, [[6, -8, 1],....:[4, 1, 3],....:[6, 3, 3],....:[7, 1, -5],....:
[7, -3, 5]])sage: G, M = A.gram_schmidt(orthonormal=True)(continues on next page)371

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: G
[ 0.5970223141259934? -0.7960297521679913? 0.09950371902099891?][ 0.6063218341690895? 0.5289635311888953? 0.5937772444966257?][ 0.5252981913594170? 0.2941669871612735? -0.798453250866314?]
sage: M
[ 10.04987562112089?
00][ 1.890570661398980? 4.735582601355131?
0][ 1.492555785314984? 7.006153332071100? 1.638930357041381?][ 2.885607851608969? 1.804330147889395? 7.963520581008761?][ 7.064764050490923? 5.626248468100069? -1.197679876299471?]
sage: M*G - A[0 0 0][0 0 0][0 0 0][0 0 0][0 0 0]sage: (G*G.transpose() - identity_matrix(3)).norm() < 10^-10
True
sage: G.row_space() == A.row_space()
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQbar, [[Integer(6), -Integer(8), Integer(1)],...
[Integer(4), Integer(1), Integer(3)],...
[Integer(6), Integer(3), Integer(3)],...
[Integer(7), Integer(1), -Integer(5)],...
[Integer(7), -Integer(3), Integer(5)]])>>> G, M = A.gram_schmidt(orthonormal=True)>>> G[ 0.5970223141259934? -0.7960297521679913? 0.09950371902099891?][ 0.6063218341690895? 0.5289635311888953? 0.5937772444966257?][ 0.5252981913594170? 0.2941669871612735? -0.798453250866314?]>>> M[ 10.04987562112089?
00][ 1.890570661398980? 4.735582601355131?
0][ 1.492555785314984? 7.006153332071100? 1.638930357041381?][ 2.885607851608969? 1.804330147889395? 7.963520581008761?][ 7.064764050490923? 5.626248468100069? -1.197679876299471?]>>> M*G - A[0 0 0][0 0 0][0 0 0][0 0 0][0 0 0]>>> (G*G.transpose() - identity_matrix(Integer(3))).norm() < Integer(10)**˓→Integer(10)True>>> G.row_space() == A.row_space()
True

After Issue #14047, the matrix can also be over the algebraic reals AA:
sage: # needs sage.rings.number_fieldsage: A = matrix(AA, [[6, -8, 1],....:[4, 1, 3],(continues on next page)372

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)....:[6, 3, 3],....:[7, 1, -5],....:
[7, -3, 5]])sage: G, M = A.gram_schmidt(orthonormal=True)
sage: G
[ 0.5970223141259934? -0.7960297521679913? 0.09950371902099891?][ 0.6063218341690895? 0.5289635311888953? 0.5937772444966257?][ 0.5252981913594170? 0.2941669871612735? -0.798453250866314?]
sage: M
[ 10.04987562112089?
00][ 1.890570661398980? 4.735582601355131?
0][ 1.492555785314984? 7.006153332071100? 1.638930357041381?][ 2.885607851608969? 1.804330147889395? 7.963520581008761?][ 7.064764050490923? 5.626248468100069? -1.197679876299471?]>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(AA, [[Integer(6), -Integer(8), Integer(1)],...
[Integer(4), Integer(1), Integer(3)],...
[Integer(6), Integer(3), Integer(3)],...
[Integer(7), Integer(1), -Integer(5)],...
[Integer(7), -Integer(3), Integer(5)]])>>> G, M = A.gram_schmidt(orthonormal=True)>>> G[ 0.5970223141259934? -0.7960297521679913? 0.09950371902099891?][ 0.6063218341690895? 0.5289635311888953? 0.5937772444966257?][ 0.5252981913594170? 0.2941669871612735? -0.798453250866314?]>>> M[ 10.04987562112089?
00][ 1.890570661398980? 4.735582601355131?
0][ 1.492555785314984? 7.006153332071100? 1.638930357041381?][ 2.885607851608969? 1.804330147889395? 7.963520581008761?][ 7.064764050490923? 5.626248468100069? -1.197679876299471?]

Starting with complex numbers with rational real and imaginary parts. Note the use of the conjugate-transpose
when checking the orthonormality.
sage: # needs sage.rings.number_fieldsage: A = matrix(QQbar, [[ -2,-I - 1, 4*I + 2,
-1],
....:
[-4*I, -2*I + 17,
0, 9*I + 1],....:[
1, -2*I - 6, -I + 11, -5*I + 1]])
sage: G, M = A.gram_schmidt(orthonormal=True)
sage: (M*G - A).norm() < 10^-10
True
sage: id3 = G*G.conjugate().transpose()sage: (id3 - identity_matrix(3)).norm() < 10^-10
True
sage: G.row_space() == A.row_space()# long timeTrue>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQbar, [[ -Integer(2),-I - Integer(1), Integer(4)*I +␣˓→Integer(2),-Integer(1)],...
[-Integer(4)*I, -Integer(2)*I + Integer(17),␣˓→Integer(0),Integer(9)*I + Integer(1)],(continues on next page)373

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
[
Integer(1), -Integer(2)*I - Integer(6), -I +␣˓→Integer(11), -Integer(5)*I + Integer(1)]])>>> G, M = A.gram_schmidt(orthonormal=True)>>> (M*G - A).norm() < Integer(10)**-Integer(10)True>>> id3 = G*G.conjugate().transpose()>>> (id3 - identity_matrix(Integer(3))).norm() < Integer(10)**-Integer(10)True>>> G.row_space() == A.row_space()# long timeTrue

A square matrix with small rank. The zero vectors produced as a result of linear dependence get eliminated,so the rows of G are a basis for the row space of A.
sage: # needs sage.rings.number_fieldsage: A = matrix(QQbar, [[2, -6, 3, 8],....:[1, -3, 2, 5],....:[0, 0, 2, 4],....:[2, -6, 3, 8]])sage: A.change_ring(QQ).rank()
2sage: G, M = A.gram_schmidt(orthonormal=True)
sage: G
[ 0.1881441736767195? -0.5644325210301583? 0.2822162605150792?
˓→7525766947068779?][-0.2502818123591464?
0.750845437077439? 0.3688363550555841?
˓→4873908977520218?]
sage: M
[10.630145812734649?
0][ 6.208757731331742? 0.6718090752798139?][ 3.574739299857670? 2.687236301119256?][10.630145812734649?
0]
sage: M*G - A[0 0 0 0][0 0 0 0][0 0 0 0][0 0 0 0]
sage: (G*G.transpose() - identity_matrix(2)).norm() < 10^-10
True
sage: G.row_space() == A.row_space()
True

0.
0.

>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQbar, [[Integer(2), -Integer(6), Integer(3), Integer(8)],...
[Integer(1), -Integer(3), Integer(2), Integer(5)],...
[Integer(0), Integer(0), Integer(2), Integer(4)],...
[Integer(2), -Integer(6), Integer(3), Integer(8)]])>>> A.change_ring(QQ).rank()
2>>> G, M = A.gram_schmidt(orthonormal=True)>>> G[ 0.1881441736767195? -0.5644325210301583? 0.2822162605150792? 0.
˓→7525766947068779?][-0.2502818123591464?
0.750845437077439? 0.3688363550555841? 0.
˓→4873908977520218?](continues on next page)

374

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> M[10.630145812734649?
0][ 6.208757731331742? 0.6718090752798139?][ 3.574739299857670? 2.687236301119256?][10.630145812734649?
0]>>> M*G - A[0 0 0 0][0 0 0 0][0 0 0 0][0 0 0 0]>>> (G*G.transpose() - identity_matrix(Integer(2))).norm() < Integer(10)**˓→Integer(10)True>>> G.row_space() == A.row_space()
True

Exact Rings, Orthogonalization:
If we forego scaling orthogonal vectors to unit vectors, we can apply Gram-Schmidt to a much greater variety of rings. Use the orthonormal=False keyword (or assume it as the default). Note that now theorthogonality check creates a diagonal matrix whose diagonal entries are the squares of the lengths of thevectors.
First, in the rationals, without involving QQbar.
sage: A = matrix(QQ, [[-1, 3, 2, 2],....:[-1, 0, -1, 0],....:[-1, -2, -3, -1],....:
[ 1, 1, 2, 0]])sage: A.rank()
3sage: G, M = A.gram_schmidt()
sage: G[
-1
3
2
2][-19/18
1/6
-8/9
1/9]
[ 2/35 -4/35 -2/35
9/35]
sage: M[100][ -1/181
0][-13/18 59/35
1][
1/3 -48/35-2]
sage: M*G-A[0 0 0 0][0 0 0 0][0 0 0 0][0 0 0 0]
sage: G*G.transpose()
[
18
0
0]
[
0 35/180][0
0 3/35]sage: G.row_space() == A.row_space()
True>>> from sage.all import *>>> A = matrix(QQ, [[-Integer(1), Integer(3), Integer(2), Integer(2)],...
[-Integer(1), Integer(0), -Integer(1), Integer(0)],...
[-Integer(1), -Integer(2), -Integer(3), -Integer(1)],(continues on next page)375

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
[ Integer(1), Integer(1),>>> A.rank()
3>>> G, M = A.gram_schmidt()
>>> G
[
-1
3
2
2]
[-19/18
1/6
-8/9
1/9]
[ 2/35 -4/35 -2/35
9/35]
>>> M
[
1
0
0]
[ -1/181
0][-13/18 59/35
1][
1/3 -48/35-2]>>> M*G-A[0 0 0 0][0 0 0 0][0 0 0 0][0 0 0 0]>>> G*G.transpose()
[
18
0
0]
[
0 35/180][0
0 3/35]>>> G.row_space() == A.row_space()
True

Integer(2),Integer(0)]])

A complex subfield of the complex numbers.
sage: # needs sage.rings.number_fieldsage: C.<z> = CyclotomicField(5)sage: A = matrix(C,....:[[-z^3 - 2*z,-z^3 - 1, 2*z^3 - 2*z^2 +␣
˓→2*z,
1],....:[z^3 - 2*z^2 + 1, -z^3 + 2*z^2 - z - 1,
␣
˓→ -1,z^2 + z],....:[-1/2*z^3 - 2*z^2 + z + 1,-z^3 + z - 2,
-2*z^3 + 1/
˓→2*z^2, 2*z^2 - z + 2]])sage: G, M = A.gram_schmidt(orthonormal=False)
sage: G[-z^3 - 2*z␣˓→-z^3 - 1␣˓→
2*z^3 - 2*z^2 + 2*z
␣
˓→
1]
[
155/139*z^3 - 161/139*z^2 + 31/139*z + 13/139
␣˓→-175/139*z^3 + 180/139*z^2 - 125/139*z - 142/139
␣˓→230/139*z^3 + 124/139*z^2 + 6/139*z + 19/139-14/139*z^
˓→3 + 92/139*z^2 - 6/139*z - 95/139][-10359/19841*z^3 - 36739/39682*z^2 + 24961/39682*z - 11879/39682 -28209/
˓→39682*z^3 - 3671/19841*z^2 + 51549/39682*z - 38613/39682-42769/39682*z^
˓→3 - 615/39682*z^2 - 1252/19841*z - 14392/19841
4895/19841*z^3 + 57885/
˓→39682*z^2 - 46094/19841*z + 65747/39682]
sage: M
[
1
␣
˓→
0
␣
˓→
0]
[
14/139*z^3 + 47/139*z^2 + 145/139*z + 95/139
␣
˓→
1
␣
˓→
0]
(continues on next page)

376

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[-7/278*z^3 + 199/278*z^2 + 183/139*z + 175/278 -3785/39682*z^3␣
˓→+ 3346/19841*z^2 - 3990/19841*z + 2039/19841
␣˓→1]
sage: M*G - A[0 0 0 0][0 0 0 0][0 0 0 0]
sage: G*G.conjugate().transpose()[
15*z^3 + 15*z^2 + 28
␣
˓→
0
␣
˓→ 0]
[
0
463/139*z^
˓→3 + 463/139*z^2 + 1971/139
␣
˓→ 0]
[
0
␣
˓→
0 230983/19841*z^3 + 230983/19841*z^2 + 1003433/
˓→39682]
sage: G.row_space() == A.row_space()
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> C = CyclotomicField(Integer(5), names=( z ,)); (z,) = C._first_ngens(1)>>> A = matrix(C,...
[[-z**Integer(3) - Integer(2)*z,
˓→z**Integer(3) - Integer(1), Integer(2)*z**Integer(3) -␣˓→Integer(2)*z**Integer(2) + Integer(2)*z,
Integer(1)],...
[z**Integer(3) - Integer(2)*z**Integer(2) + Integer(1), ˓→z**Integer(3) + Integer(2)*z**Integer(2) - z - Integer(1),␣˓→-Integer(1),z**Integer(2) + z],...
[-Integer(1)/Integer(2)*z**Integer(3) - Integer(2)*z**Integer(2) +␣
˓→z + Integer(1),-z**Integer(3) + z - Integer(2),˓→Integer(2)*z**Integer(3) + Integer(1)/Integer(2)*z**Integer(2),␣
˓→Integer(2)*z**Integer(2) - z + Integer(2)]])>>> G, M = A.gram_schmidt(orthonormal=False)>>> G[-z^3 - 2*z␣˓→-z^3 - 1␣˓→
2*z^3 - 2*z^2 + 2*z
␣
˓→
1]
[
155/139*z^3 - 161/139*z^2 + 31/139*z + 13/139
␣˓→-175/139*z^3 + 180/139*z^2 - 125/139*z - 142/139
␣˓→230/139*z^3 + 124/139*z^2 + 6/139*z + 19/139-14/139*z^
˓→3 + 92/139*z^2 - 6/139*z - 95/139][-10359/19841*z^3 - 36739/39682*z^2 + 24961/39682*z - 11879/39682 -28209/
˓→39682*z^3 - 3671/19841*z^2 + 51549/39682*z - 38613/39682-42769/39682*z^
˓→3 - 615/39682*z^2 - 1252/19841*z - 14392/19841
4895/19841*z^3 + 57885/
˓→39682*z^2 - 46094/19841*z + 65747/39682]
>>> M
[
1
␣
˓→
0
␣
˓→
0]
[
14/139*z^3 + 47/139*z^2 + 145/139*z + 95/139
␣
˓→
1
␣
˓→
0]
[
-7/278*z^3 + 199/278*z^2 + 183/139*z + 175/278 -3785/39682*z^3␣
(continues on next page)377

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)+ 3346/19841*z^2 - 3990/19841*z + 2039/19841
␣˓→1]>>> M*G - A[0 0 0 0][0 0 0 0][0 0 0 0]>>> G*G.conjugate().transpose()[
15*z^3 + 15*z^2 + 28
␣
˓→
0
␣
˓→ 0]
[
0
463/139*z^
˓→3 + 463/139*z^2 + 1971/139
␣
˓→ 0]
[
0
␣
˓→
0 230983/19841*z^3 + 230983/19841*z^2 + 1003433/
˓→39682]>>> G.row_space() == A.row_space()True˓→A slightly edited legacy example.
sage: A = matrix(ZZ, 3, [-1, 2, 5, -11, 1, 1, 1, -1, -3]); A
[ -1
2
5]
[-11
1
1]
[ 1 -1 -3]
sage: G, mu = A.gram_schmidt()
sage: G[
-1
2
5]
[ -52/5-1/5-2][ 2/187 36/187 -14/187]
sage: mu
[
1
0
0]
[
3/5
1
0]
[ -3/5 -7/187
1]
sage: G.row(0) * G.row(1)0sage: G.row(0) * G.row(2)0sage: G.row(1) * G.row(2)0>>> from sage.all import *>>> A = matrix(ZZ, Integer(3), [-Integer(1), Integer(2), Integer(5), ˓→Integer(11), Integer(1), Integer(1), Integer(1), -Integer(1), -Integer(3)]);
˓→ A
[ -1
2
5]
[-11
1
1]
[ 1 -1 -3]>>> G, mu = A.gram_schmidt()
>>> G
[
-1
2
5]
[ -52/5-1/5-2][ 2/187 36/187 -14/187]>>> mu
[
1
0
0]
[
3/5
1
0]
(continues on next page)

378

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ -3/5 -7/187
1]>>> G.row(Integer(0)) * G.row(Integer(1))
0>>> G.row(Integer(0)) * G.row(Integer(2))
0>>> G.row(Integer(1)) * G.row(Integer(2))
0

The relation between mu and A is as follows.
sage: mu*G == A
True>>> from sage.all import *>>> mu*G == A
True

hadamard_bound()Return an int n such that the absolute value of the determinant of this matrix is at most 10𝑛 .
This is got using both the row norms and the column norms.
This function only makes sense when the base field can be coerced to the real double field RDF or the MPFR
Real Field with 53-bits precision.
EXAMPLES:
sage: a = matrix(ZZ, 3, [1,2,5,7,-3,4,2,1,123])
sage: a.hadamard_bound()4
sage: a.det()-2014
sage: 10^4
10000>>> from sage.all import *>>> a = matrix(ZZ, Integer(3), [Integer(1),Integer(2),Integer(5),Integer(7),˓→Integer(3),Integer(4),Integer(2),Integer(1),Integer(123)])>>> a.hadamard_bound()4>>> a.det()-2014>>> Integer(10)**Integer(4)10000

In this example the Hadamard bound has to be computed (automatically) using MPFR instead of doubles,
since doubles overflow:
sage: a = matrix(ZZ, 2, [2^10000, 3^10000, 2^50, 3^19292])
sage: a.hadamard_bound()12215
sage: len(str(a.det()))
12215>>> from sage.all import *>>> a = matrix(ZZ, Integer(2), [Integer(2)**Integer(10000),␣
(continues on next page)379

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Integer(3)**Integer(10000), Integer(2)**Integer(50),␣
˓→Integer(3)**Integer(19292)])>>> a.hadamard_bound()12215>>> len(str(a.det()))
12215
˓→

hermite_form(include_zero_rows=True, transformation=False)
Return the Hermite form of self, if it is defined.
INPUT:• include_zero_rows – bool (default: True); if False the zero rows in the output matrix are deleted.
• transformation – bool (default: False) a matrix U such that U*self == H.
OUTPUT:• matrix H• (optional) transformation matrix U such that U*self == H, possibly with zero rows deleted…
EXAMPLES:
sage: M = FunctionField(GF(7), x ).maximal_order()sage: K.<x> = FunctionField(GF(7)); M = K.maximal_order()sage: A = matrix(M, 2, 3, [x, 1, 2*x, x, 1 + x, 2])
sage: A.hermite_form()
[
x
1
2*x]
[
0
x 5*x + 2]
sage: A.hermite_form(transformation=True)([x12*x] [1 0][0x 5*x + 2], [6 1])sage: A = matrix(M, 2, 3, [x, 1, 2*x, 2*x, 2, 4*x])
sage: A.hermite_form(transformation=True, include_zero_rows=False)([ x
1 2*x], [1 0])
sage: H, U = A.hermite_form(transformation=True, include_zero_rows=True)
sage: H, U(
[ x
1 2*x] [1 0][ 000], [5 1])
sage: U * A == H
True
sage: H, U = A.hermite_form(transformation=True, include_zero_rows=False)
sage: U * A[ x
1 2*x]
sage: U * A == H
True>>> from sage.all import *>>> M = FunctionField(GF(Integer(7)), x ).maximal_order()>>> K = FunctionField(GF(Integer(7)), names=( x ,)); (x,) = K._first_ngens(1);˓→ M = K.maximal_order()>>> A = matrix(M, Integer(2), Integer(3), [x, Integer(1), Integer(2)*x, x,␣
˓→Integer(1) + x, Integer(2)])(continues on next page)

380

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> A.hermite_form()
[
x
1
2*x]
[
0
x 5*x + 2]>>> A.hermite_form(transformation=True)([x12*x] [1 0][0x 5*x + 2], [6 1])>>> A = matrix(M, Integer(2), Integer(3), [x, Integer(1), Integer(2)*x,␣
˓→Integer(2)*x, Integer(2), Integer(4)*x])>>> A.hermite_form(transformation=True, include_zero_rows=False)([ x
1 2*x], [1 0])>>> H, U = A.hermite_form(transformation=True, include_zero_rows=True)>>> H, U([ x
1 2*x] [1 0][ 000], [5 1])>>> U * A == H
True>>> H, U = A.hermite_form(transformation=True, include_zero_rows=False)>>> U * A
[ x
1 2*x]>>> U * A == H
Truehessenberg_form()
Return Hessenberg form of self.
If the base ring is merely an integral domain (and not a field), the Hessenberg form will (in general) only be
defined over the fraction field of the base ring.
EXAMPLES:
sage: A = matrix(ZZ, 4, [2, 1, 1, -2, 2, 2, -1, -1, -1,1,2,3,4,5,6,7])
sage: h = A.hessenberg_form(); h[2 -7/2 -19/5-2][
2
1/2 -17/5-1][
0 25/4 15/2
5/2][
0
0 58/53]sage: parent(h)Full MatrixSpace of 4 by 4 dense matrices over Rational Field
sage: A.hessenbergize()
Traceback (most recent call last):...
TypeError: Hessenbergize only possible for matrices over a field>>> from sage.all import *>>> A = matrix(ZZ, Integer(4), [Integer(2), Integer(1), Integer(1), ˓→Integer(2), Integer(2), Integer(2), -Integer(1), -Integer(1), -Integer(1),˓→Integer(1),Integer(2),Integer(3),Integer(4),Integer(5),Integer(6),˓→Integer(7)])>>> h = A.hessenberg_form(); h[2 -7/2 -19/5-2][
2
1/2 -17/5-1][
0 25/4 15/2
5/2][
0
0 58/53](continues on next page)381

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> parent(h)Full MatrixSpace of 4 by 4 dense matrices over Rational Field>>> A.hessenbergize()
Traceback (most recent call last):...
TypeError: Hessenbergize only possible for matrices over a field

hessenbergize()
Transform self to Hessenberg form.
The hessenberg form of a matrix 𝐴 is a matrix that is similar to 𝐴, so has the same characteristic polynomialas 𝐴, and is upper triangular except possible for entries right below the diagonal.
ALGORITHM: See Henri Cohen’s first book.
EXAMPLES:
sage: A = matrix(QQ, 3, [2, 1, 1, -2, 2, 2, -1, -1, -1])
sage: A.hessenbergize(); A[ 2 3/2
1]
[ -2
3
2]
[ 0 -3 -2]>>> from sage.all import *>>> A = matrix(QQ, Integer(3), [Integer(2), Integer(1), Integer(1), ˓→Integer(2), Integer(2), Integer(2), -Integer(1), -Integer(1), -Integer(1)])>>> A.hessenbergize(); A[ 2 3/2
1]
[ -2
3
2]
[ 0 -3 -2]
sage: A = matrix(QQ, 4, [2, 1, 1, -2, 2, 2, -1, -1, -1,1,2,3,4,5,6,7])
sage: A.hessenbergize(); A[
2 -7/2 -19/5-2][
2
1/2 -17/5-1][
0 25/4 15/2
5/2][
0
0 58/53]>>> from sage.all import *>>> A = matrix(QQ, Integer(4), [Integer(2), Integer(1), Integer(1), ˓→Integer(2), Integer(2), Integer(2), -Integer(1), -Integer(1), -Integer(1),˓→Integer(1),Integer(2),Integer(3),Integer(4),Integer(5),Integer(6),˓→Integer(7)])>>> A.hessenbergize(); A[
2 -7/2 -19/5-2][
2
1/2 -17/5-1][
0 25/4 15/2
5/2][
0
0 58/5
3]

You can’t Hessenbergize an immutable matrix:
sage: A = matrix(QQ, 3, [1..9])sage: A.set_immutable()sage: A.hessenbergize()
Traceback (most recent call last):...
(continues on next page)382

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

ValueError: matrix is immutable; please change a copy instead (i.e., use␣˓→copy(M) to change a copy of M).
>>> from sage.all import *>>> A = matrix(QQ, Integer(3), (ellipsis_range(Integer(1),Ellipsis,
˓→Integer(9))))>>> A.set_immutable()>>> A.hessenbergize()
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).

image()
Return the image of the homomorphism on rows defined by right multiplication by this matrix: that is, therow-space.
EXAMPLES:
sage: MS1 = MatrixSpace(ZZ, 4)
sage: MS2 = MatrixSpace(QQ, 6)
sage: A = MS1.matrix([3,4,5,6, 7,3,8,10, 14,5,6,7, 2,2,10,9])
sage: B = MS2.random_element()>>> from sage.all import *>>> MS1 = MatrixSpace(ZZ, Integer(4))>>> MS2 = MatrixSpace(QQ, Integer(6))>>> A = MS1.matrix([Integer(3),Integer(4),Integer(5),Integer(6), Integer(7),˓→Integer(3),Integer(8),Integer(10), Integer(14),Integer(5),Integer(6),˓→Integer(7), Integer(2),Integer(2),Integer(10),Integer(9)])>>> B = MS2.random_element()
sage: image(A)Free module of degree 4 and rank 4 over Integer Ring
Echelon basis matrix:[ 1
00 426][ 01
0 518][ 00
1 293][ 00
0 687]>>> from sage.all import *>>> image(A)Free module of degree 4 and rank 4 over Integer Ring
Echelon basis matrix:[ 1
00 426][ 01
0 518][ 00
1 293][ 00
0 687]
sage: image(B) == B.row_module()True
sage: image(B) == B.transpose().column_module()
True

383

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> image(B) == B.row_module()
True>>> image(B) == B.transpose().column_module()
True

See also:
row_module(), column_module()
indefinite_factorization(algorithm='symmetric', check=True)
Decomposes a symmetric or Hermitian matrix into a lower triangular matrix and a diagonal matrix.
INPUT:• self – a square matrix over a ring. The base ring must have an implemented fraction field.
• algorithm – default: symmetric . Either symmetric or hermitian , according to if
the input matrix is symmetric or hermitian.
• check – (default: True); if True then performs the check that the matrix is consistent with thealgorithm keyword.
OUTPUT:
A lower triangular matrix 𝐿 with each diagonal element equal to 1 and a vector of entries that form a diagonal
matrix 𝐷. The vector of diagonal entries can be easily used to form the matrix, as demonstrated below in theexamples.
For a symmetric matrix, 𝐴, these will be related by
𝐴 = 𝐿𝐷𝐿𝑇If 𝐴 is Hermitian matrix, then the transpose of 𝐿 should be replaced by the conjugate-transpose of 𝐿.
If any leading principal submatrix (a square submatrix in the upper-left corner) is singular then this method
will fail with a ValueError.
ALGORITHM:
The algorithm employed only uses field operations, but the computation of each diagonal entry has the potential for division by zero. The number of operations is of order 𝑛3 /3, which is half the count for an LU
decomposition. This makes it an appropriate candidate for solving systems with symmetric (or Hermitian)coefficient matrices.
See also:
block_ldlt()
EXAMPLES:
There is no requirement that a matrix be positive definite, as indicated by the negative entries in the resulting
diagonal matrix. The default is that the input matrix is symmetric.
sage: A = matrix(QQ, [[ 3, -6,
9,
6, -9],....:[-6, 11, -16, -11, 17],....:
[ 9, -16, 28, 16, -40],....:[ 6, -11, 16,
9, -19],....:[-9, 17, -40, -19, 68]])
sage: A.is_symmetric()True
sage: L, d = A.indefinite_factorization()(continues on next page)384

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: D = diagonal_matrix(d)sage: L[ 1 0 0 0 0][-2 1 0 0 0]
[ 3 -2 1 0 0]
[ 2 -1 0 1 0][-3 1 -3 1 1]
sage: D[ 3 0 0 0 0]
[ 0 -1 0 0 0]
[ 0 0 5 0 0]
[ 0 0 0 -2 0][ 0 0 0 0 -1]
sage: A == L*D*L.transpose()True>>> from sage.all import *>>> A = matrix(QQ, [[ Integer(3), -Integer(6),Integer(9),Integer(6), ˓→Integer(9)],...
[-Integer(6), Integer(11), -Integer(16), -Integer(11), ␣
˓→Integer(17)],...
[ Integer(9), -Integer(16), Integer(28), Integer(16), ˓→Integer(40)],...
[ Integer(6), -Integer(11), Integer(16),Integer(9), ˓→Integer(19)],...
[-Integer(9), Integer(17), -Integer(40), -Integer(19), ␣
˓→Integer(68)]])>>> A.is_symmetric()
True>>> L, d = A.indefinite_factorization()>>> D = diagonal_matrix(d)>>> L[ 1 0 0 0 0][-2 1 0 0 0]
[ 3 -2 1 0 0]
[ 2 -1 0 1 0][-3 1 -3 1 1]>>> D
[ 3 0 0 0 0]
[ 0 -1 0 0 0]
[ 0 0 5 0 0]
[ 0 0 0 -2 0][ 0 0 0 0 -1]>>> A == L*D*L.transpose()
True

Optionally, Hermitian matrices can be factored and the result has a similar property (but not identical). Here,the field is all complex numbers with rational real and imaginary parts. As theory predicts, the diagonal entries
will be real numbers.
sage: # needs sage.rings.number_fieldsage: C.<I> = QuadraticField(-1)
sage: B = matrix(C, [[2, 4 - 2*I, 2 + 2*I],....:[4 + 2*I,
8,
10*I],....:[2 - 2*I,-10*I,-3]])sage: B.is_hermitian()(continues on next page)385

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)True
sage: L, d = B.indefinite_factorization(algorithm= hermitian )sage: D = diagonal_matrix(d)sage: L[100]
[ I + 2
1
0]
[ -I + 1 2*I + 1
1]
sage: D[ 2 0 0][ 0 -2 0][ 0 0 3]sage: B == L*D*L.conjugate_transpose()True>>> from sage.all import *>>> # needs sage.rings.number_field>>> C = QuadraticField(-Integer(1), names=( I ,)); (I,) = C._first_ngens(1)>>> B = matrix(C, [[Integer(2), Integer(4) - Integer(2)*I, Integer(2) +␣˓→Integer(2)*I],...
[Integer(4) + Integer(2)*I,
Integer(8),␣˓→Integer(10)*I],...
[Integer(2) - Integer(2)*I,-Integer(10)*I,
˓→Integer(3)]])>>> B.is_hermitian()
True>>> L, d = B.indefinite_factorization(algorithm= hermitian )>>> D = diagonal_matrix(d)
>>> L
[
1
0
0]
[ I + 2
1
0]
[ -I + 1 2*I + 1
1]>>> D[ 2 0 0][ 0 -2 0][ 0 0 3]>>> B == L*D*L.conjugate_transpose()
True

If a leading principal submatrix has zero determinant, this algorithm will fail. This will never happen with apositive definite matrix.
sage: A = matrix(QQ, [[21, 15, 12, -2],....:
[15, 12, 9, 6],....:[12, 9, 7, 3],....:[-2, 6, 3, 8]])sage: A.is_symmetric()True
sage: A[0:3,0:3].det() == 0
True
sage: A.indefinite_factorization()
Traceback (most recent call last):...
ValueError: 3x3 leading principal submatrix is singular,
so cannot create indefinite factorization

386

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = matrix(QQ, [[Integer(21), Integer(15), Integer(12), -Integer(2)],...
[Integer(15), Integer(12), Integer(9), Integer(6)],...
[Integer(12), Integer(9), Integer(7), Integer(3)],...
[-Integer(2), Integer(6), Integer(3), Integer(8)]])>>> A.is_symmetric()
True>>> A[Integer(0):Integer(3),Integer(0):Integer(3)].det() == Integer(0)True>>> A.indefinite_factorization()
Traceback (most recent call last):...
ValueError: 3x3 leading principal submatrix is singular,
so cannot create indefinite factorization

This algorithm only depends on field operations, so outside of the singular submatrix situation, any matrix
may be factored. This provides a reasonable alternative to the Cholesky decomposition.
sage: # needs sage.rings.finite_rings
sage: F.<a> = FiniteField(5^3)
sage: A = matrix(F,....:[[a^2 + 2*a, 4*a^2 + 3*a + 4,
3*a^2 + a, 2*a^2 + 2*a +␣
˓→1],
....:
[4*a^2 + 3*a + 4,
4*a^2 + 2,
3*a, 2*a^2 + 4*a +␣
˓→2],
....:
[
3*a^2 + a,3*a,
3*a^2 + 2, 3*a^2 + 2*a +␣
˓→3],
....:
[2*a^2 + 2*a + 1, 2*a^2 + 4*a + 2, 3*a^2 + 2*a + 3, 3*a^2 + 2*a +␣
˓→4]])
sage: A.is_symmetric()True
sage: L, d = A.indefinite_factorization()sage: D = diagonal_matrix(d)sage: L[1000][4*a^2 + 4*a + 3
1
0
0]
[
3
4*a^2 + a + 2
1
0][
4*a^2 + 4 2*a^2 + 3*a + 3 2*a^2 + 3*a + 1
1]
sage: D[a^2 + 2*a000][0 2*a^2 + 2*a + 4
00][00 3*a^2 + 4*a + 3
0]
[
0
0
0
a^2 + 3*a]sage: A == L*D*L.transpose()True>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> F = FiniteField(Integer(5)**Integer(3), names=( a ,)); (a,) = F._first_
˓→ngens(1)>>> A = matrix(F,...
[[a**Integer(2) + Integer(2)*a, Integer(4)*a**Integer(2) +␣˓→Integer(3)*a + Integer(4),Integer(3)*a**Integer(2) + a,␣
˓→Integer(2)*a**Integer(2) + Integer(2)*a + Integer(1)],...
[Integer(4)*a**Integer(2) + Integer(3)*a + Integer(4),␣˓→Integer(4)*a**Integer(2) + Integer(2),Integer(3)*a,␣
˓→Integer(2)*a**Integer(2) + Integer(4)*a + Integer(2)],(continues on next page)387

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
[
Integer(3)*a**Integer(2) + a,
Integer(3)*a,
˓→Integer(3)*a**Integer(2) + Integer(2), Integer(3)*a**Integer(2) +␣˓→Integer(2)*a + Integer(3)],...
[Integer(2)*a**Integer(2) + Integer(2)*a + Integer(1),␣
˓→Integer(2)*a**Integer(2) + Integer(4)*a + Integer(2),␣
˓→Integer(3)*a**Integer(2) + Integer(2)*a + Integer(3),␣
˓→Integer(3)*a**Integer(2) + Integer(2)*a + Integer(4)]])>>> A.is_symmetric()
True>>> L, d = A.indefinite_factorization()>>> D = diagonal_matrix(d)
>>> L
[
1
0
0
0]
[4*a^2 + 4*a + 3
1
0
0]
[
3
4*a^2 + a + 2
1
0][
4*a^2 + 4 2*a^2 + 3*a + 3 2*a^2 + 3*a + 1
1]
>>> D
[
a^2 + 2*a000][0 2*a^2 + 2*a + 4
00][00 3*a^2 + 4*a + 3
0]
[
0
0
0
a^2 + 3*a]>>> A == L*D*L.transpose()
True␣This works correctly for the 0x0 matrix:
sage: Matrix(0).indefinite_factorization()([], ())>>> from sage.all import *>>> Matrix(Integer(0)).indefinite_factorization()([], ())

integer_kernel(ring='ZZ')
Return the kernel of this matrix over the given ring (which should be either the base ring, or a PID whose
fraction field is the base ring).
Assume that the base field of this matrix has a numerator and denominator functions for its elements, e.g., itis the rational numbers or a fraction field. This function computes a basis over the integers for the kernel ofself.
If the matrix is not coercible into QQ, then the PID itself should be given as a second argument, as in thethird example below.
EXAMPLES:
sage: A = MatrixSpace(QQ, 4)(range(16))
sage: A.integer_kernel()
Free module of degree 4 and rank 2 over Integer Ring
Echelon basis matrix:[ 1 0 -3 2][ 0 1 -2 1]>>> from sage.all import *>>> A = MatrixSpace(QQ, Integer(4))(range(Integer(16)))>>> A.integer_kernel()(continues on next page)

388

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Free module of degree 4 and rank 2 over Integer Ring
Echelon basis matrix:[ 1 0 -3 2][ 0 1 -2 1]

The integer kernel even makes sense for matrices with fractional entries:
sage: A = MatrixSpace(QQ, 2)([1/2, 0, 0, 0])
sage: A.integer_kernel()
Free module of degree 2 and rank 1 over Integer Ring
Echelon basis matrix:[0 1]>>> from sage.all import *>>> A = MatrixSpace(QQ, Integer(2))([Integer(1)/Integer(2), Integer(0),␣
˓→Integer(0), Integer(0)])>>> A.integer_kernel()
Free module of degree 2 and rank 1 over Integer Ring
Echelon basis matrix:[0 1]

An example over a bigger ring:sage: # needs sage.rings.number_fieldsage: x = polygen(ZZ, x )sage: L.<w> = NumberField(x^2 - x + 2)
sage: OL = L.ring_of_integers()
sage: A = matrix(L, 2, [1, w/2])
sage: A.integer_kernel(OL)Free module of degree 2 and rank 1 overMaximal Order generated by w in Number Field in w
with defining polynomial x^2 - x + 2
Echelon basis matrix:[-1 -w + 1]>>> from sage.all import *>>> # needs sage.rings.number_field>>> x = polygen(ZZ, x )>>> L = NumberField(x**Integer(2) - x + Integer(2), names=( w ,)); (w,) = L._˓→first_ngens(1)>>> OL = L.ring_of_integers()>>> A = matrix(L, Integer(2), [Integer(1), w/Integer(2)])>>> A.integer_kernel(OL)Free module of degree 2 and rank 1 overMaximal Order generated by w in Number Field in w
with defining polynomial x^2 - x + 2
Echelon basis matrix:[-1 -w + 1]

inverse()Returns the inverse of self, without changing self.
Note that one can use the Python inverse operator to obtain the inverse as well.
See also:
inverse_positive_definite()389

Matrices and Spaces of Matrices, Release 10.4

EXAMPLES:
sage: m = matrix([[1,2],[3,4]])
sage: m^(-1)[ -2
1][ 3/2 -1/2]
sage: m.inverse()[ -2
1][ 3/2 -1/2]
sage: ~m
[ -2
1]
[ 3/2 -1/2]>>> from sage.all import *>>> m = matrix([[Integer(1),Integer(2)],[Integer(3),Integer(4)]])>>> m**(-Integer(1))[ -2
1][ 3/2 -1/2]>>> m.inverse()[ -2
1][ 3/2 -1/2]>>> ~m[ -2
1][ 3/2 -1/2]
sage: m = matrix([[1,2],[3,4]], sparse=True)
sage: m^(-1)[ -2
1][ 3/2 -1/2]
sage: m.inverse()[ -2
1][ 3/2 -1/2]
sage: ~m
[ -2
1]
[ 3/2 -1/2]>>> from sage.all import *>>> m = matrix([[Integer(1),Integer(2)],[Integer(3),Integer(4)]], sparse=True)>>> m**(-Integer(1))[ -2
1][ 3/2 -1/2]>>> m.inverse()[ -2
1][ 3/2 -1/2]>>> ~m[ -2
1][ 3/2 -1/2]

inverse_positive_definite()
Compute the inverse of a positive-definite matrix.
In accord with is_positive_definite(), only Hermitian matrices are considered positive-definite.
Positive-definite matrices have several factorizations (Cholesky, LDLT, et cetera) that allow them to be inverted in a fast, numerically-stable way. This method uses an appropriate factorization, and is akin to thecholinv and chol2inv functions available in R, Octave, and Stata.
You should ensure that your matrix is positive-definite before using this method. When in doubt, use thegeneric inverse() method instead.
390

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

OUTPUT:
If the given matrix is positive-definite, the return value is the same as that of the inverse() method. If
the matrix is not positive-definite, the behavior of this function is undefined.
See also:
inverse(), is_positive_definite(), cholesky(), indefinite_factorization()
EXAMPLES:
A simple two-by-two matrix with rational entries:
sage: A = matrix(QQ, [[ 2, -1],....:[-1, 2]])sage: A.is_positive_definite()True
sage: A.inverse_positive_definite()[2/3 1/3][1/3 2/3]
sage: A.inverse_positive_definite() == A.inverse()
True>>> from sage.all import *>>> A = matrix(QQ, [[ Integer(2), -Integer(1)],...
[-Integer(1), Integer(2)]])>>> A.is_positive_definite()
True>>> A.inverse_positive_definite()[2/3 1/3][1/3 2/3]>>> A.inverse_positive_definite() == A.inverse()
True

A matrix containing real roots:
sage: # needs sage.rings.number_field sage.symbolic
sage: A = matrix(AA, [ [1,0,sqrt(2)],....:[0,sqrt(3), 0],....:[sqrt(2), 0,
sqrt(5)] ])sage: A.is_positive_definite()True
sage: B = matrix(AA, [ [2*sqrt(5) + 5, 0, -sqrt(8*sqrt(5) + 18)],
....:
[0,
sqrt(1/3),
0],
....:
[-sqrt(8*sqrt(5) + 18), 0, sqrt(5) + 2] ])sage: A.inverse_positive_definite() == B
True
sage: A*B == A.matrix_space().identity_matrix()True>>> from sage.all import *>>> # needs sage.rings.number_field sage.symbolic>>> A = matrix(AA, [ [Integer(1),Integer(0),sqrt(Integer(2))],...
[Integer(0),sqrt(Integer(3)), Integer(0)],...
[sqrt(Integer(2)), Integer(0),sqrt(Integer(5))] ])>>> A.is_positive_definite()
True>>> B = matrix(AA, [ [Integer(2)*sqrt(Integer(5)) + Integer(5), Integer(0), ˓→sqrt(Integer(8)*sqrt(Integer(5)) + Integer(18))],(continues on next page)391

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...

[Integer(0),sqrt(Integer(1)/Integer(3)),˓→
Integer(0)],...
[-sqrt(Integer(8)*sqrt(Integer(5)) + Integer(18)),␣
˓→Integer(0), sqrt(Integer(5)) + Integer(2)] ])>>> A.inverse_positive_definite() == B
True>>> A*B == A.matrix_space().identity_matrix()
True␣A Hermitian (but not symmetric) matrix with complex entries:
sage: # needs sage.rings.number_field sage.symbolic
sage: A = matrix(QQbar, [ [ 1, 0,
I ],
....:
[ 0, sqrt(5), 0 ],....:[-I, 0,3 ] ])
sage: A.is_positive_definite()True
sage: B = matrix(QQbar, [ [ 3/2, 0,-I/2 ],....:[ 0,
sqrt(1/5), 0],....:[ I/2, 0,
1/2 ] ])
sage: A.inverse_positive_definite() == B
True
sage: A*B == A.matrix_space().identity_matrix()True>>> from sage.all import *>>> # needs sage.rings.number_field sage.symbolic>>> A = matrix(QQbar, [ [ Integer(1), Integer(0),I ],...
[ Integer(0), sqrt(Integer(5)), Integer(0) ],...
[-I, Integer(0),Integer(3) ] ])>>> A.is_positive_definite()
True>>> B = matrix(QQbar, [ [ Integer(3)/Integer(2), Integer(0),-I/
˓→Integer(2) ],...
[ Integer(0),sqrt(Integer(1)/Integer(5)),␣
˓→Integer(0)],...
[ I/Integer(2), Integer(0),Integer(1)/˓→Integer(2) ] ])>>> A.inverse_positive_definite() == B
True>>> A*B == A.matrix_space().identity_matrix()
True

is_Z_operator_on(K)Determine if this matrix is a Z-operator on a cone.
We say that a matrix 𝐿 is a Z-operator on a closed convex cone 𝐾 if the inner product of 𝐿𝑥 and 𝑠 is
nonpositive for all pairs of orthogonal vectors 𝑥 in 𝐾 and 𝑠 in the dual of 𝐾. This property need only bechecked for generators of 𝐾 and its dual.
A matrix is a Z-operator on 𝐾 if and only if its negation is a cross-positive operator on 𝐾.
To reliably check whether or not this matrix is a Z operator, its base ring must be either exact (for example,
the rationals) or the symbolic ring. An exact ring is more reliable, but in some cases a matrix whose entries
contain symbolic constants like 𝑒 and 𝜋 will work.
INPUT:

392

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

• K – a polyhedral closed convex cone.
OUTPUT:
If the base ring of this matrix is exact, then True will be returned if and only if this matrix is a Z-operator
on K.
If the base ring of this matrix is symbolic, then the situation is more complicated:• True will be returned if it can be proven that this matrix is a Z-operator on K.
• False will be returned if it can be proven that this matrix is not a Z-operator on K.
• False will also be returned if we can’t decide; specifically if we arrive at a symbolic inequality thatcannot be resolved.
See also:
is_positive_operator_on(), is_cross_positive_on(), is_lyapunov_like_on()
REFERENCES:
A. Berman and R. J. Plemmons. Nonnegative Matrices in the Mathematical Sciences. SIAM, Philadelphia,
1994.
EXAMPLES:
Z-matrices are Z-operators on the nonnegative orthant:
sage: K = Cone([(1,0,0), (0,1,0), (0,0,1)])
˓→needs sage.geometry.polyhedronsage: L = matrix(SR, [ [-1, -2, 0],
˓→needs sage.symbolic....:[ 0, 2, -7],....:[-3, 0, 3] ])sage: L.is_Z_operator_on(K)˓→needs sage.geometry.polyhedron sage.symbolic
True

#␣
#␣

#␣

>>> from sage.all import *>>> K = Cone([(Integer(1),Integer(0),Integer(0)), (Integer(0),Integer(1),˓→Integer(0)), (Integer(0),Integer(0),Integer(1))])␣˓→# needs sage.geometry.polyhedron>>> L = matrix(SR, [ [-Integer(1), -Integer(2), Integer(0)],␣˓→# needs sage.symbolic...
[ Integer(0), Integer(2), -Integer(7)],...
[-Integer(3), Integer(0), Integer(3)] ])>>> L.is_Z_operator_on(K)#␣˓→needs sage.geometry.polyhedron sage.symbolic
True

Symbolic entries also work in some easy cases:
sage: K = Cone([(1,0,0), (0,1,0), (0,0,1)])
˓→needs sage.geometry.polyhedronsage: L = matrix(SR, [ [-1,-e, 0 ],
˓→needs sage.symbolic
....:
[ 0,
2, -pi],....:[-sqrt(2), 0, 3 ] ])sage: L.is_Z_operator_on(K)˓→needs sage.geometry.polyhedron sage.symbolic
True

#␣
#␣

#␣

393

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> K = Cone([(Integer(1),Integer(0),Integer(0)), (Integer(0),Integer(1),˓→Integer(0)), (Integer(0),Integer(0),Integer(1))])␣˓→# needs sage.geometry.polyhedron>>> L = matrix(SR, [ [-Integer(1),-e, Integer(0) ],␣˓→# needs sage.symbolic...
[ Integer(0),Integer(2), -pi],...
[-sqrt(Integer(2)), Integer(0), Integer(3) ] ])>>> L.is_Z_operator_on(K)#␣˓→needs sage.geometry.polyhedron sage.symbolicTrueis_bistochastic(normalized=True)
Returns True if this matrix is bistochastic.
A matrix is said to be bistochastic if both the sums of the entries of each row and the sum of the entries ofeach column are equal to 1 and all entries are nonnegative.
INPUT:• normalized – if set to True (default), checks that the sums are equal to 1. When set to False,
checks that the row sums and column sums are all equal to some constant possibly different from 1.
EXAMPLES:
The identity matrix is clearly bistochastic:
sage: Matrix(5,5,1).is_bistochastic()
True>>> from sage.all import *>>> Matrix(Integer(5),Integer(5),Integer(1)).is_bistochastic()True

The same matrix, multiplied by 2, is not bistochastic anymore, though is verifies the constraints of normalized == False:
sage: (2 * Matrix(5,5,1)).is_bistochastic()
False
sage: (2 * Matrix(5,5,1)).is_bistochastic(normalized=False)
True>>> from sage.all import *>>> (Integer(2) * Matrix(Integer(5),Integer(5),Integer(1))).is_bistochastic()
False>>> (Integer(2) * Matrix(Integer(5),Integer(5),Integer(1))).is_˓→bistochastic(normalized=False)
True

Here is a matrix whose row and column sums is 1, but not all entries are nonnegative:
sage: m = matrix([[-1,2],[2,-1]])
sage: m.is_bistochastic()
False>>> from sage.all import *>>> m = matrix([[-Integer(1),Integer(2)],[Integer(2),-Integer(1)]])(continues on next page)394

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> m.is_bistochastic()
False

is_cross_positive_on(K)Determine if this matrix is cross-positive on a cone.
We say that a matrix 𝐿 is cross-positive on a closed convex cone 𝐾 if the inner product of 𝐿𝑥 and 𝑠 isnonnegative for all pairs of orthogonal vectors 𝑥 in 𝐾 and 𝑠 in the dual of 𝐾. This property need only bechecked for generators of 𝐾 and its dual.
To reliably check whether or not this matrix is cross-positive, its base ring must be either exact (for example,
the rationals) or the symbolic ring. An exact ring is more reliable, but in some cases a matrix whose entries
contain symbolic constants like 𝑒 and 𝜋 will work.
INPUT:• K – a polyhedral closed convex cone.
OUTPUT:
If the base ring of this matrix is exact, then True will be returned if and only if this matrix is cross-positiveon K.
If the base ring of this matrix is symbolic, then the situation is more complicated:• True will be returned if it can be proven that this matrix is cross-positive on K.
• False will be returned if it can be proven that this matrix is not cross-positive on K.
• False will also be returned if we can’t decide; specifically if we arrive at a symbolic inequality thatcannot be resolved.
See also:
is_positive_operator_on(), is_Z_operator_on(), is_lyapunov_like_on()
REFERENCES:
H. Schneider and M. Vidyasagar. Cross-positive matrices. SIAM Journal on Numerical Analysis, 7:508-519,
1970.
EXAMPLES:
Negative Z-matrices are cross-positive operators on the nonnegative orthant:
sage: K = Cone([(1,0,0), (0,1,0), (0,0,1)])
˓→needs sage.geometry.polyhedronsage: L = matrix(SR, [ [-1, 2, 0],
˓→needs sage.symbolic....:[ 0, 2, 7],....:[ 3, 0, 3] ])sage: L.is_cross_positive_on(K)˓→needs sage.geometry.polyhedron sage.symbolic
True

#␣
#␣

#␣

>>> from sage.all import *>>> K = Cone([(Integer(1),Integer(0),Integer(0)), (Integer(0),Integer(1),˓→Integer(0)), (Integer(0),Integer(0),Integer(1))])˓→# needs sage.geometry.polyhedron>>> L = matrix(SR, [ [-Integer(1), Integer(2), Integer(0)],˓→# needs sage.symbolic␣␣(continues on next page)395

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
[ Integer(0), Integer(2), Integer(7)],...
[ Integer(3), Integer(0), Integer(3)] ])>>> L.is_cross_positive_on(K)˓→needs sage.geometry.polyhedron sage.symbolic
True

#␣

Symbolic entries also work in some easy cases:
sage: K = Cone([(1,0,0),(0,1,0),(0,0,1)])
˓→needs sage.geometry.polyhedronsage: L = matrix(SR, [ [-1,e, 0 ],
˓→needs sage.symbolic
....:
[ 0,
2, pi],....:[ sqrt(2), 0, 3 ] ])sage: L.is_cross_positive_on(K)˓→needs sage.geometry.polyhedron sage.symbolic
True

#␣
#␣

#␣

>>> from sage.all import *>>> K = Cone([(Integer(1),Integer(0),Integer(0)),(Integer(0),Integer(1),˓→Integer(0)),(Integer(0),Integer(0),Integer(1))])˓→# needs sage.geometry.polyhedron>>> L = matrix(SR, [ [-Integer(1),e, Integer(0) ],˓→# needs sage.symbolic...
[ Integer(0),Integer(2), pi],...
[ sqrt(Integer(2)), Integer(0), Integer(3) ] ])>>> L.is_cross_positive_on(K)˓→needs sage.geometry.polyhedron sage.symbolic
True

␣
␣

#␣

is_diagonal()
Return True if this matrix is a diagonal matrix.
OUTPUT:boolean
EXAMPLES:
sage: m = matrix(QQ, 2,2, range(4))
sage: m.is_diagonal()
False
sage: m = matrix(QQ, 2, [5,0,0,5])
sage: m.is_diagonal()
True
sage: m = matrix(QQ, 2, [1,0,0,1])
sage: m.is_diagonal()
True
sage: m = matrix(QQ, 2, [1,1,1,1])
sage: m.is_diagonal()
False>>> from sage.all import *>>> m = matrix(QQ, Integer(2),Integer(2), range(Integer(4)))>>> m.is_diagonal()
False>>> m = matrix(QQ, Integer(2), [Integer(5),Integer(0),Integer(0),Integer(5)])(continues on next page)

396

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> m.is_diagonal()
True>>> m = matrix(QQ, Integer(2), [Integer(1),Integer(0),Integer(0),Integer(1)])>>> m.is_diagonal()
True>>> m = matrix(QQ, Integer(2), [Integer(1),Integer(1),Integer(1),Integer(1)])>>> m.is_diagonal()
False

is_diagonalizable(base_field=None)
Determine if the matrix is similar to a diagonal matrix.
INPUT:• base_field – a new field to use for entries of the matrix.
OUTPUT:
If self is the matrix 𝐴, then it is diagonalizable if there is an invertible matrix 𝑃 and a diagonal matrix 𝐷
such that𝑃 −1 𝐴𝑃 = 𝐷This routine returns True if self is diagonalizable. The diagonal entries of the matrix 𝐷 are the eigenvaluesof 𝐴.
A matrix not diagonalizable over the base field may become diagonalizable by extending the base field tocontain all of the eigenvalues. Over the rationals, the field of algebraic numbers, sage.rings.qqbar isa good choice.
To obtain the matrices 𝐷 and 𝑃 , use the diagonalization() method.
ALGORITHM:
For each eigenvalue, this routine checks that the algebraic multiplicity (number of occurrences as a root of
the characteristic polynomial) is equal to the geometric multiplicity (dimension of the eigenspace), which is
sufficient to ensure a basis of eigenvectors for the columns of 𝑃 .
EXAMPLES:
A matrix that is diagonalizable over the rationals:
sage: A = matrix(QQ, [[-7, 16, 12, 0,
6],
....:
[-9, 15, 0, 12, -27],....:[ 9, -8, 11, -12, 51],....:
[ 3, -4, 0, -1,
9],
....:
[-1, 0, -4,
4, -12]])sage: A.is_diagonalizable()
˓→needs sage.libs.pari
True
sage: A.diagonalization()
˓→needs sage.libs.pari([ 2 0 0 0 0] [
1
1
0
1
0]
[ 0 3 0 0 0] [ 1/20101][ 0 0 3 0 0] [ 1/6
1 -3/2
2/3 -14/9][ 0 0 0 -1 0] [ -1/6
0 -1/40 -1/3][ 0 0 0 0 -1], [ -1/6 -1/3
1/3 -1/3
4/9]
)

#␣

#␣

397

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = matrix(QQ, [[-Integer(7), Integer(16), Integer(12), Integer(0),␣
˓→Integer(6)],...
[-Integer(9), Integer(15), Integer(0), Integer(12), ˓→Integer(27)],...
[ Integer(9), -Integer(8), Integer(11), -Integer(12), ␣
˓→Integer(51)],...
[ Integer(3), -Integer(4), Integer(0), -Integer(1), ␣
˓→Integer(9)],...
[-Integer(1), Integer(0), -Integer(4),Integer(4), ˓→Integer(12)]])>>> A.is_diagonalizable()#␣˓→needs sage.libs.pari
True>>> A.diagonalization()#␣˓→needs sage.libs.pari([ 2 0 0 0 0] [
1
1
0
1
0]
[ 0 3 0 0 0] [ 1/20101][ 0 0 3 0 0] [ 1/6
1 -3/2
2/3 -14/9][ 0 0 0 -1 0] [ -1/6
0 -1/40 -1/3][ 0 0 0 0 -1], [ -1/6 -1/3
1/3 -1/3
4/9])

This is a matrix not diagonalizable over the rationals, but you can still get its Jordan form.
sage: A = matrix(QQ, [[-3, -14, 2, -1, 15],....:[4, 6, -2, 3, -8],....:[-2, -14, 0, 0, 10],....:[3, 13, -2, 0, -11],....:[-1, 6, 1, -3, 1]])
sage: A.is_diagonalizable()
˓→needs sage.libs.pari
False
sage: A.jordan_form(subdivide=False)
˓→needs sage.combinat sage.libs.pari[-1 1 0 0 0]
[ 0 -1 0 0 0]
[ 0 0 2 1 0]
[ 0 0 0 2 1]
[ 0 0 0 0 2]

#␣#␣>>> from sage.all import *>>> A = matrix(QQ, [[-Integer(3), -Integer(14), Integer(2), -Integer(1),␣
˓→Integer(15)],...
[Integer(4), Integer(6), -Integer(2), Integer(3), ˓→Integer(8)],...
[-Integer(2), -Integer(14), Integer(0), Integer(0),␣
˓→Integer(10)],...
[Integer(3), Integer(13), -Integer(2), Integer(0), ˓→Integer(11)],...
[-Integer(1), Integer(6), Integer(1), -Integer(3),␣
˓→Integer(1)]])>>> A.is_diagonalizable()#␣˓→needs sage.libs.pari
False>>> A.jordan_form(subdivide=False)#␣(continues on next page)

398

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)needs sage.combinat sage.libs.pari[-1 1 0 0 0]
[ 0 -1 0 0 0]
[ 0 0 2 1 0]
[ 0 0 0 2 1]
[ 0 0 0 0 2]
˓→

If any eigenvalue of a matrix is outside the base ring, then this routine raises an error. However, the ring canbe extended to contain the eigenvalues.
sage: A = matrix(QQ, [[1, 0, 1, 1, -1],....:
[0, 1, 0, 4, 8],....:[2, 1, 3, 5, 1],....:[2, -1, 1, 0, -2],....:
[0, -1, -1, -5, -8]])sage: [e in QQ for e in A.eigenvalues()]
˓→needs sage.rings.number_field[False, False, False, False, False]
sage: A.is_diagonalizable()
˓→needs sage.libs.pari
False
sage: A.diagonalization()
˓→needs sage.libs.pari
Traceback (most recent call last):...
ValueError: not diagonalizable over Rational Field#␣

sage: [e in QQbar for e in A.eigenvalues()]
˓→needs sage.rings.number_field[True, True, True, True, True]
sage: A.is_diagonalizable(base_field=QQbar)
˓→needs sage.rings.number_field
True

#␣

#␣

#␣

#␣

>>> from sage.all import *>>> A = matrix(QQ, [[Integer(1), Integer(0), Integer(1), Integer(1), ˓→Integer(1)],...
[Integer(0), Integer(1), Integer(0), Integer(4), ␣
˓→Integer(8)],...
[Integer(2), Integer(1), Integer(3), Integer(5), ␣˓→Integer(1)],...
[Integer(2), -Integer(1), Integer(1), Integer(0), ˓→Integer(2)],...
[Integer(0), -Integer(1), -Integer(1), -Integer(5), ˓→Integer(8)]])>>> [e in QQ for e in A.eigenvalues()]
˓→needs sage.rings.number_field[False, False, False, False, False]>>> A.is_diagonalizable()
˓→needs sage.libs.pari
False>>> A.diagonalization()
˓→needs sage.libs.pari
Traceback (most recent call last):

#␣

#␣

#␣

(continues on next page)399

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
ValueError: not diagonalizable over Rational Field>>> [e in QQbar for e in A.eigenvalues()]
˓→needs sage.rings.number_field[True, True, True, True, True]>>> A.is_diagonalizable(base_field=QQbar)
˓→needs sage.rings.number_field
True

#␣

#␣

Other exact fields may be employed, though it will not always be possible to extend their base fields to containall the eigenvalues.
sage: # needs sage.rings.finite_rings
sage: F.<b> = FiniteField(5^2)
sage: A = matrix(F, [[4, 3*b + 2, 3*b + 1, 3*b + 4],....:[2*b + 1,
4*b,
0,
2],
....:
[
4*b,
b + 2, 2*b + 3,
3],
....:
[
2*b,
3*b, 4*b + 4, 3*b + 3]])sage: A.is_diagonalizable()False
sage: A.jordan_form()
˓→needs sage.combinat
[
4
1|
0
0]
[
0
4|
0
0]
[---------------+---------------][
00|2*b + 1
1][00|
0 2*b + 1]#␣sage: # needs sage.rings.number_fieldsage: F.<c> = QuadraticField(-7)
sage: A = matrix(F, [[c + 3,
2*c - 2,
-2*c + 2,
c - 1],....:[2*c + 10, 13*c + 15, -13*c - 17, 11*c + 31],....:[2*c + 10, 14*c + 10, -14*c - 12, 12*c + 30],
....:
[
0,
2*c - 2,
-2*c + 2,
2*c + 2]])sage: A.is_diagonalizable()True
sage: A.diagonalization()
(
[
4
0
0
0] [
1
0
1
0]
[
0
-2
0
0] [
4
1
0
1]
[
0
0 c + 30] [5
1 -2/9 10/9][
000 c + 3], [1
0 -4/9 2/9])>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> F = FiniteField(Integer(5)**Integer(2), names=( b ,)); (b,) = F._first_
˓→ngens(1)>>> A = matrix(F, [[Integer(4), Integer(3)*b + Integer(2), Integer(3)*b␣
˓→+ Integer(1), Integer(3)*b + Integer(4)],...
[Integer(2)*b + Integer(1),Integer(4)*b,
␣
˓→Integer(0),Integer(2)],...
[Integer(4)*b,b + Integer(2), Integer(2)*b +␣
˓→Integer(3),Integer(3)],...
[Integer(2)*b,
Integer(3)*b, Integer(4)*b +␣
(continues on next page)

400

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Integer(4), Integer(3)*b + Integer(3)]])>>> A.is_diagonalizable()
False>>> A.jordan_form()
˓→needs sage.combinat
[
4
1|
0
0]
[
0
4|
0
0]
[---------------+---------------][
00|2*b + 1
1][00|
0 2*b + 1]
˓→#␣>>> # needs sage.rings.number_field>>> F = QuadraticField(-Integer(7), names=( c ,)); (c,) = F._first_ngens(1)>>> A = matrix(F, [[c + Integer(3),Integer(2)*c - Integer(2),˓→Integer(2)*c + Integer(2),c - Integer(1)],...
[Integer(2)*c + Integer(10), Integer(13)*c + Integer(15), ˓→Integer(13)*c - Integer(17), Integer(11)*c + Integer(31)],...
[Integer(2)*c + Integer(10), Integer(14)*c + Integer(10), ˓→Integer(14)*c - Integer(12), Integer(12)*c + Integer(30)],...
[
Integer(0),Integer(2)*c - Integer(2),˓→Integer(2)*c + Integer(2),Integer(2)*c + Integer(2)]])>>> A.is_diagonalizable()
True>>> A.diagonalization()
(
[
4
0
0
0] [
1
0
1
0]
[
0
-2
0
0] [
4
1
0
1]
[
0
0 c + 30] [5
1 -2/9 10/9][
000 c + 3], [1
0 -4/9 2/9])

A trivial matrix is diagonalizable, trivially.
sage: A = matrix(QQ, 0, 0)
sage: A.is_diagonalizable()
˓→needs sage.libs.pari
True>>> from sage.all import *>>> A = matrix(QQ, Integer(0), Integer(0))>>> A.is_diagonalizable()
˓→needs sage.libs.pari
True

#␣

#␣

A matrix must be square to be diagonalizable.
sage: A = matrix(QQ, 3, 4)
sage: A.is_diagonalizable()
Traceback (most recent call last):...
TypeError: not a square matrix>>> from sage.all import *>>> A = matrix(QQ, Integer(3), Integer(4))>>> A.is_diagonalizable()
Traceback (most recent call last):(continues on next page)401

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
TypeError: not a square matrix

The matrix must have entries from a field, and it must be an exact field.
sage: A = matrix(ZZ, 4, range(16))
sage: A.is_diagonalizable()
Traceback (most recent call last):...
ValueError: matrix entries must be from a fieldsage: A = matrix(RDF, 4, range(16))
sage: A.is_diagonalizable()
Traceback (most recent call last):...
ValueError: base field must be exact, but Real Double Field is not>>> from sage.all import *>>> A = matrix(ZZ, Integer(4), range(Integer(16)))>>> A.is_diagonalizable()
Traceback (most recent call last):...
ValueError: matrix entries must be from a field>>> A = matrix(RDF, Integer(4), range(Integer(16)))>>> A.is_diagonalizable()
Traceback (most recent call last):...
ValueError: base field must be exact, but Real Double Field is not

is_lyapunov_like_on(K)Determine if this matrix is Lyapunov-like on a cone.
We say that a matrix 𝐿 is Lyapunov-like on a closed convex cone 𝐾 if the inner product of 𝐿𝑥 and 𝑠 is zerofor all pairs of orthogonal vectors 𝑥 in 𝐾 and 𝑠 in the dual of 𝐾. This property need only be checked forgenerators of 𝐾 and its dual.
An operator is Lyapunov-like on 𝐾 if and only if both the operator itself and its negation are cross-positiveon 𝐾.
To reliably check whether or not this matrix is Lyapunov-like, its base ring must be either exact (for example,
the rationals) or the symbolic ring. An exact ring is more reliable, but in some cases a matrix whose entries
contain symbolic constants like 𝑒 and 𝜋 will work.
INPUT:• K – a polyhedral closed convex cone.
OUTPUT:
If the base ring of this matrix is exact, then True will be returned if and only if this matrix is Lyapunov-likeon K.
If the base ring of this matrix is symbolic, then the situation is more complicated:• True will be returned if it can be proven that this matrix is Lyapunov-like on K.
• False will be returned if it can be proven that this matrix is not Lyapunov-like on K.

402

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

• False will also be returned if we can’t decide; specifically if we arrive at a symbolic inequality thatcannot be resolved.
See also:
is_positive_operator_on(), is_cross_positive_on(), is_Z_operator_on()
REFERENCES:• [Or2017]
EXAMPLES:
Diagonal matrices are Lyapunov-like operators on the nonnegative orthant:
sage: K = Cone([(1,0,0), (0,1,0), (0,0,1)])
˓→needs sage.geometry.polyhedronsage: L = diagonal_matrix(random_vector(QQ, 3))
sage: L.is_lyapunov_like_on(K)˓→needs sage.geometry.polyhedron
True

#␣

#␣

>>> from sage.all import *>>> K = Cone([(Integer(1),Integer(0),Integer(0)), (Integer(0),Integer(1),˓→Integer(0)), (Integer(0),Integer(0),Integer(1))])␣˓→# needs sage.geometry.polyhedron>>> L = diagonal_matrix(random_vector(QQ, Integer(3)))>>> L.is_lyapunov_like_on(K)#␣˓→needs sage.geometry.polyhedron
True

Symbolic entries also work in some easy cases:
sage: K = Cone([(1,0,0), (0,1,0), (0,0,1)])
˓→needs sage.geometry.polyhedronsage: L = matrix(SR, [ [e, 0, 0],
˓→needs sage.symbolic....:[0, pi, 0],....:[0, 0, sqrt(2)] ])sage: L.is_lyapunov_like_on(K)˓→needs sage.geometry.polyhedron
True

#␣
#␣

#␣

>>> from sage.all import *>>> K = Cone([(Integer(1),Integer(0),Integer(0)), (Integer(0),Integer(1),˓→Integer(0)), (Integer(0),Integer(0),Integer(1))])␣˓→# needs sage.geometry.polyhedron>>> L = matrix(SR, [ [e, Integer(0), Integer(0)],␣˓→# needs sage.symbolic...
[Integer(0), pi, Integer(0)],...
[Integer(0), Integer(0), sqrt(Integer(2))] ])>>> L.is_lyapunov_like_on(K)#␣˓→needs sage.geometry.polyhedron
True

is_nilpotent()
Return if self is a nilpotent matrix.
A matrix 𝐴 is nilpotent if there exists a positive integer 𝑘 such that 𝐴𝑘 = 0. We test this by using the
Cayley-Hamilton theorem to see if the characteristic polynomial is 𝑥𝑛 = 0.
403

Matrices and Spaces of Matrices, Release 10.4

EXAMPLES:
sage: A = matrix([[0,2,1,6], [0,0,1,2], [0,0,0,3], [0,0,0,0]])
sage: A.is_nilpotent()
True
sage: B = matrix([[2,2,2,2,-4], [7,1,1,1,-5], [1,7,1,1,-5],....:[1,1,7,1,-5], [1,1,1,7,-5]])sage: B.is_nilpotent()
True
sage: C = matrix(GF(7), [[1, 2], [2, 6]])sage: C.is_nilpotent()
False
sage: D = matrix([[1,0],[0,0]])
sage: D.is_nilpotent()
False
sage: Z = matrix.zero(QQ, 5)
sage: Z.is_nilpotent()True>>> from sage.all import *>>> A = matrix([[Integer(0),Integer(2),Integer(1),Integer(6)], [Integer(0),˓→Integer(0),Integer(1),Integer(2)], [Integer(0),Integer(0),Integer(0),˓→Integer(3)], [Integer(0),Integer(0),Integer(0),Integer(0)]])>>> A.is_nilpotent()
True>>> B = matrix([[Integer(2),Integer(2),Integer(2),Integer(2),-Integer(4)],␣
˓→[Integer(7),Integer(1),Integer(1),Integer(1),-Integer(5)], [Integer(1),˓→Integer(7),Integer(1),Integer(1),-Integer(5)],...
[Integer(1),Integer(1),Integer(7),Integer(1),-Integer(5)],␣
˓→[Integer(1),Integer(1),Integer(1),Integer(7),-Integer(5)]])>>> B.is_nilpotent()
True>>> C = matrix(GF(Integer(7)), [[Integer(1), Integer(2)], [Integer(2),␣
˓→Integer(6)]])>>> C.is_nilpotent()
False>>> D = matrix([[Integer(1),Integer(0)],[Integer(0),Integer(0)]])>>> D.is_nilpotent()
False>>> Z = matrix.zero(QQ, Integer(5))>>> Z.is_nilpotent()
True

is_normal()
Returns True if the matrix commutes with its conjugate-transpose.
OUTPUT:
True if the matrix is square and commutes with its conjugate-transpose, and False otherwise.
Normal matrices are precisely those that can be diagonalized by a unitary matrix.
This routine is for matrices over exact rings and so may not work properly for matrices over RR or CC.
For matrices with approximate entries, the rings of double-precision floating-point numbers, RDF and CDF,
are a better choice since the sage.matrix.matrix_double_dense.Matrix_double_dense.
is_normal() method has a tolerance parameter. This provides control over allowing for minor discrepancies between entries when checking equality.
The result is cached.

404

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

EXAMPLES:
Hermitian matrices are normal.
sage: # needs sage.symbolic
sage: A = matrix(QQ, 5, 5, range(25)) + I*matrix(QQ, 5, 5, range(0, 50, 2))
sage: B = A*A.conjugate_transpose()sage: B.is_hermitian()True
sage: B.is_normal()True>>> from sage.all import *>>> # needs sage.symbolic>>> A = matrix(QQ, Integer(5), Integer(5), range(Integer(25))) + I*matrix(QQ,␣
˓→Integer(5), Integer(5), range(Integer(0), Integer(50), Integer(2)))>>> B = A*A.conjugate_transpose()>>> B.is_hermitian()
True>>> B.is_normal()
True

Circulant matrices are normal.
sage: # needs sage.graphs
sage: G = graphs.CirculantGraph(20, [3, 7])
sage: D = digraphs.Circuit(20)sage: A = 3*D.adjacency_matrix() - 5*G.adjacency_matrix()
sage: A.is_normal()True>>> from sage.all import *>>> # needs sage.graphs>>> G = graphs.CirculantGraph(Integer(20), [Integer(3), Integer(7)])>>> D = digraphs.Circuit(Integer(20))>>> A = Integer(3)*D.adjacency_matrix() - Integer(5)*G.adjacency_matrix()>>> A.is_normal()
True

Skew-symmetric matrices are normal.
sage: A = matrix(QQ, 5, 5, range(25))
sage: B = A - A.transpose()sage: B.is_skew_symmetric()True
sage: B.is_normal()True>>> from sage.all import *>>> A = matrix(QQ, Integer(5), Integer(5), range(Integer(25)))>>> B = A - A.transpose()>>> B.is_skew_symmetric()
True>>> B.is_normal()True

A small matrix that does not fit into any of the usual categories of normal matrices.

405

Matrices and Spaces of Matrices, Release 10.4

sage: A = matrix(ZZ, [[1, -1],....:
[1, 1]])
sage: A.is_normal()True
sage: not A.is_hermitian() and not A.is_skew_symmetric()
True>>> from sage.all import *>>> A = matrix(ZZ, [[Integer(1), -Integer(1)],...
[Integer(1), Integer(1)]])>>> A.is_normal()True>>> not A.is_hermitian() and not A.is_skew_symmetric()
True

Sage has several fields besides the entire complex numbers where conjugation is non-trivial.
sage: # needs sage.rings.number_fieldsage: F.<b> = QuadraticField(-7)
sage: C = matrix(F, [[-2*b - 3, 7*b - 6, -b + 3],....:[-2*b - 3, -3*b + 2,
-2*b],....:[
b + 1,
0,-2]])
sage: C = C*C.conjugate_transpose()sage: C.is_normal()True>>> from sage.all import *>>> # needs sage.rings.number_field>>> F = QuadraticField(-Integer(7), names=( b ,)); (b,) = F._first_ngens(1)>>> C = matrix(F, [[-Integer(2)*b - Integer(3), Integer(7)*b - Integer(6), ˓→b + Integer(3)],...
[-Integer(2)*b - Integer(3), -Integer(3)*b + Integer(2), ␣˓→-Integer(2)*b],...
[b + Integer(1),Integer(0),-Integer(2)]])>>> C = C*C.conjugate_transpose()>>> C.is_normal()True

A matrix that is nearly normal, but for a non-real diagonal entry.
sage: # needs sage.rings.number_fieldsage: A = matrix(QQbar, [[2,2-I, 1+4*I],....:[ 2+I,
3+I, 2-6*I],....:[1-4*I, 2+6*I,
5]])sage: A.is_normal()
False
sage: A[1,1] = 132
sage: A.is_normal()True>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQbar, [[Integer(2),˓→Integer(1)+Integer(4)*I],...
[ Integer(2)+I,
˓→Integer(6)*I],

Integer(2)-I,␣
Integer(3)+I, Integer(2)(continues on next page)

406

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
[Integer(1)-Integer(4)*I, Integer(2)+Integer(6)*I,
˓→Integer(5)]])>>> A.is_normal()
False>>> A[Integer(1),Integer(1)] = Integer(132)>>> A.is_normal()
True␣

Rectangular matrices are never normal.
sage: A = matrix(QQbar, 3, 4)
˓→needs sage.rings.number_fieldsage: A.is_normal()
˓→needs sage.rings.number_field
False>>> from sage.all import *>>> A = matrix(QQbar, Integer(3), Integer(4))˓→# needs sage.rings.number_field>>> A.is_normal()
˓→needs sage.rings.number_field
False

#␣
#␣

␣
#␣

A square, empty matrix is trivially normal.
sage: A = matrix(QQ, 0, 0)
sage: A.is_normal()True>>> from sage.all import *>>> A = matrix(QQ, Integer(0), Integer(0))>>> A.is_normal()True

is_one()Return True if this matrix is the identity matrix.
EXAMPLES:
sage: m = matrix(QQ, 2,2, range(4))
sage: m.is_one()False
sage: m = matrix(QQ, 2, [5,0,0,5])
sage: m.is_one()False
sage: m = matrix(QQ, 2, [1,0,0,1])
sage: m.is_one()True
sage: m = matrix(QQ, 2, [1,1,1,1])
sage: m.is_one()
False>>> from sage.all import *>>> m = matrix(QQ, Integer(2),Integer(2), range(Integer(4)))>>> m.is_one()(continues on next page)407

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

False>>> m = matrix(QQ, Integer(2), [Integer(5),Integer(0),Integer(0),Integer(5)])>>> m.is_one()
False>>> m = matrix(QQ, Integer(2), [Integer(1),Integer(0),Integer(0),Integer(1)])>>> m.is_one()True>>> m = matrix(QQ, Integer(2), [Integer(1),Integer(1),Integer(1),Integer(1)])>>> m.is_one()
False

is_permutation_of(N, check=False)
Return True if there exists a permutation of rows and columns sending self to N and False otherwise.
INPUT:• N – a matrix.
• check – boolean (default: False). If False
return Boolean indicating whether there exists a permutation of rows and columns sending self to
N and False otherwise. If True return a tuple of a Boolean and a permutation mapping self to N
if such a permutation exists, and (False, None) if it does not.
OUTPUT:
A Boolean or a tuple of a Boolean and a permutation.
EXAMPLES:
sage: M = matrix(ZZ, [[1,2,3], [3,5,3], [2,6,4]])
sage: M
[1 2 3][3 5 3][2 6 4]sage: N = matrix(ZZ, [[1,2,3], [2,6,4], [3,5,3]])
sage: N[1 2 3][2 6 4][3 5 3]sage: M.is_permutation_of(N)˓→needs sage.graphs
True

#␣

>>> from sage.all import *>>> M = matrix(ZZ, [[Integer(1),Integer(2),Integer(3)], [Integer(3),˓→Integer(5),Integer(3)], [Integer(2),Integer(6),Integer(4)]])>>> M[1 2 3][3 5 3][2 6 4]>>> N = matrix(ZZ, [[Integer(1),Integer(2),Integer(3)], [Integer(2),˓→Integer(6),Integer(4)], [Integer(3),Integer(5),Integer(3)]])>>> N[1 2 3][2 6 4][3 5 3]>>> M.is_permutation_of(N)#␣(continues on next page)

408

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)needs sage.graphs
True˓→

Some examples that are not permutations of each other:sage: N = matrix(ZZ, [[1,2,3], [4,5,6], [7,8,9]]); N[1 2 3][4 5 6][7 8 9]sage: M.is_permutation_of(N)˓→needs sage.graphs
False
sage: N = matrix(ZZ, [[1,2], [3,4]]); N
[1 2]
[3 4]
sage: M.is_permutation_of(N)
False

#␣

>>> from sage.all import *>>> N = matrix(ZZ, [[Integer(1),Integer(2),Integer(3)], [Integer(4),˓→Integer(5),Integer(6)], [Integer(7),Integer(8),Integer(9)]]); N[1 2 3][4 5 6][7 8 9]>>> M.is_permutation_of(N)#␣˓→needs sage.graphs
False>>> N = matrix(ZZ, [[Integer(1),Integer(2)], [Integer(3),Integer(4)]]); N
[1 2]
[3 4]
>>> M.is_permutation_of(N)False

And for when check is True:
sage: # needs sage.graphs sage.groups
sage: N = matrix(ZZ, [[3,5,3], [2,6,4], [1,2,3]]); N[3 5 3][2 6 4][1 2 3]sage: r = M.is_permutation_of(N, check=True)
sage: r(True, ((1,2,3), ()))
sage: p = r[1]sage: M.with_permuted_rows_and_columns(*p) == N
True>>> from sage.all import *>>> # needs sage.graphs sage.groups>>> N = matrix(ZZ, [[Integer(3),Integer(5),Integer(3)], [Integer(2),˓→Integer(6),Integer(4)], [Integer(1),Integer(2),Integer(3)]]); N[3 5 3][2 6 4][1 2 3]>>> r = M.is_permutation_of(N, check=True)>>> r(continues on next page)409

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)(True, ((1,2,3), ()))>>> p = r[Integer(1)]>>> M.with_permuted_rows_and_columns(*p) == N
True

is_positive_definite(certificate=False)
Determine if a matrix is positive-definite.
A matrix 𝐴 is positive definite if it is_hermitian() and if, for every non-zero vector 𝑥,⟨𝐴𝑥, 𝑥⟩ > 0.
ALGORITHM:
A Hermitian matrix is positive-definite if and only if the diagonal blocks in its block_ldlt() factorization
are all 1-by-1 and have positive entries. We first check that the matrix is_hermitian(), and then compute
this factorization.
INPUT:• self – a matrix• certificate – (default: False) return the lower-triangular and diagonal parts of theblock_ldlt() factorization when the matrix is positive-definite. Deprecated.
OUTPUT:
This routine will return True if the matrix is Hermitian and meets the condition above for the quadraticform.
The base ring for the elements of the matrix must
1. Have a fraction field implemented; and2. Be a subring of the real numbers, complex numbers, or symbolic ring.
If certificate is True, a triplet (b, L, d) will be returned instead, with b containing the result(true or false). If the matrix is positive-definite, then L and d will contain the lower-triangular and diagonalparts of the block_ldlt() factorization, respectively. Or if the matrix is not positive-definite (that is, if
b is False), then both L and d will be None.
See also:
block_ldlt(), is_hermitian(), is_positive_semidefinite()
EXAMPLES:
A real symmetric matrix that is positive-definite, as evidenced by the positive determinants of its leading
principal submatrices:sage: A = matrix(QQ, [[ 4, -2, 4, 2],....:[-2, 10, -2, -7],....:
[ 4, -2, 8, 4],....:[ 2, -7, 4, 7]])sage: A.is_positive_definite()True
sage: [A[:i,:i].determinant() for i in range(1, A.nrows() + 1)][4, 36, 144, 144]

410

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = matrix(QQ, [[ Integer(4), -Integer(2), Integer(4), Integer(2)],...
[-Integer(2), Integer(10), -Integer(2), -Integer(7)],...
[ Integer(4), -Integer(2), Integer(8), Integer(4)],...
[ Integer(2), -Integer(7), Integer(4), Integer(7)]])>>> A.is_positive_definite()True>>> [A[:i,:i].determinant() for i in range(Integer(1), A.nrows() +␣˓→Integer(1))][4, 36, 144, 144]

A real symmetric matrix that is not positive-definite and a vector u that makes the corresponding quadratic
form negative:
sage: A = matrix(QQ, [[ 3, -6,
9,
6, -9],....:[-6, 11, -16, -11, 17],....:
[ 9, -16, 28, 16, -40],....:[ 6, -11, 16,
9, -19],....:[-9, 17, -40, -19, 68]])
sage: A.is_positive_definite()
False
sage: u = vector(QQ, [2, 2, 0, 1, 0])
sage: (A*u).inner_product(u)-3>>> from sage.all import *>>> A = matrix(QQ, [[ Integer(3), -Integer(6),Integer(9),Integer(6), ˓→Integer(9)],...
[-Integer(6), Integer(11), -Integer(16), -Integer(11), ␣
˓→Integer(17)],...
[ Integer(9), -Integer(16), Integer(28), Integer(16), ˓→Integer(40)],...
[ Integer(6), -Integer(11), Integer(16),Integer(9), ˓→Integer(19)],...
[-Integer(9), Integer(17), -Integer(40), -Integer(19), ␣
˓→Integer(68)]])>>> A.is_positive_definite()
False>>> u = vector(QQ, [Integer(2), Integer(2), Integer(0), Integer(1),␣
˓→Integer(0)])>>> (A*u).inner_product(u)-3Another real symmetric matrix that is not positive-definite and a vector u that makes the corresponding
quadratic form zero:sage: A = matrix(QQ, [[21, 15, 12, -2],....:
[15, 12, 9, 6],....:[12, 9, 7, 3],....:[-2, 6, 3, 8]])sage: A.is_positive_definite()
False
sage: u = vector(QQ, [1,1,-3,0])
sage: (A*u).inner_product(u)0411Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = matrix(QQ, [[Integer(21), Integer(15), Integer(12), -Integer(2)],...
[Integer(15), Integer(12), Integer(9), Integer(6)],...
[Integer(12), Integer(9), Integer(7), Integer(3)],...
[-Integer(2), Integer(6), Integer(3), Integer(8)]])>>> A.is_positive_definite()
False>>> u = vector(QQ, [Integer(1),Integer(1),-Integer(3),Integer(0)])>>> (A*u).inner_product(u)0

A complex Hermitian matrix that is positive-definite, confirmed by the positive determinants of its leading
principal submatrices:sage: # needs sage.rings.number_fieldsage: x = polygen(ZZ, x )sage: C.<I> = NumberField(x^2 + 1, embedding=CC(0,1))
sage: A = matrix(C, [[23, 17*I + 3, 24*I + 25,
21*I],....:[ -17*I + 3,
38, -69*I + 89, 7*I + 15],....:[-24*I + 25, 69*I + 89,
976, 24*I + 6],....:[-21*I, -7*I + 15, -24*I + 6,28]])
sage: A.is_positive_definite()True
sage: [A[:i,:i].determinant() for i in range(1,A.nrows()+1)][23, 576, 359540, 2842600]>>> from sage.all import *>>> # needs sage.rings.number_field>>> x = polygen(ZZ, x )>>> C = NumberField(x**Integer(2) + Integer(1), embedding=CC(Integer(0),˓→Integer(1)), names=( I ,)); (I,) = C._first_ngens(1)>>> A = matrix(C, [[Integer(23), Integer(17)*I + Integer(3), ␣
˓→Integer(24)*I + Integer(25),Integer(21)*I],...
[ -Integer(17)*I + Integer(3),Integer(38), ˓→Integer(69)*I + Integer(89), Integer(7)*I + Integer(15)],...
[-Integer(24)*I + Integer(25), Integer(69)*I + Integer(89),˓→Integer(976), Integer(24)*I + Integer(6)],...
[-Integer(21)*I, -Integer(7)*I + Integer(15), ˓→Integer(24)*I + Integer(6),Integer(28)]])>>> A.is_positive_definite()True>>> [A[:i,:i].determinant() for i in range(Integer(1),A.nrows()+Integer(1))][23, 576, 359540, 2842600]

An Hermitian matrix that is not positive-definite and a vector u that makes the corresponding quadratic form
negative:sage: # needs sage.rings.number_fieldsage: C.<I> = QuadraticField(-1)
sage: B = matrix(C, [[2, 4 - 2*I, 2 + 2*I],....:[4 + 2*I,
8,
10*I],....:[2 - 2*I,-10*I,-3]])sage: B.is_positive_definite()
False
sage: u = vector(C, [-5 + 10*I, 4 - 3*I, 0])
sage: (B*u).hermitian_inner_product(u)
-50

412

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> # needs sage.rings.number_field>>> C = QuadraticField(-Integer(1), names=( I ,)); (I,) = C._first_ngens(1)>>> B = matrix(C, [[Integer(2), Integer(4) - Integer(2)*I, Integer(2) +␣˓→Integer(2)*I],...
[Integer(4) + Integer(2)*I,
Integer(8),␣˓→Integer(10)*I],...
[Integer(2) - Integer(2)*I,-Integer(10)*I,
˓→Integer(3)]])>>> B.is_positive_definite()
False>>> u = vector(C, [-Integer(5) + Integer(10)*I, Integer(4) - Integer(3)*I,␣
˓→Integer(0)])>>> (B*u).hermitian_inner_product(u)-50

A positive-definite matrix over an algebraically-closed field, confirmed by the positive determinants of its
leading principal submatrices:sage: # needs sage.rings.number_fieldsage: A = matrix(QQbar, [[2,
4 + 2*I,
6 - 4*I],....:[ -2*I + 4,
11, 10 - 12*I],....:[ 4*I + 6, 10 + 12*I,
37]])
sage: A.is_positive_definite()True
sage: [A[:i,:i].determinant() for i in range(1, A.nrows() + 1)][2, 2, 6]>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQbar, [[Integer(2),Integer(4) + Integer(2)*I, ␣
˓→Integer(6) - Integer(4)*I],...
[ -Integer(2)*I + Integer(4),Integer(11),␣
˓→Integer(10) - Integer(12)*I],...
[ Integer(4)*I + Integer(6), Integer(10) +␣˓→Integer(12)*I,
Integer(37)]])>>> A.is_positive_definite()True>>> [A[:i,:i].determinant() for i in range(Integer(1), A.nrows() +␣˓→Integer(1))][2, 2, 6]

is_positive_operator_on(K1, K2=None)
Determine if this matrix is a positive operator on a cone.
A matrix is a positive operator on a cone if the image of the cone under the matrix is itself a subset of thecone. That concept can be extended to two cones: a matrix is a positive operator on a pair of cones if theimage of the first cone is contained in the second cone.
To reliably check whether or not this matrix is a positive operator, its base ring must be either exact (forexample, the rationals) or the symbolic ring. An exact ring is more reliable, but in some cases a matrix whose
entries contain symbolic constants like 𝑒 and 𝜋 will work. Performance is best for integer or rational matrices,
for which we can check the “is a subset of the other cone” condition quickly.
INPUT:• K1 – a polyhedral closed convex cone.

413

Matrices and Spaces of Matrices, Release 10.4

• K2 – (default: K1) the codomain cone; this matrix is a positive operator if the image of K1 is a subset
of K2.
OUTPUT:
If the base ring of this matrix is exact, then True will be returned if and only if this matrix is a positive
operator.
If the base ring of this matrix is symbolic, then the situation is more complicated:• True will be returned if it can be proven that this matrix is a positive operator.
• False will be returned if it can be proven that this matrix is not a positive operator.
• False will also be returned if we can’t decide; specifically if we arrive at a symbolic inequality thatcannot be resolved.
See also:
is_cross_positive_on(), is_Z_operator_on(), is_lyapunov_like_on()
REFERENCES:
A. Berman and P. Gaiha. A generalization of irreducible monotonicity. Linear Algebra and its Applications,
5:29-38, 1972.
A. Berman and R. J. Plemmons. Nonnegative Matrices in the Mathematical Sciences. SIAM, Philadelphia,
1994.
EXAMPLES:
Nonnegative matrices are positive operators on the nonnegative orthant:
sage: K = Cone([(1,0,0), (0,1,0), (0,0,1)])
˓→needs sage.geometry.polyhedronsage: L = random_matrix(QQ, 3).apply_map(abs)sage: L.is_positive_operator_on(K)˓→needs sage.geometry.polyhedron
True

#␣

#␣

>>> from sage.all import *>>> K = Cone([(Integer(1),Integer(0),Integer(0)), (Integer(0),Integer(1),˓→Integer(0)), (Integer(0),Integer(0),Integer(1))])␣˓→# needs sage.geometry.polyhedron>>> L = random_matrix(QQ, Integer(3)).apply_map(abs)>>> L.is_positive_operator_on(K)#␣˓→needs sage.geometry.polyhedron
True

Symbolic entries also work in some easy cases:
sage: K = Cone([(1,0,0), (0,1,0), (0,0,1)])
˓→needs sage.geometry.polyhedronsage: L = matrix(SR, [ [0,e, 0 ],
˓→needs sage.symbolic
....:
[0,
2, pi],....:[sqrt(2), 0, 0 ] ])sage: L.is_positive_operator_on(K)˓→needs sage.geometry.polyhedron
True

414

#␣
#␣

#␣

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> K = Cone([(Integer(1),Integer(0),Integer(0)), (Integer(0),Integer(1),˓→Integer(0)), (Integer(0),Integer(0),Integer(1))])␣˓→# needs sage.geometry.polyhedron>>> L = matrix(SR, [ [Integer(0),e, Integer(0) ],␣˓→# needs sage.symbolic...
[Integer(0),Integer(2), pi],...
[sqrt(Integer(2)), Integer(0), Integer(0) ] ])>>> L.is_positive_operator_on(K)#␣˓→needs sage.geometry.polyhedron
TrueYour matrix can be over any exact ring, for example the ring of univariate polynomials with rational coefficients:
sage: # needs sage.geometry.polyhedronsage: K = Cone([(1,0), (-1,0), (0,1), (0,-1)])
sage: K.is_full_space()
True
sage: x = polygen(ZZ, x )sage: L = matrix(QQ[x], [[x,0],[0,1]])
sage: L.is_positive_operator_on(K)True>>> from sage.all import *>>> # needs sage.geometry.polyhedron>>> K = Cone([(Integer(1),Integer(0)), (-Integer(1),Integer(0)), (Integer(0),˓→Integer(1)), (Integer(0),-Integer(1))])>>> K.is_full_space()True>>> x = polygen(ZZ, x )>>> L = matrix(QQ[x], [[x,Integer(0)],[Integer(0),Integer(1)]])>>> L.is_positive_operator_on(K)True

is_positive_semidefinite()
Returns whether or not this matrix is positive-semidefinite.
By SageMath convention, positive (semi)definite matrices must be either real symmetric or complex Hermitian.
ALGORITHM:
Bunch and Kaufman [BK1977] describe a fast, numerically-stable scheme for computing the “inertia” of amatrix by way Sylvester’s inertia theorem and a block-𝐿𝐷𝐿𝑇 factorization. We perform this factorization,and read off the signs of the eigenvalues from the resulting diagonal blocks.
REFERENCES:• [BK1977]
See also:
block_ldlt(), is_positive_definite()
EXAMPLES:
A positive-definite matrix:

415

Matrices and Spaces of Matrices, Release 10.4

sage: A = matrix(QQ, [ [2,1],....:[1,2] ] )sage: A.eigenvalues()
˓→needs sage.rings.number_field[3, 1]
sage: A.is_positive_semidefinite()
True

#␣

>>> from sage.all import *>>> A = matrix(QQ, [ [Integer(2),Integer(1)],...
[Integer(1),Integer(2)] ] )>>> A.eigenvalues()
˓→needs sage.rings.number_field[3, 1]>>> A.is_positive_semidefinite()
True

#␣

A positive-semidefinite (but not positive-definite) matrix:
sage: A = matrix(QQ, [ [1,1],....:[1,1] ] )sage: A.eigenvalues()
˓→needs sage.rings.number_field[2, 0]
sage: A.is_positive_semidefinite()
True

#␣

>>> from sage.all import *>>> A = matrix(QQ, [ [Integer(1),Integer(1)],...
[Integer(1),Integer(1)] ] )>>> A.eigenvalues()
˓→needs sage.rings.number_field[2, 0]>>> A.is_positive_semidefinite()
True

#␣

And finally, an indefinite matrix:
sage: A = matrix(QQ, [ [0,1],....:[1,0] ] )sage: A.eigenvalues()
˓→needs sage.rings.number_field[1, -1]
sage: A.is_positive_semidefinite()
False

#␣

>>> from sage.all import *>>> A = matrix(QQ, [ [Integer(0),Integer(1)],...
[Integer(1),Integer(0)] ] )>>> A.eigenvalues()
˓→needs sage.rings.number_field[1, -1]>>> A.is_positive_semidefinite()
False

#␣

A non-Hermitian matrix cannot be positive-semidefinite, regardless of its eigenvalues:

416

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

sage: A = matrix(QQ, [ [2,1],....:[0,0] ])
sage: A.eigenvalues()
˓→needs sage.rings.number_field[2, 0]
sage: A.is_positive_semidefinite()
False>>> from sage.all import *>>> A = matrix(QQ, [ [Integer(2),Integer(1)],...
[Integer(0),Integer(0)] ])>>> A.eigenvalues()
˓→needs sage.rings.number_field[2, 0]>>> A.is_positive_semidefinite()
False

#␣

#␣

Any of the preceding examples are valid over inexact rings and with complex numbers as well:sage: # needs sage.rings.complex_double sage.symbolic
sage: A = matrix(CDF, [ [ 2, I],....:[-I, 2] ] )sage: A.is_positive_semidefinite()True
sage: A = matrix(CDF, [ [ 1, I],....:[-I, 1] ] )sage: A.is_positive_semidefinite()True
sage: A = matrix(CDF, [ [0,I],....:[I,0] ] )sage: A.is_positive_semidefinite()
False
sage: A = matrix(CDF, [ [2,I],....:[0,0] ])
sage: A.is_positive_semidefinite()
False>>> from sage.all import *>>> # needs sage.rings.complex_double sage.symbolic>>> A = matrix(CDF, [ [ Integer(2), I],...
[-I, Integer(2)] ] )>>> A.is_positive_semidefinite()
True>>> A = matrix(CDF, [ [ Integer(1), I],...
[-I, Integer(1)] ] )>>> A.is_positive_semidefinite()
True>>> A = matrix(CDF, [ [Integer(0),I],...
[I,Integer(0)] ] )>>> A.is_positive_semidefinite()
False>>> A = matrix(CDF, [ [Integer(2),I],...
[Integer(0),Integer(0)] ])>>> A.is_positive_semidefinite()False

is_scalar(a=None)417

Matrices and Spaces of Matrices, Release 10.4

Return True if this matrix is a scalar matrix.
INPUT:• base_ring element a, which is chosen as self[0][0] if a = NoneOUTPUT:• whether self is a scalar matrix (in fact the scalar matrix aI if a is input)
EXAMPLES:
sage: m = matrix(QQ, 2,2, range(4))
sage: m.is_scalar(5)False
sage: m = matrix(QQ, 2, [5,0,0,5])
sage: m.is_scalar(5)Truesage: m = matrix(QQ, 2, [1,0,0,1])
sage: m.is_scalar(1)True
sage: m = matrix(QQ, 2, [1,1,1,1])
sage: m.is_scalar(1)False>>> from sage.all import *>>> m = matrix(QQ, Integer(2),Integer(2), range(Integer(4)))>>> m.is_scalar(Integer(5))
False>>> m = matrix(QQ, Integer(2), [Integer(5),Integer(0),Integer(0),Integer(5)])>>> m.is_scalar(Integer(5))
True>>> m = matrix(QQ, Integer(2), [Integer(1),Integer(0),Integer(0),Integer(1)])>>> m.is_scalar(Integer(1))
True>>> m = matrix(QQ, Integer(2), [Integer(1),Integer(1),Integer(1),Integer(1)])>>> m.is_scalar(Integer(1))
False

is_semisimple()
Return if self is semisimple.
A (square) matrix 𝐴 is semisimple if the minimal polynomial of 𝐴 is sqaure-free.
If 𝐴 represents a linear map from 𝐹 𝑛 → 𝐹 𝑛 for some field 𝐹 , then this is equivalent to every 𝐴-invariant
subspace of 𝐹 𝑛 has a complementary 𝐴-invariant subspace. This is also equivalent to saying the matrix isdiagonalizable over 𝐹¯ , the algebraic closure of 𝐹 .
EXAMPLES:
sage: A = matrix([[0, -1], [1, 0]]); A[ 0 -1][ 1 0]
sage: A.is_semisimple()True
sage: A.change_ring(QQ).is_diagonalizable()False
sage: A.change_ring(CyclotomicField(4)).is_diagonalizable()
True

418

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = matrix([[Integer(0), -Integer(1)], [Integer(1), Integer(0)]]); A[ 0 -1][ 1 0]>>> A.is_semisimple()
True>>> A.change_ring(QQ).is_diagonalizable()
False>>> A.change_ring(CyclotomicField(Integer(4))).is_diagonalizable()True

is_similar(other, transformation=False)
Return True if self and other are similar, i.e. related by a change-of-basis matrix.
INPUT:• other – a matrix, which should be square, and of the same size as self.
• transformation – (default: False); if True, the output may include the change-of-basis matrix(also known as the similarity transformation). See below for an exact description.
OUTPUT:
Two matrices, 𝐴 and 𝐵 are similar if they are square matrices of the same size and there is an invertible
matrix 𝑆 such that 𝐴 = 𝑆 −1 𝐵𝑆. 𝑆 can be interpreted as a change-of-basis matrix if 𝐴 and 𝐵 are viewed as
matrix representations of the same linear transformation from a vector space to itself.
When transformation=False this method will return True if such a matrix 𝑆 exists, otherwise it will
return False. When transformation=True the method returns a pair. The first part of the pair isTrue or False depending on if the matrices are similar. The second part of the pair is the change-of-basis
matrix when the matrices are similar and None when the matrices are not similar.
When a similarity transformation matrix S is requested, it will satisfy self = S.inverse()*other*S.
rings and coefficients
Inexact rings are not supported. Only rings having a fraction field can be used as coefficients.
The base rings for the matrices are promoted to a common field for the similarity check using rational form
over this field.
If the fraction fields of both matrices are the same, this field is used. Otherwise, if the fraction fields are only
related by a canonical coercion, the common coercion field is used.
In all cases, the result is about similarity over a common field.
similarity transformation
For computation of the similarity transformation, the matrices are first checked to be similar over their common field.
In this case, a similarity transformation is then searched for over the common field. If this fails, the matrices are promoted to the algebraic closure of their common field (whenever it is available) and a similarity
transformation is looked for over the algebraic closure.
For example, matrices over the rationals may be promoted to the field of algebraic numbers (QQbar) forcomputation of the similarity transformation.

419

Matrices and Spaces of Matrices, Release 10.4

Warning: When the two matrices are similar, this routine may fail to find the similarity transformation.
A technical explanation follows.
The similarity check is accomplished with rational form, which will be successful for any pair of matrices
over the same field. However, the computation of rational form does not provide a transformation. So we
instead compute Jordan form, which does provide a transformation. But Jordan form will require that the
eigenvalues of the matrix can be represented within Sage, requiring the existence of the appropriate extension
field. When this is not possible, a RuntimeError is raised, as demonstrated in an example below.
EXAMPLES:
The two matrices in this example were constructed to be similar. The computations happen in the field ofalgebraic numbers, but we are able to convert the change-of-basis matrix back to the rationals (which may
not always be possible).
sage: A = matrix(ZZ, [[-5, 2, -11],....:[-6, 7, -42],....:[0, 1, -6]])
sage: B = matrix(ZZ, [[ 1, 12, 3],....:[-1, -6, -1],....:
[ 0, 6, 1]])
sage: A.is_similar(B)True
sage: # needs sage.combinat sage.libs.pari
sage: _, T = A.is_similar(B, transformation=True)
sage: T[ 1.0000000000000? + 0.?e-13*I
0.?e-13 + 0.?e-13*I
0.?e˓→13 + 0.?e-13*I][-0.6666666666667? + 0.?e-13*I 0.16666666666667? + 0.?e-14*I -0.8333333333334?
˓→ + 0.?e-13*I][ 0.6666666666667? + 0.?e-13*I
0.?e-13 + 0.?e-13*I -0.333333333334?
˓→ + 0.?e-13*I]
sage: T.change_ring(QQ)[100][-2/3 1/6 -5/6][ 2/3
0 -1/3]sage: A == T.inverse()*B*T
True>>> from sage.all import *>>> A = matrix(ZZ, [[-Integer(5), Integer(2), -Integer(11)],...
[-Integer(6), Integer(7), -Integer(42)],...
[Integer(0), Integer(1), -Integer(6)]])>>> B = matrix(ZZ, [[ Integer(1), Integer(12), Integer(3)],...
[-Integer(1), -Integer(6), -Integer(1)],...
[ Integer(0), Integer(6), Integer(1)]])>>> A.is_similar(B)True>>> # needs sage.combinat sage.libs.pari>>> _, T = A.is_similar(B, transformation=True)>>> T[ 1.0000000000000? + 0.?e-13*I
0.?e-13 + 0.?e-13*I
0.?e˓→13 + 0.?e-13*I][-0.6666666666667? + 0.?e-13*I 0.16666666666667? + 0.?e-14*I -0.8333333333334?
(continues on next page)

420

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)+ 0.?e-13*I][ 0.6666666666667? + 0.?e-13*I
˓→ + 0.?e-13*I]>>> T.change_ring(QQ)[100][-2/3 1/6 -5/6][ 2/3
0 -1/3]>>> A == T.inverse()*B*T
True˓→0.?e-13 + 0.?e-13*I-0.333333333334?

Other exact fields are supported.
sage: # needs sage.rings.finite_rings
sage: F.<a> = FiniteField(7^2)
sage: A = matrix(F, [[2*a + 5, 6*a + 6,
a + 3],....:[ a + 3, 2*a + 2, 4*a + 2],....:[2*a + 6, 5*a + 5,
3*a]])
sage: B = matrix(F, [[5*a + 5, 6*a + 4,
a + 1],....:[ a + 5, 4*a + 3, 3*a + 3],....:[3*a + 5,
a + 4, 5*a + 6]])sage: A.is_similar(B)True
sage: B.is_similar(A)True
sage: _, T = A.is_similar(B, transformation=True)
sage: T[10
0]
[6*a + 1 4*a + 3 4*a + 2]
[6*a + 3 3*a + 5 3*a + 6]
sage: A == T.inverse() * B * T
True>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> F = FiniteField(Integer(7)**Integer(2), names=( a ,)); (a,) = F._first_
˓→ngens(1)>>> A = matrix(F, [[Integer(2)*a + Integer(5), Integer(6)*a + Integer(6),a␣
˓→+ Integer(3)],...
[ a + Integer(3), Integer(2)*a + Integer(2), Integer(4)*a␣
˓→+ Integer(2)],...
[Integer(2)*a + Integer(6), Integer(5)*a + Integer(5),␣˓→Integer(3)*a]])>>> B = matrix(F, [[Integer(5)*a + Integer(5), Integer(6)*a + Integer(4),a␣
˓→+ Integer(1)],...
[ a + Integer(5), Integer(4)*a + Integer(3), Integer(3)*a␣
˓→+ Integer(3)],...
[Integer(3)*a + Integer(5),a + Integer(4), Integer(5)*a␣
˓→+ Integer(6)]])>>> A.is_similar(B)
True>>> B.is_similar(A)True>>> _, T = A.is_similar(B, transformation=True)
>>> T
[
1
0
0]
[6*a + 1 4*a + 3 4*a + 2]
(continues on next page)421

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[6*a + 3 3*a + 5 3*a + 6]>>> A == T.inverse() * B * T
True

Two matrices with different sets of eigenvalues, so they cannot possibly be similar.
sage: A = matrix(QQ, [[ 2, 3, -3, -6],....:
[ 0, 1, -2, -8],....:[-3, -3, 4, 3],....:[-1, -2, 2, 6]])sage: B = matrix(QQ, [[ 1, 1, 2, 4],....:[-1, 2, -3, -7],....:[-2, 3, -4, -7],....:
[ 0, -1, 0, 0]])sage: A.eigenvalues() == B.eigenvalues()
˓→needs sage.rings.number_field
False
sage: A.is_similar(B, transformation=True)(False, None)#␣>>> from sage.all import *>>> A = matrix(QQ, [[ Integer(2), Integer(3), -Integer(3), -Integer(6)],...
[ Integer(0), Integer(1), -Integer(2), -Integer(8)],...
[-Integer(3), -Integer(3), Integer(4), Integer(3)],...
[-Integer(1), -Integer(2), Integer(2), Integer(6)]])>>> B = matrix(QQ, [[ Integer(1), Integer(1), Integer(2), Integer(4)],...
[-Integer(1), Integer(2), -Integer(3), -Integer(7)],...
[-Integer(2), Integer(3), -Integer(4), -Integer(7)],...
[ Integer(0), -Integer(1), Integer(0), Integer(0)]])>>> A.eigenvalues() == B.eigenvalues()#␣˓→needs sage.rings.number_field
False>>> A.is_similar(B, transformation=True)(False, None)

Similarity is an equivalence relation, so this routine computes a representative of the equivalence class foreach matrix, the rational form, as provided by rational_form(). The matrices below have identicaleigenvalues (as evidenced by equal characteristic polynomials), but slightly different rational forms, and hence
are not similar.
sage: A = matrix(QQ, [[ 19, -7, -29],....:[-16, 11, 30],....:
[ 15, -7, -25]])
sage: B = matrix(QQ, [[-38, -63, 42],....:
[ 14, 25, -14],....:[-14, -21, 18]])
sage: A.charpoly() == B.charpoly()
˓→needs sage.libs.pari
True
sage: A.rational_form()[ 0
0 -48]
[ 1
0
8]
[ 0
1
5]
sage: B.rational_form()[ 4| 0 0][--+-----]#␣(continues on next page)422

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 0| 0 12][ 0| 1 1]
sage: A.is_similar(B)False>>> from sage.all import *>>> A = matrix(QQ, [[ Integer(19), -Integer(7), -Integer(29)],...
[-Integer(16), Integer(11), Integer(30)],...
[ Integer(15), -Integer(7), -Integer(25)]])>>> B = matrix(QQ, [[-Integer(38), -Integer(63), Integer(42)],...
[ Integer(14), Integer(25), -Integer(14)],...
[-Integer(14), -Integer(21), Integer(18)]])>>> A.charpoly() == B.charpoly()
˓→needs sage.libs.pari
True>>> A.rational_form()[ 0
0 -48]
[ 1
0
8]
[ 0
1
5]
>>> B.rational_form()[ 4| 0 0][--+-----][ 0| 0 12][ 0| 1 1]>>> A.is_similar(B)
False

#␣

Obtaining the transformation between two similar matrices requires the Jordan form, which requires computing the eigenvalues of the matrix, which may not lie in the field used for entries of the matrix. In thisunfortunate case, the computation of the transformation may fail with a RuntimeError, EVEN when thematrices are similar. This is not the case for matrices over the integers, rationals or algebraic numbers, since
the computations are done in the algebraically closed field of algebraic numbers. Here is an example where
the similarity is obvious by design, but we are not able to resurrect a similarity transformation.
sage: # needs sage.rings.finite_rings
sage: F.<a> = FiniteField(7^2)
sage: C = matrix(F, [[ a + 2, 5*a + 4],....:[6*a + 6, 6*a + 4]])sage: S = matrix(F, [[0, 1],....:[1, 0]])
sage: D = S.inverse()*C*S
sage: C.is_similar(D)True
sage: C.is_similar(D, transformation=True)
˓→needs sage.combinat
Traceback (most recent call last):...
RuntimeError: unable to compute transformation for similar matrices
sage: C.jordan_form()
˓→needs sage.combinat
Traceback (most recent call last):...
RuntimeError: Some eigenvalue does not exist in
Finite Field in a of size 7^2.

#␣

#␣

423

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> F = FiniteField(Integer(7)**Integer(2), names=( a ,)); (a,) = F._first_
˓→ngens(1)>>> C = matrix(F, [[ a + Integer(2), Integer(5)*a + Integer(4)],...
[Integer(6)*a + Integer(6), Integer(6)*a + Integer(4)]])>>> S = matrix(F, [[Integer(0), Integer(1)],...
[Integer(1), Integer(0)]])>>> D = S.inverse()*C*S>>> C.is_similar(D)True>>> C.is_similar(D, transformation=True)#␣˓→needs sage.combinat
Traceback (most recent call last):...
RuntimeError: unable to compute transformation for similar matrices>>> C.jordan_form()#␣˓→needs sage.combinat
Traceback (most recent call last):...
RuntimeError: Some eigenvalue does not exist in
Finite Field in a of size 7^2.

An example over a finite field of prime order, which uses the algebraic closure of this field to find thechange-of-basis matrix:
sage: # needs sage.combinat sage.graphs sage.rings.finite_rings
sage: cox = posets.TamariLattice(3).coxeter_transformation()sage: M = cox.change_ring(GF(3))
sage: M.is_similar(M**3, True)# long time(
[1 0 0 0 0]
[0 1 1 0 2]
[0 0 0 0 1]
[1 2 0 2 1]
True, [0 0 1 0 0])>>> from sage.all import *>>> # needs sage.combinat sage.graphs sage.rings.finite_rings>>> cox = posets.TamariLattice(Integer(3)).coxeter_transformation()>>> M = cox.change_ring(GF(Integer(3)))>>> M.is_similar(M**Integer(3), True)# long time(
[1 0 0 0 0]
[0 1 1 0 2]
[0 0 0 0 1]
[1 2 0 2 1]
True, [0 0 1 0 0])

Inexact rings and fields are not supported.
sage: A = matrix(CDF, 2, 2, range(4))
sage: B = copy(A)sage: A.is_similar(B)Traceback (most recent call last):(continues on next page)424

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
TypeError: matrix entries must come from an exact field,
not Complex Double Field>>> from sage.all import *>>> A = matrix(CDF, Integer(2), Integer(2), range(Integer(4)))>>> B = copy(A)>>> A.is_similar(B)Traceback (most recent call last):...
TypeError: matrix entries must come from an exact field,
not Complex Double Field

Base rings for the matrices need to have a fraction field. So in particular, the ring needs to be at least an
integral domain.
sage: Z6 = Integers(6)sage: A = matrix(Z6, 2, 2, range(4))
sage: A.is_similar(A)Traceback (most recent call last):...
ValueError: base ring of a matrix needs a fraction field,
maybe the ring is not an integral domain>>> from sage.all import *>>> Z6 = Integers(Integer(6))>>> A = matrix(Z6, Integer(2), Integer(2), range(Integer(4)))>>> A.is_similar(A)Traceback (most recent call last):...
ValueError: base ring of a matrix needs a fraction field,
maybe the ring is not an integral domain

If the fraction fields of the entries are unequal and do not coerce in a common field, it is an error.
sage: A = matrix(GF(3), 2, 2, range(4))
sage: B = matrix(GF(2), 2, 2, range(4))
sage: A.is_similar(B, transformation=True)
Traceback (most recent call last):...
TypeError: no common canonical parent for objects with parents:
Full MatrixSpace of 2 by 2 dense matrices over Finite Fieldof size 3 andFull MatrixSpace of 2 by 2 dense matrices over Finite Fieldof size 2>>> from sage.all import *>>> A = matrix(GF(Integer(3)), Integer(2), Integer(2), range(Integer(4)))>>> B = matrix(GF(Integer(2)), Integer(2), Integer(2), range(Integer(4)))>>> A.is_similar(B, transformation=True)
Traceback (most recent call last):...
TypeError: no common canonical parent for objects with parents:
Full MatrixSpace of 2 by 2 dense matrices over Finite Fieldof size 3 and(continues on next page)425

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Full MatrixSpace of 2 by 2 dense matrices over Finite Fieldof size 2

A matrix over the integers and a matrix over the algebraic numbers will be compared over the algebraic
numbers (by coercion of QQ in QQbar).
sage: A = matrix(ZZ, 2, 2, range(4))
sage: B = matrix(QQbar, 2, 2, range(4))˓→needs sage.rings.number_fieldsage: A.is_similar(B)˓→needs sage.rings.number_field
True

#␣
#␣

>>> from sage.all import *>>> A = matrix(ZZ, Integer(2), Integer(2), range(Integer(4)))>>> B = matrix(QQbar, Integer(2), Integer(2), range(Integer(4)))˓→# needs sage.rings.number_field>>> A.is_similar(B)˓→needs sage.rings.number_field
True

␣
#␣

is_triangular(side='lower')
Return True if this matrix is a triangular matrix.
INPUT:• side – either "lower" (default) or "upper"
OUTPUT:boolean
EXAMPLES:
sage: m = matrix(QQ, 2, 2, range(4))
sage: m.is_triangular()False
sage: m = matrix(QQ, 2, [5, 0, 0, 5])
sage: m.is_triangular()True
sage: m = matrix(QQ, 2, [1, 2, 0, 1])
sage: m.is_triangular("upper")True
sage: m.is_triangular("lower")False>>> from sage.all import *>>> m = matrix(QQ, Integer(2), Integer(2), range(Integer(4)))>>> m.is_triangular()False>>> m = matrix(QQ, Integer(2), [Integer(5), Integer(0), Integer(0),␣
˓→Integer(5)])>>> m.is_triangular()True>>> m = matrix(QQ, Integer(2), [Integer(1), Integer(2), Integer(0),␣
˓→Integer(1)])>>> m.is_triangular("upper")(continues on next page)

426

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)True>>> m.is_triangular("lower")
False

is_unitary()
Return True if the columns of the matrix are an orthonormal basis.
For a matrix with real entries this determines if a matrix is “orthogonal” and for a matrix with complex entries
this determines if the matrix is “unitary.”
OUTPUT:
True if the matrix is square and its conjugate-transpose is its inverse, and False otherwise. In other words,
a matrix is orthogonal or unitary if the product of its conjugate-transpose times the matrix is the identity
matrix.
For numerical matrices a specialized routine available over RDF and CDF is a good choice.
EXAMPLES:
sage: A = matrix(QQbar,#␣˓→needs sage.rings.number_field sage.symbolic....:[[(1/sqrt(5))*(1+i), (1/sqrt(55))*(3+2*I), (1/˓→sqrt(22))*(2+2*I)],....:[(1/sqrt(5))*(1-i), (1/sqrt(55))*(2+2*I), (1/sqrt(22))*(˓→3+I)],....:[(1/sqrt(5))*I, (1/sqrt(55))*(3-5*I),(1/sqrt(22))*(˓→2)]])sage: A.is_unitary()#␣˓→needs sage.rings.number_field sage.symbolicTrue>>> from sage.all import *>>> A = matrix(QQbar,#␣˓→needs sage.rings.number_field sage.symbolic...
[[(Integer(1)/sqrt(Integer(5)))*(Integer(1)+i), (Integer(1)/˓→sqrt(Integer(55)))*(Integer(3)+Integer(2)*I), (Integer(1)/˓→sqrt(Integer(22)))*(Integer(2)+Integer(2)*I)],...
[(Integer(1)/sqrt(Integer(5)))*(Integer(1)-i), (Integer(1)/˓→sqrt(Integer(55)))*(Integer(2)+Integer(2)*I),(Integer(1)/˓→sqrt(Integer(22)))*(-Integer(3)+I)],...
[(Integer(1)/sqrt(Integer(5)))*I, (Integer(1)/˓→sqrt(Integer(55)))*(Integer(3)-Integer(5)*I),(Integer(1)/˓→sqrt(Integer(22)))*(-Integer(2))]])>>> A.is_unitary()#␣˓→needs sage.rings.number_field sage.symbolic
True

A permutation matrix is always orthogonal.
sage: # needs sage.combinat
sage: sigma = Permutation([1,3,4,5,2])
sage: P = sigma.to_matrix(); P[1 0 0 0 0]
[0 0 0 0 1]
[0 1 0 0 0]
[0 0 1 0 0](continues on next page)427

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 0 0 1 0]
sage: P.is_unitary()Truesage: P.change_ring(GF(3)).is_unitary()Truesage: P.change_ring(GF(3)).is_unitary()True>>> from sage.all import *>>> # needs sage.combinat>>> sigma = Permutation([Integer(1),Integer(3),Integer(4),Integer(5),˓→Integer(2)])>>> P = sigma.to_matrix(); P[1 0 0 0 0]
[0 0 0 0 1]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]>>> P.is_unitary()
True>>> P.change_ring(GF(Integer(3))).is_unitary()
True>>> P.change_ring(GF(Integer(3))).is_unitary()True

A square matrix far from unitary.
sage: A = matrix(QQ, 4, range(16))
sage: A.is_unitary()
False>>> from sage.all import *>>> A = matrix(QQ, Integer(4), range(Integer(16)))>>> A.is_unitary()
False

Rectangular matrices are never unitary.
sage: A = matrix(QQbar, 3, 4)
˓→needs sage.rings.number_fieldsage: A.is_unitary()
False

#␣

>>> from sage.all import *>>> A = matrix(QQbar, Integer(3), Integer(4))˓→# needs sage.rings.number_field>>> A.is_unitary()
False

␣

jordan_decomposition()
Return the Jordan decomposition of self.
The Jordan decomposition of a matrix 𝐴 is a pair of matrices (𝑆, 𝑁 ) such that
• 𝐴 = 𝑆 + 𝑁,
• 𝑆 is semisimple,
428

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

• 𝑁 is nilpotent.
EXAMPLES:
sage: A = matrix(QQ, 5, 5, {(0,1): -1, (1,0): 1, (2,3): -1}); A[ 0 -1 0 0 0]
[ 1 0 0 0 0]
[ 0 0 0 -1 0][ 0 0 0 0 0]
[ 0 0 0 0 0]
sage: S, N = A.jordan_decomposition()sage: S[ 0 -1 0 0 0]
[ 1 0 0 0 0]
[ 0 0 0 0 0]
[ 0 0 0 0 0]
[ 0 0 0 0 0]
sage: N[ 0 0 0 0 0]
[ 0 0 0 0 0]
[ 0 0 0 -1 0][ 0 0 0 0 0]
[ 0 0 0 0 0]
sage: A == S + N
True
sage: S.is_semisimple()True
sage: N.is_nilpotent()
True
sage: A.jordan_form()
Traceback (most recent call last):...
RuntimeError: Some eigenvalue does not exist in Rational Field.
>>> from sage.all import *>>> A = matrix(QQ, Integer(5), Integer(5), {(Integer(0),Integer(1)): ˓→Integer(1), (Integer(1),Integer(0)): Integer(1), (Integer(2),Integer(3)): ˓→Integer(1)}); A[ 0 -1 0 0 0]
[ 1 0 0 0 0]
[ 0 0 0 -1 0][ 0 0 0 0 0]
[ 0 0 0 0 0]>>> S, N = A.jordan_decomposition()>>> S[ 0 -1 0 0 0]
[ 1 0 0 0 0]
[ 0 0 0 0 0]
[ 0 0 0 0 0]
[ 0 0 0 0 0]>>> N
[ 0 0 0 0 0]
[ 0 0 0 0 0]
[ 0 0 0 -1 0][ 0 0 0 0 0]
[ 0 0 0 0 0]>>> A == S + N
True(continues on next page)429

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> S.is_semisimple()
True>>> N.is_nilpotent()
True>>> A.jordan_form()
Traceback (most recent call last):...
RuntimeError: Some eigenvalue does not exist in Rational Field.

jordan_form(base_ring=None, sparse=False, subdivide=True, transformation=False, eigenvalues=None,check_input=True)
Compute the Jordan normal form of this square matrix 𝐴, if it exists.
This computation is performed in a naive way using the ranks of powers of 𝐴 − 𝑥𝐼, where 𝑥 is an eigenvalueof the matrix 𝐴. If desired, a transformation matrix 𝑃 can be returned, which is such that the Jordan canonical form is given by 𝑃 −1 𝐴𝑃 ; if the matrix is diagonalizable, this equals to eigendecomposition or spectral
decomposition.
INPUT:• base_ring – Ring in which to compute the Jordan form.
• sparse – (default False) If sparse=True, return a sparse matrix.
• subdivide – (default True) If subdivide=True, the subdivisions for the Jordan blocks in thematrix are shown.
• transformation – (default False) If transformation=True, computes also the transformation matrix.
• eigenvalues – (default None) A complete set of roots, with multiplicity, of the characteristic polynomial of 𝐴, encoded as a list of pairs, each having the form (𝑟, 𝑚) with 𝑟 a root and 𝑚 its multiplicity.
If this is None, then Sage computes this list itself, but this is only possible over base rings in whose
quotient fields polynomial factorization is implemented. Over all other rings, providing this list manuallyis the only way to compute Jordan normal forms.
• check_input – (default True) A Boolean specifying whether the list eigenvalues (if provided)
has to be checked for correctness. Set this to False for a speedup if the eigenvalues are known to becorrect.
Note: Currently, the Jordan normal form is not computed over inexact rings in any but the trivial cases whenthe matrix is either 0 × 0 or 1 × 1.
In the case of exact rings, this method does not compute any generalized form of the Jordan normal form, but
is only able to compute the result if the characteristic polynomial of the matrix splits over the specific basering.
Note that the base ring must be a field or a ring with an implemented fraction field.
EXAMPLES:
sage: # needs sage.combinat sage.libs.pari
sage: a = matrix(ZZ,4,[1, 0, 0, 0, 0, 1, 0, 0,....:
1, -1, 1, 0, 1, -1, 1, 2]); a[ 1 0 0 0]
[ 0 1 0 0]
[ 1 -1 1 0]
(continues on next page)

430

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 1 -1 1 2]
sage: a.jordan_form()[2|0 0|0][-+---+-][0|1 1|0][0|0 1|0][-+---+-][0|0 0|1]
sage: a.jordan_form(subdivide=False)[2 0 0 0][0 1 1 0][0 0 1 0][0 0 0 1]
sage: b = matrix(ZZ,3,3,range(9)); b[0 1 2][3 4 5][6 7 8]sage: b.jordan_form()
Traceback (most recent call last):...
RuntimeError: Some eigenvalue does not exist in Rational Field.
sage: b.jordan_form(RealField(15))
Traceback (most recent call last):...
ValueError: Jordan normal form not implemented over inexact rings.
>>> from sage.all import *>>> # needs sage.combinat sage.libs.pari>>> a = matrix(ZZ,Integer(4),[Integer(1), Integer(0), Integer(0), Integer(0),␣
˓→Integer(0), Integer(1), Integer(0), Integer(0),...
Integer(1), -Integer(1), Integer(1), Integer(0),␣
˓→Integer(1), -Integer(1), Integer(1), Integer(2)]); a[ 1 0 0 0]
[ 0 1 0 0]
[ 1 -1 1 0]
[ 1 -1 1 2]>>> a.jordan_form()[2|0 0|0][-+---+-][0|1 1|0][0|0 1|0][-+---+-][0|0 0|1]>>> a.jordan_form(subdivide=False)[2 0 0 0][0 1 1 0][0 0 1 0][0 0 0 1]>>> b = matrix(ZZ,Integer(3),Integer(3),range(Integer(9))); b[0 1 2][3 4 5][6 7 8]>>> b.jordan_form()
Traceback (most recent call last):...
RuntimeError: Some eigenvalue does not exist in Rational Field.
(continues on next page)431

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> b.jordan_form(RealField(Integer(15)))
Traceback (most recent call last):...
ValueError: Jordan normal form not implemented over inexact rings.

Here we need to specify a field, since the eigenvalues are not defined in the smallest ring containing the matrix
entries (Issue #14508):
sage: c = matrix([[0,1,0], [0,0,1], [1,0,0]])
sage: c.jordan_form(CyclotomicField(3))˓→needs sage.combinat sage.rings.number_field
[
1|
0|
0]
[----------+----------+----------][
0|
zeta3|
0][----------+----------+----------][
0|0|-zeta3 - 1]

#␣>>> from sage.all import *>>> c = matrix([[Integer(0),Integer(1),Integer(0)], [Integer(0),Integer(0),˓→Integer(1)], [Integer(1),Integer(0),Integer(0)]])>>> c.jordan_form(CyclotomicField(Integer(3)))˓→# needs sage.combinat sage.rings.number_field
[
1|
0|
0]
[----------+----------+----------][
0|
zeta3|
0][----------+----------+----------][
0|0|-zeta3 - 1]

␣If you need the transformation matrix as well as the Jordan form of self, then pass the option transformation=True. For example:
sage: # needs sage.combinat sage.libs.pari
sage: m = matrix([[5,4,2,1], [0,1,-1,-1], [-1,-1,3,0], [1,1,-1,2]]); m[ 5 4 2 1]
[ 0 1 -1 -1][-1 -1 3 0]
[ 1 1 -1 2]
sage: jf, p = m.jordan_form(transformation=True)
sage: jf
[2|0|0 0][-+-+---][0|1|0 0][-+-+---][0|0|4 1][0|0|0 4]
sage: ~p * m * p[2 0 0 0][0 1 0 0][0 0 4 1][0 0 0 4]>>> from sage.all import *>>> # needs sage.combinat sage.libs.pari>>> m = matrix([[Integer(5),Integer(4),Integer(2),Integer(1)], [Integer(0),˓→Integer(1),-Integer(1),-Integer(1)], [-Integer(1),-Integer(1),Integer(3),˓→Integer(0)], [Integer(1),Integer(1),-Integer(1),Integer(2)]]); m(continues on next page)

432

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 5 4 2 1]
[ 0 1 -1 -1][-1 -1 3 0]
[ 1 1 -1 2]>>> jf, p = m.jordan_form(transformation=True)>>> jf[2|0|0 0][-+-+---][0|1|0 0][-+-+---][0|0|4 1][0|0|0 4]>>> ~p * m * p[2 0 0 0][0 1 0 0][0 0 4 1][0 0 0 4]

Note that for matrices over inexact rings, we do not attempt to compute the Jordan normal form, since it is
not numerically stable:
sage: b = matrix(ZZ, 3, 3, range(9))
sage: jf, p = b.jordan_form(RealField(15), transformation=True)
˓→needs sage.combinat
Traceback (most recent call last):...
ValueError: Jordan normal form not implemented over inexact rings.
>>> from sage.all import *>>> b = matrix(ZZ, Integer(3), Integer(3), range(Integer(9)))>>> jf, p = b.jordan_form(RealField(Integer(15)), transformation=True)˓→# needs sage.combinat
Traceback (most recent call last):...
ValueError: Jordan normal form not implemented over inexact rings.

#␣␣

kernel(*args, **kwds)
Returns the left kernel of this matrix, as a vector space or free module. This is the set of vectors x such thatx*self = 0.
Note: For the right kernel, use right_kernel(). The method kernel() is exactly equal toleft_kernel().
For inexact rings use right_kernel_matrix() with basis= computed (on the transpose of thematrix) to avoid echolonizing.
INPUT:• algorithm – (default: ‘default’); a keyword that selects the algorithm employed. Allowable values are:– ‘default’ – allows the algorithm to be chosen automatically– ‘generic’ – naive algorithm usable for matrices over any field– ‘flint’ – FLINT library code for matrices over the rationals or the integers– ‘pari’ – PARI library code for matrices over number fields or the integers
433

Matrices and Spaces of Matrices, Release 10.4

– ‘padic’ – padic algorithm from IML library for matrices over the rationals and integers– ‘pluq’ – PLUQ matrix factorization for matrices mod 2• basis – (default: ‘echelon’); a keyword that describes the format of the basis used to construct the left
kernel. Allowable values are:– ‘echelon’: the basis matrix is returned in echelon form
– ‘pivot’ : each basis vector is computed from the reduced row-echelon form of self by placing asingle one in a non-pivot column and zeros in the remaining non-pivot columns. Only available formatrices over fields.
– ‘LLL’: an LLL-reduced basis. Only available for matrices over the integers.
OUTPUT:
A vector space or free module whose degree equals the number of rows in self and which contains all thevectors x such that x*self = 0.
If self has 0 rows, the kernel has dimension 0, while if self has 0 columns the kernel is the entire ambient
vector space.
The result is cached. Requesting the left kernel a second time, but with a different basis format, will returnthe cached result with the format from the first computation.
Note: For much more detailed documentation of the various options see right_kernel(), since thismethod just computes the right kernel of the transpose of self.
EXAMPLES:Over the rationals with a basis matrix in echelon form.
sage: A = matrix(QQ, [[1, 2, 4, -7, 4],....:[1, 1, 0, 2, -1],....:
[1, 0, 3, -3, 1],....:[0, -1, -1, 3, -2],....:[0, 0, -1, 2, -1]])
sage: A.left_kernel()
Vector space of degree 5 and dimension 2 over Rational Field
Basis matrix:[ 1 0 -1 2 -1][ 0 1 -1 1 -4]>>> from sage.all import *>>> A = matrix(QQ, [[Integer(1), Integer(2), Integer(4), -Integer(7),␣
˓→Integer(4)],...
[Integer(1), Integer(1), Integer(0), Integer(2), ˓→Integer(1)],...
[Integer(1), Integer(0), Integer(3), -Integer(3),␣
˓→Integer(1)],...
[Integer(0), -Integer(1), -Integer(1), Integer(3), ˓→Integer(2)],...
[Integer(0), Integer(0), -Integer(1), Integer(2), ˓→Integer(1)]])>>> A.left_kernel()
Vector space of degree 5 and dimension 2 over Rational Field
Basis matrix:[ 1 0 -1 2 -1][ 0 1 -1 1 -4]

434

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

Over a finite field, with a basis matrix in “pivot” format.
sage: A = matrix(FiniteField(7), [[5, 0, 5, 2, 4],....:[1, 3, 2, 3, 6],....:[1, 1, 6, 5, 3],....:[2, 5, 6, 0, 0]])sage: A.kernel(basis= pivot )Vector space of degree 4 and dimension 2 over Finite Field of size 7User basis matrix:[5 2 1 0][6 3 0 1]>>> from sage.all import *>>> A = matrix(FiniteField(Integer(7)), [[Integer(5), Integer(0), Integer(5),␣
˓→Integer(2), Integer(4)],...
[Integer(1), Integer(3), Integer(2),␣
˓→Integer(3), Integer(6)],...
[Integer(1), Integer(1), Integer(6),␣
˓→Integer(5), Integer(3)],...
[Integer(2), Integer(5), Integer(6),␣
˓→Integer(0), Integer(0)]])>>> A.kernel(basis= pivot )Vector space of degree 4 and dimension 2 over Finite Field of size 7User basis matrix:[5 2 1 0][6 3 0 1]

The left kernel of a zero matrix is the entire ambient vector space whose degree equals the number of rowsof self (i.e. everything).
sage: A = MatrixSpace(QQ, 3, 4)(0)sage: A.kernel()
Vector space of degree 3 and dimension 3 over Rational Field
Basis matrix:[1 0 0][0 1 0][0 0 1]>>> from sage.all import *>>> A = MatrixSpace(QQ, Integer(3), Integer(4))(Integer(0))>>> A.kernel()
Vector space of degree 3 and dimension 3 over Rational Field
Basis matrix:[1 0 0][0 1 0][0 0 1]

We test matrices with no rows or columns.
sage: A = matrix(QQ, 2, 0)
sage: A.left_kernel()
Vector space of degree 2 and dimension 2 over Rational Field
Basis matrix:
[1 0]
[0 1]
sage: A = matrix(QQ, 0, 2)
sage: A.left_kernel()(continues on next page)435

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Vector space of degree 0 and dimension 0 over Rational Field
Basis matrix:[]>>> from sage.all import *>>> A = matrix(QQ, Integer(2), Integer(0))>>> A.left_kernel()
Vector space of degree 2 and dimension 2 over Rational Field
Basis matrix:
[1 0]
[0 1]
>>> A = matrix(QQ, Integer(0), Integer(2))>>> A.left_kernel()
Vector space of degree 0 and dimension 0 over Rational Field
Basis matrix:[]

The results are cached. Note that requesting a new format for the basis is ignored and the cached copy isreturned. Work with a copy if you need a new left kernel, or perhaps investigate the right_kernel_matrix() method on the transpose, which does not cache its results and is more flexible.
sage: A = matrix(QQ, [[1,1],[2,2]])
sage: K1 = A.left_kernel()sage: K1
Vector space of degree 2 and dimension 1 over Rational Field
Basis matrix:[
1 -1/2]sage: K2 = A.left_kernel()sage: K1 is K2
True
sage: K3 = A.left_kernel(basis= pivot )sage: K3
Vector space of degree 2 and dimension 1 over Rational Field
Basis matrix:[
1 -1/2]sage: B = copy(A)sage: K3 = B.left_kernel(basis= pivot )sage: K3
Vector space of degree 2 and dimension 1 over Rational Field
User basis matrix:[-2 1]
sage: K3 is K1
False
sage: K3 == K1
True>>> from sage.all import *>>> A = matrix(QQ, [[Integer(1),Integer(1)],[Integer(2),Integer(2)]])>>> K1 = A.left_kernel()>>> K1
Vector space of degree 2 and dimension 1 over Rational Field
Basis matrix:[
1 -1/2]>>> K2 = A.left_kernel()>>> K1 is K2
True(continues on next page)

436

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> K3 = A.left_kernel(basis= pivot )>>> K3Vector space of degree 2 and dimension 1 over Rational Field
Basis matrix:[
1 -1/2]>>> B = copy(A)>>> K3 = B.left_kernel(basis= pivot )>>> K3Vector space of degree 2 and dimension 1 over Rational Field
User basis matrix:[-2 1]>>> K3 is K1
False>>> K3 == K1
Truekernel_on(V, poly=None, check=True)
Return the kernel of self restricted to the invariant subspace V. The result is a vector subspace of V, which isalso a subspace of the ambient space.
INPUT:• V – vector subspace• check – (optional) default: True; whether to check that V is invariant under the action of self.
• poly – (optional) default: None; if not None, compute instead the kernel of poly(self) on V.
OUTPUT:• a subspace
Warning: This function does not check that V is in fact invariant under self if check is False. With
check False this function is much faster.
EXAMPLES:
sage: t = matrix(QQ, 4, [39, -10, 0, -12, 0, 2, 0, -1, 0, 1, -2, 0, 0, 2, 0, ˓→2]); t[ 39 -10
0 -12]
[ 0
2
0 -1]
[ 0
1 -2
0]
[ 0
2
0 -2]
sage: t.fcp()#␣˓→needs sage.libs.pari(x - 39) * (x + 2) * (x^2 - 2)sage: s = (t-39)*(t^2-2)
sage: V = s.kernel(); V
Vector space of degree 4 and dimension 3 over Rational Field
Basis matrix:[1 0 0 0][0 1 0 0][0 0 0 1]
sage: s.restrict(V)[0 0 0][0 0 0][0 0 0](continues on next page)437

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: s.kernel_on(V)
Vector space of degree 4 and dimension 3 over Rational Field
Basis matrix:[1 0 0 0][0 1 0 0][0 0 0 1]
sage: k = t-39
sage: k.restrict(V)[ 0 -10 -12]
[ 0 -37 -1][ 0
2 -41]
sage: ker = k.kernel_on(V); ker
Vector space of degree 4 and dimension 1 over Rational Field
Basis matrix:[
1 -2/7
0 -2/7]sage: ker.0 * k(0, 0, 0, 0)>>> from sage.all import *>>> t = matrix(QQ, Integer(4), [Integer(39), -Integer(10), Integer(0), ˓→Integer(12), Integer(0), Integer(2), Integer(0), -Integer(1), Integer(0),␣
˓→Integer(1), -Integer(2), Integer(0), Integer(0), Integer(2), Integer(0), ˓→Integer(2)]); t[ 39 -10
0 -12]
[ 0
2
0 -1]
[ 0
1 -2
0]
[ 0
2
0 -2]
>>> t.fcp()#␣˓→needs sage.libs.pari(x - 39) * (x + 2) * (x^2 - 2)>>> s = (t-Integer(39))*(t**Integer(2)-Integer(2))>>> V = s.kernel(); V
Vector space of degree 4 and dimension 3 over Rational Field
Basis matrix:[1 0 0 0][0 1 0 0][0 0 0 1]>>> s.restrict(V)[0 0 0][0 0 0][0 0 0]>>> s.kernel_on(V)
Vector space of degree 4 and dimension 3 over Rational Field
Basis matrix:[1 0 0 0][0 1 0 0][0 0 0 1]>>> k = t-Integer(39)>>> k.restrict(V)[ 0 -10 -12]
[ 0 -37 -1][ 0
2 -41]>>> ker = k.kernel_on(V); ker
Vector space of degree 4 and dimension 1 over Rational Field
Basis matrix:[
1 -2/7
0 -2/7](continues on next page)

438

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> ker.gen(0) * k(0, 0, 0, 0)

Test that Issue #9425 is fixed.
sage: V = span([[1/7,0,0] ,[0,1,0]], ZZ); V
Free module of degree 3 and rank 2 over Integer Ring
Echelon basis matrix:
[1/7
0
0]
[ 0
1
0]
sage: T = matrix(ZZ,3,[1,0,0,0,0,0,0,0,0]); T[1 0 0][0 0 0][0 0 0]sage: W = T.kernel_on(V); W.basis()[(0, 1, 0)]
sage: W.is_submodule(V)True>>> from sage.all import *>>> V = span([[Integer(1)/Integer(7),Integer(0),Integer(0)] ,[Integer(0),˓→Integer(1),Integer(0)]], ZZ); V
Free module of degree 3 and rank 2 over Integer Ring
Echelon basis matrix:
[1/7
0
0]
[ 0
1
0]
>>> T = matrix(ZZ,Integer(3),[Integer(1),Integer(0),Integer(0),Integer(0),˓→Integer(0),Integer(0),Integer(0),Integer(0),Integer(0)]); T[1 0 0][0 0 0][0 0 0]>>> W = T.kernel_on(V); W.basis()[(0, 1, 0)]>>> W.is_submodule(V)True

left_eigenmatrix(other=None)
Return matrices 𝐷 and 𝑃 , where 𝐷 is a diagonal matrix of eigenvalues and the rows of 𝑃 are corresponding
eigenvectors (or zero vectors).
INPUT:• other – a square matrix 𝐵 (default: None) in a generalized eigenvalue problem; if None, an ordinary
eigenvalue problem is solved
OUTPUT:
If self is a square matrix 𝐴, then the output is a diagonal matrix 𝐷 and a matrix 𝑃 such that𝑃 𝐴 = 𝐷𝑃,
where the rows of 𝑃 are eigenvectors of 𝐴 and the diagonal entries of 𝐷 are the corresponding eigenvalues.

439

Matrices and Spaces of Matrices, Release 10.4

If a matrix 𝐵 is passed as optional argument, the output is a solution to the generalized eigenvalue problem
such that𝑃 𝐴 = 𝐷𝑃 𝐵.
The ordinary eigenvalue problem is equivalent to the generalized one if 𝐵 is the identity matrix.
The generalized eigenvector decomposition is currently only implemented for matrices over RDF and CDF.
EXAMPLES:
sage: # needs sage.rings.number_fieldsage: A = matrix(QQ, 3, 3, range(9)); A[0 1 2][3 4 5][6 7 8]sage: D, P = A.eigenmatrix_left()
sage: D[00
0][
0 -1.348469228349535?
0][0
0 13.34846922834954?]
sage: P[
1-2
1][
1 0.3101020514433644? -0.3797958971132713?][
1
1.289897948556636?
1.579795897113272?]
sage: P*A == D*P
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQ, Integer(3), Integer(3), range(Integer(9))); A[0 1 2][3 4 5][6 7 8]>>> D, P = A.eigenmatrix_left()
>>> D
[
0
0
0]
[
0 -1.348469228349535?
0][0
0 13.34846922834954?]
>>> P
[
1
-2
1]
[
1 0.3101020514433644? -0.3797958971132713?][
1
1.289897948556636?
1.579795897113272?]>>> P*A == D*P
True

Because 𝑃 is invertible, 𝐴 is diagonalizable.
sage: A == (~P)*D*P
˓→needs sage.rings.number_field
True>>> from sage.all import *>>> A == (~P)*D*P
˓→needs sage.rings.number_field
True

#␣

#␣

The matrix 𝑃 may contain zero rows corresponding to eigenvalues for which the algebraic multiplicity isgreater than the geometric multiplicity. In these cases, the matrix is not diagonalizable.
440

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

sage: # needs sage.rings.number_fieldsage: A = jordan_block(2, 3); A[2 1 0][0 2 1][0 0 2]sage: D, P = A.eigenmatrix_left()
sage: D
[2 0 0][0 2 0][0 0 2]sage: P[0 0 1][0 0 0][0 0 0]sage: P*A == D*P
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = jordan_block(Integer(2), Integer(3)); A[2 1 0][0 2 1][0 0 2]>>> D, P = A.eigenmatrix_left()>>> D[2 0 0][0 2 0][0 0 2]>>> P[0 0 1][0 0 0][0 0 0]>>> P*A == D*P
True

A generalized eigenvector decomposition:
sage: # needs scipy
sage: A = matrix(RDF, [[1, -2], [3, 4]])sage: B = matrix(RDF, [[0, 7], [2, -3]])
sage: D, P = A.eigenmatrix_left(B)sage: (P * A - D * P * B).norm() < 1e-14
True>>> from sage.all import *>>> # needs scipy>>> A = matrix(RDF, [[Integer(1), -Integer(2)], [Integer(3), Integer(4)]])>>> B = matrix(RDF, [[Integer(0), Integer(7)], [Integer(2), -Integer(3)]])>>> D, P = A.eigenmatrix_left(B)>>> (P * A - D * P * B).norm() < RealNumber( 1e-14 )True

The matrix 𝐵 in a generalized eigenvalue problem may be singular:
sage: # needs scipy sage.rings.complex_double sage.symbolic
sage: A = matrix.identity(CDF, 2)
sage: B = matrix(CDF, [[2, 1+I], [4, 2+2*I]])(continues on next page)441

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: D, P = A.eigenmatrix_left(B)sage: D.diagonal() # tol 1e-14[0.2 - 0.1*I, +infinity]>>> from sage.all import *>>> # needs scipy sage.rings.complex_double sage.symbolic>>> A = matrix.identity(CDF, Integer(2))>>> B = matrix(CDF, [[Integer(2), Integer(1)+I], [Integer(4),␣
˓→Integer(2)+Integer(2)*I]])>>> D, P = A.eigenmatrix_left(B)>>> D.diagonal() # tol 1e-14[0.2 - 0.1*I, +infinity]

In this case, we can still verify the eigenvector equation for the first eigenvalue and first eigenvector:
sage: # needs scipy sage.rings.complex_double sage.symbolic
sage: l = D[0, 0]
sage: v = P[0, :]sage: (v * A - l * v * B).norm() < 1e-14
True>>> from sage.all import *>>> # needs scipy sage.rings.complex_double sage.symbolic>>> l = D[Integer(0), Integer(0)]>>> v = P[Integer(0), :]>>> (v * A - l * v * B).norm() < RealNumber( 1e-14 )True

The second eigenvector is contained in the left kernel of 𝐵:
sage: (P[1, :] * B).norm() < 1e-14
˓→needs scipy sage.rings.complex_double sage.symbolic
True

#␣

>>> from sage.all import *>>> (P[Integer(1), :] * B).norm() < RealNumber( 1e-14 )˓→# needs scipy sage.rings.complex_double sage.symbolicTrue␣

See also:
eigenvalues(),
eigenvectors_left(),eigenvectors_left(), eigenmatrix_right().

Matrix_double_dense.

left_eigenspaces(format='all', var='a', algebraic_multiplicity=False)
Compute the left eigenspaces of a matrix.
Note that eigenspaces_left() and left_eigenspaces() are identical methods. Here “left”
refers to the eigenvectors being placed to the left of the matrix.
INPUT:• self – a square matrix over an exact field. For inexact matrices consult the numerical or symbolic
matrix classes.
• format – one of:442

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4–

all – Attempts to create every eigenspace. This will always be possible for matrices with rational
entries.

–

galois – For each irreducible factor of the characteristic polynomial, a single eigenspace will
be output for a single root/eigenvalue for the irreducible factor.

– None (default) – Uses the all format if the base ring is contained in an algebraically closed
field which is implemented. Otherwise, uses the galois format.
• var – string (default: a ); variable name used to represent elements of the root field of each irreducible
factor of the characteristic polynomial. If var= a , then the root fields will be in terms of a0, a1,
a2, ..., where the numbering runs across all the irreducible factors of the characteristic polynomial,
even for linear factors.
• algebraic_multiplicity – (boolean, default: False); whether to include the algebraic multiplicity of each eigenvalue in the output. See the discussion below.
OUTPUT:
If algebraic_multiplicity=False, return a list of pairs (𝑒, 𝑉 ) where 𝑒 is an eigenvalue of thematrix, and 𝑉 is the corresponding left eigenspace. For Galois conjugates of eigenvalues, there may be justone representative eigenspace, depending on the format keyword.
If algebraic_multiplicity=True, return a list of triples (𝑒, 𝑉, 𝑛) where 𝑒 and 𝑉 are as above and𝑛 is the algebraic multiplicity of the eigenvalue.
Warning: Uses a somewhat naive algorithm (simply factors the characteristic polynomial and computes
kernels directly over the extension field).
EXAMPLES:
We compute the left eigenspaces of a 3 × 3 rational matrix. First, we request all of the eigenvalues, so
the results are in the field of algebraic numbers, QQbar. Then we request just one eigenspace per irreducible
factor of the characteristic polynomial with format= galois .
sage: A = matrix(QQ, 3, 3, range(9)); A[0 1 2][3 4 5][6 7 8]sage: es = A.eigenspaces_left(format= all ); es
˓→needs sage.rings.number_field[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]),(-1.348469228349535?,
Vector space of degree 3 and dimension 1 over Algebraic Field
User basis matrix:[
1 0.3101020514433644? -0.3797958971132713?]),(13.34846922834954?,
Vector space of degree 3 and dimension 1 over Algebraic Field
User basis matrix:[
1 1.289897948556636? 1.579795897113272?]) ]#␣sage: # needs sage.rings.number_fieldsage: es = A.eigenspaces_left(format= galois ); es[ (0,Vector space of degree 3 and dimension 1 over Rational Field(continues on next page)443

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

User basis matrix:[ 1 -2 1]),(a1,
Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/15*a1 + 2/5 2/15*a1 - 1/5]) ]sage: es = A.eigenspaces_left(format= galois ,....:algebraic_multiplicity=True); es[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1],1),(a1,
Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/15*a1 + 2/5 2/15*a1 - 1/5],1) ]sage: e, v, n = es[0]; v = v.basis()[0]sage: delta = e*v - v*A
sage: abs(abs(delta)) < 1e-10
True>>> from sage.all import *>>> A = matrix(QQ, Integer(3), Integer(3), range(Integer(9))); A[0 1 2][3 4 5][6 7 8]>>> es = A.eigenspaces_left(format= all ); es
˓→needs sage.rings.number_field[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]),(-1.348469228349535?,
Vector space of degree 3 and dimension 1 over Algebraic Field
User basis matrix:[
1 0.3101020514433644? -0.3797958971132713?]),(13.34846922834954?,
Vector space of degree 3 and dimension 1 over Algebraic Field
User basis matrix:[
1 1.289897948556636? 1.579795897113272?]) ]#␣>>> # needs sage.rings.number_field>>> es = A.eigenspaces_left(format= galois ); es[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]),(a1,
Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/15*a1 + 2/5 2/15*a1 - 1/5]) ](continues on next page)444

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> es = A.eigenspaces_left(format= galois ,...
algebraic_multiplicity=True); es[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1],1),(a1,
Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/15*a1 + 2/5 2/15*a1 - 1/5],
1) ]>>> e, v, n = es[Integer(0)]; v = v.basis()[Integer(0)]>>> delta = e*v - v*A>>> abs(abs(delta)) < RealNumber( 1e-10 )True

The same computation, but with implicit base change to a field.
sage: A = matrix(ZZ, 3, 3, range(9)); A[0 1 2][3 4 5][6 7 8]sage: A.eigenspaces_left(format= galois )˓→needs sage.rings.number_field[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]),(a1,
Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/15*a1 + 2/5 2/15*a1 - 1/5]) ]>>> from sage.all import *>>> A = matrix(ZZ, Integer(3), Integer(3), range(Integer(9))); A[0 1 2][3 4 5][6 7 8]>>> A.eigenspaces_left(format= galois )˓→needs sage.rings.number_field[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]),(a1,
Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/15*a1 + 2/5 2/15*a1 - 1/5]) ]#␣#␣We compute the left eigenspaces of the matrix of the Hecke operator 𝑇2 on level 43 modular symbols, bothwith all eigenvalues (the default) and with one subspace per factor.

445

Matrices and Spaces of Matrices, Release 10.4

sage: # needs sage.modular
sage: A = ModularSymbols(43).T(2).matrix(); A[ 3 0 0 0 0 0 -1][ 0 -2 1 0 0 0 0]
[ 0 -1 1 1 0 -1 0][ 0 -1 0 -1 2 -1 1][ 0 -1 0 1 1 -1 1][ 0 0 -2 0 2 -2 1][ 0 0 -1 0 1 0 -1]
sage: A.base_ring()
Rational Field
sage: f = A.charpoly(); fx^7 + x^6 - 12*x^5 - 16*x^4 + 36*x^3 + 52*x^2 - 32*x - 48
sage: factor(f)(x - 3) * (x + 2)^2 * (x^2 - 2)^2
sage: A.eigenspaces_left(algebraic_multiplicity=True)[ (3,Vector space of degree 7 and dimension 1 over Rational Field
User basis matrix:
[
1
0 1/7
0 -1/7
0 -2/7],1),(-2,Vector space of degree 7 and dimension 2 over Rational Field
User basis matrix:[ 0 1 0 1 -1 1 -1][ 0 0 1 0 -1 2 -1],
2),(-1.414213562373095?,
Vector space of degree 7 and dimension 2 over Algebraic Field
User basis matrix:
[
0
1
0
␣
˓→
-1 0.4142135623730951?
1
-1]
[
0
0
1
␣
˓→
0
-1
0 2.414213562373095?],2),(1.414213562373095?,
Vector space of degree 7 and dimension 2 over Algebraic Field
User basis matrix:
[
0
1
0
␣
˓→
-1 -2.414213562373095?
1
-1]
[
0
0
1
␣
˓→
0
-1
0 -0.4142135623730951?],2) ]sage: A.eigenspaces_left(format= galois , algebraic_multiplicity=True)[ (3,Vector space of degree 7 and dimension 1 over Rational Field
User basis matrix:
[
1
0 1/7
0 -1/7
0 -2/7],1),(-2,Vector space of degree 7 and dimension 2 over Rational Field
User basis matrix:[ 0 1 0 1 -1 1 -1][ 0 0 1 0 -1 2 -1],2),(a2,Vector space of degree 7 and dimension 2(continues on next page)

446

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

over Number Field in a2 with defining polynomial x^2 - 2
User basis matrix:[0
1
0-1 -a2 - 1
1
-1]
[
0
0
1
0
-1
0 -a2 + 1],2) ]>>> from sage.all import *>>> # needs sage.modular>>> A = ModularSymbols(Integer(43)).T(Integer(2)).matrix(); A[ 3 0 0 0 0 0 -1][ 0 -2 1 0 0 0 0]
[ 0 -1 1 1 0 -1 0][ 0 -1 0 -1 2 -1 1][ 0 -1 0 1 1 -1 1][ 0 0 -2 0 2 -2 1][ 0 0 -1 0 1 0 -1]>>> A.base_ring()
Rational Field>>> f = A.charpoly(); fx^7 + x^6 - 12*x^5 - 16*x^4 + 36*x^3 + 52*x^2 - 32*x - 48>>> factor(f)(x - 3) * (x + 2)^2 * (x^2 - 2)^2>>> A.eigenspaces_left(algebraic_multiplicity=True)[ (3,Vector space of degree 7 and dimension 1 over Rational Field
User basis matrix:
[
1
0 1/7
0 -1/7
0 -2/7],1),(-2,Vector space of degree 7 and dimension 2 over Rational Field
User basis matrix:[ 0 1 0 1 -1 1 -1][ 0 0 1 0 -1 2 -1],
2),(-1.414213562373095?,
Vector space of degree 7 and dimension 2 over Algebraic Field
User basis matrix:
[
0
1
0
␣
˓→
-1 0.4142135623730951?
1
-1]
[
0
0
1
␣
˓→
0
-1
0 2.414213562373095?],2),(1.414213562373095?,
Vector space of degree 7 and dimension 2 over Algebraic Field
User basis matrix:
[
0
1
0
␣
˓→
-1 -2.414213562373095?
1
-1]
[
0
0
1
␣
˓→
0
-1
0 -0.4142135623730951?],
2) ]>>> A.eigenspaces_left(format= galois , algebraic_multiplicity=True)[ (3,Vector space of degree 7 and dimension 1 over Rational Field
User basis matrix:
[
1
0 1/7
0 -1/7
0 -2/7],
1),(continues on next page)447

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)(-2,
Vector space of degree 7 and dimension 2 over Rational Field
User basis matrix:[ 0 1 0 1 -1 1 -1][ 0 0 1 0 -1 2 -1],2),(a2,Vector space of degree 7 and dimension 2over Number Field in a2 with defining polynomial x^2 - 2
User basis matrix:[0
1
0-1 -a2 - 1
1
-1]
[
0
0
1
0
-1
0 -a2 + 1],
2) ]Next we compute the left eigenspaces over the finite field of order 11.
sage: # needs sage.modular sage.rings.finite_rings
sage: A = ModularSymbols(43, base_ring=GF(11), sign=1).T(2).matrix(); A[ 3 0 9 0]
[ 0 9 0 10][ 0 0 10 1][ 0 0 1 1]
sage: A.base_ring()
Finite Field of size 11
sage: A.charpoly()x^4 + 10*x^3 + 3*x^2 + 2*x + 1
sage: A.eigenspaces_left(format= galois , var= beta )[ (9,Vector space of degree 4 and dimension 1 over Finite Field of size 11
User basis matrix: [0 1 5 6]),(3, Vector space of degree 4 and dimension 1 over Finite Field of size 11
User basis matrix: [1 0 1 6]),(beta2, Vector space of degree 4 and dimension 1
over Univariate Quotient Polynomial Ring in beta2
over Finite Field of size 11 with modulus x^2 + 9
User basis matrix: [00
1 beta2 + 1])]>>> from sage.all import *>>> # needs sage.modular sage.rings.finite_rings>>> A = ModularSymbols(Integer(43), base_ring=GF(Integer(11)),␣
˓→sign=Integer(1)).T(Integer(2)).matrix(); A[ 3 0 9 0]
[ 0 9 0 10][ 0 0 10 1][ 0 0 1 1]>>> A.base_ring()
Finite Field of size 11>>> A.charpoly()x^4 + 10*x^3 + 3*x^2 + 2*x + 1>>> A.eigenspaces_left(format= galois , var= beta )[ (9,Vector space of degree 4 and dimension 1 over Finite Field of size 11
User basis matrix: [0 1 5 6]),(3, Vector space of degree 4 and dimension 1 over Finite Field of size 11
User basis matrix: [1 0 1 6]),
(continues on next page)

448

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)(beta2, Vector space of degree 4 and dimension 1
over Univariate Quotient Polynomial Ring in beta2
over Finite Field of size 11 with modulus x^2 + 9
User basis matrix: [00
1 beta2 + 1])]

This method is only applicable to exact matrices. The “eigenmatrix” routines for matrices withdouble-precision floating-point entries (RDF, CDF) are the best alternative. (Since some platforms return
eigenvectors that are the negatives of those given here, this one example is not tested here.) There are also
“eigenmatrix” routines for matrices with symbolic entries.
sage: A = matrix(QQ, 3, 3, range(9))
sage: A.change_ring(RR).eigenspaces_left()
Traceback (most recent call last):...
NotImplementedError: eigenspaces cannot be computed reliably
for inexact rings such as Real Field with 53 bits of precision,
consult numerical or symbolic matrix classes for other options
sage: # needs scipy
sage: em = A.change_ring(RDF).eigenmatrix_left()
sage: eigenvalues = em[0]; eigenvalues.dense_matrix()[13.348469228349522
0.0[
0.0 -1.348469228349534
[
0.0
0.0
sage: eigenvectors = em[1]; eigenvectors # not tested[ 0.440242867... 0.567868371... 0.695493875...][ 0.897878732... 0.278434036... -0.341010658...][ 0.408248290... -0.816496580... 0.408248290...]# abs tol 1e-13
0.0]
0.0]
0.0]

sage: # needs sage.symbolic
sage: x, y = var( x y )sage: S = matrix([[x, y], [y, 3*x^2]])sage: em = S.eigenmatrix_left()
sage: eigenvalues = em[0]; eigenvalues[3/2*x^2 + 1/2*x - 1/2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2)
␣
˓→
0]
[
0 3/2*x^2 + 1/2*x + 1/
˓→2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2)]
sage: eigenvectors = em[1]; eigenvectors[
1 1/2*(3*x^2 - x -␣˓→sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y][
1 1/2*(3*x^2 - x +␣˓→sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y]>>> from sage.all import *>>> A = matrix(QQ, Integer(3), Integer(3), range(Integer(9)))>>> A.change_ring(RR).eigenspaces_left()
Traceback (most recent call last):...
NotImplementedError: eigenspaces cannot be computed reliably
for inexact rings such as Real Field with 53 bits of precision,
consult numerical or symbolic matrix classes for other options>>> # needs scipy>>> em = A.change_ring(RDF).eigenmatrix_left()(continues on next page)449

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> eigenvalues = em[Integer(0)]; eigenvalues.dense_matrix()[13.348469228349522
0.0
0.0]
[
0.0 -1.348469228349534
0.0]
[
0.0
0.0
0.0]
>>> eigenvectors = em[Integer(1)]; eigenvectors # not tested[ 0.440242867... 0.567868371... 0.695493875...][ 0.897878732... 0.278434036... -0.341010658...][ 0.408248290... -0.816496580... 0.408248290...]# abs tol 1e-13>>> # needs sage.symbolic>>> x, y = var( x y )>>> S = matrix([[x, y], [y, Integer(3)*x**Integer(2)]])>>> em = S.eigenmatrix_left()>>> eigenvalues = em[Integer(0)]; eigenvalues[3/2*x^2 + 1/2*x - 1/2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2)
␣
˓→
0]
[
0 3/2*x^2 + 1/2*x + 1/
˓→2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2)]>>> eigenvectors = em[Integer(1)]; eigenvectors[
1 1/2*(3*x^2 - x -␣˓→sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y][
1 1/2*(3*x^2 - x +␣˓→sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y]

A request for all the eigenvalues, when it is not possible, will raise an error. Using the galois
format option is more likely to be successful.
sage: # needs sage.rings.finite_rings
sage: F.<b> = FiniteField(11^2)sage: A = matrix(F, [[b + 1, b + 1], [10*b + 4, 5*b + 4]])sage: A.eigenspaces_left(format= all )#␣˓→needs sage.rings.number_field
Traceback (most recent call last):...
NotImplementedError: unable to construct eigenspaces for eigenvalues outside␣˓→the base field,
try the keyword option: format= galois
sage: A.eigenspaces_left(format= galois )#␣˓→needs sage.rings.number_field[ (a0,
Vector space of degree 2 and dimension 1 over
Univariate Quotient Polynomial Ring in a0 over
Finite Field in b of size 11^2
with modulus x^2 + (5*b + 6)*x + 8*b + 10
User basis matrix:[
1 6*b*a0 + 3*b + 1]) ]>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> F = FiniteField(Integer(11)**Integer(2), names=( b ,)); (b,) = F._first_
˓→ngens(1)>>> A = matrix(F, [[b + Integer(1), b + Integer(1)], [Integer(10)*b +␣
˓→Integer(4), Integer(5)*b + Integer(4)]])>>> A.eigenspaces_left(format= all )#␣˓→needs sage.rings.number_field
Traceback (most recent call last):(continues on next page)

450

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
NotImplementedError: unable to construct eigenspaces for eigenvalues outside␣˓→the base field,
try the keyword option: format= galois>>> A.eigenspaces_left(format= galois )#␣˓→needs sage.rings.number_field[ (a0,
Vector space of degree 2 and dimension 1 over
Univariate Quotient Polynomial Ring in a0 over
Finite Field in b of size 11^2
with modulus x^2 + (5*b + 6)*x + 8*b + 10
User basis matrix:[
1 6*b*a0 + 3*b + 1]) ]left_eigenvectors(other=None, extend=True)
Compute the left eigenvectors of a matrix.
INPUT:• other – a square matrix 𝐵 (default: None) in a generalized eigenvalue problem; if None, an ordinary
eigenvalue problem is solved (currently supported only if the base ring of self is RDF or CDF)
• extend – boolean (default: True)OUTPUT:For each distinct eigenvalue, returns a list of the form (e,V,n) where e is the eigenvalue, V is a list of eigenvectors forming a basis for the corresponding left eigenspace, and n is the algebraic multiplicity of the eigenvalue.
If the option extend is set to False, then only the eigenvalues that live in the base ring are considered.
EXAMPLES:
We compute the left eigenvectors of a 3 × 3 rational matrix.
sage: # needs sage.rings.number_fieldsage: A = matrix(QQ, 3, 3, range(9)); A[0 1 2][3 4 5][6 7 8]sage: es = A.eigenvectors_left(); es[(0, [ (1, -2, 1) ], 1),(-1.348469228349535?, [(1, 0.3101020514433644?, -0.3797958971132713?)], 1),(13.34846922834954?, [(1, 1.289897948556636?, 1.579795897113272?)], 1)]
sage: eval, [evec], mult = es[0]sage: delta = eval*evec - evec*A
sage: abs(abs(delta)) < 1e-10
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQ, Integer(3), Integer(3), range(Integer(9))); A[0 1 2][3 4 5][6 7 8]>>> es = A.eigenvectors_left(); es[(0, [ (1, -2, 1) ], 1),(-1.348469228349535?, [(1, 0.3101020514433644?, -0.3797958971132713?)], 1),(13.34846922834954?, [(1, 1.289897948556636?, 1.579795897113272?)], 1)](continues on next page)451

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> eval, [evec], mult = es[Integer(0)]>>> delta = eval*evec - evec*A>>> abs(abs(delta)) < RealNumber( 1e-10 )True

Notice the difference between considering ring extensions or not.
sage: M = matrix(QQ, [[0,-1,0], [1,0,0], [0,0,2]])
sage: M.eigenvectors_left()
˓→needs sage.rings.number_field[(2,[ (0, 0, 1) ], 1),(-1*I, [(1, -1*I, 0)], 1),(1*I, [(1, 1*I, 0)], 1)]
sage: M.eigenvectors_left(extend=False)
˓→needs sage.rings.number_field[(2,[ (0, 0, 1) ], 1)]>>> from sage.all import *>>> M = matrix(QQ, [[Integer(0),-Integer(1),Integer(0)], [Integer(1),˓→Integer(0),Integer(0)], [Integer(0),Integer(0),Integer(2)]])>>> M.eigenvectors_left()
˓→needs sage.rings.number_field[(2,[ (0, 0, 1) ], 1),(-1*I, [(1, -1*I, 0)], 1),(1*I, [(1, 1*I, 0)], 1)]>>> M.eigenvectors_left(extend=False)
˓→needs sage.rings.number_field[(2,[ (0, 0, 1) ], 1)]

#␣

#␣

#␣

#␣

left_kernel(*args, **kwds)
Returns the left kernel of this matrix, as a vector space or free module. This is the set of vectors x such thatx*self = 0.
Note: For the right kernel, use right_kernel(). The method kernel() is exactly equal toleft_kernel().
For inexact rings use right_kernel_matrix() with basis= computed (on the transpose of thematrix) to avoid echolonizing.
INPUT:• algorithm – (default: ‘default’); a keyword that selects the algorithm employed. Allowable values are:– ‘default’ – allows the algorithm to be chosen automatically– ‘generic’ – naive algorithm usable for matrices over any field– ‘flint’ – FLINT library code for matrices over the rationals or the integers– ‘pari’ – PARI library code for matrices over number fields or the integers– ‘padic’ – padic algorithm from IML library for matrices over the rationals and integers– ‘pluq’ – PLUQ matrix factorization for matrices mod 2• basis – (default: ‘echelon’); a keyword that describes the format of the basis used to construct the left
kernel. Allowable values are:452

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

– ‘echelon’: the basis matrix is returned in echelon form
– ‘pivot’ : each basis vector is computed from the reduced row-echelon form of self by placing asingle one in a non-pivot column and zeros in the remaining non-pivot columns. Only available formatrices over fields.
– ‘LLL’: an LLL-reduced basis. Only available for matrices over the integers.
OUTPUT:
A vector space or free module whose degree equals the number of rows in self and which contains all thevectors x such that x*self = 0.
If self has 0 rows, the kernel has dimension 0, while if self has 0 columns the kernel is the entire ambient
vector space.
The result is cached. Requesting the left kernel a second time, but with a different basis format, will returnthe cached result with the format from the first computation.
Note: For much more detailed documentation of the various options see right_kernel(), since thismethod just computes the right kernel of the transpose of self.
EXAMPLES:Over the rationals with a basis matrix in echelon form.
sage: A = matrix(QQ, [[1, 2, 4, -7, 4],....:[1, 1, 0, 2, -1],....:
[1, 0, 3, -3, 1],....:[0, -1, -1, 3, -2],....:[0, 0, -1, 2, -1]])
sage: A.left_kernel()
Vector space of degree 5 and dimension 2 over Rational Field
Basis matrix:[ 1 0 -1 2 -1][ 0 1 -1 1 -4]>>> from sage.all import *>>> A = matrix(QQ, [[Integer(1), Integer(2), Integer(4), -Integer(7),␣
˓→Integer(4)],...
[Integer(1), Integer(1), Integer(0), Integer(2), ˓→Integer(1)],...
[Integer(1), Integer(0), Integer(3), -Integer(3),␣
˓→Integer(1)],...
[Integer(0), -Integer(1), -Integer(1), Integer(3), ˓→Integer(2)],...
[Integer(0), Integer(0), -Integer(1), Integer(2), ˓→Integer(1)]])>>> A.left_kernel()
Vector space of degree 5 and dimension 2 over Rational Field
Basis matrix:[ 1 0 -1 2 -1][ 0 1 -1 1 -4]

Over a finite field, with a basis matrix in “pivot” format.
sage: A = matrix(FiniteField(7), [[5, 0, 5, 2, 4],....:[1, 3, 2, 3, 6],(continues on next page)453

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)....:[1, 1, 6, 5, 3],....:[2, 5, 6, 0, 0]])sage: A.kernel(basis= pivot )Vector space of degree 4 and dimension 2 over Finite Field of size 7User basis matrix:[5 2 1 0][6 3 0 1]>>> from sage.all import *>>> A = matrix(FiniteField(Integer(7)), [[Integer(5), Integer(0), Integer(5),␣
˓→Integer(2), Integer(4)],...
[Integer(1), Integer(3), Integer(2),␣
˓→Integer(3), Integer(6)],...
[Integer(1), Integer(1), Integer(6),␣
˓→Integer(5), Integer(3)],...
[Integer(2), Integer(5), Integer(6),␣
˓→Integer(0), Integer(0)]])>>> A.kernel(basis= pivot )Vector space of degree 4 and dimension 2 over Finite Field of size 7User basis matrix:[5 2 1 0][6 3 0 1]

The left kernel of a zero matrix is the entire ambient vector space whose degree equals the number of rowsof self (i.e. everything).
sage: A = MatrixSpace(QQ, 3, 4)(0)sage: A.kernel()
Vector space of degree 3 and dimension 3 over Rational Field
Basis matrix:[1 0 0][0 1 0][0 0 1]>>> from sage.all import *>>> A = MatrixSpace(QQ, Integer(3), Integer(4))(Integer(0))>>> A.kernel()
Vector space of degree 3 and dimension 3 over Rational Field
Basis matrix:[1 0 0][0 1 0][0 0 1]

We test matrices with no rows or columns.
sage: A = matrix(QQ, 2, 0)
sage: A.left_kernel()
Vector space of degree 2 and dimension 2 over Rational Field
Basis matrix:
[1 0]
[0 1]
sage: A = matrix(QQ, 0, 2)
sage: A.left_kernel()
Vector space of degree 0 and dimension 0 over Rational Field
Basis matrix:[]

454

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = matrix(QQ, Integer(2), Integer(0))>>> A.left_kernel()
Vector space of degree 2 and dimension 2 over Rational Field
Basis matrix:
[1 0]
[0 1]
>>> A = matrix(QQ, Integer(0), Integer(2))>>> A.left_kernel()
Vector space of degree 0 and dimension 0 over Rational Field
Basis matrix:[]

The results are cached. Note that requesting a new format for the basis is ignored and the cached copy isreturned. Work with a copy if you need a new left kernel, or perhaps investigate the right_kernel_matrix() method on the transpose, which does not cache its results and is more flexible.
sage: A = matrix(QQ, [[1,1],[2,2]])
sage: K1 = A.left_kernel()sage: K1
Vector space of degree 2 and dimension 1 over Rational Field
Basis matrix:[
1 -1/2]sage: K2 = A.left_kernel()sage: K1 is K2
True
sage: K3 = A.left_kernel(basis= pivot )sage: K3
Vector space of degree 2 and dimension 1 over Rational Field
Basis matrix:[
1 -1/2]sage: B = copy(A)sage: K3 = B.left_kernel(basis= pivot )sage: K3
Vector space of degree 2 and dimension 1 over Rational Field
User basis matrix:[-2 1]
sage: K3 is K1
False
sage: K3 == K1
True>>> from sage.all import *>>> A = matrix(QQ, [[Integer(1),Integer(1)],[Integer(2),Integer(2)]])>>> K1 = A.left_kernel()>>> K1
Vector space of degree 2 and dimension 1 over Rational Field
Basis matrix:[
1 -1/2]>>> K2 = A.left_kernel()>>> K1 is K2
True>>> K3 = A.left_kernel(basis= pivot )>>> K3Vector space of degree 2 and dimension 1 over Rational Field
Basis matrix:[
1 -1/2](continues on next page)455

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> B = copy(A)>>> K3 = B.left_kernel(basis= pivot )>>> K3Vector space of degree 2 and dimension 1 over Rational Field
User basis matrix:[-2 1]>>> K3 is K1
False>>> K3 == K1
True

left_kernel_matrix(*args, **kwds)
Returns a matrix whose rows form a basis for the left kernel of self.
This method is a thin wrapper around right_kernel_matrix(). For supported parameters and input/output formats, see there.
EXAMPLES:
sage: M = matrix([[1,2],[3,4],[5,6]])
sage: K = M.left_kernel_matrix(); K[ 1 -2 1]
sage: K * M[0 0]>>> from sage.all import *>>> M = matrix([[Integer(1),Integer(2)],[Integer(3),Integer(4)],[Integer(5),˓→Integer(6)]])>>> K = M.left_kernel_matrix(); K[ 1 -2 1]>>> K * M
[0 0]left_nullity()
Return the (left) nullity of this matrix, which is the dimension of the (left) kernel of this matrix acting fromthe right on row vectors.
EXAMPLES:
sage: M = Matrix(QQ, [[1,0,0,1], [0,1,1,0], [1,1,1,0]])
sage: M.nullity()0sage: M.left_nullity()0>>> from sage.all import *>>> M = Matrix(QQ, [[Integer(1),Integer(0),Integer(0),Integer(1)],␣
˓→[Integer(0),Integer(1),Integer(1),Integer(0)], [Integer(1),Integer(1),˓→Integer(1),Integer(0)]])>>> M.nullity()0>>> M.left_nullity()0sage: A = M.transpose()sage: A.nullity()(continues on next page)

456

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)1
sage: A.left_nullity()1>>> from sage.all import *>>> A = M.transpose()>>> A.nullity()1>>> A.left_nullity()1sage: M = M.change_ring(ZZ)
sage: M.nullity()0sage: A = M.transpose()sage: A.nullity()1>>> from sage.all import *>>> M = M.change_ring(ZZ)>>> M.nullity()0>>> A = M.transpose()>>> A.nullity()1matrix_window(row=0, col=0, nrows=-1, ncols=-1, check=1)
Return the requested matrix window.
EXAMPLES:
sage: A = matrix(QQ, 3, 3, range(9))
sage: A.matrix_window(1,1, 2, 1)
Matrix window of size 2 x 1 at (1,1):[0 1 2][3 4 5][6 7 8]>>> from sage.all import *>>> A = matrix(QQ, Integer(3), Integer(3), range(Integer(9)))>>> A.matrix_window(Integer(1),Integer(1), Integer(2), Integer(1))
Matrix window of size 2 x 1 at (1,1):[0 1 2][3 4 5][6 7 8]We test the optional check flag.
sage: matrix([1]).matrix_window(0,1,1,1, check=False)
Matrix window of size 1 x 1 at (0,1):[1]
sage: matrix([1]).matrix_window(0,1,1,1)
Traceback (most recent call last):...
IndexError: matrix window index out of range457

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> matrix([Integer(1)]).matrix_window(Integer(0),Integer(1),Integer(1),˓→Integer(1), check=False)
Matrix window of size 1 x 1 at (0,1):[1]>>> matrix([Integer(1)]).matrix_window(Integer(0),Integer(1),Integer(1),˓→Integer(1))
Traceback (most recent call last):...
IndexError: matrix window index out of range

Another test of bounds checking:sage: matrix([1]).matrix_window(1,1,1,1)
Traceback (most recent call last):...
IndexError: matrix window index out of range>>> from sage.all import *>>> matrix([Integer(1)]).matrix_window(Integer(1),Integer(1),Integer(1),˓→Integer(1))
Traceback (most recent call last):...
IndexError: matrix window index out of range

maxspin(v)Computes the largest integer n such that the list of vectors 𝑆 = [𝑣, 𝑣 * 𝐴, ..., 𝑣 * 𝐴𝑛 ] are linearly independent,
and returns that list.
INPUT:• self – Matrix• v – Vector
OUTPUT:• list – list of Vectors
ALGORITHM: The current implementation just adds vectors to a vector space until the dimension doesn’t
grow. This could be optimized by directly using matrices and doing an efficient Echelon form. Also, when thebase is Q, maybe we could simultaneously keep track of what is going on in the reduction modulo p, whichmight make things much faster.
EXAMPLES:
sage: t = matrix(QQ, 3, 3, range(9)); t[0 1 2][3 4 5][6 7 8]sage: v = (QQ^3).0
sage: t.maxspin(v)[(1, 0, 0), (0, 1, 2), (15, 18, 21)]sage: k = t.kernel(); kVector space of degree 3 and dimension 1 over Rational Field
Basis matrix:[ 1 -2 1]
sage: t.maxspin(k.0)[(1, -2, 1)]458

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> t = matrix(QQ, Integer(3), Integer(3), range(Integer(9))); t[0 1 2][3 4 5][6 7 8]>>> v = (QQ**Integer(3)).gen(0)>>> t.maxspin(v)[(1, 0, 0), (0, 1, 2), (15, 18, 21)]>>> k = t.kernel(); kVector space of degree 3 and dimension 1 over Rational Field
Basis matrix:[ 1 -2 1]>>> t.maxspin(k.gen(0))[(1, -2, 1)]

minimal_polynomial(var='x', **kwds)
This is a synonym for self.minpoly
EXAMPLES:
sage: a = matrix(QQ, 4, 4, range(16))
sage: a.minimal_polynomial( z )˓→needs sage.libs.pariz^3 - 30*z^2 - 80*z
sage: a.minpoly()
˓→needs sage.libs.parix^3 - 30*x^2 - 80*x>>> from sage.all import *>>> a = matrix(QQ, Integer(4), Integer(4), range(Integer(16)))>>> a.minimal_polynomial( z )˓→needs sage.libs.pariz^3 - 30*z^2 - 80*z>>> a.minpoly()
˓→needs sage.libs.parix^3 - 30*x^2 - 80*x

#␣

#␣

#␣

#␣

minors(k)Return the list of all 𝑘 × 𝑘 minors of self.
Let 𝐴 be an 𝑚 × 𝑛 matrix and 𝑘 an integer with 0 ≤ 𝑘, 𝑘 ≤ 𝑚 and 𝑘 ≤ 𝑛. A 𝑘 × 𝑘 minor of 𝐴 is thedeterminant of a 𝑘 × 𝑘 matrix obtained from 𝐴 by deleting 𝑚 − 𝑘 rows and 𝑛 − 𝑘 columns. There are no𝑘 × 𝑘 minors of 𝐴 if 𝑘 is larger than either 𝑚 or 𝑛.
The returned list is sorted in lexicographical row major ordering, e.g., if A is a 3 × 3 matrix then the minors
returned are with these rows/columns: [ [0, 1]x[0, 1], [0, 1]x[0, 2], [0, 1]x[1, 2], [0, 2]x[0, 1], [0, 2]x[0, 2],[0, 2]x[1, 2], [1, 2]x[0, 1], [1, 2]x[0, 2], [1, 2]x[1, 2] ].
INPUT:• k – integer
EXAMPLES:
sage: A = Matrix(ZZ, 2,3, [1,2,3,4,5,6]); A[1 2 3][4 5 6]sage: A.minors(2)(continues on next page)459

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[-3, -6, -3]
sage: A.minors(1)[1, 2, 3, 4, 5, 6]
sage: A.minors(0)[1]sage: A.minors(5)[]>>> from sage.all import *>>> A = Matrix(ZZ, Integer(2),Integer(3), [Integer(1),Integer(2),Integer(3),˓→Integer(4),Integer(5),Integer(6)]); A[1 2 3][4 5 6]>>> A.minors(Integer(2))[-3, -6, -3]>>> A.minors(Integer(1))[1, 2, 3, 4, 5, 6]>>> A.minors(Integer(0))[1]>>> A.minors(Integer(5))[]
sage: k = GF(37)sage: P.<x0,x1,x2> = PolynomialRing(k)sage: A = Matrix(P, 2, 3, [x0*x1, x0, x1, x2, x2 + 16, x2 + 5*x1])
sage: A.minors(2)˓→needs sage.rings.finite_rings[x0*x1*x2 + 16*x0*x1 - x0*x2,
5*x0*x1^2 + x0*x1*x2 - x1*x2,
5*x0*x1 + x0*x2 - x1*x2 - 16*x1]>>> from sage.all import *>>> k = GF(Integer(37))>>> P = PolynomialRing(k, names=( x0 , x1 , x2 ,)); (x0, x1, x2,) = P._
˓→first_ngens(3)>>> A = Matrix(P, Integer(2), Integer(3), [x0*x1, x0, x1, x2, x2 +␣˓→Integer(16), x2 + Integer(5)*x1])>>> A.minors(Integer(2))˓→# needs sage.rings.finite_rings[x0*x1*x2 + 16*x0*x1 - x0*x2,
5*x0*x1^2 + x0*x1*x2 - x1*x2,
5*x0*x1 + x0*x2 - x1*x2 - 16*x1]#␣␣This test addresses an issue raised at Issue #20512:
sage: A.minors(0)[0].parent() == P
True>>> from sage.all import *>>> A.minors(Integer(0))[Integer(0)].parent() == P
Trueminpoly(var='x', **kwds)
Return the minimal polynomial of self.
This uses a simplistic - and potentially very very slow - algorithm that involves computing kernels to determine
460

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

the powers of the factors of the charpoly that divide the minpoly.
EXAMPLES:
sage: # needs sage.rings.finite_rings
sage: A = matrix(GF(9, c ), 4, [1,1,0,0, 0,1,0,0, 0,0,5,0, 0,0,0,5])
sage: factor(A.minpoly())(x + 1) * (x + 2)^2
sage: A.minpoly()(A) == 0
True
sage: factor(A.charpoly())(x + 1)^2 * (x + 2)^2>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> A = matrix(GF(Integer(9), c ), Integer(4), [Integer(1),Integer(1),˓→Integer(0),Integer(0), Integer(0),Integer(1),Integer(0),Integer(0),␣
˓→Integer(0),Integer(0),Integer(5),Integer(0), Integer(0),Integer(0),˓→Integer(0),Integer(5)])>>> factor(A.minpoly())(x + 1) * (x + 2)^2>>> A.minpoly()(A) == Integer(0)True>>> factor(A.charpoly())(x + 1)^2 * (x + 2)^2

The default variable name is 𝑥, but you can specify another name:sage: factor(A.minpoly( y ))˓→needs sage.rings.finite_rings(y + 1) * (y + 2)^2>>> from sage.all import *>>> factor(A.minpoly( y ))˓→needs sage.rings.finite_rings(y + 1) * (y + 2)^2#␣#␣

norm(p=2)
Return the p-norm of this matrix, where 𝑝 can be 1, 2, inf, or the Frobenius norm.
INPUT:• self – a matrix whose entries are coercible into CDF• p – one of the following options:• 1 – the largest column-sum norm
• 2 (default) – the Euclidean norm
• Infinity – the largest row-sum norm•

frob – the Frobenius (sum of squares) norm

OUTPUT: RDF number
See also:• sage.misc.functional.norm()
EXAMPLES:
461

Matrices and Spaces of Matrices, Release 10.4

sage: A = matrix(ZZ, [[1,2,4,3], [-1,0,3,-10]])sage: A.norm(1)13.0
sage: A.norm(Infinity)
14.0
sage: B = random_matrix(QQ, 20, 21)
sage: B.norm(Infinity) == (B.transpose()).norm(1)True>>> from sage.all import *>>> A = matrix(ZZ, [[Integer(1),Integer(2),Integer(4),Integer(3)], [˓→Integer(1),Integer(0),Integer(3),-Integer(10)]])>>> A.norm(Integer(1))
13.0>>> A.norm(Infinity)
14.0>>> B = random_matrix(QQ, Integer(20), Integer(21))>>> B.norm(Infinity) == (B.transpose()).norm(Integer(1))
True
sage: Id = identity_matrix(12)sage: Id.norm(2)˓→needs scipy
1.0#␣

sage: # needs scipy sage.rings.real_mpfr
sage: A = matrix(RR, 2, 2, [13,-4,-4,7])
sage: A.norm() # rel tol 2e-16
14.999999999999998>>> from sage.all import *>>> Id = identity_matrix(Integer(12))>>> Id.norm(Integer(2))˓→# needs scipy
1.0␣

>>> # needs scipy sage.rings.real_mpfr>>> A = matrix(RR, Integer(2), Integer(2), [Integer(13),-Integer(4),˓→Integer(4),Integer(7)])>>> A.norm() # rel tol 2e-16
14.999999999999998

Norms of numerical matrices over high-precision reals are computed by this routine. Faster routines fordouble precision entries from 𝑅𝐷𝐹 or 𝐶𝐷𝐹 are provided by the Matrix_double_dense class.
sage: # needs sage.rings.real_mpfr sage.symbolic
sage: A = matrix(CC, 2, 3, [3*I,4,1-I,1,2,0])
sage: A.norm( frob )5.656854249492381
sage: A.norm(2)5.470684443210...
sage: A.norm(1)6.0
sage: A.norm(Infinity)
8.414213562373096(continues on next page)462

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: a = matrix([[],[],[],[]])
sage: a.norm()
0.0
sage: a.norm(Infinity) == a.norm(1)True>>> from sage.all import *>>> # needs sage.rings.real_mpfr sage.symbolic>>> A = matrix(CC, Integer(2), Integer(3), [Integer(3)*I,Integer(4),˓→Integer(1)-I,Integer(1),Integer(2),Integer(0)])>>> A.norm( frob )5.656854249492381>>> A.norm(Integer(2))
5.470684443210...
>>> A.norm(Integer(1))
6.0>>> A.norm(Infinity)
8.414213562373096>>> a = matrix([[],[],[],[]])>>> a.norm()
0.0>>> a.norm(Infinity) == a.norm(Integer(1))
Truenullity()
Return the (left) nullity of this matrix, which is the dimension of the (left) kernel of this matrix acting fromthe right on row vectors.
EXAMPLES:
sage: M = Matrix(QQ, [[1,0,0,1], [0,1,1,0], [1,1,1,0]])
sage: M.nullity()0sage: M.left_nullity()0>>> from sage.all import *>>> M = Matrix(QQ, [[Integer(1),Integer(0),Integer(0),Integer(1)],␣
˓→[Integer(0),Integer(1),Integer(1),Integer(0)], [Integer(1),Integer(1),˓→Integer(1),Integer(0)]])>>> M.nullity()0>>> M.left_nullity()0sage: A = M.transpose()sage: A.nullity()1sage: A.left_nullity()1>>> from sage.all import *>>> A = M.transpose()>>> A.nullity()(continues on next page)463

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

1>>> A.left_nullity()1sage: M = M.change_ring(ZZ)
sage: M.nullity()0sage: A = M.transpose()sage: A.nullity()1>>> from sage.all import *>>> M = M.change_ring(ZZ)>>> M.nullity()0>>> A = M.transpose()>>> A.nullity()
1

numerical_approx(prec=None, digits=None, algorithm=None)
Return a numerical approximation of self with prec bits (or decimal digits) of precision.
INPUT:• prec – precision in bits
• digits – precision in decimal digits (only used if prec is not given)• algorithm – ignored for matrices
OUTPUT: A matrix converted to a real or complex field
EXAMPLES:
sage: # needs sage.symbolic
sage: d = matrix([[3, 0], [0, sqrt(2)]])sage: b = matrix([[1, -1], [2, 2]]); e = b * d * b.inverse(); e[ 1/2*sqrt(2) + 3/2 -1/4*sqrt(2) + 3/4][
-sqrt(2) + 3 1/2*sqrt(2) + 3/2]
sage: e.numerical_approx(53)[ 2.20710678118655 0.396446609406726][ 1.58578643762690 2.20710678118655]
sage: e.numerical_approx(20)[ 2.2071 0.39645][ 1.5858 2.2071]
sage: (e - I).numerical_approx(20)[2.2071 - 1.0000*I
0.39645][
1.5858 2.2071 - 1.0000*I]>>> from sage.all import *>>> # needs sage.symbolic>>> d = matrix([[Integer(3), Integer(0)], [Integer(0), sqrt(Integer(2))]])>>> b = matrix([[Integer(1), -Integer(1)], [Integer(2), Integer(2)]]); e = b␣˓→* d * b.inverse(); e[ 1/2*sqrt(2) + 3/2 -1/4*sqrt(2) + 3/4][
-sqrt(2) + 3 1/2*sqrt(2) + 3/2]>>> e.numerical_approx(Integer(53))(continues on next page)464

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 2.20710678118655 0.396446609406726][ 1.58578643762690 2.20710678118655]>>> e.numerical_approx(Integer(20))[ 2.2071 0.39645][ 1.5858 2.2071]>>> (e - I).numerical_approx(Integer(20))[2.2071 - 1.0000*I
0.39645][
1.5858 2.2071 - 1.0000*I]
sage: M = matrix(QQ, 4, [i/(i+1) for i in range(12)]); M
[
0
1/2
2/3]
[ 3/4
4/5
5/6]
[ 6/7
7/8
8/9]
[ 9/10 10/11 11/12]>>> from sage.all import *>>> M = matrix(QQ, Integer(4), [i/(i+Integer(1)) for i in␣
˓→range(Integer(12))]); M
[
0
1/2
2/3]
[ 3/4
4/5
5/6]
[ 6/7
7/8
8/9]
[ 9/10 10/11 11/12]
sage: M.numerical_approx()[0.000000000000000 0.500000000000000 0.666666666666667][0.750000000000000 0.800000000000000 0.833333333333333][0.857142857142857 0.875000000000000 0.888888888888889][0.900000000000000 0.909090909090909 0.916666666666667]>>> from sage.all import *>>> M.numerical_approx()[0.000000000000000 0.500000000000000 0.666666666666667][0.750000000000000 0.800000000000000 0.833333333333333][0.857142857142857 0.875000000000000 0.888888888888889][0.900000000000000 0.909090909090909 0.916666666666667]
sage: matrix(SR, 2, 2, range(4)).n()˓→needs sage.symbolic[0.000000000000000 1.00000000000000][ 2.00000000000000 3.00000000000000]>>> from sage.all import *>>> matrix(SR, Integer(2), Integer(2), range(Integer(4))).n()˓→# needs sage.symbolic[0.000000000000000 1.00000000000000][ 2.00000000000000 3.00000000000000]#␣␣

sage: numerical_approx(M)[0.000000000000000 0.500000000000000 0.666666666666667][0.750000000000000 0.800000000000000 0.833333333333333][0.857142857142857 0.875000000000000 0.888888888888889][0.900000000000000 0.909090909090909 0.916666666666667]

465

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> numerical_approx(M)[0.000000000000000 0.500000000000000 0.666666666666667][0.750000000000000 0.800000000000000 0.833333333333333][0.857142857142857 0.875000000000000 0.888888888888889][0.900000000000000 0.909090909090909 0.916666666666667]

We check that Issue #29700 is fixed:
sage: M = matrix(3, [1,1,1,1,0,0,0,1,0])
sage: A, B = M.diagonalization(QQbar)
˓→needs sage.rings.number_fieldsage: _ = A.n()
˓→needs sage.rings.number_field#␣#␣>>> from sage.all import *>>> M = matrix(Integer(3), [Integer(1),Integer(1),Integer(1),Integer(1),˓→Integer(0),Integer(0),Integer(0),Integer(1),Integer(0)])>>> A, B = M.diagonalization(QQbar)
˓→needs sage.rings.number_field>>> _ = A.n()
˓→needs sage.rings.number_field#␣#␣permanent(algorithm='Ryser')
Return the permanent of this matrix.
Let 𝐴 = (𝑎𝑖,𝑗 ) be an 𝑚 × 𝑛 matrix over any commutative ring with 𝑚 ≤ 𝑛. The permanent of 𝐴 is∑︁per(𝐴) =𝑎1,𝜋(1) 𝑎2,𝜋(2) · · · 𝑎𝑚,𝜋(𝑚)𝜋where the summation extends over all one-to-one functions 𝜋 from {1, . . . , 𝑚} to {1, . . . , 𝑛}.
The product 𝑎1,𝜋(1) 𝑎2,𝜋(2) · · · 𝑎𝑚,𝜋(𝑚) is called diagonal product. So the permanent of an 𝑚 × 𝑛 matrix 𝐴
is the sum of all the diagonal products of 𝐴.
By default, this method uses Ryser’s algorithm, but setting algorithm to “ButeraPernici” you can use
the algorithm of Butera and Pernici (which is well suited for band matrices, i.e. matrices whose entries areconcentrated near the diagonal).
INPUT:• A – matrix of size 𝑚 × 𝑛 with 𝑚 ≤ 𝑛• algorithm – either “Ryser” (default) or “ButeraPernici”. The Butera-Pernici algorithm takes advantage of presence of zeros and is very well suited for sparse matrices.
ALGORITHM:
The Ryser algorithm is implemented in the method _permanent_ryser(). It is a modification of theorem 7.1.1. from Brualdi and Ryser: Combinatorial Matrix Theory. Instead of deleting columns from 𝐴, wechoose columns from 𝐴 and calculate the product of the row sums of the selected submatrix.
The Butera-Pernici algorithm is implemented in the function permanental_minor_polynomial().
It takes advantage of cancellations that may occur in the computations.
EXAMPLES:

466

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

sage: A = ones_matrix(4,4)
sage: A.permanent()24
sage: A = matrix(3,6, [1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1])
sage: A.permanent()
36
sage: B = A.change_ring(RR)
sage: B.permanent()
36.0000000000000>>> from sage.all import *>>> A = ones_matrix(Integer(4),Integer(4))>>> A.permanent()
24>>> A = matrix(Integer(3),Integer(6), [Integer(1),Integer(1),Integer(1),˓→Integer(1),Integer(0),Integer(0),Integer(0),Integer(1),Integer(1),˓→Integer(1),Integer(1),Integer(0),Integer(0),Integer(0),Integer(1),˓→Integer(1),Integer(1),Integer(1)])>>> A.permanent()
36>>> B = A.change_ring(RR)>>> B.permanent()
36.0000000000000

The permanent above is directed to the Sloane’s sequence OEIS sequence A079908 (“The Dancing School
Problems”) for which the third term is 36:
sage: oeis(79908)# optional -- internet
A079908: Solution to the Dancing School Problem with 3 girls and n+3 boys:␣
˓→f(3,n).
sage: _(3)# optional -- internet
36>>> from sage.all import *>>> oeis(Integer(79908))# optional -- internet
A079908: Solution to the Dancing School Problem with 3 girls and n+3 boys:␣
˓→f(3,n).
>>> _(Integer(3))# optional -- internet
36
sage: A = matrix(4,5, [1,1,0,1,1,0,1,1,1,1,1,0,1,0,1,1,1,0,1,0])
sage: A.permanent()
32>>> from sage.all import *>>> A = matrix(Integer(4),Integer(5), [Integer(1),Integer(1),Integer(0),˓→Integer(1),Integer(1),Integer(0),Integer(1),Integer(1),Integer(1),˓→Integer(1),Integer(1),Integer(0),Integer(1),Integer(0),Integer(1),˓→Integer(1),Integer(1),Integer(0),Integer(1),Integer(0)])>>> A.permanent()
32

A huge permanent that cannot be reasonably computed with the Ryser algorithm (a 50 × 50 band matrix withwidth 5):467

Matrices and Spaces of Matrices, Release 10.4

sage: n, w = 50, 5
sage: A = matrix(ZZ, n, n, lambda i,j: (i+j)%5 + 1 if abs(i-j) <= w else 0)
sage: A.permanent(algorithm="ButeraPernici")
57766972735511097036962481710892268404670105604676932908>>> from sage.all import *>>> n, w = Integer(50), Integer(5)>>> A = matrix(ZZ, n, n, lambda i,j: (i+j)%Integer(5) + Integer(1) if abs(i˓→j) <= w else Integer(0))>>> A.permanent(algorithm="ButeraPernici")
57766972735511097036962481710892268404670105604676932908

See Minc: Permanents, Example 2.1, p. 5.
sage: A = matrix(QQ, 2,2, [1/5,2/7,3/2,4/5])
sage: A.permanent()
103/175>>> from sage.all import *>>> A = matrix(QQ, Integer(2),Integer(2), [Integer(1)/Integer(5),Integer(2)/˓→Integer(7),Integer(3)/Integer(2),Integer(4)/Integer(5)])>>> A.permanent()
103/175
sage: R.<a> = PolynomialRing(ZZ)
sage: A = matrix(R, 2,2, [a,1,a,a+1])
sage: A.permanent()a^2 + 2*a>>> from sage.all import *>>> R = PolynomialRing(ZZ, names=( a ,)); (a,) = R._first_ngens(1)>>> A = matrix(R, Integer(2),Integer(2), [a,Integer(1),a,a+Integer(1)])>>> A.permanent()a^2 + 2*asage: R.<x,y> = PolynomialRing(ZZ, 2)
sage: A = matrix(R, 2,2, [x, y, x^2, y^2])
sage: A.permanent()x^2*y + x*y^2>>> from sage.all import *>>> R = PolynomialRing(ZZ, Integer(2), names=( x , y ,)); (x, y,) = R._first_
˓→ngens(2)>>> A = matrix(R, Integer(2),Integer(2), [x, y, x**Integer(2), y**Integer(2)])>>> A.permanent()x^2*y + x*y^2permanental_minor(k, algorithm='Ryser')
Return the permanental 𝑘-minor of this matrix.
The permanental 𝑘-minor of a matrix 𝐴 is the sum of the permanents of all possible 𝑘 by 𝑘 submatrices of
𝐴. Note that the maximal permanental minor is just the permanent.
For a (0,1)-matrix 𝐴 the permanental 𝑘-minor counts the number of different selections of 𝑘 1’s of 𝐴 withno two of the 1’s on the same row and no two of the 1’s on the same column.

468

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

See Brualdi and Ryser: Combinatorial Matrix Theory, p. 203. Note the typo 𝑝0 (𝐴) = 0 in that reference!
For applications see Theorem 7.2.1 and Theorem 7.2.4.
See also:
The method rook_vector() returns the list of all permanental minors.
INPUT:• k – the size of the minor• algorithm – either “Ryser” (default) or “ButeraPernici”. The Butera-Pernici algorithm is well suitedfor band matrices.
EXAMPLES:
sage: A = matrix(4, [1,0,1,0,1,0,1,0,1,0,10,10,1,0,1,1])
sage: A.permanental_minor(2)114>>> from sage.all import *>>> A = matrix(Integer(4), [Integer(1),Integer(0),Integer(1),Integer(0),˓→Integer(1),Integer(0),Integer(1),Integer(0),Integer(1),Integer(0),˓→Integer(10),Integer(10),Integer(1),Integer(0),Integer(1),Integer(1)])>>> A.permanental_minor(Integer(2))
114
sage: A = matrix(3,6, [1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1])
sage: A.permanental_minor(0)1sage: A.permanental_minor(1)12sage: A.permanental_minor(2)40sage: A.permanental_minor(3)36>>> from sage.all import *>>> A = matrix(Integer(3),Integer(6), [Integer(1),Integer(1),Integer(1),˓→Integer(1),Integer(0),Integer(0),Integer(0),Integer(1),Integer(1),˓→Integer(1),Integer(1),Integer(0),Integer(0),Integer(0),Integer(1),˓→Integer(1),Integer(1),Integer(1)])>>> A.permanental_minor(Integer(0))
1>>> A.permanental_minor(Integer(1))
12>>> A.permanental_minor(Integer(2))
40>>> A.permanental_minor(Integer(3))
36Note that if 𝑘 = 𝑚 = 𝑛, the permanental 𝑘-minor equals per(𝐴):sage: A.permanent()36>>> from sage.all import *>>> A.permanent()
36469

Matrices and Spaces of Matrices, Release 10.4

The permanental minors of the “complement” matrix of 𝐴 is related to the permanent of 𝐴:
sage: m, n = 3, 6
sage: C = matrix(m, n, lambda i,j: 1 - A[i,j])
sage: sum((-1)^k * C.permanental_minor(k)*factorial(n-k)/factorial(n-m)....:
for k in range(m+1))
36>>> from sage.all import *>>> m, n = Integer(3), Integer(6)>>> C = matrix(m, n, lambda i,j: Integer(1) - A[i,j])>>> sum((-Integer(1))**k * C.permanental_minor(k)*factorial(n-k)/factorial(n˓→m)...
for k in range(m+Integer(1)))
36

See Theorem 7.2.1 of Brualdi and Ryser: Combinatorial Matrix Theory: per(A)permutation_normal_form(check=False)
Take the set of matrices that are self permuted by any row and column permutation, and return the maximal
one of the set where matrices are ordered lexicographically going along each row.
INPUT:• check – (default: False) If True return a tuple of the maximal matrix and the permutations taking
self to the maximal matrix. If False, return only the maximal matrix.
OUTPUT:
The maximal matrix.
EXAMPLES:
sage: M = matrix(ZZ, [[0, 0, 1], [1, 0, 2], [0, 0, 0]])sage: M
[0 0 1][1 0 2][0 0 0]sage: M.permutation_normal_form()[2 1 0][1 0 0][0 0 0]sage: M = matrix(ZZ, [[-1, 3], [-1, 5], [2, 4]])sage: M[-1 3][-1 5][ 2 4]
sage: M.permutation_normal_form(check=True)
˓→needs sage.graphs sage.groups([ 5 -1][ 4 2][ 3 -1],((1,2,3), (1,2))
)

470

#␣

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> M = matrix(ZZ, [[Integer(0), Integer(0), Integer(1)], [Integer(1),␣
˓→Integer(0), Integer(2)], [Integer(0), Integer(0), Integer(0)]])>>> M[0 0 1][1 0 2][0 0 0]>>> M.permutation_normal_form()[2 1 0][1 0 0][0 0 0]>>> M = matrix(ZZ, [[-Integer(1), Integer(3)], [-Integer(1), Integer(5)],␣
˓→[Integer(2), Integer(4)]])>>> M[-1 3][-1 5][ 2 4]>>> M.permutation_normal_form(check=True)
˓→needs sage.graphs sage.groups([ 5 -1][ 4 2][ 3 -1],((1,2,3), (1,2)))#␣pfaffian(algorithm=None, check=True)
Return the Pfaffian of self, assuming that self is an alternating matrix.
The result is cached.
INPUT:• algorithm (default: None) – string, the algorithm to use; currently the following algorithms havebeen implemented:–

bfl – using the Bär-Faddeev-LeVerrier algorithm–

definition – using the definition given by perfect matchings• check (default: True) – boolean determining whether to check self for alternatingness and squareness. This has to be set to False if self is defined over a non-discrete ring.
The Pfaffian of an alternating matrix is defined as follows:
Let 𝐴 be an alternating 𝑘 × 𝑘 matrix over a commutative ring. (Here, “alternating” means that 𝐴𝑇 = −𝐴and that the diagonal entries of 𝐴 are zero.) If 𝑘 is odd, then the Pfaffian of the matrix 𝐴 is defined to be
0. Let us now define it when 𝑘 is even. In this case, set 𝑛 = 𝑘/2 (this is an integer). For every 𝑖 and 𝑗, wedenote the (𝑖, 𝑗)-th entry of 𝐴 by 𝑎𝑖,𝑗 . Let 𝑀 denote the set of all perfect matchings of the set {1, 2, . . . , 2𝑛}(see sage.combinat.perfect_matching.PerfectMatchings ). For every matching 𝑚 ∈ 𝑀 ,define the sign sign(𝑚) of 𝑚 by writing 𝑚 as {{𝑖1 , 𝑗1 }, {𝑖2 , 𝑗2 }, . . . , {𝑖𝑛 , 𝑗𝑛 }} with 𝑖𝑘 < 𝑗𝑘 for all 𝑘, andsetting sign(𝑚) to be the sign of the permutation (𝑖1 , 𝑗1 , 𝑖2 , 𝑗2 , . . . , 𝑖𝑛 , 𝑗𝑛 ) (written here in one-line notation).
For every matching 𝑚 ∈ 𝑀 , define the weight 𝑤(𝑚) of 𝑚 by writing 𝑚 as {{𝑖1 , 𝑗1 }, {𝑖2 , 𝑗2 }, . . . , {𝑖𝑛 , 𝑗𝑛 }}with 𝑖𝑘 < 𝑗𝑘 for all 𝑘, and setting 𝑤(𝑚) = 𝑎𝑖1 ,𝑗1 𝑎𝑖2 ,𝑗2 · · · 𝑎𝑖𝑛 ,𝑗𝑛 . Now, the Pfaffian of the matrix 𝐴 is defined471

Matrices and Spaces of Matrices, Release 10.4

to be the sum∑︁sign(𝑚)𝑤(𝑚).

𝑚∈𝑀

The Pfaffian of 𝐴 is commonly denoted by Pf(𝐴). It is well-known that (Pf(𝐴))2 = det 𝐴 for every alternating matrix 𝐴, and that Pf(𝑈 𝑇 𝐴𝑈 ) = det 𝑈 · Pf(𝐴) for any 𝑛 × 𝑛 matrix 𝑈 and any alternating 𝑛 × 𝑛matrix 𝐴.
See [Knu1995], [DW1995] and [Rot2001], [Baer2020], just to name a few sources, for further properties ofPfaffians.
ALGORITHM:
If the matrix is small, namely up to size 4 × 4, the naive formulas are always used.
The Bär-Faddeev-LeVerrier algorithm can be accessed using bfl . It works over any -algebra or ring
whose fraction field is an -algebra (see [Baer2020] for details). If that check fails, the implementation raises
an error because correct results cannot be guaranteed.
To access the algorithm using the above definition, use definition . However, notice that this algorithm
is usually very slow.
By default, i.e. if no options are set, the implementation tries to apply the BFL algorithm first. If BFL is notapplicable, it uses the definition by perfect matchings.
The alternatingness of the matrix self is checked only if check is True (this is important because even
if self is alternating, a non-discrete base ring might prevent Sage from being able to check this).
EXAMPLES:
A 3 × 3 alternating matrix has Pfaffian 0 independently of its entries:
sage: MSp = MatrixSpace(Integers(27), 3)
sage: A = MSp([0, 2, -3, -2, 0, 8, 3, -8, 0])
sage: A.pfaffian()0
sage: parent(A.pfaffian())
Ring of integers modulo 27>>> from sage.all import *>>> MSp = MatrixSpace(Integers(Integer(27)), Integer(3))>>> A = MSp([Integer(0), Integer(2), -Integer(3), -Integer(2), Integer(0),␣
˓→Integer(8),Integer(3), -Integer(8), Integer(0)])>>> A.pfaffian()0>>> parent(A.pfaffian())
Ring of integers modulo 27

The Pfaffian of a 2 × 2 alternating matrix is just its northeast entry:
sage: MSp = MatrixSpace(QQ, 2)
sage: A = MSp([0, 4, -4, 0])
sage: A.pfaffian()4
sage: parent(A.pfaffian())
Rational Field>>> from sage.all import *>>> MSp = MatrixSpace(QQ, Integer(2))(continues on next page)472

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> A = MSp([Integer(0), Integer(4),>>> A.pfaffian()4>>> parent(A.pfaffian())
Rational Field-Integer(4), Integer(0)])

The Pfaffian of a 0 × 0 alternating matrix is 1:
sage: MSp = MatrixSpace(ZZ, 0)
sage: A = MSp([])
sage: A.pfaffian()1
sage: parent(A.pfaffian())
Integer Ring>>> from sage.all import *>>> MSp = MatrixSpace(ZZ, Integer(0))>>> A = MSp([])>>> A.pfaffian()1>>> parent(A.pfaffian())
Integer Ring

Let us compute the Pfaffian of a generic 4 × 4 alternating matrix:
sage: R = PolynomialRing(QQ, x12,x13,x14,x23,x24,x34 )sage: x12, x13, x14, x23, x24, x34 = R.gens()
sage: A = matrix(R, [[0, x12, x13, x14],....:[-x12,
0, x23, x24],....:[-x13, -x23,
0, x34],....:[-x14, -x24, -x34,
0]])
sage: A.pfaffian()x14*x23 - x13*x24 + x12*x34
sage: parent(A.pfaffian())
Multivariate Polynomial Ring in x12, x13, x14, x23, x24, x34 over Rational␣
˓→Field>>> from sage.all import *>>> R = PolynomialRing(QQ, x12,x13,x14,x23,x24,x34 )>>> x12, x13, x14, x23, x24, x34 = R.gens()>>> A = matrix(R, [[Integer(0), x12, x13, x14],...
[-x12,
Integer(0), x23, x24],...
[-x13, -x23,
Integer(0), x34],...
[-x14, -x24, -x34,
Integer(0)]])>>> A.pfaffian()x14*x23 - x13*x24 + x12*x34>>> parent(A.pfaffian())
Multivariate Polynomial Ring in x12, x13, x14, x23, x24, x34 over Rational␣
˓→Field

The Pfaffian of an alternating matrix squares to its determinant:sage: A = [[0] * 6 for i in range(6)]sage: for i in range(6):....:for j in range(i):....:u = floor(random() * 10)(continues on next page)473

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)....:
A[i][j] = u....:
A[j][i] = -u....:A[i][i] = 0
sage: AA = Matrix(ZZ, A)
sage: AA.pfaffian() ** 2 == AA.det()True>>> from sage.all import *>>> A = [[Integer(0)] * Integer(6) for i in range(Integer(6))]>>> for i in range(Integer(6)):...
for j in range(i):...
u = floor(random() * Integer(10))...
A[i][j] = u...
A[j][i] = -u...
A[i][i] = Integer(0)>>> AA = Matrix(ZZ, A)>>> AA.pfaffian() ** Integer(2) == AA.det()
True

In order to use the Bär-Faddeev-LeVerrier algorithm, the base ring must have characteristic zero:sage: A = matrix(GF(5), [(0, 3, 4, 1, 3, 4),....:(2, 0, 2, 0, 1, 0),....:(1, 3, 0, 4, 1, 0),....:(4, 0, 1, 0, 2, 0),....:(2, 4, 4, 3, 0, 0),....:(1, 0, 0, 0, 0, 0)])sage: A.pfaffian(algorithm= bfl )Traceback (most recent call last):...
TypeError: Bär-Faddeev-LeVerrier algorithm not applicable,
use another algorithm instead>>> from sage.all import *>>> A = matrix(GF(Integer(5)), [(Integer(0), Integer(3), Integer(4),␣
˓→Integer(1), Integer(3), Integer(4)),...
(Integer(2), Integer(0), Integer(2), Integer(0),␣
˓→Integer(1), Integer(0)),...
(Integer(1), Integer(3), Integer(0), Integer(4),␣
˓→Integer(1), Integer(0)),...
(Integer(4), Integer(0), Integer(1), Integer(0),␣
˓→Integer(2), Integer(0)),...
(Integer(2), Integer(4), Integer(4), Integer(3),␣
˓→Integer(0), Integer(0)),...
(Integer(1), Integer(0), Integer(0), Integer(0),␣
˓→Integer(0), Integer(0))])>>> A.pfaffian(algorithm= bfl )Traceback (most recent call last):...
TypeError: Bär-Faddeev-LeVerrier algorithm not applicable,
use another algorithm instead

In that case, the definition by perfect matchings is used instead:sage: A.pfaffian()
˓→needs sage.combinat#␣(continues on next page)474

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)2>>> from sage.all import *>>> A.pfaffian()
˓→needs sage.combinat
2#␣

pivot_rows()
Return the pivot row positions for this matrix, which are a topmost subset of the rows that span the row space
and are linearly independent.
OUTPUT: a tuple of integers
EXAMPLES:
sage: A = matrix(QQ, 3,3, [0,0,0,1,2,3,2,4,6]); A[0 0 0][1 2 3][2 4 6]sage: A.pivot_rows()(1,)
sage: A.pivot_rows() # testing cached value(1,)>>> from sage.all import *>>> A = matrix(QQ, Integer(3),Integer(3), [Integer(0),Integer(0),Integer(0),˓→Integer(1),Integer(2),Integer(3),Integer(2),Integer(4),Integer(6)]); A[0 0 0][1 2 3][2 4 6]>>> A.pivot_rows()(1,)>>> A.pivot_rows() # testing cached value(1,)

plot(*args, **kwds)
A plot of this matrix.
Each (ith, jth) matrix element is given a different color value depending on its relative size compared to theother elements in the matrix.
The tick marks drawn on the frame axes denote the (ith, jth) element of the matrix.
This method just calls matrix_plot. *args and **kwds are passed to matrix_plot.
EXAMPLES:
A matrix over ZZ colored with different grey levels:
sage: A = matrix([[1,3,5,1],[2,4,5,6],[1,3,5,7]])
sage: A.plot()
˓→needs sage.plot
Graphics object consisting of 1 graphics primitive#␣>>> from sage.all import *>>> A = matrix([[Integer(1),Integer(3),Integer(5),Integer(1)],[Integer(2),˓→Integer(4),Integer(5),Integer(6)],[Integer(1),Integer(3),Integer(5),(continues on next page)475

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Integer(7)]])>>> A.plot()
˓→needs sage.plot
Graphics object consisting of 1 graphics primitive˓→#␣Here we make a random matrix over RR and use cmap= hsv to color the matrix elements different RGB
colors (see documentation for matrix_plot for more information on cmaps):
sage: A = random_matrix(RDF, 50)
sage: plot(A, cmap= hsv )˓→needs sage.plot
Graphics object consisting of 1 graphics primitive>>> from sage.all import *>>> A = random_matrix(RDF, Integer(50))>>> plot(A, cmap= hsv )˓→needs sage.plot
Graphics object consisting of 1 graphics primitive#␣#␣Another random plot, but over GF(389):
sage: A = random_matrix(GF(389), 10)
sage: A.plot(cmap= Oranges )˓→needs sage.plot
Graphics object consisting of 1 graphics primitive>>> from sage.all import *>>> A = random_matrix(GF(Integer(389)), Integer(10))>>> A.plot(cmap= Oranges )˓→needs sage.plot
Graphics object consisting of 1 graphics primitive#␣#␣

principal_square_root(check_positivity=True)
Return the principal square root of a positive definite matrix.
A positive definite matrix 𝐴 has a unique positive definite matrix 𝑀 such that 𝑀 2 = 𝐴.
See Wikipedia article Square_root_of_a_matrix.
EXAMPLES:
sage: A = Matrix([[1,-1/2,0], [-1/2,1,-1/2], [0,-1/2,1]])
sage: B = A.principal_square_root()
sage: A == B^2
True>>> from sage.all import *>>> A = Matrix([[Integer(1),-Integer(1)/Integer(2),Integer(0)], [-Integer(1)/˓→Integer(2),Integer(1),-Integer(1)/Integer(2)], [Integer(0),-Integer(1)/˓→Integer(2),Integer(1)]])>>> B = A.principal_square_root()>>> A == B**Integer(2)True

prod_of_row_sums(cols)
Calculate the product of all row sums of a submatrix of 𝐴 for a list of selected columns cols.

476

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

EXAMPLES:
sage: a = matrix(QQ, 2, 2, [1,2,3,2]); a
[1 2]
[3 2]
sage: a.prod_of_row_sums([0,1])
15>>> from sage.all import *>>> a = matrix(QQ, Integer(2), Integer(2), [Integer(1),Integer(2),Integer(3),˓→Integer(2)]); a
[1 2]
[3 2]
>>> a.prod_of_row_sums([Integer(0),Integer(1)])
15Another example:
sage: a = matrix(QQ, 2,3, [1,2,3,2,5,6]); a[1 2 3][2 5 6]sage: a.prod_of_row_sums([1,2])
55>>> from sage.all import *>>> a = matrix(QQ, Integer(2),Integer(3), [Integer(1),Integer(2),Integer(3),˓→Integer(2),Integer(5),Integer(6)]); a[1 2 3][2 5 6]>>> a.prod_of_row_sums([Integer(1),Integer(2)])
55

pseudoinverse(algorithm=None)
Return the Moore-Penrose pseudoinverse of this matrix.
INPUT:• algorithm (default: guess) – one of the following:– "numpy" – Use numpy’s linalg.pinv() which is suitable over real or complex fields.
– "exact" – Use a simple algorithm which is not numerically stable but useful over exact fields.
Assume that no conjugation is needed, that the conjugate transpose is just the transpose.
– "exactconj" – Like exact but use the conjugate transpose.
OUTPUT: a matrix
EXAMPLES:
sage: # needs sage.rings.complex_double sage.symbolic
sage: M = diagonal_matrix(CDF, [0, I, 1+I]); M
[
0.0
0.0
0.0]
[
0.0
1.0*I
0.0]
[
0.0
0.0 1.0 + 1.0*I]
sage: M.pseudoinverse() # tol 1e-15
[
0.0
0.0
0.0]
[
0.0
-1.0*I
0.0][
0.0
0.0 0.5 - 0.5*I]

477

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> # needs sage.rings.complex_double sage.symbolic>>> M = diagonal_matrix(CDF, [Integer(0), I, Integer(1)+I]); M
[
0.0
0.0
0.0]
[
0.0
1.0*I
0.0]
[
0.0
0.0 1.0 + 1.0*I]>>> M.pseudoinverse() # tol 1e-15
[
0.0
0.0
0.0]
[
0.0
-1.0*I
0.0][
0.0
0.0 0.5 - 0.5*I]

We check the properties of the pseudoinverse over an exact field:
sage: M = random_matrix(QQ, 6, 3) * random_matrix(QQ, 3, 5)
sage: Mx = M.pseudoinverse()
sage: M * Mx * M == M
True
sage: Mx * M * Mx == Mx
Truesage: (M * Mx).is_symmetric()True
sage: (Mx * M).is_symmetric()
True>>> from sage.all import *>>> M = random_matrix(QQ, Integer(6), Integer(3)) * random_matrix(QQ,␣
˓→Integer(3), Integer(5))>>> Mx = M.pseudoinverse()>>> M * Mx * M == M
True>>> Mx * M * Mx == MxTrue>>> (M * Mx).is_symmetric()True>>> (Mx * M).is_symmetric()
True

Beware that the exact algorithm is not numerically stable, but the default numpy algorithm is:sage: M = matrix.hilbert(12, ring=RR)
sage: (~M * M).norm() # a considerable error
˓→needs scipy
1.3...
sage: Mx = M.pseudoinverse(algorithm="exact")
sage: (Mx * M).norm() # huge error
˓→needs scipy
11.5...
sage: Mx = M.pseudoinverse(algorithm="numpy")
˓→needs numpy
sage: (Mx * M).norm() # still OK
1.00...
>>> from sage.all import *>>> M = matrix.hilbert(Integer(12), ring=RR)>>> (~M * M).norm() # a considerable error
˓→needs scipy
1.3...

#␣

#␣

#␣

#␣

(continues on next page)

478

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> Mx = M.pseudoinverse(algorithm="exact")>>> (Mx * M).norm() # huge error
˓→needs scipy
11.5...
>>> Mx = M.pseudoinverse(algorithm="numpy")
˓→needs numpy>>> (Mx * M).norm() # still OK
1.00...

#␣#␣

When multiplying the given matrix with the pseudoinverse, the result is symmetric for the exact algorithmor hermitian for the exactconj algorithm:
sage: # needs sage.rings.number_field sage.symbolic
sage: M = matrix(QQbar, 2, 2, [1, sqrt(-3), -sqrt(-3), 3])
sage: M * M.pseudoinverse()[
0.2500000000000000? 0.4330127018922193?*I][-0.4330127018922193?*I
0.750000000000000?]
sage: M * M.pseudoinverse(algorithm="exactconj")[
1/4 0.4330127018922193?*I][-0.4330127018922193?*I
3/4]
sage: M * M.pseudoinverse(algorithm="exact")[-1/2 0.866025403784439?*I][0.866025403784439?*I
3/2]>>> from sage.all import *>>> # needs sage.rings.number_field sage.symbolic>>> M = matrix(QQbar, Integer(2), Integer(2), [Integer(1), sqrt(-Integer(3)),␣
˓→-sqrt(-Integer(3)), Integer(3)])>>> M * M.pseudoinverse()[
0.2500000000000000? 0.4330127018922193?*I][-0.4330127018922193?*I
0.750000000000000?]>>> M * M.pseudoinverse(algorithm="exactconj")[
1/4 0.4330127018922193?*I][-0.4330127018922193?*I
3/4]>>> M * M.pseudoinverse(algorithm="exact")[-1/2 0.866025403784439?*I][0.866025403784439?*I
3/2]

For an invertible matrix, the pseudoinverse is just the inverse:
sage: M = matrix([[1,2], [3,4]])
sage: ~M
[ -2
1]
[ 3/2 -1/2]
sage: M.pseudoinverse()[ -2
1][ 3/2 -1/2]>>> from sage.all import *>>> M = matrix([[Integer(1),Integer(2)], [Integer(3),Integer(4)]])>>> ~M[ -2
1][ 3/2 -1/2]>>> M.pseudoinverse()[ -2
1][ 3/2 -1/2]

479

Matrices and Spaces of Matrices, Release 10.4

Numpy gives a strange answer due to rounding errors:
sage: M.pseudoinverse(algorithm="numpy") # random
˓→needs numpy[-1286742750677287/643371375338643 1000799917193445/1000799917193444][ 519646110850445/346430740566963 -300239975158034/600479950316067]>>> from sage.all import *>>> M.pseudoinverse(algorithm="numpy") # random
˓→needs numpy[-1286742750677287/643371375338643 1000799917193445/1000799917193444][ 519646110850445/346430740566963 -300239975158034/600479950316067]#␣#␣

Although it is not too far off:sage: (~M - M.pseudoinverse(algorithm="numpy")).norm() < 1e-14
˓→needs numpy
True

#␣

>>> from sage.all import *>>> (~M - M.pseudoinverse(algorithm="numpy")).norm() < RealNumber( 1e-14 )˓→# needs numpyTrue␣qdet(q=None)
Return the quantum deteminant of self.
The quantum determinant of a matrix 𝑀 = (𝑚𝑖𝑗 )𝑛𝑖,𝑗=1 is defined bydet(𝑀 ) =𝑞∑︁(−𝑞)ℓ(𝜎) 𝑀𝜎(𝑖),𝑗 ,𝜎∈𝑆𝑛where 𝑆𝑛 is the symmetric group on {1, . . . , 𝑛} and ℓ(𝜎) denotes the length of 𝜎 written as simple transpositions (equivalently the number of inversions when written in one-line notation).
INPUT:• q – the parameter 𝑞; the default is 𝑞 ∈ 𝐹 [𝑞], where 𝐹 is the base ring of self
EXAMPLES:
sage: A = matrix(SR, 2, lambda i, j: f a{i}{j} ); A˓→needs sage.symbolic[a00 a01][a10 a11]
sage: A.quantum_determinant()
˓→needs sage.symbolic-a01*a10*q + a00*a11#␣

sage: A = matrix(SR, 3, lambda i, j: f a{i}{j} )˓→needs sage.symbolic
sage: A.quantum_determinant()
˓→needs sage.symbolic-a02*a11*a20*q^3 + (a01*a12*a20 + a02*a10*a21)*q^2+ (-a00*a12*a21 - a01*a10*a22)*q + a00*a11*a22

#␣

#␣

#␣

sage: R.<q> = LaurentPolynomialRing(ZZ)
sage: MS = MatrixSpace(Integers(8), 3)(continues on next page)

480

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: A = MS([1,7,3, 1,1,1, 3,4,5])
sage: A.det()6
sage: A.quantum_determinant(q^-2)
7*q^-6 + q^-4 + q^-2 + 5
sage: S.<x,y> = PolynomialRing(GF(7))
sage: R.<q> = LaurentPolynomialRing(S)sage: MS = MatrixSpace(S, 3, sparse=True)
sage: A = MS([[x, y, 3], [4, 2+y, x^2], [0, 1-x, x+y]])sage: A.det()x^4 - x^3 + x^2*y + x*y^2 + 2*x^2 - 2*x*y + 3*y^2 + 2*x - 2
sage: A.quantum_determinant()(2*x - 2)*q^2 + (x^4 - x^3 + 3*x*y + 3*y^2)*q + x^2*y + x*y^2 + 2*x^2 + 2*x*y
sage: A.quantum_determinant(int(2))
2*x^4 - 2*x^3 + x^2*y + x*y^2 + 2*x^2 + x*y - y^2 + x - 1
sage: A.quantum_determinant(q*x + q^-1*y)(2*x*y^2 - 2*y^2)*q^-2 + (x^4*y - x^3*y + 3*x*y^2 + 3*y^3)*q^-1+ (-2*x^2*y + x*y^2 + 2*x^2 - 2*x*y)+ (x^5 - x^4 + 3*x^2*y + 3*x*y^2)*q + (2*x^3 - 2*x^2)*q^2>>> from sage.all import *>>> A = matrix(SR, Integer(2), lambda i, j: f a{i}{j} ); A˓→
# needs sage.symbolic[a00 a01][a10 a11]>>> A.quantum_determinant()
˓→needs sage.symbolic-a01*a10*q + a00*a11

␣#␣>>> A = matrix(SR, Integer(3), lambda i, j: f a{i}{j} )˓→# needs sage.symbolic>>> A.quantum_determinant()
˓→needs sage.symbolic-a02*a11*a20*q^3 + (a01*a12*a20 + a02*a10*a21)*q^2+ (-a00*a12*a21 - a01*a10*a22)*q + a00*a11*a22

␣#␣>>> R = LaurentPolynomialRing(ZZ, names=( q ,)); (q,) = R._first_ngens(1)>>> MS = MatrixSpace(Integers(Integer(8)), Integer(3))>>> A = MS([Integer(1),Integer(7),Integer(3), Integer(1),Integer(1),˓→Integer(1), Integer(3),Integer(4),Integer(5)])>>> A.det()
6>>> A.quantum_determinant(q**-Integer(2))
7*q^-6 + q^-4 + q^-2 + 5>>> S = PolynomialRing(GF(Integer(7)), names=( x , y ,)); (x, y,) = S._first_
˓→ngens(2)>>> R = LaurentPolynomialRing(S, names=( q ,)); (q,) = R._first_ngens(1)>>> MS = MatrixSpace(S, Integer(3), sparse=True)>>> A = MS([[x, y, Integer(3)], [Integer(4), Integer(2)+y, x**Integer(2)],␣
˓→[Integer(0), Integer(1)-x, x+y]])>>> A.det()x^4 - x^3 + x^2*y + x*y^2 + 2*x^2 - 2*x*y + 3*y^2 + 2*x - 2>>> A.quantum_determinant()(2*x - 2)*q^2 + (x^4 - x^3 + 3*x*y + 3*y^2)*q + x^2*y + x*y^2 + 2*x^2 + 2*x*y(continues on next page)481

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> A.quantum_determinant(int(Integer(2)))
2*x^4 - 2*x^3 + x^2*y + x*y^2 + 2*x^2 + x*y - y^2 + x - 1>>> A.quantum_determinant(q*x + q**-Integer(1)*y)(2*x*y^2 - 2*y^2)*q^-2 + (x^4*y - x^3*y + 3*x*y^2 + 3*y^3)*q^-1+ (-2*x^2*y + x*y^2 + 2*x^2 - 2*x*y)+ (x^5 - x^4 + 3*x^2*y + 3*x*y^2)*q + (2*x^3 - 2*x^2)*q^2

quantum_determinant(q=None)
Return the quantum deteminant of self.
The quantum determinant of a matrix 𝑀 = (𝑚𝑖𝑗 )𝑛𝑖,𝑗=1 is defined by∑︁det(𝑀 ) =(−𝑞)ℓ(𝜎) 𝑀𝜎(𝑖),𝑗 ,𝑞

𝜎∈𝑆𝑛where 𝑆𝑛 is the symmetric group on {1, . . . , 𝑛} and ℓ(𝜎) denotes the length of 𝜎 written as simple transpositions (equivalently the number of inversions when written in one-line notation).
INPUT:• q – the parameter 𝑞; the default is 𝑞 ∈ 𝐹 [𝑞], where 𝐹 is the base ring of self
EXAMPLES:
sage: A = matrix(SR, 2, lambda i, j: f a{i}{j} ); A˓→needs sage.symbolic[a00 a01][a10 a11]
sage: A.quantum_determinant()
˓→needs sage.symbolic-a01*a10*q + a00*a11#␣

sage: A = matrix(SR, 3, lambda i, j: f a{i}{j} )˓→needs sage.symbolic
sage: A.quantum_determinant()
˓→needs sage.symbolic-a02*a11*a20*q^3 + (a01*a12*a20 + a02*a10*a21)*q^2+ (-a00*a12*a21 - a01*a10*a22)*q + a00*a11*a22

#␣

#␣

#␣

sage: R.<q> = LaurentPolynomialRing(ZZ)
sage: MS = MatrixSpace(Integers(8), 3)
sage: A = MS([1,7,3, 1,1,1, 3,4,5])
sage: A.det()6
sage: A.quantum_determinant(q^-2)
7*q^-6 + q^-4 + q^-2 + 5
sage: S.<x,y> = PolynomialRing(GF(7))
sage: R.<q> = LaurentPolynomialRing(S)sage: MS = MatrixSpace(S, 3, sparse=True)
sage: A = MS([[x, y, 3], [4, 2+y, x^2], [0, 1-x, x+y]])sage: A.det()x^4 - x^3 + x^2*y + x*y^2 + 2*x^2 - 2*x*y + 3*y^2 + 2*x - 2
sage: A.quantum_determinant()(2*x - 2)*q^2 + (x^4 - x^3 + 3*x*y + 3*y^2)*q + x^2*y + x*y^2 + 2*x^2 + 2*x*y
sage: A.quantum_determinant(int(2))
2*x^4 - 2*x^3 + x^2*y + x*y^2 + 2*x^2 + x*y - y^2 + x - 1
sage: A.quantum_determinant(q*x + q^-1*y)(continues on next page)482

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)(2*x*y^2 - 2*y^2)*q^-2 + (x^4*y - x^3*y + 3*x*y^2 + 3*y^3)*q^-1+ (-2*x^2*y + x*y^2 + 2*x^2 - 2*x*y)+ (x^5 - x^4 + 3*x^2*y + 3*x*y^2)*q + (2*x^3 - 2*x^2)*q^2>>> from sage.all import *>>> A = matrix(SR, Integer(2), lambda i, j: f a{i}{j} ); A˓→
# needs sage.symbolic[a00 a01][a10 a11]>>> A.quantum_determinant()
˓→needs sage.symbolic-a01*a10*q + a00*a11>>> A = matrix(SR, Integer(3), lambda i, j: f a{i}{j} )˓→# needs sage.symbolic>>> A.quantum_determinant()
˓→needs sage.symbolic-a02*a11*a20*q^3 + (a01*a12*a20 + a02*a10*a21)*q^2+ (-a00*a12*a21 - a01*a10*a22)*q + a00*a11*a22

␣

#␣

␣
#␣

>>> R = LaurentPolynomialRing(ZZ, names=( q ,)); (q,) = R._first_ngens(1)>>> MS = MatrixSpace(Integers(Integer(8)), Integer(3))>>> A = MS([Integer(1),Integer(7),Integer(3), Integer(1),Integer(1),˓→Integer(1), Integer(3),Integer(4),Integer(5)])>>> A.det()
6>>> A.quantum_determinant(q**-Integer(2))
7*q^-6 + q^-4 + q^-2 + 5>>> S = PolynomialRing(GF(Integer(7)), names=( x , y ,)); (x, y,) = S._first_
˓→ngens(2)>>> R = LaurentPolynomialRing(S, names=( q ,)); (q,) = R._first_ngens(1)>>> MS = MatrixSpace(S, Integer(3), sparse=True)>>> A = MS([[x, y, Integer(3)], [Integer(4), Integer(2)+y, x**Integer(2)],␣
˓→[Integer(0), Integer(1)-x, x+y]])>>> A.det()x^4 - x^3 + x^2*y + x*y^2 + 2*x^2 - 2*x*y + 3*y^2 + 2*x - 2>>> A.quantum_determinant()(2*x - 2)*q^2 + (x^4 - x^3 + 3*x*y + 3*y^2)*q + x^2*y + x*y^2 + 2*x^2 + 2*x*y>>> A.quantum_determinant(int(Integer(2)))
2*x^4 - 2*x^3 + x^2*y + x*y^2 + 2*x^2 + x*y - y^2 + x - 1>>> A.quantum_determinant(q*x + q**-Integer(1)*y)(2*x*y^2 - 2*y^2)*q^-2 + (x^4*y - x^3*y + 3*x*y^2 + 3*y^3)*q^-1+ (-2*x^2*y + x*y^2 + 2*x^2 - 2*x*y)+ (x^5 - x^4 + 3*x^2*y + 3*x*y^2)*q + (2*x^3 - 2*x^2)*q^2

randomize(density=1, nonzero=False, *args, **kwds)
Replace a proportion of the entries of a matrix by random elements, leaving the remaining entries unchanged.
Note: The locations of the entries of the matrix to change are determined randomly, with the total numberof locations determined by the density keyword. These locations are not guaranteed to be distinct. So
it is possible that the same position can be chosen multiple times, especially for a very small matrix. The
exception is when density = 1, in which case every entry of the matrix will be changed.
INPUT:
483

Matrices and Spaces of Matrices, Release 10.4

• density – float (default: 1); upper bound for the proportion of entries that are changed• nonzero – Bool (default: False); if True, then new entries will be nonzero• *args, **kwds – Remaining parameters may be passed to the random_element function of thebase ring
EXAMPLES:
We construct the zero matrix over a polynomial ring.
sage: a = matrix(QQ[ x ], 3); a[0 0 0][0 0 0][0 0 0]>>> from sage.all import *>>> a = matrix(QQ[ x ], Integer(3)); a[0 0 0][0 0 0][0 0 0]We then randomize roughly half the entries:
sage: a.randomize(0.5)
sage: a.density() <= 0.5
True>>> from sage.all import *>>> a.randomize(RealNumber( 0.5 ))>>> a.density() <= RealNumber( 0.5 )True

Now we randomize all the entries of the resulting matrix:
sage: while a.density() < 0.9:....:
a = matrix(QQ[ x ], 3)....:a.randomize()>>> from sage.all import *>>> while a.density() < RealNumber( 0.9 ):...
a = matrix(QQ[ x ], Integer(3))...
a.randomize()

We create the zero matrix over the integers:
sage: a = matrix(ZZ, 2); a
[0 0]
[0 0]
>>> from sage.all import *>>> a = matrix(ZZ, Integer(2)); a
[0 0]
[0 0]

Then we randomize it; the x and y keywords, which determine the size of the random elements, are passed
on to the random_element method for ZZ.

484

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

sage: a.randomize(x=-2^64, y=2^64)
sage: while all(abs(b) < 2^63 for b in a.list()):....:
a.randomize(x=-2^64, y=2^64)
sage: all(abs(b) < 2^64 for b in a.list())
True>>> from sage.all import *>>> a.randomize(x=-Integer(2)**Integer(64), y=Integer(2)**Integer(64))>>> while all(abs(b) < Integer(2)**Integer(63) for b in a.list()):...
a.randomize(x=-Integer(2)**Integer(64), y=Integer(2)**Integer(64))>>> all(abs(b) < Integer(2)**Integer(64) for b in a.list())
True

rational_form(format='right', subdivide=True)
Returns the rational canonical form, also known as Frobenius form.
INPUT:• self – a square matrix with entries from an exact field.
• format – (default: ‘right’); one of ‘right’, ‘bottom’, ‘left’, ‘top’ or ‘invariants’. The first four will causea matrix to be returned with companion matrices dictated by the keyword. The value ‘invariants’ willcause a list of lists to be returned, where each list contains coefficients of a polynomial associated with acompanion matrix.
• subdivide – (default: ‘True’); if ‘True’ and a matrix is returned, then it contains subdivisions delineating the companion matrices along the diagonal.
OUTPUT:The rational form of a matrix is a similar matrix composed of submatrices (“blocks”) placed on the main
diagonal. Each block is a companion matrix. Associated with each companion matrix is a polynomial. In
rational form, the polynomial of one block will divide the polynomial of the next block (and thus, the polynomials of all subsequent blocks).
Rational form, also known as Frobenius form, is a canonical form. In other words, two matrices are similar
if and only if their rational canonical forms are equal. The algorithm used does not provide the similarity
transformation matrix (also known as the change-of-basis matrix).
Companion matrices may be written in one of four styles, and any such style may be selected withthe format keyword. See the companion matrix constructor, sage.matrix.constructor.
companion_matrix(), for more information about companion matrices.
If the ‘invariants’ value is used for the format keyword, then the return value is a list of lists, where each list
is the coefficients of the polynomial associated with one of the companion matrices on the diagonal. These
coefficients include the leading one of the monic polynomial and are ready to be coerced into any polynomial
ring over the same field (see examples of this below). This return value is intended to be the most compact
representation and the easiest to use for testing equality of rational forms.
Because the minimal and characteristic polynomials of a companion matrix are the associated polynomial, it
is easy to see that the product of the polynomials of the blocks will be the characteristic polynomial and thefinal polynomial will be the minimal polynomial of the entire matrix.
ALGORITHM:
We begin with ZigZag form, which is due to Arne Storjohann and is documented at zigzag_form(). Then
we eliminate ‘’corner’’ entries enroute to rational form via an additional algorithm of Storjohann’s [Sto2011].
EXAMPLES:

485

Matrices and Spaces of Matrices, Release 10.4

The lists of coefficients returned with the invariants keyword are designed to easily convert to the polynomials associated with the companion matrices. This is illustrated by the construction below of the polyslist. Then we can test the divisibility condition on the list of polynomials. Also the minimal and characteristic
polynomials are easy to determine from this list.
sage: A = matrix(QQ, [[ 11, 14, -15, -4, -38, -29, 1, 23, 14, -63, 17, ␣
˓→24,
36, 32],
....:
[ 18,
6, -17, -11, -31, -43, 12, 26,
0, -69, 11, ␣
˓→13,
17, 24],....:[ 11, 16, -22, -8, -48, -34, 0, 31, 16, -82, 26, ␣
˓→31,
39, 37],....:[ -8, -18, 22, 10, 46, 33, 3, -27, -12, 70, -19, ˓→20, -42, -31],....:[-13, -21, 16, 10, 52, 43, 4, -28, -25, 89, -37, ˓→20, -53, -62],....:[ -2, -6,
0,0,
6, 10, 1,
1, -7, 14, -11, ␣
˓→-3, -10, -18],....:[ -9, -19, -3,
4, 23, 30, 8, -3, -27, 55, -40, ␣
˓→-5, -40, -69],....:[ 4, -8, -1, -1,
5, -4, 9,5, -11,4, -14, ␣
˓→-2, -13, -17],....:[ 1, -2, 16, -1, 19, -2, -1, -17,
2, 19,
5, ˓→25,-7, 14],....:[ 7,
7, -13, -4, -26, -21, 3, 18,
5, -40,7, ␣
˓→15,20, 14],....:[ -6, -7, -12,
4, -1, 18, 3,
8, -11, 15, -18, ␣
˓→17, -15, -41],....:[ 5, 11, -11, -3, -26, -19, -1, 14, 10, -42, 14, ␣
˓→17,
25, 23],....:[-16, -15,
3, 10, 29, 45, -1, -13, -19, 71, -35, ␣
˓→-2, -35, -65],
....:
[ 4,
2,
3, -2, -2, -10, 1,
0,
3, -11,6, ␣
˓→-4,
6, 17]])
sage: A.rational_form()
[
0
-4|
0
0
0
0|
0
0
0
0
0
0
0
0]
[
1
4|
0
0
0
0|
0
0
0
0
0
0
0
0]
[---------+-------------------+---------------------------------------]
[
0
0|
0
0
0
12|
0
0
0
0
0
0
0
0]
[
0
0|
1
0
0
-4|
0
0
0
0
0
0
0
0]
[
0
0|
0
1
0
-9|
0
0
0
0
0
0
0
0]
[
0
0|
0
0
1
6|
0
0
0
0
0
0
0
0]
[---------+-------------------+---------------------------------------]
[
0
0|
0
0
0
0|
0
0
0
0
0
0
0 -216]
[
0
0|
0
0
0
0|
1
0
0
0
0
0
0 108]
[
0
0|
0
0
0
0|
0
1
0
0
0
0
0 306]
[
0
0|
0
0
0
0|
0
0
1
0
0
0
0 -271]
[
0
0|
0
0
0
0|
0
0
0
1
0
0
0 -41]
[
0
0|
0
0
0
0|
0
0
0
0
1
0
0 134]
[
0
0|
0
0
0
0|
0
0
0
0
0
1
0 -64]
[
0
0|
0
0
0
0|
0
0
0
0
0
0
1
13]
sage: R = PolynomialRing(QQ, x )sage: invariants = A.rational_form(format= invariants )sage: invariants[[4, -4, 1], [-12, 4, 9, -6, 1], [216, -108, -306, 271, 41, -134, 64, -13, 1]]
sage: polys = [R(p) for p in invariants]
sage: [p.factor() for p in polys]#␣˓→needs sage.rings.finite_rings(continues on next page)

486

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[(x - 2)^2, (x - 3) * (x + 1) * (x - 2)^2, (x + 1)^2 * (x - 3)^3 * (x - 2)^3]
sage: all(polys[i].divides(polys[i+1]) for i in range(len(polys)-1))
True
sage: polys[-1] == A.minimal_polynomial(var= x )#␣˓→needs sage.libs.pari
True
sage: prod(polys) == A.characteristic_polynomial(var= x )#␣˓→needs sage.libs.pari
True>>> from sage.all import *>>> A = matrix(QQ, [[ Integer(11), Integer(14), -Integer(15), -Integer(4), ˓→Integer(38), -Integer(29),Integer(1), Integer(23), Integer(14), ˓→Integer(63),Integer(17), Integer(24), Integer(36), Integer(32)],...
[ Integer(18),Integer(6), -Integer(17), -Integer(11), ˓→Integer(31), -Integer(43), Integer(12),Integer(26),Integer(0), ˓→Integer(69),Integer(11), Integer(13), Integer(17), Integer(24)],...
[ Integer(11), Integer(16), -Integer(22), -Integer(8), ˓→Integer(48), -Integer(34),Integer(0), Integer(31), Integer(16), ˓→Integer(82),Integer(26), Integer(31), Integer(39), Integer(37)],...
[ -Integer(8), -Integer(18), Integer(22), Integer(10), ␣
˓→Integer(46),Integer(33), Integer(3), -Integer(27), -Integer(12), ␣
˓→Integer(70), -Integer(19), -Integer(20), -Integer(42), -Integer(31)],...
[-Integer(13), -Integer(21), Integer(16), Integer(10), ␣
˓→Integer(52),Integer(43), Integer(4), -Integer(28), -Integer(25), ␣˓→Integer(89), -Integer(37), -Integer(20), -Integer(53), -Integer(62)],...
[ -Integer(2), -Integer(6),Integer(0),Integer(0), ␣
˓→ Integer(6),Integer(10), Integer(1),Integer(1), -Integer(7), ␣˓→Integer(14), -Integer(11),-Integer(3), -Integer(10), -Integer(18)],...
[ -Integer(9), -Integer(19), -Integer(3),Integer(4), ␣
˓→Integer(23),Integer(30), Integer(8), -Integer(3), -Integer(27), ␣˓→Integer(55), -Integer(40),-Integer(5), -Integer(40), -Integer(69)],...
[ Integer(4), -Integer(8), -Integer(1), -Integer(1), ␣
˓→ Integer(5),-Integer(4), Integer(9),Integer(5), -Integer(11), ␣
˓→Integer(4), -Integer(14),-Integer(2), -Integer(13), -Integer(17)],...
[ Integer(1), -Integer(2), Integer(16), -Integer(1), ␣
˓→Integer(19),-Integer(2), -Integer(1), -Integer(17),Integer(2), ␣
˓→Integer(19),Integer(5), -Integer(25), -Integer(7), Integer(14)],...
[ Integer(7),Integer(7), -Integer(13), -Integer(4), ˓→Integer(26),-Integer(21), Integer(3), Integer(18),Integer(5), ˓→Integer(40),Integer(7), Integer(15), Integer(20), Integer(14)],...
[ -Integer(6), -Integer(7), -Integer(12),Integer(4), ␣˓→-Integer(1),Integer(18), Integer(3),Integer(8), -Integer(11), ␣
˓→Integer(15), -Integer(18),Integer(17), -Integer(15), -Integer(41)],...
[ Integer(5), Integer(11), -Integer(11), -Integer(3), ˓→Integer(26), -Integer(19), -Integer(1),Integer(14), Integer(10), ˓→Integer(42),Integer(14), Integer(17), Integer(25), Integer(23)],...
[-Integer(16), -Integer(15),Integer(3), Integer(10), ␣
˓→Integer(29),Integer(45), -Integer(1), -Integer(13), -Integer(19), ␣
˓→Integer(71), -Integer(35),-Integer(2), -Integer(35), -Integer(65)],...
[ Integer(4),Integer(2),Integer(3), -Integer(2), ␣˓→-Integer(2), -Integer(10),Integer(1),Integer(0),Integer(3), ˓→Integer(11),Integer(6), -Integer(4),Integer(6), Integer(17)]])>>> A.rational_form()
[
0
-4|
0
0
0
0|
0
0
0
0
0
0
0
0]
[
1
4|
0
0
0
0|
0
0
0
0
0
0
0
0]
(continues on next page)487

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[---------+-------------------+---------------------------------------]
[
0
0|
0
0
0
12|
0
0
0
0
0
0
0
0]
[
0
0|
1
0
0
-4|
0
0
0
0
0
0
0
0]
[
0
0|
0
1
0
-9|
0
0
0
0
0
0
0
0]
[
0
0|
0
0
1
6|
0
0
0
0
0
0
0
0]
[---------+-------------------+---------------------------------------]
[
0
0|
0
0
0
0|
0
0
0
0
0
0
0 -216]
[
0
0|
0
0
0
0|
1
0
0
0
0
0
0 108]
[
0
0|
0
0
0
0|
0
1
0
0
0
0
0 306]
[
0
0|
0
0
0
0|
0
0
1
0
0
0
0 -271]
[
0
0|
0
0
0
0|
0
0
0
1
0
0
0 -41]
[
0
0|
0
0
0
0|
0
0
0
0
1
0
0 134]
[
0
0|
0
0
0
0|
0
0
0
0
0
1
0 -64]
[
0
0|
0
0
0
0|
0
0
0
0
0
0
1
13]
>>> R = PolynomialRing(QQ, x )>>> invariants = A.rational_form(format= invariants )>>> invariants[[4, -4, 1], [-12, 4, 9, -6, 1], [216, -108, -306, 271, 41, -134, 64, -13, 1]]>>> polys = [R(p) for p in invariants]>>> [p.factor() for p in polys]#␣˓→needs sage.rings.finite_rings[(x - 2)^2, (x - 3) * (x + 1) * (x - 2)^2, (x + 1)^2 * (x - 3)^3 * (x - 2)^3]>>> all(polys[i].divides(polys[i+Integer(1)]) for i in range(len(polys)˓→Integer(1)))
True>>> polys[-Integer(1)] == A.minimal_polynomial(var= x )␣˓→# needs sage.libs.pariTrue>>> prod(polys) == A.characteristic_polynomial(var= x )#␣˓→needs sage.libs.pari
True

Rational form is a canonical form. Any two matrices are similar if and only if their rational forms are equal.
By starting with Jordan canonical forms, the matrices C and D below were built as similar matrices, while
E was built to be just slightly different. All three matrices have equal characteristic polynomials though E’s
minimal polynomial differs.
sage: C = matrix(QQ, [[2, 31, -10, -9, -125, 13, 62, -12],....:[0, 48, -16, -16, -188, 20, 92, -16],
....:
[0,
9, -1,
2, -33,
5, 18,
0],....:[0, 15, -5,
0, -59,7, 30, -4],....:
[0, -21,7,
2,84, -10, -42,
5],
....:
[0, -42, 14,
8, 167, -17, -84, 13],....:[0, -50, 17, 10, 199, -23, -98, 14],....:[0, 15, -5, -2, -59,
7, 30, -2]])
sage: C.minimal_polynomial().factor()˓→needs sage.libs.pari(x - 2)^2
sage: C.characteristic_polynomial().factor()˓→needs sage.libs.pari(x - 2)^8
sage: C.rational_form()[ 0 -4| 0 0| 0 0| 0 0]
[ 1 4| 0 0| 0 0| 0 0][-----+-----+-----+-----]#␣#␣

(continues on next page)

488

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 0 0| 0 -4| 0 0| 0 0]
[ 0 0| 1 4| 0 0| 0 0][-----+-----+-----+-----][ 0 0| 0 0| 0 -4| 0 0]
[ 0 0| 0 0| 1 4| 0 0][-----+-----+-----+-----][ 0 0| 0 0| 0 0| 0 -4][ 0 0| 0 0| 0 0| 1 4]
sage: D = matrix(QQ, [[ -4,3,
7,2, -4,
5,
7,
-3],
....:
[ -6,
5,
7,
2, -4,
5,
7,
-3],
....:
[ 21, -12,
89, 25,8, 27,
98, -95],
....:
[ -9,
5, -44, -11, -3, -13, -48,
47],
....:
[ 23, -13,
74, 21, 12, 22,
85, -84],....:[ 31, -18, 135, 38, 12, 47, 155, -147],....:[-33, 19, -138, -39, -13, -45, -156, 151],
....:
[ -7,
4, -29, -8, -3, -10, -34, 34]])
sage: D.minimal_polynomial().factor()˓→needs sage.libs.pari(x - 2)^2
sage: D.characteristic_polynomial().factor()˓→needs sage.libs.pari(x - 2)^8
sage: D.rational_form()[ 0 -4| 0 0| 0 0| 0 0]
[ 1 4| 0 0| 0 0| 0 0][-----+-----+-----+-----][ 0 0| 0 -4| 0 0| 0 0]
[ 0 0| 1 4| 0 0| 0 0][-----+-----+-----+-----][ 0 0| 0 0| 0 -4| 0 0]
[ 0 0| 0 0| 1 4| 0 0][-----+-----+-----+-----][ 0 0| 0 0| 0 0| 0 -4][ 0 0| 0 0| 0 0| 1 4]
sage: E = matrix(QQ, [[ 0, -8,
4, -6, -2,
5, -3, 11],....:[-2, -4,
2, -4, -2,
4, -2,
6],....:[ 5, 14, -7, 12, 3, -8, 6, -27],....:[-3, -8,
7, -5, 0,2, -6, 17],....:
[ 0, 5,0, 2, 4, -4, 1,
2],
....:
[-3, -7,
5, -6, -1,
5, -4, 14],....:
[ 6, 18, -10, 14, 4, -10, 10, -28],....:[-2, -6,
4, -5, -1,
3, -3, 13]])sage: E.minimal_polynomial().factor()˓→needs sage.libs.pari(x - 2)^3
sage: E.characteristic_polynomial().factor()˓→needs sage.libs.pari(x - 2)^8
sage: E.rational_form()[ 2| 0
0| 0
0| 0
0
0]
[---+-------+-------+-----------][ 0| 0 -4| 0
0| 0
0
0]
[ 0| 1
4| 0
0| 0
0
0]
[---+-------+-------+-----------][ 0| 00| 0 -4| 0
0
0]

#␣

#␣

#␣

#␣

(continues on next page)489

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 0| 0
0| 1
4| 0
0
0]
[---+-------+-------+-----------][ 0| 0
0| 0
0| 0
0
8]
[ 0| 00| 0
0| 1
0 -12][ 0| 0
0| 0
0| 0
1
6]
>>> from sage.all import *>>> C = matrix(QQ, [[Integer(2), Integer(31), -Integer(10), -Integer(9), ˓→Integer(125),
Integer(13), Integer(62), -Integer(12)],...
[Integer(0), Integer(48), -Integer(16), -Integer(16), ˓→Integer(188),
Integer(20), Integer(92), -Integer(16)],...
[Integer(0),Integer(9), -Integer(1),Integer(2), ˓→Integer(33),Integer(5), Integer(18),Integer(0)],...
[Integer(0), Integer(15), -Integer(5),Integer(0), ˓→Integer(59),Integer(7), Integer(30), -Integer(4)],...
[Integer(0), -Integer(21),Integer(7),Integer(2), ␣
˓→Integer(84), -Integer(10), -Integer(42),Integer(5)],...
[Integer(0), -Integer(42), Integer(14),Integer(8), ␣
˓→Integer(167), -Integer(17), -Integer(84),Integer(13)],...
[Integer(0), -Integer(50), Integer(17), Integer(10), ␣
˓→Integer(199), -Integer(23), -Integer(98),Integer(14)],...
[Integer(0), Integer(15), -Integer(5), -Integer(2), ˓→Integer(59),Integer(7), Integer(30), -Integer(2)]])>>> C.minimal_polynomial().factor()#␣˓→needs sage.libs.pari(x - 2)^2>>> C.characteristic_polynomial().factor()#␣˓→needs sage.libs.pari(x - 2)^8>>> C.rational_form()[ 0 -4| 0 0| 0 0| 0 0]
[ 1 4| 0 0| 0 0| 0 0][-----+-----+-----+-----][ 0 0| 0 -4| 0 0| 0 0]
[ 0 0| 1 4| 0 0| 0 0][-----+-----+-----+-----][ 0 0| 0 0| 0 -4| 0 0]
[ 0 0| 0 0| 1 4| 0 0][-----+-----+-----+-----][ 0 0| 0 0| 0 0| 0 -4][ 0 0| 0 0| 0 0| 1 4]>>> D = matrix(QQ, [[ -Integer(4),Integer(3),Integer(7),Integer(2),␣
˓→ -Integer(4),Integer(5),Integer(7),-Integer(3)],...
[ -Integer(6),Integer(5),Integer(7),Integer(2),␣
˓→ -Integer(4),Integer(5),Integer(7),-Integer(3)],...
[ Integer(21), -Integer(12),Integer(89), Integer(25),␣
˓→
Integer(8), Integer(27),Integer(98), -Integer(95)],...
[ -Integer(9),Integer(5), -Integer(44), -Integer(11),␣
˓→ -Integer(3), -Integer(13),-Integer(48),Integer(47)],...
[ Integer(23), -Integer(13),Integer(74), Integer(21),␣
˓→ Integer(12),Integer(22),Integer(85), -Integer(84)],...
[ Integer(31), -Integer(18), Integer(135), Integer(38),␣
˓→ Integer(12),Integer(47), Integer(155), -Integer(147)],...
[-Integer(33), Integer(19), -Integer(138), -Integer(39),␣
˓→-Integer(13), -Integer(45), -Integer(156),
Integer(151)],(continues on next page)

490

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...

[ -Integer(7),Integer(4), -Integer(29),
˓→ -Integer(3), -Integer(10),-Integer(34), Integer(34)]])>>> D.minimal_polynomial().factor()˓→needs sage.libs.pari(x - 2)^2>>> D.characteristic_polynomial().factor()˓→needs sage.libs.pari(x - 2)^8>>> D.rational_form()[ 0 -4| 0 0| 0 0| 0 0]
[ 1 4| 0 0| 0 0| 0 0][-----+-----+-----+-----][ 0 0| 0 -4| 0 0| 0 0]
[ 0 0| 1 4| 0 0| 0 0][-----+-----+-----+-----][ 0 0| 0 0| 0 -4| 0 0]
[ 0 0| 0 0| 1 4| 0 0][-----+-----+-----+-----][ 0 0| 0 0| 0 0| 0 -4][ 0 0| 0 0| 0 0| 1 4]-Integer(8),␣
#␣#␣>>> E = matrix(QQ, [[ Integer(0), -Integer(8),Integer(4), -Integer(6), ˓→Integer(2),Integer(5), -Integer(3), Integer(11)],...
[-Integer(2), -Integer(4),Integer(2), -Integer(4), ˓→Integer(2),Integer(4), -Integer(2),Integer(6)],...
[ Integer(5), Integer(14), -Integer(7), Integer(12), ␣
˓→Integer(3),-Integer(8), Integer(6), -Integer(27)],...
[-Integer(3), -Integer(8),Integer(7), -Integer(5), ␣˓→Integer(0),Integer(2), -Integer(6), Integer(17)],...
[ Integer(0), Integer(5),Integer(0), Integer(2), ␣
˓→Integer(4),-Integer(4), Integer(1),Integer(2)],...
[-Integer(3), -Integer(7),Integer(5), -Integer(6), ˓→Integer(1),Integer(5), -Integer(4), Integer(14)],...
[ Integer(6), Integer(18), -Integer(10), Integer(14), ␣
˓→Integer(4), -Integer(10), Integer(10), -Integer(28)],...
[-Integer(2), -Integer(6),Integer(4), -Integer(5), ˓→Integer(1),Integer(3), -Integer(3), Integer(13)]])>>> E.minimal_polynomial().factor()#␣˓→needs sage.libs.pari(x - 2)^3>>> E.characteristic_polynomial().factor()#␣˓→needs sage.libs.pari(x - 2)^8>>> E.rational_form()[ 2| 0
0| 0
0| 0
0
0]
[---+-------+-------+-----------][ 0| 0 -4| 0
0| 0
0
0]
[ 0| 1
4| 0
0| 0
0
0]
[---+-------+-------+-----------][ 0| 00| 0 -4| 000][ 0| 0
0| 1
4| 0
0
0]
[---+-------+-------+-----------][ 0| 0
0| 0
0| 0
0
8]
[ 0| 00| 0
0| 1
0 -12][ 0| 0
0| 0
0| 0
1
6]

The principal feature of rational canonical form is that it can be computed over any field using only field

491

Matrices and Spaces of Matrices, Release 10.4

operations. Other forms, such as Jordan canonical form, are complicated by the need to determine the eigenvalues of the matrix, which can lie outside
the field. The following matrix has all of its eigenvalues outside√
the rationals - some are irrational (± 2) and the rest are complex (−1 ± 2𝑖).
sage: A = matrix(QQ,....: [[-154, -3, -54,
44,
48, -244, -19,
67, -326,85,
355, ␣
˓→581],....: [ 504, 25, 156, -145, -171, 793,
99, -213, 1036, -247, -1152, ˓→1865],....: [ 294, -1, 112, -89, -90, 469,
36, -128, 634, -160, -695, ˓→1126],....: [ -49, -32, 25,
7,37, -64, -58,
12, -42, -14,72, ␣
˓→106],....: [-261, -123, 65,
47, 169, -358, -254,
70, -309, -29,
454, ␣
˓→673],....: [-448, -123, -10, 109, 227, -668, -262, 163, -721,
95,896, ␣
˓→1410],....: [ 38,7,8, -14, -17,
66,
6, -23,73, -29,-78, ˓→143],....: [ -96,
10, -55,
37,
24, -168,
17,56, -231,
88,
237, ␣
˓→412],....: [ 310,
67, 31, -81, -143, 473, 143, -122, 538, -98, -641, ˓→1029],....: [ 139, -35, 99, -49, -18, 236, -41, -70, 370, -118, -377, ˓→619],....: [ 243,
9, 81, -72, -81, 386,
43, -105, 508, -124, -564, ˓→911],....: [-155,-3, -55,
45,
50, -245, -27,
65, -328,
77,
365, ␣
˓→583]])
sage: A.characteristic_polynomial().factor()#␣˓→needs sage.libs.pari(x^2 - 2)^2 * (x^2 + 2*x + 5)^4
sage: A.eigenvalues(extend=False)#␣˓→needs sage.libs.pari[]
sage: A.rational_form()[ 0 -5| 0
0
0
0| 0
0
0
0
0
0]
[ 1 -2| 0
0
0
0| 0
0
0
0
0
0]
[-------+---------------+-----------------------]
[ 0
0| 0
0
0 10| 0
0
0
0
0
0]
[ 0
0| 1
0
0
4| 0
0
0
0
0
0]
[ 0
0| 0
1
0 -3| 0
0
0
0
0
0]
[ 0
0| 0
0
1 -2| 000000][-------+---------------+-----------------------]
[ 0
0| 0
0
0
0| 0
0
0
0
0 50]
[ 0
0| 0
0
0
0| 1
0
0
0
0 40]
[ 0
0| 0
0
0
0| 0
1
0
0
0
3]
[ 0
0| 0
0
0
0| 0
0
1
0
0 -12]
[ 0
0| 0
0
0
0| 0
0
0
1
0 -12]
[ 0
0| 0
0
0
0| 0
0
0
0
1 -4]
sage: F.<x> = QQ[]
sage: polys = A.rational_form(format= invariants )sage: [F(p).factor() for p in polys]#␣˓→needs sage.libs.pari[x^2 + 2*x + 5, (x^2 - 2) * (x^2 + 2*x + 5), (x^2 - 2) * (x^2 + 2*x + 5)^2]>>> from sage.all import *(continues on next page)492

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> A = matrix(QQ,... [[-Integer(154), -Integer(3), -Integer(54),Integer(44), ␣
˓→Integer(48), -Integer(244),-Integer(19),Integer(67), -Integer(326), ␣
˓→Integer(85),Integer(355),
Integer(581)],... [ Integer(504), Integer(25), Integer(156), -Integer(145), ˓→Integer(171),Integer(793),
Integer(99), -Integer(213), Integer(1036), ˓→Integer(247), -Integer(1152), -Integer(1865)],... [ Integer(294), -Integer(1), Integer(112), -Integer(89), ˓→Integer(90),Integer(469),
Integer(36), -Integer(128), Integer(634), ˓→Integer(160),-Integer(695), -Integer(1126)],... [ -Integer(49), -Integer(32), Integer(25),Integer(7), ␣˓→Integer(37),-Integer(64), -Integer(58),Integer(12), -Integer(42), ˓→Integer(14),Integer(72),Integer(106)],... [-Integer(261), -Integer(123), Integer(65),Integer(47), ␣˓→Integer(169), -Integer(358), -Integer(254),
Integer(70), -Integer(309), ˓→Integer(29),Integer(454),
Integer(673)],... [-Integer(448), -Integer(123), -Integer(10), Integer(109), ␣
˓→Integer(227), -Integer(668), -Integer(262),
Integer(163), -Integer(721), ␣
˓→Integer(95),
Integer(896), Integer(1410)],... [ Integer(38),Integer(7),Integer(8), -Integer(14), ˓→Integer(17),Integer(66),Integer(6), -Integer(23),Integer(73), ˓→Integer(29),-Integer(78), -Integer(143)],... [ -Integer(96),Integer(10), -Integer(55),Integer(37), ␣˓→Integer(24), -Integer(168),
Integer(17),Integer(56), -Integer(231), ␣
˓→Integer(88),Integer(237),
Integer(412)],... [ Integer(310),
Integer(67), Integer(31), -Integer(81), ˓→Integer(143),
Integer(473), Integer(143), -Integer(122), Integer(538), ˓→Integer(98),-Integer(641), -Integer(1029)],... [ Integer(139), -Integer(35), Integer(99), -Integer(49), ˓→Integer(18),Integer(236), -Integer(41), -Integer(70), Integer(370), ˓→Integer(118),-Integer(377), -Integer(619)],... [ Integer(243),
Integer(9), Integer(81), -Integer(72), ˓→Integer(81),Integer(386),
Integer(43), -Integer(105), Integer(508), ˓→Integer(124),-Integer(564), -Integer(911)],... [-Integer(155),-Integer(3), -Integer(55),Integer(45), ␣˓→Integer(50), -Integer(245),-Integer(27),Integer(65), -Integer(328), ␣
˓→Integer(77),Integer(365), Integer(583)]])>>> A.characteristic_polynomial().factor()#␣˓→needs sage.libs.pari(x^2 - 2)^2 * (x^2 + 2*x + 5)^4>>> A.eigenvalues(extend=False)#␣˓→needs sage.libs.pari[]>>> A.rational_form()[ 0 -5| 0
0
0
0| 0
0
0
0
0
0]
[ 1 -2| 0
0
0
0| 0
0
0
0
0
0]
[-------+---------------+-----------------------]
[ 0
0| 0
0
0 10| 0
0
0
0
0
0]
[ 0
0| 1
0
0
4| 0
0
0
0
0
0]
[ 0
0| 0
1
0 -3| 0
0
0
0
0
0]
[ 0
0| 0
0
1 -2| 000000][-------+---------------+-----------------------]
[ 0
0| 0
0
0
0| 0
0
0
0
0 50]
[ 0
0| 0
0
0
0| 1
0
0
0
0 40]
[ 0
0| 0
0
0
0| 0
1
0
0
0
3]
[ 0
0| 0
0
0
0| 0
0
1
0
0 -12]
[ 0
0| 0
0
0
0| 0
0
0
1
0 -12](continues on next page)493

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[ 0
0| 0
0
0
0| 0
0
0
0
1 -4]
>>> F = QQ[ x ]; (x,) = F._first_ngens(1)>>> polys = A.rational_form(format= invariants )>>> [F(p).factor() for p in polys]#␣˓→needs sage.libs.pari[x^2 + 2*x + 5, (x^2 - 2) * (x^2 + 2*x + 5), (x^2 - 2) * (x^2 + 2*x + 5)^2]

Rational form may be computed over any field. The matrix below is an example where the eigenvalues lie
outside the field.
sage: # needs sage.rings.finite_rings
sage: F.<a> = FiniteField(7^2)
sage: A = matrix(F,....: [[5*a + 3, 4*a + 1, 6*a + 2, 2*a + 5,
6, 4*a + 5, 4*a + 5,␣˓→5,a + 6,
5, 4*a + 4],....: [6*a + 3, 2*a + 4,
0,
6, 5*a + 5,
2*a, 5*a + 1,␣˓→1, 5*a + 2,
4*a, 5*a + 6],....: [3*a + 1, 6*a + 6,
a + 6,
2,0, 3*a + 6, 5*a + 4, 5*a +␣˓→6, 5*a + 2,
3, 4*a + 2],....: [
3*a,
6*a,
3*a,
4*a, 4*a + 4, 3*a + 6,
6*a,
␣
˓→4, 3*a + 4, 6*a + 2,
4*a],....: [4*a + 5,
a + 1, 4*a + 3, 6*a + 5, 5*a + 2, 5*a + 2,
6*a, 4*a +␣˓→6, 6*a + 4, 5*a + 3, 3*a + 1],....: [
3*a,
6*a, 4*a + 1, 6*a + 2, 2*a + 5, 4*a + 6,2,
a +␣˓→5, 2*a + 4, 2*a + 1, 2*a + 1],....: [4*a + 5, 3*a + 3,
6, 4*a + 1, 4*a + 3, 6*a + 3,
6, 3*a +␣˓→3,3,
a + 3,
0],....: [6*a + 6,
a + 4, 2*a + 6, 3*a + 5, 4*a + 3,
2,a, 3*a +␣˓→4,
5*a, 2*a + 5, 4*a + 3],....: [3*a + 5, 6*a + 2,
4*a,a + 5,
0,
5*a, 6*a + 5, 2*a +␣˓→1, 3*a + 1, 3*a + 5, 4*a + 2],....: [3*a + 2,
a + 3, 3*a + 6,
a, 3*a + 5, 5*a + 1, 3*a + 2,
a +␣
˓→3,
a + 2, 6*a + 1, 3*a + 3],....: [6*a + 6, 5*a + 1,
4*a,2, 5*a + 5, 3*a + 5, 3*a + 1,␣
˓→2*a,
2*a, 2*a + 4, 4*a + 2]])sage: A.rational_form()[ a + 2|
0
0
0|
0
0
0
0
0
␣
˓→ 0
0]
[-------+-----------------------+--------------------------------------------˓→----------][
0|0
0
a + 6|
0
0
0
0
0
␣
˓→ 0
0]
[
0|
1
0 6*a + 4|
0
0
0
0
0
␣
˓→ 0
0]
[
0|
0
1 6*a + 4|
0
0
0
0
0
␣
˓→ 0
0]
[-------+-----------------------+--------------------------------------------˓→----------]
[
0|
0
0
0|
0
0
0
0
0
␣
˓→ 0
2*a]
[
0|
0
0
0|
1
0
0
0
0
␣
˓→ 0 6*a + 3]
[
0|
0
0
0|
0
1
0
0
0
␣
˓→ 0 6*a + 1]
[
0|
0
0
0|
0
0
1
0
0
␣
˓→ 0
a + 2]
[
0|
0
0
0|
0
0
0
1
0
␣

(continues on next page)494

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)a + 6]
[
0|
0
0
0|
0
0
0
0
1
␣
˓→ 0 2*a + 1]
[
0|
0
0
0|
0
0
0
0
0
␣
˓→ 1 2*a + 1]
sage: invariants = A.rational_form(format= invariants )sage: invariants[[6*a + 5, 1], [6*a + 1, a + 3, a + 3, 1], [5*a, a + 4, a + 6, 6*a + 5, 6*a +␣˓→1, 5*a + 6, 5*a + 6, 1]]
sage: R.<x> = F[]sage: polys = [R(p) for p in invariants]
sage: [p.factor() for p in polys][x + 6*a + 5, (x + 6*a + 5) * (x^2 + (2*a + 5)*x + 5*a), (x + 6*a + 5) * (x^2␣˓→+ (2*a + 5)*x + 5*a)^3]
sage: polys[-1] == A.minimal_polynomial()
True
sage: prod(polys) == A.characteristic_polynomial()
True
sage: A.eigenvalues()
Traceback (most recent call last):...
NotImplementedError: algebraic closures of finite fields are only implemented␣
˓→for prime fields
˓→0>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> F = FiniteField(Integer(7)**Integer(2), names=( a ,)); (a,) = F._first_
˓→ngens(1)>>> A = matrix(F,... [[Integer(5)*a + Integer(3), Integer(4)*a + Integer(1), Integer(6)*a +␣˓→Integer(2), Integer(2)*a + Integer(5),Integer(6), Integer(4)*a +␣˓→Integer(5), Integer(4)*a + Integer(5),Integer(5),a + Integer(6), ␣˓→Integer(5), Integer(4)*a + Integer(4)],... [Integer(6)*a + Integer(3), Integer(2)*a + Integer(4),Integer(0),␣
˓→Integer(6), Integer(5)*a + Integer(5),Integer(2)*a, Integer(5)*a␣
˓→+ Integer(1),Integer(1), Integer(5)*a + Integer(2),Integer(4)*a,
˓→ Integer(5)*a + Integer(6)],... [Integer(3)*a + Integer(1), Integer(6)*a + Integer(6),a + Integer(6),␣
˓→
Integer(2),Integer(0), Integer(3)*a + Integer(6), Integer(5)*a␣
˓→+ Integer(4), Integer(5)*a + Integer(6), Integer(5)*a + Integer(2),␣˓→Integer(3), Integer(4)*a + Integer(2)],... [Integer(3)*a,
Integer(6)*a,
Integer(3)*a,
Integer(4)*a,␣
˓→Integer(4)*a + Integer(4), Integer(3)*a + Integer(6),Integer(6)*a,␣˓→Integer(4), Integer(3)*a + Integer(4), Integer(6)*a + Integer(2),␣˓→Integer(4)*a],... [Integer(4)*a + Integer(5),a + Integer(1), Integer(4)*a + Integer(3),␣
˓→Integer(6)*a + Integer(5), Integer(5)*a + Integer(2), Integer(5)*a +␣˓→Integer(2),Integer(6)*a, Integer(4)*a + Integer(6), Integer(6)*a +␣˓→Integer(4), Integer(5)*a + Integer(3), Integer(3)*a + Integer(1)],... [Integer(3)*a,
Integer(6)*a, Integer(4)*a + Integer(1),␣
˓→Integer(6)*a + Integer(2), Integer(2)*a + Integer(5), Integer(4)*a +␣˓→Integer(6),Integer(2),a + Integer(5), Integer(2)*a + Integer(4),␣
˓→Integer(2)*a + Integer(1), Integer(2)*a + Integer(1)],... [Integer(4)*a + Integer(5), Integer(3)*a + Integer(3),Integer(6),␣
˓→Integer(4)*a + Integer(1), Integer(4)*a + Integer(3), Integer(6)*a +␣˓→Integer(3),Integer(6), Integer(3)*a + Integer(3),Integer(3), ␣(continues on next page)495

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)a + Integer(3),Integer(0)],... [Integer(6)*a + Integer(6),a + Integer(4), Integer(2)*a + Integer(6),␣
˓→Integer(3)*a + Integer(5), Integer(4)*a + Integer(3),Integer(2),␣˓→a, Integer(3)*a + Integer(4),Integer(5)*a, Integer(2)*a + Integer(5),˓→ Integer(4)*a + Integer(3)],... [Integer(3)*a + Integer(5), Integer(6)*a + Integer(2),Integer(4)*a,␣˓→
a + Integer(5),Integer(0),Integer(5)*a, Integer(6)*a +␣˓→Integer(5), Integer(2)*a + Integer(1), Integer(3)*a + Integer(1),␣
˓→Integer(3)*a + Integer(5), Integer(4)*a + Integer(2)],... [Integer(3)*a + Integer(2),a + Integer(3), Integer(3)*a + Integer(6),␣
˓→a, Integer(3)*a + Integer(5), Integer(5)*a + Integer(1), Integer(3)*a␣
˓→+ Integer(2),a + Integer(3),a + Integer(2), Integer(6)*a + Integer(1),˓→ Integer(3)*a + Integer(3)],... [Integer(6)*a + Integer(6), Integer(5)*a + Integer(1),Integer(4)*a,␣˓→Integer(2), Integer(5)*a + Integer(5), Integer(3)*a + Integer(5),␣
˓→Integer(3)*a + Integer(1),Integer(2)*a,
Integer(2)*a, Integer(2)*a␣
˓→+ Integer(4), Integer(4)*a + Integer(2)]])>>> A.rational_form()[ a + 2|
0
0
0|
0
0
0
0
0
␣
˓→ 0
0]
[-------+-----------------------+--------------------------------------------˓→----------][
0|0
0
a + 6|
0
0
0
0
0
␣
˓→ 0
0]
[
0|
1
0 6*a + 4|
0
0
0
0
0
␣
˓→ 0
0]
[
0|
0
1 6*a + 4|
0
0
0
0
0
␣
˓→ 0
0]
[-------+-----------------------+--------------------------------------------˓→----------]
[
0|
0
0
0|
0
0
0
0
0
␣
˓→ 0
2*a]
[
0|
0
0
0|
1
0
0
0
0
␣
˓→ 0 6*a + 3]
[
0|
0
0
0|
0
1
0
0
0
␣
˓→ 0 6*a + 1]
[
0|
0
0
0|
0
0
1
0
0
␣
˓→ 0
a + 2]
[
0|
0
0
0|
0
0
0
1
0
␣
˓→ 0
a + 6]
[
0|
0
0
0|
0
0
0
0
1
␣
˓→ 0 2*a + 1]
[
0|
0
0
0|
0
0
0
0
0
␣
˓→ 1 2*a + 1]>>> invariants = A.rational_form(format= invariants )>>> invariants[[6*a + 5, 1], [6*a + 1, a + 3, a + 3, 1], [5*a, a + 4, a + 6, 6*a + 5, 6*a +␣˓→1, 5*a + 6, 5*a + 6, 1]]>>> R = F[ x ]; (x,) = R._first_ngens(1)>>> polys = [R(p) for p in invariants]>>> [p.factor() for p in polys][x + 6*a + 5, (x + 6*a + 5) * (x^2 + (2*a + 5)*x + 5*a), (x + 6*a + 5) * (x^2␣˓→+ (2*a + 5)*x + 5*a)^3]>>> polys[-Integer(1)] == A.minimal_polynomial()
True>>> prod(polys) == A.characteristic_polynomial()
True˓→(continues on next page)

496

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> A.eigenvalues()
Traceback (most recent call last):...
NotImplementedError: algebraic closures of finite fields are only implemented␣
˓→for prime fields

Companion matrices may be selected as any one of four different types. See the documentation for the companion matrix constructor, sage.matrix.constructor.companion_matrix(), for more information.
sage: A = matrix(QQ, [[35, -18, -2, -45],....:[22, -22, 12, -16],....:[ 5, -12, 12,
4],
....:
[16, -6, -4, -23]])
sage: A.rational_form(format= right )[ 2| 0 0 0][--+--------][ 0| 0 0 10][ 0| 1 0 -1][ 0| 0 1 0]
sage: A.rational_form(format= bottom )[ 2| 0 0 0][--+--------][ 0| 0 1 0]
[ 0| 0 0 1]
[ 0|10 -1 0]
sage: A.rational_form(format= left )[ 2| 0 0 0][--+--------][ 0| 0 1 0]
[ 0|-1 0 1]
[ 0|10 0 0]
sage: A.rational_form(format= top )[ 2| 0 0 0][--+--------][ 0| 0 -1 10][ 0| 1 0 0]
[ 0| 0 1 0]>>> from sage.all import *>>> A = matrix(QQ, [[Integer(35), -Integer(18), -Integer(2), -Integer(45)],...
[Integer(22), -Integer(22), Integer(12), -Integer(16)],...
[ Integer(5), -Integer(12), Integer(12),Integer(4)],...
[Integer(16), -Integer(6), -Integer(4), -Integer(23)]])>>> A.rational_form(format= right )[ 2| 0 0 0][--+--------][ 0| 0 0 10][ 0| 1 0 -1][ 0| 0 1 0]>>> A.rational_form(format= bottom )[ 2| 0 0 0][--+--------][ 0| 0 1 0]
[ 0| 0 0 1]
[ 0|10 -1 0](continues on next page)497

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> A.rational_form(format= left )[ 2| 0 0 0][--+--------][ 0| 0 1 0]
[ 0|-1 0 1]
[ 0|10 0 0]>>> A.rational_form(format= top )[ 2| 0 0 0][--+--------][ 0| 0 -1 10][ 0| 1 0 0]
[ 0| 0 1 0]

restrict(V, check=True)
Returns the matrix that defines the action of self on the chosen basis for the invariant subspace V. If V is anambient, returns self (not a copy of self).
INPUT:• V – vector subspace• check – (optional) default: True; if False may not check that V is invariant (hence can be faster).
OUTPUT: a matrix
Warning: This function returns an nxn matrix, where V has dimension n. It does not check that V is infact invariant under self, unless check is True.
EXAMPLES:
sage: V = VectorSpace(QQ, 3)
sage: M = MatrixSpace(QQ, 3)
sage: A = M([1,2,0, 3,4,0, 0,0,0])
sage: W = V.subspace([[1,0,0], [0,1,0]])
sage: A.restrict(W)
[1 2]
[3 4]
sage: A.restrict(W, check=True)
[1 2]
[3 4]
>>> from sage.all import *>>> V = VectorSpace(QQ, Integer(3))>>> M = MatrixSpace(QQ, Integer(3))>>> A = M([Integer(1),Integer(2),Integer(0), Integer(3),Integer(4),Integer(0),˓→ Integer(0),Integer(0),Integer(0)])>>> W = V.subspace([[Integer(1),Integer(0),Integer(0)], [Integer(0),˓→Integer(1),Integer(0)]])>>> A.restrict(W)
[1 2]
[3 4]
>>> A.restrict(W, check=True)
[1 2]
[3 4]

We illustrate the warning about invariance not being checked by default, by giving a non-invariant subspace.
498

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

With the default check=False this function returns the ‘restriction’ matrix, which is meaningless as check=Truereveals.
sage: W2 = V.subspace([[1,0,0], [0,1,1]])
sage: A.restrict(W2, check=False)
[1 2]
[3 4]
sage: A.restrict(W2, check=True)
Traceback (most recent call last):...
ArithmeticError: subspace is not invariant under matrix>>> from sage.all import *>>> W2 = V.subspace([[Integer(1),Integer(0),Integer(0)], [Integer(0),˓→Integer(1),Integer(1)]])>>> A.restrict(W2, check=False)
[1 2]
[3 4]
>>> A.restrict(W2, check=True)
Traceback (most recent call last):...
ArithmeticError: subspace is not invariant under matrix

restrict_codomain(V)Suppose that self defines a linear map from some domain to a codomain that contains 𝑉 and that the imageof self is contained in 𝑉 . This function returns a new matrix 𝐴 that represents this linear map but as a map
to 𝑉 , in the sense that if 𝑥 is in the domain, then 𝑥𝐴 is the linear combination of the elements of the basis of
𝑉 that equals v*self.
INPUT:• V – vector space (space of degree self.ncols()) that contains the image of self.
See also:
restrict(), restrict_domain()
EXAMPLES:
sage: A = matrix(QQ, 3, [1..9])sage: V = (QQ^3).span([[1,2,3], [7,8,9]]); V
Vector space of degree 3 and dimension 2 over Rational Field
Basis matrix:[ 1 0 -1]
[ 0 1 2]sage: z = vector(QQ,[1,2,5])
sage: B = A.restrict_codomain(V); B
[1 2]
[4 5]
[7 8]
sage: z*B
(44, 52)
sage: z*A
(44, 52, 60)
sage: 44*V.0 + 52*V.1(44, 52, 60)

499

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = matrix(QQ, Integer(3), (ellipsis_range(Integer(1),Ellipsis,
˓→Integer(9))))>>> V = (QQ**Integer(3)).span([[Integer(1),Integer(2),Integer(3)],␣
˓→[Integer(7),Integer(8),Integer(9)]]); V
Vector space of degree 3 and dimension 2 over Rational Field
Basis matrix:[ 1 0 -1]
[ 0 1 2]>>> z = vector(QQ,[Integer(1),Integer(2),Integer(5)])>>> B = A.restrict_codomain(V); B
[1 2]
[4 5]
[7 8]
>>> z*B(44, 52)>>> z*A(44, 52, 60)>>> Integer(44)*V.gen(0) + Integer(52)*V.gen(1)(44, 52, 60)

restrict_domain(V)Compute the matrix relative to the basis for V on the domain obtained by restricting self to V, but not changing
the codomain of the matrix. This is the matrix whose rows are the images of the basis for V.
INPUT:• V – vector space (subspace of ambient space on which self acts)
See also:
restrict()
EXAMPLES:
sage: V = QQ^3sage: A = matrix(QQ, 3, [1,2,0, 3,4,0, 0,0,0])
sage: W = V.subspace([[1,0,0], [1,2,3]])
sage: A.restrict_domain(W)[1 2 0][3 4 0]sage: W2 = V.subspace_with_basis([[1,0,0], [1,2,3]])
sage: A.restrict_domain(W2)[ 1 2 0]
[ 7 10 0]>>> from sage.all import *>>> V = QQ**Integer(3)>>> A = matrix(QQ, Integer(3), [Integer(1),Integer(2),Integer(0), Integer(3),˓→Integer(4),Integer(0), Integer(0),Integer(0),Integer(0)])>>> W = V.subspace([[Integer(1),Integer(0),Integer(0)], [Integer(1),˓→Integer(2),Integer(3)]])>>> A.restrict_domain(W)[1 2 0][3 4 0]>>> W2 = V.subspace_with_basis([[Integer(1),Integer(0),Integer(0)],␣
˓→[Integer(1),Integer(2),Integer(3)]])>>> A.restrict_domain(W2)(continues on next page)

500

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 1 2[ 7 10

0]
0]

right_eigenmatrix(other=None)
Return matrices 𝐷 and 𝑃 , where 𝐷 is a diagonal matrix of eigenvalues and the columns of 𝑃 are corresponding eigenvectors (or zero vectors).
INPUT:• other – a square matrix 𝐵 (default: None) in a generalized eigenvalue problem; if None, an ordinary
eigenvalue problem is solved
OUTPUT:
If self is a square matrix 𝐴, then the output is a diagonal matrix 𝐷 and a matrix 𝑃 such that𝐴𝑃 = 𝑃 𝐷,
where the columns of 𝑃 are eigenvectors of 𝐴 and the diagonal entries of 𝐷 are the corresponding eigenvalues.
If a matrix 𝐵 is passed as optional argument, the output is a solution to the generalized eigenvalue problem
such that𝐴𝑃 = 𝐵𝑃 𝐷.
The ordinary eigenvalue problem is equivalent to the generalized one if 𝐵 is the identity matrix.
The generalized eigenvector decomposition is currently only implemented for matrices over RDF and CDF.
EXAMPLES:
sage: # needs sage.rings.number_fieldsage: A = matrix(QQ, 3, 3, range(9)); A[0 1 2][3 4 5][6 7 8]sage: D, P = A.eigenmatrix_right()
sage: D[00
0][
0 -1.348469228349535?
0][0
0 13.34846922834954?]
sage: P[1
1
1][
-2 0.1303061543300932?
3.069693845669907?][
1 -0.7393876913398137?
5.139387691339814?]
sage: A*P == P*D
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQ, Integer(3), Integer(3), range(Integer(9))); A[0 1 2][3 4 5][6 7 8]>>> D, P = A.eigenmatrix_right()
>>> D
[
0
0
0]
[
0 -1.348469228349535?
0](continues on next page)501

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[
>>> P
[
[
[
>>> A*P == P*D
True

0

0

13.34846922834954?]

1
1-2 0.1303061543300932?
1 -0.7393876913398137?

1]
3.069693845669907?]
5.139387691339814?]

Because 𝑃 is invertible, 𝐴 is diagonalizable.
sage: A == P*D*(~P)˓→needs sage.rings.number_field
True

#␣

>>> from sage.all import *>>> A == P*D*(~P)˓→needs sage.rings.number_field
True

#␣

The matrix 𝑃 may contain zero columns corresponding to eigenvalues for which the algebraic multiplicity isgreater than the geometric multiplicity. In these cases, the matrix is not diagonalizable.
sage: # needs sage.rings.number_fieldsage: A = jordan_block(2, 3); A[2 1 0][0 2 1][0 0 2]sage: D, P = A.eigenmatrix_right()
sage: D
[2 0 0][0 2 0][0 0 2]sage: P
[1 0 0][0 0 0][0 0 0]sage: A*P == P*D
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = jordan_block(Integer(2), Integer(3)); A[2 1 0][0 2 1][0 0 2]>>> D, P = A.eigenmatrix_right()>>> D[2 0 0][0 2 0][0 0 2]>>> P[1 0 0][0 0 0][0 0 0]>>> A*P == P*D
True

502

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

A generalized eigenvector decomposition:
sage: # needs scipy
sage: A = matrix(RDF, [[1, -2], [3, 4]])sage: B = matrix(RDF, [[0, 7], [2, -3]])
sage: D, P = A.eigenmatrix_right(B)sage: (A * P - B * P * D).norm() < 1e-14
True>>> from sage.all import *>>> # needs scipy>>> A = matrix(RDF, [[Integer(1), -Integer(2)], [Integer(3), Integer(4)]])>>> B = matrix(RDF, [[Integer(0), Integer(7)], [Integer(2), -Integer(3)]])>>> D, P = A.eigenmatrix_right(B)>>> (A * P - B * P * D).norm() < RealNumber( 1e-14 )True

The matrix 𝐵 in a generalized eigenvalue problem may be singular:
sage: # needs scipy
sage: A = matrix.identity(RDF, 2)
sage: B = matrix(RDF, [[3, 5], [6, 10]])sage: D, P = A.eigenmatrix_right(B); D# tol 1e-14[0.07692307692307694
0.0]
[
0.0
+infinity]>>> from sage.all import *>>> # needs scipy>>> A = matrix.identity(RDF, Integer(2))>>> B = matrix(RDF, [[Integer(3), Integer(5)], [Integer(6), Integer(10)]])>>> D, P = A.eigenmatrix_right(B); D# tol 1e-14[0.07692307692307694
0.0]
[
0.0
+infinity]

In this case, we can still verify the eigenvector equation for the first eigenvalue and first eigenvector:
sage: # needs scipy
sage: l = D[0, 0]
sage: v = P[:, 0]
sage: (A * v - B * v * l).norm() < 1e-14
True>>> from sage.all import *>>> # needs scipy>>> l = D[Integer(0), Integer(0)]>>> v = P[:, Integer(0)]>>> (A * v - B * v * l).norm() < RealNumber( 1e-14 )True

The second eigenvector is contained in the right kernel of 𝐵:
sage: (B * P[:, 1]).norm() < 1e-14
˓→needs scipy
True

#␣

503

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> (B * P[:, Integer(1)]).norm() < RealNumber( 1e-14 )˓→# needs scipy
True␣

See also:
eigenvalues(),
eigenvectors_right(),
eigenvectors_right(), eigenmatrix_left().

Matrix_double_dense.

right_eigenspaces(format='all', var='a', algebraic_multiplicity=False)
Compute the right eigenspaces of a matrix.
Note that eigenspaces_right() and right_eigenspaces() are identical methods. Here “right”
refers to the eigenvectors being placed to the right of the matrix.
INPUT:• self – a square matrix over an exact field. For inexact matrices consult the numerical or symbolic
matrix classes.
• format – default: None–

all – attempts to create every eigenspace. This will always be possible for matrices with rational
entries.

–

galois – for each irreducible factor of the characteristic polynomial, a single eigenspace will
be output for a single root/eigenvalue for the irreducible factor.

– None – Uses the ‘all’ format if the base ring is contained in an algebraically closed field which is
implemented. Otherwise, uses the ‘galois’ format.
• var – (default: ‘a’); variable name used to represent elements of the root field of each irreducible factorof the characteristic polynomial. If var=’a’, then the root fields will be in terms of a0, a1, a2, …., where
the numbering runs across all the irreducible factors of the characteristic polynomial, even for linear
factors.
• algebraic_multiplicity – (default: False); whether or not to include the algebraic multiplicity of each eigenvalue in the output. See the discussion below.
OUTPUT:
If algebraic_multiplicity=False, return a list of pairs (e, V) where e is an eigenvalue of the matrix, and V isthe corresponding left eigenspace. For Galois conjugates of eigenvalues, there may be just one representative
eigenspace, depending on the format keyword.
If algebraic_multiplicity=True, return a list of triples (e, V, n) where e and V are as above and n is the algebraic
multiplicity of the eigenvalue.
Warning: Uses a somewhat naive algorithm (simply factors the characteristic polynomial and computes
kernels directly over the extension field).
EXAMPLES:
Right eigenspaces are computed from the left eigenspaces of the transpose of the matrix. As such, there is agreater collection of illustrative examples at the eigenspaces_left().
We compute the right eigenspaces of a 3 × 3 rational matrix.

504

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

sage: # needs sage.rings.number_fieldsage: A = matrix(QQ, 3, 3, range(9)); A[0 1 2][3 4 5][6 7 8]sage: A.eigenspaces_right()[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]),(-1.348469228349535?,
Vector space of degree 3 and dimension 1 over Algebraic Field
User basis matrix:[
1 0.1303061543300932? -0.7393876913398137?]),(13.34846922834954?,
Vector space of degree 3 and dimension 1 over Algebraic Field
User basis matrix:[
1 3.069693845669907? 5.139387691339814?]) ]sage: es = A.eigenspaces_right(format= galois ); es[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]),(a1,
Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/5*a1 + 2/5 2/5*a1 - 1/5]) ]sage: es = A.eigenspaces_right(format= galois ,....:algebraic_multiplicity=True); es[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1],1),(a1,
Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/5*a1 + 2/5 2/5*a1 - 1/5],1) ]sage: e, v, n = es[0]; v = v.basis()[0]sage: delta = v*e - A*v
sage: abs(abs(delta)) < 1e-10
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQ, Integer(3), Integer(3), range(Integer(9))); A[0 1 2][3 4 5][6 7 8]>>> A.eigenspaces_right()[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]),
(continues on next page)505

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)(-1.348469228349535?,
Vector space of degree 3 and dimension 1 over Algebraic Field
User basis matrix:[
1 0.1303061543300932? -0.7393876913398137?]),(13.34846922834954?,
Vector space of degree 3 and dimension 1 over Algebraic Field
User basis matrix:[
1 3.069693845669907? 5.139387691339814?]) ]>>> es = A.eigenspaces_right(format= galois ); es[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]),(a1,
Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/5*a1 + 2/5 2/5*a1 - 1/5]) ]>>> es = A.eigenspaces_right(format= galois ,...
algebraic_multiplicity=True); es[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1],1),(a1,
Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/5*a1 + 2/5 2/5*a1 - 1/5],
1) ]>>> e, v, n = es[Integer(0)]; v = v.basis()[Integer(0)]>>> delta = v*e - A*v>>> abs(abs(delta)) < RealNumber( 1e-10 )True

The same computation, but with implicit base change to a field:
sage: A = matrix(ZZ, 3, range(9)); A[0 1 2][3 4 5][6 7 8]sage: A.eigenspaces_right(format= galois )˓→needs sage.rings.number_field[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]),(a1,
Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/5*a1 + 2/5 2/5*a1 - 1/5]) ]#␣>>> from sage.all import *>>> A = matrix(ZZ, Integer(3), range(Integer(9))); A(continues on next page)

506

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 1 2][3 4 5][6 7 8]>>> A.eigenspaces_right(format= galois )˓→needs sage.rings.number_field[ (0,Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]),(a1,
Vector space of degree 3 and dimension 1 overNumber Field in a1 with defining polynomial x^2 - 12*x - 18
User basis matrix:[
1 1/5*a1 + 2/5 2/5*a1 - 1/5]) ]#␣This method is only applicable to exact matrices. The “eigenmatrix” routines for matrices withdouble-precision floating-point entries (RDF, CDF) are the best alternative. (Since some platforms return
eigenvectors that are the negatives of those given here, this one example is not tested here.) There are also
“eigenmatrix” routines for matrices with symbolic entries.
sage: B = matrix(RR, 3, 3, range(9))
sage: B.eigenspaces_right()
Traceback (most recent call last):...
NotImplementedError: eigenspaces cannot be computed reliably
for inexact rings such as Real Field with 53 bits of precision,
consult numerical or symbolic matrix classes for other options
sage: # needs scipy
sage: em = B.change_ring(RDF).eigenmatrix_right()
sage: eigenvalues = em[0]; eigenvalues.dense_matrix() # abs tol 1e-13[13.348469228349522
0.0
0.0]
[
0.0 -1.348469228349534
0.0]
[
0.0
0.0
0.0]
sage: eigenvectors = em[1]; eigenvectors # not tested[ 0.164763817... 0.799699663... 0.408248290...][ 0.505774475... 0.104205787... -0.816496580...][ 0.846785134... -0.591288087... 0.408248290...]sage: # needs sage.symbolic
sage: x, y = var( x y )sage: S = matrix([[x, y], [y, 3*x^2]])sage: em = S.eigenmatrix_right()
sage: eigenvalues = em[0]; eigenvalues[3/2*x^2 + 1/2*x - 1/2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2)
␣
˓→
0]
[
0 3/2*x^2 + 1/2*x + 1/
˓→2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2)]
sage: eigenvectors = em[1]; eigenvectors
[
1
␣
˓→
1]
[1/2*(3*x^2 - x - sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y 1/2*(3*x^2 - x +␣˓→sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y]>>> from sage.all import *>>> B = matrix(RR, Integer(3), Integer(3), range(Integer(9)))(continues on next page)507

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> B.eigenspaces_right()
Traceback (most recent call last):...
NotImplementedError: eigenspaces cannot be computed reliably
for inexact rings such as Real Field with 53 bits of precision,
consult numerical or symbolic matrix classes for other options>>> # needs scipy>>> em = B.change_ring(RDF).eigenmatrix_right()>>> eigenvalues = em[Integer(0)]; eigenvalues.dense_matrix()[13.348469228349522
0.0
0.0]
[
0.0 -1.348469228349534
0.0]
[
0.0
0.0
0.0]
>>> eigenvectors = em[Integer(1)]; eigenvectors # not tested[ 0.164763817... 0.799699663... 0.408248290...][ 0.505774475... 0.104205787... -0.816496580...][ 0.846785134... -0.591288087... 0.408248290...]# abs tol 1e-13>>> # needs sage.symbolic>>> x, y = var( x y )>>> S = matrix([[x, y], [y, Integer(3)*x**Integer(2)]])>>> em = S.eigenmatrix_right()>>> eigenvalues = em[Integer(0)]; eigenvalues[3/2*x^2 + 1/2*x - 1/2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2)
␣
˓→
0]
[
0 3/2*x^2 + 1/2*x + 1/
˓→2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2)]>>> eigenvectors = em[Integer(1)]; eigenvectors
[
1
␣
˓→
1]
[1/2*(3*x^2 - x - sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y 1/2*(3*x^2 - x +␣˓→sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y]right_eigenvectors(other=None, extend=True)
Compute the right eigenvectors of a matrix.
INPUT:• other – a square matrix 𝐵 (default: None) in a generalized eigenvalue problem; if None, an ordinary
eigenvalue problem is solved (currently supported only if the base ring of self is RDF or CDF)
• extend – boolean (default: True)OUTPUT:For each distinct eigenvalue, returns a list of the form (e,V,n) where e is the eigenvalue, V is a list of eigenvectors forming a basis for the corresponding right eigenspace, and n is the algebraic multiplicity of theeigenvalue. If extend = True (the default), this will return eigenspaces over the algebraic closure of thebase field where this is implemented; otherwise it will restrict to eigenvalues in the base field.
EXAMPLES:
We compute the right eigenvectors of a 3 × 3 rational matrix.
sage: # needs sage.rings.number_fieldsage: A = matrix(QQ, 3, 3, range(9)); A[0 1 2][3 4 5](continues on next page)

508

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[6 7 8]sage: es = A.eigenvectors_right(); es[(0, [ (1, -2, 1) ], 1),(-1.348469228349535?, [(1, 0.1303061543300932?, -0.7393876913398137?)], 1),(13.34846922834954?, [(1, 3.069693845669907?, 5.139387691339814?)], 1)]
sage: A.eigenvectors_right(extend=False)[(0, [ (1, -2, 1) ], 1)]
sage: eval, [evec], mult = es[0]sage: delta = eval*evec - A*evec
sage: abs(abs(delta)) < 1e-10
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> A = matrix(QQ, Integer(3), Integer(3), range(Integer(9))); A[0 1 2][3 4 5][6 7 8]>>> es = A.eigenvectors_right(); es[(0, [ (1, -2, 1) ], 1),(-1.348469228349535?, [(1, 0.1303061543300932?, -0.7393876913398137?)], 1),(13.34846922834954?, [(1, 3.069693845669907?, 5.139387691339814?)], 1)]>>> A.eigenvectors_right(extend=False)[(0, [ (1, -2, 1) ], 1)]>>> eval, [evec], mult = es[Integer(0)]>>> delta = eval*evec - A*evec>>> abs(abs(delta)) < RealNumber( 1e-10 )Trueright_kernel(*args, **kwds)
Returns the right kernel of this matrix, as a vector space or free module. This is the set of vectors x such thatself*x = 0.
Note: For the left kernel, use left_kernel(). The method kernel() is exactly equal to left_kernel().
For inexact rings use right_kernel_matrix() with basis= computed to avoid echolonizing.
INPUT:• algorithm – (default: ‘default’); a keyword that selects the algorithm employed. Allowable values are:– ‘default’ – allows the algorithm to be chosen automatically– ‘generic’ – naive algorithm usable for matrices over any field– ‘flint’ – FLINT library code for matrices over the rationals or the integers– ‘pari’ – PARI library code for matrices over number fields or the integers– ‘padic’ – padic algorithm from IML library for matrices over the rationals and integers– ‘pluq’ – PLUQ matrix factorization for matrices mod 2• basis – (default: ‘echelon’); a keyword that describes the format of the basis used to construct the right
kernel. Allowable values are:– ‘echelon’: the basis matrix is returned in echelon form

509

Matrices and Spaces of Matrices, Release 10.4

– ‘pivot’ : each basis vector is computed from the reduced row-echelon form of self by placing asingle one in a non-pivot column and zeros in the remaining non-pivot columns. Only available formatrices over fields.
– ‘LLL’: an LLL-reduced basis. Only available for matrices over the integers.
OUTPUT:
A vector space or free module whose degree equals the number of columns in self and which contains all
the vectors x such that self*x = 0.
If self has 0 columns, the kernel has dimension 0, while if self has 0 rows the kernel is the entire ambient
vector space.
The result is cached. Requesting the right kernel a second time, but with a different basis format, will returnthe cached result with the format from the first computation.
Note: For more detailed documentation on the selection of algorithms used and a more flexible method
for computing a basis matrix for a right kernel (rather than computing a vector space), see right_kernel_matrix(), which powers the computations for this method.
EXAMPLES:
sage: A = matrix(QQ, [[0, 0, 1, 2, 2, -5, 3],....:[-1, 5, 2, 2, 1, -7, 5],....:[0, 0, -2, -3, -3, 8, -5],....:[-1, 5, 0, -1, -2, 1, 0]])sage: K = A.right_kernel(); K
Vector space of degree 7 and dimension 4 over Rational Field
Basis matrix:[ 1 0 0 0 -1 -1 -1][ 0 1 0 0 5 5 5]
[ 0 0 1 0 -1 -2 -3][ 0 0 0 1 0 1 1]
sage: A * K.basis_matrix().transpose() == zero_matrix(QQ, 4, 4)
True>>> from sage.all import *>>> A = matrix(QQ, [[Integer(0), Integer(0), Integer(1), Integer(2),␣
˓→Integer(2), -Integer(5), Integer(3)],...
[-Integer(1), Integer(5), Integer(2), Integer(2),␣
˓→Integer(1), -Integer(7), Integer(5)],...
[Integer(0), Integer(0), -Integer(2), -Integer(3), ˓→Integer(3), Integer(8), -Integer(5)],...
[-Integer(1), Integer(5), Integer(0), -Integer(1), ˓→Integer(2), Integer(1), Integer(0)]])>>> K = A.right_kernel(); K
Vector space of degree 7 and dimension 4 over Rational Field
Basis matrix:[ 1 0 0 0 -1 -1 -1][ 0 1 0 0 5 5 5]
[ 0 0 1 0 -1 -2 -3][ 0 0 0 1 0 1 1]>>> A * K.basis_matrix().transpose() == zero_matrix(QQ, Integer(4),␣
˓→Integer(4))
True

The default is basis vectors that form a matrix in echelon form. A “pivot basis” instead has a basis matrix
510

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

where the columns of an identity matrix are in the locations of the non-pivot columns of the original matrix.
This alternate format is available whenever the base ring is a field.
sage: A = matrix(QQ, [[0, 0, 1, 2, 2, -5, 3],....:[-1, 5, 2, 2, 1, -7, 5],....:[0, 0, -2, -3, -3, 8, -5],....:[-1, 5, 0, -1, -2, 1, 0]])sage: A.rref()[ 1 -5 0 0 1 1 -1][ 0 0 1 0 0 -1 1][ 0 0 0 1 1 -2 1][ 0 0 0 0 0 0 0]
sage: A.nonpivots()(1, 4, 5, 6)
sage: K = A.right_kernel(basis= pivot ); K
Vector space of degree 7 and dimension 4 over Rational Field
User basis matrix:[ 5 1 0 0 0 0 0][-1 0 0 -1 1 0 0][-1 0 1 2 0 1 0]
[ 1 0 -1 -1 0 0 1]
sage: A * K.basis_matrix().transpose() == zero_matrix(QQ, 4, 4)
True>>> from sage.all import *>>> A = matrix(QQ, [[Integer(0), Integer(0), Integer(1), Integer(2),␣
˓→Integer(2), -Integer(5), Integer(3)],...
[-Integer(1), Integer(5), Integer(2), Integer(2),␣
˓→Integer(1), -Integer(7), Integer(5)],...
[Integer(0), Integer(0), -Integer(2), -Integer(3), ˓→Integer(3), Integer(8), -Integer(5)],...
[-Integer(1), Integer(5), Integer(0), -Integer(1), ˓→Integer(2), Integer(1), Integer(0)]])>>> A.rref()[ 1 -5 0 0 1 1 -1][ 0 0 1 0 0 -1 1][ 0 0 0 1 1 -2 1][ 0 0 0 0 0 0 0]>>> A.nonpivots()(1, 4, 5, 6)>>> K = A.right_kernel(basis= pivot ); K
Vector space of degree 7 and dimension 4 over Rational Field
User basis matrix:[ 5 1 0 0 0 0 0][-1 0 0 -1 1 0 0][-1 0 1 2 0 1 0]
[ 1 0 -1 -1 0 0 1]>>> A * K.basis_matrix().transpose() == zero_matrix(QQ, Integer(4),␣
˓→Integer(4))
True

Matrices may have any field as a base ring. Number fields are computed by PARI library code, matrices
over 𝐺𝐹 (2) are computed by the M4RI library, and matrices over the rationals are computed by the IML
library. For any of these specialized cases, general-purpose code can be called instead with the keyword
setting algorithm= generic .
Over an arbitrary field, with two basis formats. Same vector space, different bases.

511

Matrices and Spaces of Matrices, Release 10.4

sage: # needs sage.rings.finite_rings
sage: F.<a> = FiniteField(5^2)
sage: A = matrix(F, 3, 4, [[ 1,a,1+a, a^3+a^5],....:[ a, a^4,
a+a^4, a^4+a^8],....:[a^2, a^6, a^2+a^6, a^5+a^10]])sage: K = A.right_kernel(); K
Vector space of degree 4 and dimension 2over Finite Field in a of size 5^2
Basis matrix:[
1
0 3*a + 4 2*a + 2][
01
2*a 3*a + 3]
sage: A * K.basis_matrix().transpose() == zero_matrix(F, 3, 2)
True>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> F = FiniteField(Integer(5)**Integer(2), names=( a ,)); (a,) = F._first_
˓→ngens(1)>>> A = matrix(F, Integer(3), Integer(4), [[ Integer(1),a,␣˓→Integer(1)+a,a**Integer(3)+a**Integer(5)],...
[ a, a**Integer(4),a+a**Integer(4), ␣
˓→a**Integer(4)+a**Integer(8)],...
[a**Integer(2), a**Integer(6),␣
˓→a**Integer(2)+a**Integer(6), a**Integer(5)+a**Integer(10)]])>>> K = A.right_kernel(); K
Vector space of degree 4 and dimension 2over Finite Field in a of size 5^2
Basis matrix:[
1
0 3*a + 4 2*a + 2][
01
2*a 3*a + 3]>>> A * K.basis_matrix().transpose() == zero_matrix(F, Integer(3), Integer(2))
True

In the following test, we have to force usage of Matrix_generic_dense, since the option basis =pivot would simply yield the same result as the previous test, if the optional meataxe package is installed.
sage: from sage.matrix.matrix_generic_dense import Matrix_generic_dense
sage: B = Matrix_generic_dense(A.parent(), A.list(), False, False)
sage: P = B.right_kernel(basis= pivot ); P˓→needs sage.rings.finite_rings
Vector space of degree 4 and dimension 2over Finite Field in a of size 5^2
User basis matrix:
[
4
4
1
0]
[ a + 2 3*a + 3
01]>>> from sage.all import *>>> from sage.matrix.matrix_generic_dense import Matrix_generic_dense>>> B = Matrix_generic_dense(A.parent(), A.list(), False, False)>>> P = B.right_kernel(basis= pivot ); P˓→needs sage.rings.finite_rings
Vector space of degree 4 and dimension 2over Finite Field in a of size 5^2
User basis matrix:
[
4
4
1
0]
[ a + 2 3*a + 3
0
1]

512

#␣

#␣

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

If the optional meataxe package is installed, we again have to make sure to work with a copy of B that has
the same type as P.basis_matrix():
sage: (B.parent()(B.list()) * P.basis_matrix().transpose()
˓→needs sage.rings.finite_rings....:== zero_matrix(F, 3, 2))True
sage: K == P˓→needs sage.rings.finite_rings
True

#␣

#␣

>>> from sage.all import *>>> (B.parent()(B.list()) * P.basis_matrix().transpose()
˓→needs sage.rings.finite_rings...
== zero_matrix(F, Integer(3), Integer(2)))
True>>> K == P˓→needs sage.rings.finite_rings
True

#␣

#␣

Over number fields, PARI is used by default, but general-purpose code can be requested. Same vector space,same bases, different code.:sage: # needs sage.rings.number_fieldsage: Q = QuadraticField(-7)
sage: a = Q.gen(0)sage: A = matrix(Q, [[2, 5 - a,
15 - a, 16 + 4*a],....:[2 + a,a, -7 + 5*a, -3 + 3*a]])sage: K = A.right_kernel(algorithm= default ); K
Vector space of degree 4 and dimension 2over Number Field in a with defining polynomial x^2 + 7 with a = 2.
˓→645751311064591?*I
Basis matrix:[
1
0
7/88*a + 3/88 -3/176*a - 39/176][
01-1/88*a - 13/88 13/176*a - 7/176]
sage: A * K.basis_matrix().transpose() == zero_matrix(Q, 2, 2)
True
sage: B = copy(A)sage: G = A.right_kernel(algorithm= generic ); G
Vector space of degree 4 and dimension 2over Number Field in a with defining polynomial x^2 + 7 with a = 2.
˓→645751311064591?*I
Basis matrix:[
1
0
7/88*a + 3/88 -3/176*a - 39/176][
01-1/88*a - 13/88 13/176*a - 7/176]
sage: B * G.basis_matrix().transpose() == zero_matrix(Q, 2, 2)
True
sage: K == G
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> Q = QuadraticField(-Integer(7))>>> a = Q.gen(Integer(0))>>> A = matrix(Q, [[Integer(2), Integer(5) - a,Integer(15) - a,␣
˓→Integer(16) + Integer(4)*a],...
[Integer(2) + a,a, -Integer(7) + Integer(5)*a, (continues on next page)513

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Integer(3) + Integer(3)*a]])>>> K = A.right_kernel(algorithm= default ); K
Vector space of degree 4 and dimension 2over Number Field in a with defining polynomial x^2 + 7 with a = 2.
˓→645751311064591?*I
Basis matrix:[
1
0
7/88*a + 3/88 -3/176*a - 39/176][
01-1/88*a - 13/88 13/176*a - 7/176]>>> A * K.basis_matrix().transpose() == zero_matrix(Q, Integer(2), Integer(2))
True>>> B = copy(A)>>> G = A.right_kernel(algorithm= generic ); G
Vector space of degree 4 and dimension 2over Number Field in a with defining polynomial x^2 + 7 with a = 2.
˓→645751311064591?*I
Basis matrix:[
1
0
7/88*a + 3/88 -3/176*a - 39/176][
01-1/88*a - 13/88 13/176*a - 7/176]>>> B * G.basis_matrix().transpose() == zero_matrix(Q, Integer(2), Integer(2))
True>>> K == GTrue˓→For matrices over the integers, several options are possible. The basis can be an LLL-reduced basis or anechelon basis. The pivot basis isnot available. A heuristic will decide whether to use a p-adic algorithm
from the IML library or an algorithm from the PARI library. Note how specifying the algorithm can mildly
influence the LLL basis.
sage: A = matrix(ZZ, [[0, -1, -1, 2, 9, 4, -4],....:[-1, 1, 0, -2, -7, -1, 6],....:[2, 0, 1, 0, 1, -5, -2],....:[-1, -1, -1, 3, 10, 10, -9],....:[-1, 2, 0, -3, -7, 1, 6]])sage: A.right_kernel(basis= echelon )Free module of degree 7 and rank 2 over Integer Ring
Echelon basis matrix:[ 1
5 -8
3 -1 -1 -1][ 0 11 -19
5 -2 -3 -3]
sage: B = copy(A)sage: B.right_kernel(basis= LLL )Free module of degree 7 and rank 2 over Integer Ring
User basis matrix:[ 2 -1 3 1 0 1 1][-5 -3 2 -5 1 -1 -1]
sage: C = copy(A)sage: C.right_kernel(basis= pivot )Traceback (most recent call last):...
ValueError: pivot basis only available over a field, not over Integer Ringsage: D = copy(A)sage: D.right_kernel(algorithm= pari )Free module of degree 7 and rank 2 over Integer Ring
Echelon basis matrix:[ 1
5 -8
3 -1 -1 -1][ 0 11 -19
5 -2 -3 -3]
sage: E = copy(A)(continues on next page)

514

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: E.right_kernel(algorithm= padic , basis= LLL )Free module of degree 7 and rank 2 over Integer Ring
User basis matrix:[-2 1 -3 -1 0 -1 -1][ 5 3 -2 5 -1 1 1]>>> from sage.all import *>>> A = matrix(ZZ, [[Integer(0), -Integer(1), -Integer(1), Integer(2),␣
˓→Integer(9), Integer(4), -Integer(4)],...
[-Integer(1), Integer(1), Integer(0), -Integer(2), ˓→Integer(7), -Integer(1), Integer(6)],...
[Integer(2), Integer(0), Integer(1), Integer(0),␣
˓→Integer(1), -Integer(5), -Integer(2)],...
[-Integer(1), -Integer(1), -Integer(1), Integer(3),␣
˓→Integer(10), Integer(10), -Integer(9)],...
[-Integer(1), Integer(2), Integer(0), -Integer(3), ˓→Integer(7), Integer(1), Integer(6)]])>>> A.right_kernel(basis= echelon )Free module of degree 7 and rank 2 over Integer Ring
Echelon basis matrix:[ 1
5 -8
3 -1 -1 -1][ 0 11 -19
5 -2 -3 -3]>>> B = copy(A)>>> B.right_kernel(basis= LLL )Free module of degree 7 and rank 2 over Integer Ring
User basis matrix:[ 2 -1 3 1 0 1 1][-5 -3 2 -5 1 -1 -1]>>> C = copy(A)>>> C.right_kernel(basis= pivot )Traceback (most recent call last):...
ValueError: pivot basis only available over a field, not over Integer Ring>>> D = copy(A)>>> D.right_kernel(algorithm= pari )Free module of degree 7 and rank 2 over Integer Ring
Echelon basis matrix:[ 1
5 -8
3 -1 -1 -1][ 0 11 -19
5 -2 -3 -3]>>> E = copy(A)>>> E.right_kernel(algorithm= padic , basis= LLL )Free module of degree 7 and rank 2 over Integer Ring
User basis matrix:[-2 1 -3 -1 0 -1 -1][ 5 3 -2 5 -1 1 1]

Besides the integers, rings may be as general as principal ideal domains. Results are then free modules.
sage: R.<y> = QQ[]
sage: A = matrix(R, [[ 1,y, 1+y^2],....:[y^3, y^2, 2*y^3]])sage: K = A.right_kernel(algorithm= default , basis= echelon ); K
Free module of degree 3 and rank 1
over Univariate Polynomial Ring in y over Rational Field
Echelon basis matrix:[-1 -y 1](continues on next page)515

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: A * K.basis_matrix().transpose() == zero_matrix(ZZ, 2, 1)
True>>> from sage.all import *>>> R = QQ[ y ]; (y,) = R._first_ngens(1)>>> A = matrix(R, [[ Integer(1),y, Integer(1)+y**Integer(2)],...
[y**Integer(3), y**Integer(2), Integer(2)*y**Integer(3)]])>>> K = A.right_kernel(algorithm= default , basis= echelon ); K
Free module of degree 3 and rank 1
over Univariate Polynomial Ring in y over Rational Field
Echelon basis matrix:[-1 -y 1]>>> A * K.basis_matrix().transpose() == zero_matrix(ZZ, Integer(2),␣
˓→Integer(1))
True

It is possible to compute a kernel for a matrix over an integral domain which is not a PID, but usually thiswill fail.
sage: D.<x> = ZZ[]
sage: A = matrix(D, 2, 2, [[x^2 - x, -x + 5],....:[x^2 - 8, -x + 2]])sage: A.right_kernel()
Traceback (most recent call last):...
ArithmeticError: Ideal Ideal (x^2 - x, x^2 - 8) of Univariate
Polynomial Ring in x over Integer Ring not principal>>> from sage.all import *>>> D = ZZ[ x ]; (x,) = D._first_ngens(1)>>> A = matrix(D, Integer(2), Integer(2), [[x**Integer(2) - x, -x +␣˓→Integer(5)],...
[x**Integer(2) - Integer(8), -x + Integer(2)]])>>> A.right_kernel()
Traceback (most recent call last):...
ArithmeticError: Ideal Ideal (x^2 - x, x^2 - 8) of Univariate
Polynomial Ring in x over Integer Ring not principal

Matrices over non-commutative rings are not a good idea either. These are the “usual” quaternions.
sage: Q.<i,j,k> = QuaternionAlgebra(-1,-1)
sage: A = matrix(Q, 2, [i,j,-1,k])
sage: A.right_kernel()
Traceback (most recent call last):...
NotImplementedError: Cannot compute a matrix kernel over
Quaternion Algebra (-1, -1) with base ring Rational Field>>> from sage.all import *>>> Q = QuaternionAlgebra(-Integer(1),-Integer(1), names=( i ,˓→(i, j, k,) = Q._first_ngens(3)>>> A = matrix(Q, Integer(2), [i,j,-Integer(1),k])>>> A.right_kernel()
Traceback (most recent call last):j ,k ,));␣

(continues on next page)

516

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
NotImplementedError: Cannot compute a matrix kernel over
Quaternion Algebra (-1, -1) with base ring Rational Field

Sparse matrices, over the rationals and the integers, use the same routines as the dense versions.
sage: A = matrix(ZZ, [[0, -1, 1, 1, 2],....:[1, -2, 0, 1, 3],....:[-1, 2, 0, -1, -3]],....:sparse=True)
sage: A.right_kernel()
Free module of degree 5 and rank 3 over Integer Ring
Echelon basis matrix:[ 1 0 0 2 -1][ 0 1 0 -1 1][ 0 0 1 -3 1]
sage: B = A.change_ring(QQ)
sage: B.is_sparse()
True
sage: B.right_kernel()
Vector space of degree 5 and dimension 3 over Rational Field
Basis matrix:[ 1 0 0 2 -1][ 0 1 0 -1 1][ 0 0 1 -3 1]>>> from sage.all import *>>> A = matrix(ZZ, [[Integer(0), -Integer(1), Integer(1), Integer(1),␣
˓→Integer(2)],...
[Integer(1), -Integer(2), Integer(0), Integer(1),␣
˓→Integer(3)],...
[-Integer(1), Integer(2), Integer(0), -Integer(1), ˓→Integer(3)]],...
sparse=True)>>> A.right_kernel()
Free module of degree 5 and rank 3 over Integer Ring
Echelon basis matrix:[ 1 0 0 2 -1][ 0 1 0 -1 1][ 0 0 1 -3 1]>>> B = A.change_ring(QQ)>>> B.is_sparse()
True>>> B.right_kernel()
Vector space of degree 5 and dimension 3 over Rational Field
Basis matrix:[ 1 0 0 2 -1][ 0 1 0 -1 1][ 0 0 1 -3 1]

With no columns, the kernel can only have dimension zero. With no rows, every possible vector is in the
kernel.
sage: A = matrix(QQ, 2, 0)
sage: A.right_kernel()
Vector space of degree 0 and dimension 0 over Rational Field(continues on next page)517

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Basis matrix:[]
sage: A = matrix(QQ, 0, 2)
sage: A.right_kernel()
Vector space of degree 2 and dimension 2 over Rational Field
Basis matrix:
[1 0]
[0 1]
>>> from sage.all import *>>> A = matrix(QQ, Integer(2), Integer(0))>>> A.right_kernel()
Vector space of degree 0 and dimension 0 over Rational Field
Basis matrix:[]>>> A = matrix(QQ, Integer(0), Integer(2))>>> A.right_kernel()
Vector space of degree 2 and dimension 2 over Rational Field
Basis matrix:
[1 0]
[0 1]

Every vector is in the kernel of a zero matrix, the dimension is the number of columns.
sage: A = zero_matrix(QQ, 10, 20)
sage: A.right_kernel()
Vector space of degree 20 and dimension 20 over Rational Field
Basis matrix:
20 x 20 dense matrix over Rational Field>>> from sage.all import *>>> A = zero_matrix(QQ, Integer(10), Integer(20))>>> A.right_kernel()
Vector space of degree 20 and dimension 20 over Rational Field
Basis matrix:
20 x 20 dense matrix over Rational Field

Results are cached as the right kernel of the matrix. Subsequent requests for the right kernel will return thecached result, without regard for new values of the algorithm or format keyword. Work with a copy if you
need a new right kernel, or perhaps investigate the right_kernel_matrix() method, which does notcache its results and is more flexible.
sage: A = matrix(QQ, 3, 3, range(9))
sage: K1 = A.right_kernel(basis= echelon )sage: K1
Vector space of degree 3 and dimension 1 over Rational Field
Basis matrix:[ 1 -2 1]
sage: K2 = A.right_kernel(basis= pivot )sage: K2
Vector space of degree 3 and dimension 1 over Rational Field
Basis matrix:[ 1 -2 1]
sage: K1 is K2
True
sage: B = copy(A)(continues on next page)

518

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: K3 = B.kernel(basis= pivot )sage: K3
Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]
sage: K3 is K1
False
sage: K3 == K1
True>>> from sage.all import *>>> A = matrix(QQ, Integer(3), Integer(3), range(Integer(9)))>>> K1 = A.right_kernel(basis= echelon )>>> K1
Vector space of degree 3 and dimension 1 over Rational Field
Basis matrix:[ 1 -2 1]>>> K2 = A.right_kernel(basis= pivot )>>> K2Vector space of degree 3 and dimension 1 over Rational Field
Basis matrix:[ 1 -2 1]>>> K1 is K2
True>>> B = copy(A)>>> K3 = B.kernel(basis= pivot )>>> K3Vector space of degree 3 and dimension 1 over Rational Field
User basis matrix:[ 1 -2 1]>>> K3 is K1
False>>> K3 == K1
Trueright_kernel_matrix(*args, **kwds)
Returns a matrix whose rows form a basis for the right kernel of self.
INPUT:• algorithm – (default: ‘default’); a keyword that selects the algorithm employed. Allowable values are:– ‘default’ – allows the algorithm to be chosen automatically– ‘generic’ – naive algorithm usable for matrices over any field– ‘flint’ – FLINT library code for matrices over the rationals or the integers– ‘pari’ – PARI library code for matrices over number fields or the integers– ‘padic’ – padic algorithm from IML library for matrices over the rationals and integers– ‘pluq’ – PLUQ matrix factorization for matrices mod 2• basis – (default: ‘default’); a keyword that describes the format of the basis returned. Allowable valuesare:– ‘default’: uses ‘echelon’ over fields; ‘computed’ otherwise.
– ‘echelon’: the basis matrix is returned in echelon form.

519

Matrices and Spaces of Matrices, Release 10.4

– ‘pivot’ : each basis vector is computed from the reduced row-echelon form of self by placing asingle one in a non-pivot column and zeros in the remaining non-pivot columns. Only available formatrices over fields.
– ‘LLL’: an LLL-reduced basis. Only available for matrices over the integers.
– ‘computed’: no work is done to transform the basis, it is returned exactly as provided by whicheverroutine actually computed the basis. Request this for the least possible computation possible, butwith no guarantees about the format of the basis. This option is recommended for inexact rings.
OUTPUT:
A matrix X whose rows are an independent set spanning the right kernel of self.
transpose() is a zero matrix.

So self*X.

The output varies depending on the choice of algorithm and the format chosen by basis.
The results of this routine are not cached, so you can call it again with different options to get possibly different
output (like the basis format). Conversely, repeated calls on the same matrix will always start from scratch.
Note: If you want to get the most basic description of a kernel, with a minimum of overhead, then ask forthe right kernel matrix with the basis format requested as ‘computed’. You are then free to work with theoutput for whatever purpose. For a left kernel, call this method on the transpose of your matrix.
For greater convenience, plus cached results, request an actual vector space or free module withright_kernel() or left_kernel().
EXAMPLES:Over the Rational Numbers:
Kernels are computed by the IML library in _right_kernel_matrix(). Setting the 𝑎𝑙𝑔𝑜𝑟𝑖𝑡ℎ𝑚 keyword to ‘default’, ‘padic’ or unspecified will yield the same result, as there is no optional behavior. The‘computed’ format of the basis vectors are exactly the negatives of the vectors in the ‘pivot’ format.
sage: A = matrix(QQ, [[1, 0, 1, -3, 1],....:[-5, 1, 0, 7, -3],....:
[0, -1, -4, 6, -2],....:
[4, -1, 0, -6, 2]])sage: C = A.right_kernel_matrix(algorithm= default , basis= computed ); C[-1 2 -2 -1 0][ 1 2 0 0 -1]
sage: A * C.transpose() == zero_matrix(QQ, 4, 2)
True
sage: P = A.right_kernel_matrix(algorithm= padic , basis= pivot ); P
[ 1 -2 2 1 0][-1 -2 0 0 1]
sage: A * P.transpose() == zero_matrix(QQ, 4, 2)
True
sage: C == -P
True
sage: E = A.right_kernel_matrix(algorithm= default , basis= echelon ); E[10
1 1/2 -1/2][
0
1 -1/2 -1/4 -1/4]
sage: A * E.transpose() == zero_matrix(QQ, 4, 2)
True

520

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = matrix(QQ, [[Integer(1), Integer(0), Integer(1), -Integer(3),␣
˓→Integer(1)],...
[-Integer(5), Integer(1), Integer(0), Integer(7), ˓→Integer(3)],...
[Integer(0), -Integer(1), -Integer(4), Integer(6), ˓→Integer(2)],...
[Integer(4), -Integer(1), Integer(0), -Integer(6),␣
˓→Integer(2)]])>>> C = A.right_kernel_matrix(algorithm= default , basis= computed ); C[-1 2 -2 -1 0][ 1 2 0 0 -1]>>> A * C.transpose() == zero_matrix(QQ, Integer(4), Integer(2))
True>>> P = A.right_kernel_matrix(algorithm= padic , basis= pivot ); P
[ 1 -2 2 1 0][-1 -2 0 0 1]>>> A * P.transpose() == zero_matrix(QQ, Integer(4), Integer(2))
True>>> C == -P
True>>> E = A.right_kernel_matrix(algorithm= default , basis= echelon ); E[10
1 1/2 -1/2][
0
1 -1/2 -1/4 -1/4]>>> A * E.transpose() == zero_matrix(QQ, Integer(4), Integer(2))
True

Since the rationals are a field, we can call the general code available for any field by using the ‘generic’ keyword.
sage: A = matrix(QQ, [[1, 0, 1, -3, 1],....:[-5, 1, 0, 7, -3],....:
[0, -1, -4, 6, -2],....:
[4, -1, 0, -6, 2]])sage: G = A.right_kernel_matrix(algorithm= generic , basis= echelon ); G[10
1 1/2 -1/2][
0
1 -1/2 -1/4 -1/4]
sage: A * G.transpose() == zero_matrix(QQ, 4, 2)
True>>> from sage.all import *>>> A = matrix(QQ, [[Integer(1), Integer(0), Integer(1), -Integer(3),␣
˓→Integer(1)],...
[-Integer(5), Integer(1), Integer(0), Integer(7), ˓→Integer(3)],...
[Integer(0), -Integer(1), -Integer(4), Integer(6), ˓→Integer(2)],...
[Integer(4), -Integer(1), Integer(0), -Integer(6),␣
˓→Integer(2)]])>>> G = A.right_kernel_matrix(algorithm= generic , basis= echelon ); G[10
1 1/2 -1/2][
0
1 -1/2 -1/4 -1/4]>>> A * G.transpose() == zero_matrix(QQ, Integer(4), Integer(2))
True

We verify that the rational matrix code is called for both dense and sparse rational matrices, with equal result.
sage: A = matrix(QQ, [[1, 0, 1, -3, 1],(continues on next page)521

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)....:[-5, 1, 0, 7, -3],....:
[0, -1, -4, 6, -2],....:
[4, -1, 0, -6, 2]],....:sparse=False)
sage: B = copy(A).sparse_matrix()
sage: from sage.misc.verbose import set_verbose
sage: set_verbose(2)sage: D = A.right_kernel(); Dverbose 2 (<module>) computing a right kernel for 4x5 matrix over Rational␣
˓→Field...
Vector space of degree 5 and dimension 2 over Rational Field
Basis matrix:[
10
1 1/2 -1/2][
0
1 -1/2 -1/4 -1/4]
sage: S = B.right_kernel(); Sverbose 2 (<module>) computing a right kernel for 4x5 matrix over Rational␣
˓→Field...
Vector space of degree 5 and dimension 2 over Rational Field
Basis matrix:[
10
1 1/2 -1/2][
0
1 -1/2 -1/4 -1/4]
sage: set_verbose(0)sage: D == S
True>>> from sage.all import *>>> A = matrix(QQ, [[Integer(1), Integer(0), Integer(1), -Integer(3),␣
˓→Integer(1)],...
[-Integer(5), Integer(1), Integer(0), Integer(7), ˓→Integer(3)],...
[Integer(0), -Integer(1), -Integer(4), Integer(6), ˓→Integer(2)],...
[Integer(4), -Integer(1), Integer(0), -Integer(6),␣
˓→Integer(2)]],...
sparse=False)>>> B = copy(A).sparse_matrix()>>> from sage.misc.verbose import set_verbose>>> set_verbose(Integer(2))>>> D = A.right_kernel(); Dverbose 2 (<module>) computing a right kernel for 4x5 matrix over Rational␣
˓→Field...
Vector space of degree 5 and dimension 2 over Rational Field
Basis matrix:[
10
1 1/2 -1/2][
0
1 -1/2 -1/4 -1/4]>>> S = B.right_kernel(); Sverbose 2 (<module>) computing a right kernel for 4x5 matrix over Rational␣
˓→Field...
Vector space of degree 5 and dimension 2 over Rational Field
Basis matrix:[
10
1 1/2 -1/2][
0
1 -1/2 -1/4 -1/4](continues on next page)522

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> set_verbose(Integer(0))>>> D == S
True

Over Number Fields:
Kernels are by default computed by PARI, (except for exceptions like the rationals themselves). The raw
results from PARI are a pivot basis, so the 𝑏𝑎𝑠𝑖𝑠 keywords ‘computed’ and ‘pivot’ will return the same results.
sage: # needs sage.rings.number_fieldsage: Q = QuadraticField(-7)
sage: a = Q.gen(0)sage: A = matrix(Q, [[2, 5-a, 15-a, 16+4*a],....:[2+a, a, -7 + 5*a, -3+3*a]])sage: C = A.right_kernel_matrix(algorithm= default , basis= computed ); C
[
-a
-3
1
0]
[
-2 -a - 101]
sage: A*C.transpose() == zero_matrix(Q, 2, 2)
True
sage: P = A.right_kernel_matrix(algorithm= pari , basis= pivot ); P˓→needs sage.libs.pari
[
-a
-3
1
0]
[
-2 -a - 101]
sage: A*P.transpose() == zero_matrix(Q, 2, 2)
˓→needs sage.libs.pari
True
sage: E = A.right_kernel_matrix(algorithm= default , basis= echelon ); E[
10
7/88*a + 3/88 -3/176*a - 39/176][
01-1/88*a - 13/88 13/176*a - 7/176]
sage: A*E.transpose() == zero_matrix(Q, 2, 2)
True

#␣

#␣

>>> from sage.all import *>>> # needs sage.rings.number_field>>> Q = QuadraticField(-Integer(7))>>> a = Q.gen(Integer(0))>>> A = matrix(Q, [[Integer(2), Integer(5)-a, Integer(15)-a,␣˓→Integer(16)+Integer(4)*a],...
[Integer(2)+a, a, -Integer(7) + Integer(5)*a, ˓→Integer(3)+Integer(3)*a]])>>> C = A.right_kernel_matrix(algorithm= default , basis= computed ); C
[
-a
-3
1
0]
[
-2 -a - 1
0
1]>>> A*C.transpose() == zero_matrix(Q, Integer(2), Integer(2))
True>>> P = A.right_kernel_matrix(algorithm= pari , basis= pivot ); P#␣˓→needs sage.libs.pari
[
-a
-3
1
0]
[
-2 -a - 1
0
1]>>> A*P.transpose() == zero_matrix(Q, Integer(2), Integer(2))␣˓→# needs sage.libs.pari
True>>> E = A.right_kernel_matrix(algorithm= default , basis= echelon ); E[
10
7/88*a + 3/88 -3/176*a - 39/176][
01-1/88*a - 13/88 13/176*a - 7/176]>>> A*E.transpose() == zero_matrix(Q, Integer(2), Integer(2))
True

523

Matrices and Spaces of Matrices, Release 10.4

We can bypass using PARI for number fields and use Sage’s general code for matrices over any field. The
basis vectors as computed are in pivot format.
sage: # needs sage.rings.number_fieldsage: Q = QuadraticField(-7)
sage: a = Q.gen(0)sage: A = matrix(Q, [[2, 5-a, 15-a, 16+4*a], [2+a, a, -7 + 5*a, -3+3*a]])sage: G = A.right_kernel_matrix(algorithm= generic , basis= computed ); G
[
-a
-3
1
0]
[
-2 -a - 101]
sage: A*G.transpose() == zero_matrix(Q, 2, 2)
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> Q = QuadraticField(-Integer(7))>>> a = Q.gen(Integer(0))>>> A = matrix(Q, [[Integer(2), Integer(5)-a, Integer(15)-a,␣˓→Integer(16)+Integer(4)*a], [Integer(2)+a, a, -Integer(7) + Integer(5)*a, ˓→Integer(3)+Integer(3)*a]])>>> G = A.right_kernel_matrix(algorithm= generic , basis= computed ); G
[
-a
-3
1
0]
[
-2 -a - 1
0
1]>>> A*G.transpose() == zero_matrix(Q, Integer(2), Integer(2))
True

We check that number fields are handled by the right routine as part of typical right kernel computation.
sage: # needs sage.rings.number_fieldsage: Q = QuadraticField(-7)
sage: a = Q.gen(0)sage: A = matrix(Q, [[2, 5-a, 15-a, 16+4*a], [2+a, a, -7 + 5*a, -3+3*a]])sage: set_verbose(2)sage: A.right_kernel(algorithm= default )verbose ...
verbose 2 (<module>) computing right kernel matrix over a number field for␣
˓→2x4 matrix
verbose 2 (<module>) done computing right kernel matrix over a number field␣
˓→for 2x4 matrix...
Vector space of degree 4 and dimension 2 overNumber Field in a with defining polynomial x^2 + 7 with a = 2.
˓→645751311064591?*I
Basis matrix:[
1
0
7/88*a + 3/88 -3/176*a - 39/176][
01-1/88*a - 13/88 13/176*a - 7/176]
sage: set_verbose(0)>>> from sage.all import *>>> # needs sage.rings.number_field>>> Q = QuadraticField(-Integer(7))>>> a = Q.gen(Integer(0))>>> A = matrix(Q, [[Integer(2), Integer(5)-a, Integer(15)-a,␣˓→Integer(16)+Integer(4)*a], [Integer(2)+a, a, -Integer(7) + Integer(5)*a, ˓→Integer(3)+Integer(3)*a]])>>> set_verbose(Integer(2))>>> A.right_kernel(algorithm= default )(continues on next page)524

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

verbose ...
verbose 2 (<module>) computing right kernel matrix over a number field for␣
˓→2x4 matrix
verbose 2 (<module>) done computing right kernel matrix over a number field␣
˓→for 2x4 matrix...
Vector space of degree 4 and dimension 2 overNumber Field in a with defining polynomial x^2 + 7 with a = 2.
˓→645751311064591?*I
Basis matrix:[
1
0
7/88*a + 3/88 -3/176*a - 39/176][
01-1/88*a - 13/88 13/176*a - 7/176]>>> set_verbose(Integer(0))

Over the Finite Field of Order 2:
Kernels are computed by the M4RI library using PLUQ matrix decomposition in the _right_kernel_matrix() method. There are no options for the algorithm used.
sage: A = matrix(GF(2),[[0, 1, 1, 0, 0, 0],....:[1, 0, 0, 0, 1, 1,],....:
[1, 0, 0, 0, 1, 1]])
sage: E = A.right_kernel_matrix(algorithm= default , format= echelon ); E
[1 0 0 0 0 1]
[0 1 1 0 0 0]
[0 0 0 1 0 0]
[0 0 0 0 1 1]
sage: A*E.transpose() == zero_matrix(GF(2), 3, 4)
True>>> from sage.all import *>>> A = matrix(GF(Integer(2)),[[Integer(0), Integer(1), Integer(1),␣
˓→Integer(0), Integer(0), Integer(0)],...
[Integer(1), Integer(0), Integer(0), Integer(0),␣
˓→Integer(1), Integer(1),],...
[Integer(1), Integer(0), Integer(0), Integer(0),␣
˓→Integer(1), Integer(1)]])>>> E = A.right_kernel_matrix(algorithm= default , format= echelon ); E
[1 0 0 0 0 1]
[0 1 1 0 0 0]
[0 0 0 1 0 0]
[0 0 0 0 1 1]>>> A*E.transpose() == zero_matrix(GF(Integer(2)), Integer(3), Integer(4))
True

Since GF(2) is a field we can route this computation to the generic code and obtain the ‘pivot’ form of thebasis. The algorithm keywords, ‘pluq’, ‘default’ and unspecified, all have the same effect as there is no
optional behavior.
sage: A = matrix(GF(2), [[0, 1, 1, 0, 0, 0],....:[1, 0, 0, 0, 1, 1,],....:
[1, 0, 0, 0, 1, 1]])
sage: P = A.right_kernel_matrix(algorithm= generic , basis= pivot ); P
[0 1 1 0 0 0]
[0 0 0 1 0 0]
[1 0 0 0 1 0]
(continues on next page)525

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[1 0 0 0 0 1]
sage: A*P.transpose() == zero_matrix(GF(2), 3, 4)
True
sage: DP = A.right_kernel_matrix(algorithm= default , basis= pivot ); DP[0 1 1 0 0 0]
[0 0 0 1 0 0]
[1 0 0 0 1 0]
[1 0 0 0 0 1]
sage: A*DP.transpose() == zero_matrix(GF(2), 3, 4)
True
sage: A.right_kernel_matrix(algorithm= pluq , basis= echelon )˓→needs sage.libs.m4ri[1 0 0 0 0 1]
[0 1 1 0 0 0]
[0 0 0 1 0 0]
[0 0 0 0 1 1]#␣>>> from sage.all import *>>> A = matrix(GF(Integer(2)), [[Integer(0), Integer(1), Integer(1),␣
˓→Integer(0), Integer(0), Integer(0)],...
[Integer(1), Integer(0), Integer(0), Integer(0),␣
˓→Integer(1), Integer(1),],...
[Integer(1), Integer(0), Integer(0), Integer(0),␣
˓→Integer(1), Integer(1)]])>>> P = A.right_kernel_matrix(algorithm= generic , basis= pivot ); P
[0 1 1 0 0 0]
[0 0 0 1 0 0]
[1 0 0 0 1 0]
[1 0 0 0 0 1]>>> A*P.transpose() == zero_matrix(GF(Integer(2)), Integer(3), Integer(4))
True>>> DP = A.right_kernel_matrix(algorithm= default , basis= pivot ); DP[0 1 1 0 0 0]
[0 0 0 1 0 0]
[1 0 0 0 1 0]
[1 0 0 0 0 1]>>> A*DP.transpose() == zero_matrix(GF(Integer(2)), Integer(3), Integer(4))
True>>> A.right_kernel_matrix(algorithm= pluq , basis= echelon )#␣˓→needs sage.libs.m4ri[1 0 0 0 0 1]
[0 1 1 0 0 0]
[0 0 0 1 0 0]
[0 0 0 0 1 1]

We test that the mod 2 code is called for matrices over GF(2).
sage: A = matrix(GF(2), [[0, 1, 1, 0, 0, 0],....:[1, 0, 0, 0, 1, 1,],....:
[1, 0, 0, 0, 1, 1]])
sage: set_verbose(2)#␣˓→needs sage.rings.finite_rings
sage: A.right_kernel(algorithm= default )verbose ...
verbose ... (<module>) computing right kernel matrix over integers mod 2 for␣
˓→3x6 matrix(continues on next page)

526

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

verbose ... (<module>) done computing right kernel matrix over integers mod 2␣˓→for 3x6 matrix...
Vector space of degree 6 and dimension 4 over Finite Field of size 2
Basis matrix:[1 0 0 0 0 1]
[0 1 1 0 0 0]
[0 0 0 1 0 0]
[0 0 0 0 1 1]
sage: set_verbose(0)>>> from sage.all import *>>> A = matrix(GF(Integer(2)), [[Integer(0), Integer(1), Integer(1),␣
˓→Integer(0), Integer(0), Integer(0)],...
[Integer(1), Integer(0), Integer(0), Integer(0),␣
˓→Integer(1), Integer(1),],...
[Integer(1), Integer(0), Integer(0), Integer(0),␣
˓→Integer(1), Integer(1)]])>>> set_verbose(Integer(2))␣˓→# needs sage.rings.finite_rings>>> A.right_kernel(algorithm= default )verbose ...
verbose ... (<module>) computing right kernel matrix over integers mod 2 for␣
˓→3x6 matrix
verbose ... (<module>) done computing right kernel matrix over integers mod 2␣˓→for 3x6 matrix...
Vector space of degree 6 and dimension 4 over Finite Field of size 2
Basis matrix:[1 0 0 0 0 1]
[0 1 1 0 0 0]
[0 0 0 1 0 0]
[0 0 0 0 1 1]>>> set_verbose(Integer(0))

Over Arbitrary Fields:
For kernels over fields not listed above, totally general code will compute a set of basis vectors in the pivot
format. These could be returned as a basis in echelon form.
sage: # needs sage.rings.finite_rings
sage: F.<a> = FiniteField(5^2)
sage: A = matrix(F, 3, 4, [[ 1,a,1+a, a^3+a^5],....:[ a, a^4,
a+a^4, a^4+a^8],....:[a^2, a^6, a^2+a^6, a^5+a^10]])sage: P = A.right_kernel_matrix(algorithm= default , basis= pivot ); P
[
4
4
1
0]
[ a + 2 3*a + 3
01]
sage: A*P.transpose() == zero_matrix(F, 3, 2)
True
sage: E = A.right_kernel_matrix(algorithm= default , basis= echelon ); E[10 3*a + 4 2*a + 2][
01
2*a 3*a + 3]
sage: A*E.transpose() == zero_matrix(F, 3, 2)
True

527

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> F = FiniteField(Integer(5)**Integer(2), names=( a ,)); (a,) = F._first_
˓→ngens(1)>>> A = matrix(F, Integer(3), Integer(4), [[ Integer(1),a,␣˓→Integer(1)+a,a**Integer(3)+a**Integer(5)],...
[ a, a**Integer(4),a+a**Integer(4), ␣
˓→a**Integer(4)+a**Integer(8)],...
[a**Integer(2), a**Integer(6),␣
˓→a**Integer(2)+a**Integer(6), a**Integer(5)+a**Integer(10)]])>>> P = A.right_kernel_matrix(algorithm= default , basis= pivot ); P
[
4
4
1
0]
[ a + 2 3*a + 3
0
1]>>> A*P.transpose() == zero_matrix(F, Integer(3), Integer(2))
True>>> E = A.right_kernel_matrix(algorithm= default , basis= echelon ); E[10 3*a + 4 2*a + 2][
01
2*a 3*a + 3]>>> A*E.transpose() == zero_matrix(F, Integer(3), Integer(2))
TrueThis general code can be requested for matrices over any field with the algorithm keyword ‘generic’.
Normally, matrices over the rationals would be handled by specific routines from the IML library. The default
format is an echelon basis, but a pivot basis may be requested, which is identical to the computed basis.
sage: A = matrix(QQ, 3, 4, [[1,3,-2,4],....:[2,0,2,2],....:[-1,1,-2,0]])
sage: G = A.right_kernel_matrix(algorithm= generic ); G[1
0 -1/2 -1/2][
0
1 1/2 -1/2]
sage: A*G.transpose() == zero_matrix(QQ, 3, 2)
True
sage: C = A.right_kernel_matrix(algorithm= generic , basis= computed ); C[-1 1 1 0][-1 -1 0 1]
sage: A*C.transpose() == zero_matrix(QQ, 3, 2)
True>>> from sage.all import *>>> A = matrix(QQ, Integer(3), Integer(4), [[Integer(1),Integer(3),˓→Integer(2),Integer(4)],...
[Integer(2),Integer(0),Integer(2),Integer(2)],...
[-Integer(1),Integer(1),-Integer(2),Integer(0)]])>>> G = A.right_kernel_matrix(algorithm= generic ); G[1
0 -1/2 -1/2][
0
1 1/2 -1/2]>>> A*G.transpose() == zero_matrix(QQ, Integer(3), Integer(2))
True>>> C = A.right_kernel_matrix(algorithm= generic , basis= computed ); C[-1 1 1 0][-1 -1 0 1]>>> A*C.transpose() == zero_matrix(QQ, Integer(3), Integer(2))
True

We test that the generic code is called for matrices over fields, lacking any more specific routine.

528

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

sage: # needs sage.rings.finite_rings
sage: F.<a> = FiniteField(5^2)
sage: A = matrix(F, 3, 4, [[ 1,a,1+a, a^3+a^5],....:[ a, a^4,
a+a^4, a^4+a^8],....:[a^2, a^6, a^2+a^6, a^5+a^10]])sage: set_verbose(2)sage: A.right_kernel(algorithm= default )verbose ...
verbose 2 (<module>) computing right kernel matrix over an arbitrary field␣
˓→for 3x4 matrix...
Vector space of degree 4 and dimension 2 over Finite Field in a of size 5^2
Basis matrix:[
1
0 3*a + 4 2*a + 2][
01
2*a 3*a + 3]
sage: set_verbose(0)>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> F = FiniteField(Integer(5)**Integer(2), names=( a ,)); (a,) = F._first_
˓→ngens(1)>>> A = matrix(F, Integer(3), Integer(4), [[ Integer(1),a,␣˓→Integer(1)+a,a**Integer(3)+a**Integer(5)],...
[ a, a**Integer(4),a+a**Integer(4), ␣
˓→a**Integer(4)+a**Integer(8)],...
[a**Integer(2), a**Integer(6),␣
˓→a**Integer(2)+a**Integer(6), a**Integer(5)+a**Integer(10)]])>>> set_verbose(Integer(2))>>> A.right_kernel(algorithm= default )verbose ...
verbose 2 (<module>) computing right kernel matrix over an arbitrary field␣
˓→for 3x4 matrix...
Vector space of degree 4 and dimension 2 over Finite Field in a of size 5^2
Basis matrix:[
1
0 3*a + 4 2*a + 2][
01
2*a 3*a + 3]>>> set_verbose(Integer(0))

Over the Integers:
Either the IML or PARI libraries are used to provide a set of basis vectors. The algorithm keyword can beused to select either, or when set to ‘default’ a heuristic will choose between the two. Results can be returnedin the ‘compute’ format, straight out of the libraries. Unique to the integers, the basis vectors can be returned
as an LLL basis. Note the similarities and differences in the results. The ‘pivot’ format is not available, since
the integers are not a field.
sage: A = matrix(ZZ, [[8, 0, 7, 1, 3, 4, 6],....:[4, 0, 3, 4, 2, 7, 7],....:[1, 4, 6, 1, 2, 8, 5],....:[0, 3, 1, 2, 3, 6, 2]])sage: X = A.right_kernel_matrix(algorithm= default , basis= echelon ); X
[ 1 123 14 -3 -10
1][ 0 35
0 25 -1 -31 17][ 0
0
7 12 -3 -1 -8]
sage: A*X.transpose() == zero_matrix(ZZ, 4, 3)(continues on next page)529

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)True
sage: X = A.right_kernel_matrix(algorithm= padic , basis= LLL ); X
[ -3 -1
5
7
2 -3 -2]
[ 3
1
2
5 -5
2 -6]
[ -4 -13
2 -7
5
7 -3]
sage: A*X.transpose() == zero_matrix(ZZ, 4, 3)
True
sage: # needs sage.libs.pari
sage: X = A.right_kernel_matrix(algorithm= pari , basis= computed ); X
[ 3 1 -5 -7 -2 3 2]
[ 3 1 2 5 -5 2 -6][ 4 13 -2 7 -5 -7 3]
sage: A*X.transpose() == zero_matrix(ZZ, 4, 3)
True
sage: X = A.right_kernel_matrix(algorithm= padic , basis= computed ); X
[ 265 345 -178
17 -29700][-242 -314 163 -14 271-10][ -36 -47
25
-1
40
0
-1]
sage: A*X.transpose() == zero_matrix(ZZ, 4, 3)
True>>> from sage.all import *>>> A = matrix(ZZ, [[Integer(8), Integer(0), Integer(7), Integer(1),␣
˓→Integer(3), Integer(4), Integer(6)],...
[Integer(4), Integer(0), Integer(3), Integer(4),␣
˓→Integer(2), Integer(7), Integer(7)],...
[Integer(1), Integer(4), Integer(6), Integer(1),␣
˓→Integer(2), Integer(8), Integer(5)],...
[Integer(0), Integer(3), Integer(1), Integer(2),␣
˓→Integer(3), Integer(6), Integer(2)]])>>> X = A.right_kernel_matrix(algorithm= default , basis= echelon ); X
[ 1 123 14 -3 -10
1][ 0 35
0 25 -1 -31 17][ 0
0
7 12 -3 -1 -8]>>> A*X.transpose() == zero_matrix(ZZ, Integer(4), Integer(3))
True>>> X = A.right_kernel_matrix(algorithm= padic , basis= LLL ); X
[ -3 -1
5
7
2 -3 -2]
[ 3
1
2
5 -5
2 -6]
[ -4 -13
2 -7
5
7 -3]
>>> A*X.transpose() == zero_matrix(ZZ, Integer(4), Integer(3))
True>>> # needs sage.libs.pari>>> X = A.right_kernel_matrix(algorithm= pari , basis= computed ); X
[ 3 1 -5 -7 -2 3 2]
[ 3 1 2 5 -5 2 -6][ 4 13 -2 7 -5 -7 3]>>> A*X.transpose() == zero_matrix(ZZ, Integer(4), Integer(3))
True(continues on next page)

530

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> X = A.right_kernel_matrix(algorithm= padic , basis= computed ); X
[ 265 345 -178
17 -29700][-242 -314 163 -14 271-10][ -36 -47
25
-1
40
0
-1]
>>> A*X.transpose() == zero_matrix(ZZ, Integer(4), Integer(3))
True

We test that the code for integer matrices is called for matrices defined over the integers, both dense andsparse, with equal result.
sage: A = matrix(ZZ, [[8, 0, 7, 1, 3, 4, 6],....:[4, 0, 3, 4, 2, 7, 7],....:[1, 4, 6, 1, 2, 8, 5],....:[0, 3, 1, 2, 3, 6, 2]],....:sparse=False)
sage: B = copy(A).sparse_matrix()
sage: set_verbose(2)sage: D = A.right_kernel(); Dverbose ... (<module>) computing a right kernel for 4x7 matrix over Integer␣
˓→Ringverbose ... (<module>) computing right kernel matrix over the integers for␣
˓→4x7 matrix...
verbose ... (<module>) done computing right kernel matrix over the integers␣˓→for 4x7 matrix...
Free module of degree 7 and rank 3 over Integer Ring
Echelon basis matrix:[ 1 123 14 -3 -10
1][ 0 35
0 25 -1 -31 17][ 0
0
7 12 -3 -1 -8]
sage: S = B.right_kernel(); Sverbose ... (<module>) computing a right kernel for 4x7 matrix over Integer␣
˓→Ringverbose ... (<module>) computing right kernel matrix over the integers for␣
˓→4x7 matrix...
verbose ... (<module>) done computing right kernel matrix over the integers␣˓→for 4x7 matrix...
Free module of degree 7 and rank 3 over Integer Ring
Echelon basis matrix:[ 1 123 14 -3 -10
1][ 0 35
0 25 -1 -31 17][ 0
0
7 12 -3 -1 -8]
sage: set_verbose(0)sage: D == S
True>>> from sage.all import *>>> A = matrix(ZZ, [[Integer(8), Integer(0), Integer(7), Integer(1),␣
˓→Integer(3), Integer(4), Integer(6)],...
[Integer(4), Integer(0), Integer(3), Integer(4),␣
˓→Integer(2), Integer(7), Integer(7)],...
[Integer(1), Integer(4), Integer(6), Integer(1),␣
˓→Integer(2), Integer(8), Integer(5)],(continues on next page)531

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
[Integer(0), Integer(3), Integer(1), Integer(2),␣
˓→Integer(3), Integer(6), Integer(2)]],...
sparse=False)>>> B = copy(A).sparse_matrix()>>> set_verbose(Integer(2))>>> D = A.right_kernel(); Dverbose ... (<module>) computing a right kernel for 4x7 matrix over Integer␣
˓→Ringverbose ... (<module>) computing right kernel matrix over the integers for␣
˓→4x7 matrix...
verbose ... (<module>) done computing right kernel matrix over the integers␣˓→for 4x7 matrix...
Free module of degree 7 and rank 3 over Integer Ring
Echelon basis matrix:[ 1 123 14 -3 -10
1][ 0 35
0 25 -1 -31 17][ 0
0
7 12 -3 -1 -8]>>> S = B.right_kernel(); Sverbose ... (<module>) computing a right kernel for 4x7 matrix over Integer␣
˓→Ringverbose ... (<module>) computing right kernel matrix over the integers for␣
˓→4x7 matrix...
verbose ... (<module>) done computing right kernel matrix over the integers␣˓→for 4x7 matrix...
Free module of degree 7 and rank 3 over Integer Ring
Echelon basis matrix:[ 1 123 14 -3 -10
1][ 0 35
0 25 -1 -31 17][ 0
0
7 12 -3 -1 -8]>>> set_verbose(Integer(0))>>> D == S
True

Over Principal Ideal Domains:
Kernels can be computed using Smith normal form. Only the default algorithm is available, and the ‘pivot’basis format is not available.
sage: R.<y> = QQ[]
sage: A = matrix(R, [[ 1,y, 1+y^2],....:[y^3, y^2, 2*y^3]])sage: E = A.right_kernel_matrix(algorithm= default , basis= echelon ); E[-1 -y 1]
sage: A*E.transpose() == zero_matrix(ZZ, 2, 1)
True>>> from sage.all import *>>> R = QQ[ y ]; (y,) = R._first_ngens(1)>>> A = matrix(R, [[ Integer(1),y, Integer(1)+y**Integer(2)],...
[y**Integer(3), y**Integer(2), Integer(2)*y**Integer(3)]])>>> E = A.right_kernel_matrix(algorithm= default , basis= echelon ); E[-1 -y 1]>>> A*E.transpose() == zero_matrix(ZZ, Integer(2), Integer(1))(continues on next page)532

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)True

It can be computationally expensive to determine if an integral domain is a principal ideal domain. The Smith
normal form routine can fail for non-PIDs, as in this example.
sage: D.<x> = ZZ[]
sage: A = matrix(D, 2, 2, [[x^2 - x, -x + 5],....:[x^2 - 8, -x + 2]])sage: A.right_kernel_matrix()
Traceback (most recent call last):...
ArithmeticError: Ideal Ideal (x^2 - x, x^2 - 8) of
Univariate Polynomial Ring in x over Integer Ring not principal>>> from sage.all import *>>> D = ZZ[ x ]; (x,) = D._first_ngens(1)>>> A = matrix(D, Integer(2), Integer(2), [[x**Integer(2) - x, -x +␣˓→Integer(5)],...
[x**Integer(2) - Integer(8), -x + Integer(2)]])>>> A.right_kernel_matrix()
Traceback (most recent call last):...
ArithmeticError: Ideal Ideal (x^2 - x, x^2 - 8) of
Univariate Polynomial Ring in x over Integer Ring not principal

We test that the domain code is called for domains that lack any extra structure.
sage: R.<y> = QQ[]
sage: A = matrix(R, [[ 1,y, 1+y^2],....:[y^3, y^2, 2*y^3]])sage: set_verbose(2)sage: A.right_kernel(algorithm= default , basis= echelon )verbose ...
verbose 2 (<module>) computing right kernel matrix over a domain for 2x3␣˓→matrix
verbose 2 (<module>) done computing right kernel matrix over a domain for 2x3␣˓→matrix...
Free module of degree 3 and rank 1 over
Univariate Polynomial Ring in y over Rational Field
Echelon basis matrix:[-1 -y 1]
sage: set_verbose(0)>>> from sage.all import *>>> R = QQ[ y ]; (y,) = R._first_ngens(1)>>> A = matrix(R, [[ Integer(1),y, Integer(1)+y**Integer(2)],...
[y**Integer(3), y**Integer(2), Integer(2)*y**Integer(3)]])>>> set_verbose(Integer(2))>>> A.right_kernel(algorithm= default , basis= echelon )verbose ...
verbose 2 (<module>) computing right kernel matrix over a domain for 2x3␣˓→matrix
verbose 2 (<module>) done computing right kernel matrix over a domain for 2x3␣˓→matrix...
(continues on next page)533

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Free module of degree 3 and rank 1 over
Univariate Polynomial Ring in y over Rational Field
Echelon basis matrix:[-1 -y 1]>>> set_verbose(Integer(0))

Over inexact rings:
For inexact rings one should avoid echolonizing if possible:
sage: A = Matrix(....: [[
0.0,
0.5, 0.8090169944],....: [
0.0,
0.5, -0.8090169944],....: [
0.0,
-0.5, 0.8090169944],....: [
0.0,
-0.5, -0.8090169944],....: [
0.5, 0.8090169944,
0.0],....: [
0.5, -0.8090169944,
0.0],....: [
-0.5, 0.8090169944,
0.0],....: [
-0.5, -0.8090169944,
0.0],....: [ 0.8090169944,
0.0,
0.5],
....: [-0.8090169944,
0.0,
0.5],
....: [ 0.8090169944,
0.0,-0.5],....: [-0.8090169944,
0.0,-0.5]]).transpose()sage: (A * A.right_kernel_matrix().transpose()).norm() > 2
Truesage: (A * A.right_kernel_matrix(basis= computed ).transpose()).norm() < 1e-15
True>>> from sage.all import *>>> A = Matrix(... [[RealNumber( 0.0 ),RealNumber( 0.5 ), RealNumber(
˓→ 0.8090169944 )],... [RealNumber( 0.0 ),RealNumber( 0.5 ), -RealNumber(
˓→ 0.8090169944 )],... [RealNumber( 0.0 ),-RealNumber( 0.5 ), RealNumber(
˓→ 0.8090169944 )],... [RealNumber( 0.0 ),-RealNumber( 0.5 ), -RealNumber(
˓→ 0.8090169944 )],... [RealNumber( 0.5 ), RealNumber( 0.8090169944 ),␣
˓→RealNumber( 0.0 )],... [RealNumber( 0.5 ), -RealNumber( 0.8090169944 ),␣
˓→RealNumber( 0.0 )],... [-RealNumber( 0.5 ), RealNumber( 0.8090169944 ),␣
˓→RealNumber( 0.0 )],... [-RealNumber( 0.5 ), -RealNumber( 0.8090169944 ),␣
˓→RealNumber( 0.0 )],... [ RealNumber( 0.8090169944 ),RealNumber( 0.0 ),␣
˓→RealNumber( 0.5 )],... [-RealNumber( 0.8090169944 ),RealNumber( 0.0 ),␣
˓→RealNumber( 0.5 )],... [ RealNumber( 0.8090169944 ),RealNumber( 0.0 ),˓→RealNumber( 0.5 )],... [-RealNumber( 0.8090169944 ),RealNumber( 0.0 ),˓→RealNumber( 0.5 )]]).transpose()>>> (A * A.right_kernel_matrix().transpose()).norm() > Integer(2)True>>> (A * A.right_kernel_matrix(basis= computed ).transpose()).norm() <␣(continues on next page)534

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

RealNumber( 1e-15 )True˓→Trivial Cases:
We test two trivial cases. Any possible values for the keywords (algorithm, basis) will return identicalresults.
sage: A = matrix(ZZ, 0, 2)
sage: A.right_kernel_matrix()
[1 0]
[0 1]
sage: A = matrix(FiniteField(7), 2, 0)
sage: A.right_kernel_matrix().parent()
Full MatrixSpace of 0 by 0 dense matrices over Finite Field of size 7>>> from sage.all import *>>> A = matrix(ZZ, Integer(0), Integer(2))>>> A.right_kernel_matrix()
[1 0]
[0 1]
>>> A = matrix(FiniteField(Integer(7)), Integer(2), Integer(0))>>> A.right_kernel_matrix().parent()
Full MatrixSpace of 0 by 0 dense matrices over Finite Field of size 7

right_nullity()
Return the right nullity of this matrix, which is the dimension of the right kernel.
EXAMPLES:
sage: A = MatrixSpace(QQ,3,2)(range(6))
sage: A.right_nullity()0>>> from sage.all import *>>> A = MatrixSpace(QQ,Integer(3),Integer(2))(range(Integer(6)))>>> A.right_nullity()0sage: A = matrix(ZZ,3,3,range(9))
sage: A.right_nullity()1>>> from sage.all import *>>> A = matrix(ZZ,Integer(3),Integer(3),range(Integer(9)))>>> A.right_nullity()1

rook_vector(algorithm=None, complement=False, use_complement=None)
Return the rook vector of this matrix.
Let 𝐴 be an 𝑚 by 𝑛 (0,1)-matrix. We identify 𝐴 with a chessboard where rooks can be placed on the fields(𝑖, 𝑗) with 𝐴𝑖,𝑗 = 1. The number 𝑟𝑘 = 𝑝𝑘 (𝐴) (the permanental 𝑘-minor) counts the number of ways toplace 𝑘 rooks on this board so that no rook can attack another.

535

Matrices and Spaces of Matrices, Release 10.4

The rook vector of the matrix 𝐴 is the list consisting of 𝑟0 , 𝑟1 , . . . , 𝑟ℎ , where ℎ = 𝑚𝑖𝑛(𝑚, 𝑛). The rook∑︀ℎpolynomial is defined by 𝑟(𝑥) = 𝑘=0 𝑟𝑘 𝑥𝑘 .
The rook vector can be generalized to matrices defined over any rings using permanental minors. Among theavailable algorithms, only “Godsil” needs the condition on the entries to be either 0 or 1.
See Wikipedia article Rook_polynomial for more information and also the method permanental_minor() to compute individual permanental minor.
See also sage.matrix.matrix2.permanental_minor_polynomial and the graph method
matching_polynomial.
INPUT:• self – an 𝑚 by 𝑛 matrix• algorithm – a string which must be either “Ryser” or “ButeraPernici” (default) or “Godsil”; Ryser
one might be faster on simple and small instances. Godsil only accepts input in 0,1.
• complement – boolean (default: False) whether we consider the rook vector of the complement
matrix. If set to True then the matrix must have entries in {0, 1} and the complement matrix is the one
for which the 0’s are replaced by 1’s and 1’s by 0’s.
• use_complement – Boolean (default: None) whether to compute the rook vector of a (0,1)-matrix
from its complement. By default this is determined by the density of ones in the matrix.
EXAMPLES:
The standard chessboard is an 8 by 8 grid in which any positions is allowed. In that case one gets that the
number of ways to position 4 non-attacking rooks is 117600 while for 8 rooks it is 40320:
sage: ones_matrix(8,8).rook_vector()[1, 64, 1568, 18816, 117600, 376320, 564480, 322560, 40320]>>> from sage.all import *>>> ones_matrix(Integer(8),Integer(8)).rook_vector()[1, 64, 1568, 18816, 117600, 376320, 564480, 322560, 40320]

These numbers are the coefficients of a modified Laguerre polynomial:
sage: x = polygen(QQ)
sage: factorial(8) * laguerre(8,-x)
˓→needs sage.symbolicx^8 + 64*x^7 + 1568*x^6 + 18816*x^5 + 117600*x^4 + 376320*x^3 +564480*x^2 + 322560*x + 40320>>> from sage.all import *>>> x = polygen(QQ)>>> factorial(Integer(8)) * laguerre(Integer(8),-x)
˓→# needs sage.symbolicx^8 + 64*x^7 + 1568*x^6 + 18816*x^5 + 117600*x^4 + 376320*x^3 +564480*x^2 + 322560*x + 40320#␣␣

The number of derangements of length 𝑛 is the permanent of a matrix with 0 on the diagonal and 1 elsewhere;
for 𝑛 = 21 it is 18795307255050944540 (see OEIS sequence A000166):
sage:
A
=
identity_matrix(21)sage:
A.rook_vector(complement=True)[-1]
18795307255050944540 sage:
Derangements(21).cardinality() # needs sage.combinat
18795307255050944540
An other example that we convert into a rook polynomial:
536

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

sage: A = matrix(3,6, [1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1])
sage: A
[1 1 1 1 0 0]
[0 1 1 1 1 0]
[0 0 1 1 1 1]
sage: A.rook_vector()[1, 12, 40, 36]
sage: R = PolynomialRing(ZZ,
sage: R(A.rook_vector())
36*x^3 + 40*x^2 + 12*x + 1

x )>>> from sage.all import *>>> A = matrix(Integer(3),Integer(6), [Integer(1),Integer(1),Integer(1),˓→Integer(1),Integer(0),Integer(0),Integer(0),Integer(1),Integer(1),˓→Integer(1),Integer(1),Integer(0),Integer(0),Integer(0),Integer(1),˓→Integer(1),Integer(1),Integer(1)])>>> A[1 1 1 1 0 0]
[0 1 1 1 1 0]
[0 0 1 1 1 1]>>> A.rook_vector()[1, 12, 40, 36]>>> R = PolynomialRing(ZZ,>>> R(A.rook_vector())
36*x^3 + 40*x^2 + 12*x + 1

x )Different algorithms are available:
sage: A = matrix([[1,0,0,1],[0,1,1,0],[0,1,1,0],[1,0,0,1]])
sage: A.rook_vector(algorithm="ButeraPernici")[1, 8, 20, 16, 4]
sage: A.rook_vector(algorithm="Ryser")[1, 8, 20, 16, 4]
sage: A.rook_vector(algorithm="Godsil")
˓→needs sage.graphs sage.libs.flint[1, 8, 20, 16, 4]#␣>>> from sage.all import *>>> A = matrix([[Integer(1),Integer(0),Integer(0),Integer(1)],[Integer(0),˓→Integer(1),Integer(1),Integer(0)],[Integer(0),Integer(1),Integer(1),˓→Integer(0)],[Integer(1),Integer(0),Integer(0),Integer(1)]])>>> A.rook_vector(algorithm="ButeraPernici")[1, 8, 20, 16, 4]>>> A.rook_vector(algorithm="Ryser")[1, 8, 20, 16, 4]>>> A.rook_vector(algorithm="Godsil")#␣˓→needs sage.graphs sage.libs.flint[1, 8, 20, 16, 4]

When the matrix 𝐴 has more ones then zeroes it is usually faster to compute the rook polynomial of thecomplementary matrix, with zeroes and ones interchanged, and use the inclusion-exclusion theorem, giving
for a 𝑚 × 𝑛 matrix 𝐴 with complementary matrix 𝐵
𝑟𝑘 (𝐴) =

(︂
)︂(︂
)︂
𝑘
∑︁
𝑚−𝑗
𝑛−𝑗
(−1)𝑗
(𝑘 − 𝑗)!𝑟𝑗 (𝐵)
𝑘−𝑗
𝑘−𝑗
𝑗=0
537

Matrices and Spaces of Matrices, Release 10.4

see [Rio1958] or the introductory text [AS2011]. This can be done setting the argument use_complement
to True.
An example with an exotic matrix (for which only Butera-Pernici and Ryser algorithms are available):sage: R.<x,y> = PolynomialRing(GF(5))
sage: A = matrix(R, [[1, x, y], [x*y, x**2+y, 0]])sage: A.rook_vector(algorithm="ButeraPernici")[1, x^2 + x*y + x + 2*y + 1, 2*x^2*y + x*y^2 + x^2 + y^2 + y]sage: A.rook_vector(algorithm="Ryser")[1, x^2 + x*y + x + 2*y + 1, 2*x^2*y + x*y^2 + x^2 + y^2 + y]sage: A.rook_vector(algorithm="Godsil")Traceback (most recent call last):...
ValueError: coefficients must be zero or one, but we have x in position (0,˓→1).
sage: B = A.transpose()sage: B.rook_vector(algorithm="ButeraPernici")[1, x^2 + x*y + x + 2*y + 1, 2*x^2*y + x*y^2 + x^2 + y^2 + y]sage: B.rook_vector(algorithm="Ryser")[1, x^2 + x*y + x + 2*y + 1, 2*x^2*y + x*y^2 + x^2 + y^2 + y]>>> from sage.all import *>>> R = PolynomialRing(GF(Integer(5)), names=( x , y ,)); (x, y,) = R._first_
˓→ngens(2)>>> A = matrix(R, [[Integer(1), x, y], [x*y, x**Integer(2)+y, Integer(0)]])>>> A.rook_vector(algorithm="ButeraPernici")[1, x^2 + x*y + x + 2*y + 1, 2*x^2*y + x*y^2 + x^2 + y^2 + y]>>> A.rook_vector(algorithm="Ryser")[1, x^2 + x*y + x + 2*y + 1, 2*x^2*y + x*y^2 + x^2 + y^2 + y]>>> A.rook_vector(algorithm="Godsil")Traceback (most recent call last):...
ValueError: coefficients must be zero or one, but we have x in position (0,˓→1).
>>> B = A.transpose()>>> B.rook_vector(algorithm="ButeraPernici")[1, x^2 + x*y + x + 2*y + 1, 2*x^2*y + x*y^2 + x^2 + y^2 + y]>>> B.rook_vector(algorithm="Ryser")[1, x^2 + x*y + x + 2*y + 1, 2*x^2*y + x*y^2 + x^2 + y^2 + y]

row_module(base_ring=None)
Return the free module over the base ring spanned by the rows of self.
EXAMPLES:
sage: A = MatrixSpace(IntegerRing(), 2)([1,2,3,4])
sage: A.row_module()
Free module of degree 2 and rank 2 over Integer Ring
Echelon basis matrix:
[1 0]
[0 2]
>>> from sage.all import *>>> A = MatrixSpace(IntegerRing(), Integer(2))([Integer(1),Integer(2),˓→Integer(3),Integer(4)])>>> A.row_module()
Free module of degree 2 and rank 2 over Integer Ring
(continues on next page)

538

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Echelon basis matrix:
[1 0]
[0 2]

row_space(base_ring=None)
Return the row space of this matrix. (Synonym for self.row_module().)
EXAMPLES:
sage: t = matrix(QQ, 3, 3, range(9)); t[0 1 2][3 4 5][6 7 8]sage: t.row_space()
Vector space of degree 3 and dimension 2 over Rational Field
Basis matrix:[ 1 0 -1]
[ 0 1 2]>>> from sage.all import *>>> t = matrix(QQ, Integer(3), Integer(3), range(Integer(9))); t[0 1 2][3 4 5][6 7 8]>>> t.row_space()
Vector space of degree 3 and dimension 2 over Rational Field
Basis matrix:[ 1 0 -1]
[ 0 1 2]sage: m = Matrix(Integers(5),2,2,[2,2,2,2])
sage: m.row_space()
Vector space of degree 2 and dimension 1 over Ring of integers modulo 5
Basis matrix:[1 1]>>> from sage.all import *>>> m = Matrix(Integers(Integer(5)),Integer(2),Integer(2),[Integer(2),˓→Integer(2),Integer(2),Integer(2)])>>> m.row_space()
Vector space of degree 2 and dimension 1 over Ring of integers modulo 5
Basis matrix:[1 1]

rref(*args, **kwds)
Return the reduced row echelon form of the matrix, considered as a matrix over a field.
If the matrix is over a ring, then an equivalent matrix is constructed over the fraction field, and then row
reduced.
All arguments are passed on to echelon_form().
Note: Because the matrix is viewed as a matrix over a field, every leading coefficient of the returned matrix
will be one and will be the only nonzero entry in its column.

539

Matrices and Spaces of Matrices, Release 10.4

EXAMPLES:
sage: A = matrix(3,range(9)); A[0 1 2][3 4 5][6 7 8]sage: A.rref()[ 1 0 -1]
[ 0 1 2][ 0 0 0]>>> from sage.all import *>>> A = matrix(Integer(3),range(Integer(9))); A[0 1 2][3 4 5][6 7 8]>>> A.rref()[ 1 0 -1]
[ 0 1 2][ 0 0 0]Note that there is a difference between rref() and echelon_form() when the matrix is not over a field(in this case, the integers instead of the rational numbers):
sage: A.base_ring()
Integer Ringsage: A.echelon_form()[ 3 0 -3]
[ 0 1 2][ 0 0 0]sage: B = random_matrix(QQ, 3, num_bound=10)
sage: while B.rank() != 3:....:
B = random_matrix(QQ, 3, num_bound=10)
sage: B.rref()[1 0 0][0 1 0][0 0 1]>>> from sage.all import *>>> A.base_ring()
Integer Ring>>> A.echelon_form()[ 3 0 -3]
[ 0 1 2][ 0 0 0]>>> B = random_matrix(QQ, Integer(3), num_bound=Integer(10))>>> while B.rank() != Integer(3):...
B = random_matrix(QQ, Integer(3), num_bound=Integer(10))>>> B.rref()[1 0 0][0 1 0][0 0 1]In this case, since B is a matrix over a field (the rational numbers), rref() and echelon_form() areexactly the same:

540

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

sage: B.echelon_form()[1 0 0][0 1 0][0 0 1]
sage: B.echelon_form() is B.rref()True>>> from sage.all import *>>> B.echelon_form()[1 0 0][0 1 0][0 0 1]>>> B.echelon_form() is B.rref()True

Since echelon_form() is not implemented for every ring, sometimes behavior varies, as here:
sage: R.<x> = ZZ[]
sage: C = matrix(3, [2,x,x^2, x+1,3-x,-1, 3,2,1])
sage: C.rref()[1 0 0][0 1 0][0 0 1]
sage: C.base_ring()
Univariate Polynomial Ring in x over Integer Ringsage: C.echelon_form()
Traceback (most recent call last):...
NotImplementedError: Ideal Ideal (2, x + 1) of Univariate
Polynomial Ring in x over Integer Ring not principal
Echelon form not implemented over Univariate Polynomial Ring in x over␣
˓→Integer Ring .
sage: C = matrix(3,[2,x,x^2,x+1,3-x,-1,3,2,1/2])
sage: C.echelon_form()
[
2
x
␣
˓→
x^2]
[
0
1
␣
˓→15*x^2 - 3/2*x - 31/2][
0
0 5/2*x^3 -␣
˓→15/4*x^2 - 9/4*x + 7/2]
sage: C.rref()[1 0 0][0 1 0][0 0 1]
sage: C = matrix(3, [2,x,x^2, x+1,3-x,-1/x, 3,2,1/2])
sage: C.echelon_form()[1 0 0][0 1 0][0 0 1]>>> from sage.all import *>>> R = ZZ[ x ]; (x,) = R._first_ngens(1)>>> C = matrix(Integer(3), [Integer(2),x,x**Integer(2), x+Integer(1),˓→Integer(3)-x,-Integer(1), Integer(3),Integer(2),Integer(1)])>>> C.rref()[1 0 0][0 1 0](continues on next page)541

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 0 1]>>> C.base_ring()
Univariate Polynomial Ring in x over Integer Ring>>> C.echelon_form()
Traceback (most recent call last):...
NotImplementedError: Ideal Ideal (2, x + 1) of Univariate
Polynomial Ring in x over Integer Ring not principal
Echelon form not implemented over Univariate Polynomial Ring in x over␣
˓→Integer Ring .
>>> C = matrix(Integer(3),[Integer(2),x,x**Integer(2),x+Integer(1),Integer(3)˓→x,-Integer(1),Integer(3),Integer(2),Integer(1)/Integer(2)])>>> C.echelon_form()
[
2
x
␣
˓→
x^2]
[
0
1
␣
˓→15*x^2 - 3/2*x - 31/2][
0
0 5/2*x^3 -␣
˓→15/4*x^2 - 9/4*x + 7/2]>>> C.rref()[1 0 0][0 1 0][0 0 1]>>> C = matrix(Integer(3), [Integer(2),x,x**Integer(2), x+Integer(1),˓→Integer(3)-x,-Integer(1)/x, Integer(3),Integer(2),Integer(1)/Integer(2)])>>> C.echelon_form()[1 0 0][0 1 0][0 0 1]

set_block(row, col, block)Sets the sub-matrix of self, with upper left corner given by row, col to block.
EXAMPLES:
sage: A = matrix(QQ, 3, 3, range(9))/2
sage: B = matrix(ZZ, 2, 1, [100,200])
sage: A.set_block(0, 1, B)
sage: A[ 0 1001][3/2 200 5/2]
[ 3 7/2
4]>>> from sage.all import *>>> A = matrix(QQ, Integer(3), Integer(3), range(Integer(9)))/Integer(2)>>> B = matrix(ZZ, Integer(2), Integer(1), [Integer(100),Integer(200)])>>> A.set_block(Integer(0), Integer(1), B)>>> A[ 0 1001][3/2 200 5/2]
[ 3 7/2
4]

We test that an exception is raised when the block is out of bounds:
sage: matrix([1]).set_block(0,1,matrix([1]))Traceback (most recent call last):(continues on next page)542

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
IndexError: matrix window index out of range>>> from sage.all import *>>> matrix([Integer(1)]).set_block(Integer(0),Integer(1),matrix([Integer(1)]))
Traceback (most recent call last):...
IndexError: matrix window index out of range

smith_form(transformation=True, integral=None, exact=True)
Return a Smith normal form of this matrix.
For a matrix 𝑀 , a Smith normal form is a matrix 𝑆 = 𝑈 𝑀 𝑉 such that:• 𝑈 and 𝑉 are invertible matrices• the only non-vanishing entries of 𝑆 are located on the diagonal (though 𝑆 might not be a square matrix)• if 𝑑𝑖 denotes the entry of 𝑆 at (𝑖, 𝑖), then 𝑑𝑖 divides 𝑑𝑖+1 for all 𝑖, i.e., the 𝑑𝑖 are the ordered elementary_divisors() of 𝑀
Note that the matrices 𝑈 and 𝑉 are not uniquely determined and the 𝑑𝑖 are only uniquely determined up tounits. For some base rings, such as local rings, the 𝑑𝑖 might be further normalized, see LOCAL RINGS
below.
If the base ring is not a PID, the routine might work, or else it will fail having found an example of anon-principal ideal. Note that we do not call any methods to check whether or not the base ring is a PID,
since this might be quite expensive (e.g. for rings of integers of number fields of large degree).
INPUT:• transformation – a boolean (default: True); whether the matrices 𝑈 and 𝑉 should be returned• integral – a subring of the base ring, boolean or None (default: None); the entries of 𝑈 and 𝑉 are
taken from this subring. If True, the ring is taken to be the ring of integers of the base ring; if False
the fraction field of the base ring; if None the base ring itself. When a subring is specified, multiplying
by the denominator must map the entries into the subring; in this case the transformation matrices will
have entries in this subring.
• exact – a boolean (default: True), only used for local rings/fields. See LOCAL RINGS for moredetails.
OUTPUT:
The matrices 𝑆, 𝑈, 𝑉 or the matrix 𝑆 depending on transformation.
ALGORITHM:
If the base ring has a method _matrix_smith_form, use it; note that _matrix_smith_form mightchoose to further normalize the output.
Otherwise, use the algorithm from Wikipedia article Smith_normal_form.
LOCAL RINGS:Over local rings, we normalize 𝑆 to only contain powers of the uniformizer.
In order to simplify the precision handling, we truncate the absolute precision of the input matrix to theminimum absolute precision of any of its entries. As long as all of the elementary divisors are nonzero
modulo this precision, they can be determined exactly since they are defined to be powers of the uniformizer.
In this case, which is specified by the keyword exact=True, one of the transformation matrices will beinexact: 𝑈 in the case that the number of rows is at least the number of columns, and 𝑉 otherwise.
543

Matrices and Spaces of Matrices, Release 10.4

If exact=False, we instead return an inexact Smith form. Now the transformation matrices are exact andwe can deal gracefully with elementary divisors that are zero modulo the working precision. However, theoff-diagonal entries of the smith form carry a precision that can affect the precision of future calculations.
See _matrix_smith_form on the base ring for more detail.
EXAMPLES:
An example over the ring of integers of a number field (of class number 1):
sage: # needs sage.rings.number_fieldsage: x = polygen(ZZ, x )sage: OE.<w> = EquationOrder(x^2 - x + 2)
sage: m = Matrix([[1, w], [w, 7]])sage: d, u, v = m.smith_form()
sage: (d, u, v)([
10] [ 1 0] [ 1 -w][
0 -w + 9], [-w 1], [ 0 1])
sage: u * m * v == dTruesage: u.base_ring() == v.base_ring() == d.base_ring() == OE
True
sage: u.det().is_unit() and v.det().is_unit()
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> x = polygen(ZZ, x )>>> OE = EquationOrder(x**Integer(2) - x + Integer(2), names=( w ,)); (w,) =␣
˓→OE._first_ngens(1)>>> m = Matrix([[Integer(1), w], [w, Integer(7)]])>>> d, u, v = m.smith_form()>>> (d, u, v)([
10] [ 1 0] [ 1 -w][
0 -w + 9], [-w 1], [ 0 1])>>> u * m * v == dTrue>>> u.base_ring() == v.base_ring() == d.base_ring() == OE
True>>> u.det().is_unit() and v.det().is_unit()
True

An example over the polynomial ring QQ[x]:sage: R.<x> = QQ[]; m = x*matrix(R, 2, 2, 1) - matrix(R, 2, 2, [3,-4,1,-1])
sage: m.smith_form()
(
[
1
0] [
0
-1] [
1 x + 1][
0 x^2 - 2*x + 1], [1 x - 3], [0
1])>>> from sage.all import *>>> R = QQ[ x ]; (x,) = R._first_ngens(1); m = x*matrix(R, Integer(2),␣
˓→Integer(2), Integer(1)) - matrix(R, Integer(2), Integer(2), [Integer(3),(continues on next page)544

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Integer(4),Integer(1),-Integer(1)])>>> m.smith_form()
(
[
1
0] [
0
-1] [
[
0 x^2 - 2*x + 1], [1 x - 3], [)˓→

1 x + 1]0
1]

An example over a field:
sage: m = matrix(GF(17), 3, 3, [11,5,1, 3,6,8, 1,16,0])
sage: d, u, v = m.smith_form()
sage: d[1 0 0][0 1 0][0 0 0]sage: u * m * v == dTrue>>> from sage.all import *>>> m = matrix(GF(Integer(17)), Integer(3), Integer(3), [Integer(11),
˓→Integer(5),Integer(1), Integer(3),Integer(6),Integer(8), Integer(1),˓→Integer(16),Integer(0)])>>> d, u, v = m.smith_form()>>> d[1 0 0][0 1 0][0 0 0]>>> u * m * v == dTrue

When the base ring has a ring_of_integers method and supports denominators, you can get an integral
version of the smith form:
sage: m = matrix(QQ, 2, 2, [17/6, 47/6, 25/6, 23/2])
sage: m.smith_form()([1 0] [6/170] [1 -47/17][0 1], [ 75 -51], [0
1])
sage: m.smith_form(integral=True)([1/60] [ 3 -2] [ 1 3]
[ 0 1/3], [-25 17], [ 0 -1])>>> from sage.all import *>>> m = matrix(QQ, Integer(2), Integer(2), [Integer(17)/Integer(6),␣
˓→Integer(47)/Integer(6), Integer(25)/Integer(6), Integer(23)/Integer(2)])>>> m.smith_form()([1 0] [6/170] [1 -47/17][0 1], [ 75 -51], [0
1])>>> m.smith_form(integral=True)([1/60] [ 3 -2] [ 1 3]
(continues on next page)545

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[)

0 1/3], [-2517], [ 0 -1]

Some examples over non-PID’s work anyway:
sage: # needs sage.rings.number_fieldsage: R.
 = EquationOrder(x^2 + 5) # class number 2
sage: A = matrix(R, 2, 2, [s - 1, -s, -s, 2*s + 1])
sage: D, U, V = A.smith_form()
sage: D, U, V
(
[
1
0] [
4 s + 4] [1 -5*s + 6][
0 -s - 6], [s s - 1], [0
1])
sage: D == U * A * V
True>>> from sage.all import *>>> # needs sage.rings.number_field>>> R = EquationOrder(x**Integer(2) + Integer(5), names=( s ,)); (s,) = R._
˓→first_ngens(1)# class number 2>>> A = matrix(R, Integer(2), Integer(2), [s - Integer(1), -s, -s,␣˓→Integer(2)*s + Integer(1)])>>> D, U, V = A.smith_form()>>> D, U, V
(
[
1
0] [
4 s + 4] [1 -5*s + 6][
0 -s - 6], [s s - 1], [0
1])>>> D == U * A * V
True

Others don’t, but they fail quite constructively:
sage: matrix(R, 2, 2, [s - 1, -s - 2, -2*s, -s - 2]).smith_form()
˓→needs sage.rings.number_field
Traceback (most recent call last):...
ArithmeticError: Ideal Fractional ideal (2, s + 1) not principal#␣>>> from sage.all import *>>> matrix(R, Integer(2), Integer(2), [s - Integer(1), -s - Integer(2), ˓→Integer(2)*s, -s - Integer(2)]).smith_form()# needs sage.rings.
˓→number_field
Traceback (most recent call last):...
ArithmeticError: Ideal Fractional ideal (2, s + 1) not principal

Empty matrices are handled safely:
sage: # needs sage.rings.number_fieldsage: m = MatrixSpace(OE, 2,0)(0)sage: d, u, v = m.smith_form(); u * m * v == dTruesage: m = MatrixSpace(OE, 0,2)(0)sage: d, u, v = m.smith_form(); u * m * v == d(continues on next page)

546

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)True
sage: m = MatrixSpace(OE, 0,0)(0)sage: d, u, v = m.smith_form(); u * m * v == dTrue>>> from sage.all import *>>> # needs sage.rings.number_field>>> m = MatrixSpace(OE, Integer(2),Integer(0))(Integer(0))>>> d, u, v = m.smith_form(); u * m * v == dTrue>>> m = MatrixSpace(OE, Integer(0),Integer(2))(Integer(0))>>> d, u, v = m.smith_form(); u * m * v == dTrue>>> m = MatrixSpace(OE, Integer(0),Integer(0))(Integer(0))>>> d, u, v = m.smith_form(); u * m * v == dTrue

Some pathological cases that crashed earlier versions:sage: # needs sage.rings.number_fieldsage: m = Matrix(OE, [[ 2*w,
2*w - 1, -w + 1],....:[ 2*w + 2, -2*w - 1,
w - 1],....:[-2*w - 1, -2*w - 2, 2*w - 1]])
sage: d, u, v = m.smith_form(); u * m * v == dTruesage: m = matrix(OE, [[-5*w - 1, -2*w - 2, 4*w - 10],....:
[ 8*w,-w,
w - 1],
....:
[
-1,
1,
-8]])
sage: d, u, v = m.smith_form(); u * m * v == dTrue>>> from sage.all import *>>> # needs sage.rings.number_field>>> m = Matrix(OE, [[ Integer(2)*w,
Integer(2)*w - Integer(1), -w +␣˓→Integer(1)],...
[ Integer(2)*w + Integer(2), -Integer(2)*w - Integer(1), ␣
˓→ w - Integer(1)],...
[-Integer(2)*w - Integer(1), -Integer(2)*w - Integer(2),␣
˓→Integer(2)*w - Integer(1)]])>>> d, u, v = m.smith_form(); u * m * v == dTrue>>> m = matrix(OE, [[-Integer(5)*w - Integer(1), -Integer(2)*w - Integer(2),␣
˓→Integer(4)*w - Integer(10)],...
[ Integer(8)*w,-w,
w - Integer(1)],...
[-Integer(1),Integer(1),-Integer(8)]])>>> d, u, v = m.smith_form(); u * m * v == dTrue

Over local fields, we can request the transformation matrices to be integral:;sage: K = Qp(2, 5, print_mode=’terse’) # needs sage.rings.padics sage: M = matrix(K, 2, 3,[1/2, 1, 2, 1/3, 1, 3]) # needs sage.rings.padics sage: M.smith_form(integral=True) # needs
sage.rings.padics ( [1/2 + O(2^4) 0 0] [ 1 + O(2^5) 0] [ 0 1 + O(2^5) 0], [42 + O(2^6) 1 + O(2^5)],<BLANKLINE> [ 1 + O(2^5) 26 + O(2^5) 6 + O(2^5)] [ O(2^4) 3 + O(2^4) 11 + O(2^4)] [ 0 0
1 + O(2^5)] )solve_left(B, check=True, extend=True)
547

Matrices and Spaces of Matrices, Release 10.4

Try to find a solution 𝑋 to the equation 𝑋𝐴 = 𝐵.
If self is a matrix 𝐴, then this function returns a vector or matrix 𝑋 such that 𝑋𝐴 = 𝐵. If 𝐵 is a vector
then 𝑋 is a vector and if 𝐵 is a matrix, then 𝑋 is a matrix.
Over inexact rings, the output of this function may not be an exact solution. For example, over the real orcomplex double field, this method computes a least-squares solution if the system is not square.
INPUT:• B – a matrix or vector• extend – boolean (default: True); when set to True, some solvers will return solutions over a larger
ring than the base ring of the inputs (a typical case are rational solutions for integer linear systems).
When set to False, a solution over the base ring is returned, with a ValueError being raised if none
exists.
• check – boolean (default: True); verify the answer if the system is non-square or rank-deficient, andif its entries lie in an exact ring. Meaningless over most inexact rings, or when the system is square andof full rank.
OUTPUT:
If the system is square and has full rank, the unique solution is returned, and no check is done on the answer.
Over inexact rings, you should expect this answer to be inexact. Moreover, due to the numerical issues
involved, an error may be thrown in this case – specifically if the system is singular but if SageMath fails to
notice that.
If the system is not square or does not have full rank, then a solution is attempted via other means. For
example, over RDF or CDF a least-squares solution is returned, as with MATLAB’s “backslash” operator.
For most inexact rings, the check parameter is ignored because an approximate solution will be returned inany case. Over exact rings, on the other hand, setting the check parameter results in an additional test to
determine whether or not the answer actually solves the system exactly. If a symbolic system involves only
exact elements, its solution can still be checked.
If 𝐵 is a vector, the result is returned as a vector, as well, and as a matrix, otherwise.
See also:
solve_right()
EXAMPLES:
sage: A = matrix(QQ, 4,2, [0, -1, 1, 0, -2, 2, 1, 0])
sage: B = matrix(QQ, 2,2, [1, 0, 1, -1])
sage: X = A.solve_left(B)sage: X*A == B
True
sage: X == B / A
True>>> from sage.all import *>>> A = matrix(QQ, Integer(4),Integer(2), [Integer(0), -Integer(1),␣
˓→Integer(1), Integer(0), -Integer(2), Integer(2), Integer(1), Integer(0)])>>> B = matrix(QQ, Integer(2),Integer(2), [Integer(1), Integer(0), Integer(1),˓→ -Integer(1)])>>> X = A.solve_left(B)>>> X*A == B
True(continues on next page)

548

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> X == B / A
True
sage: A = matrix([(3, -1, 0, 0), (1, 1, -2, 0), (0, 0, 0, -3)])
sage: B = matrix(QQ, 3, 1, [0, 0, -1])
sage: A.solve_left(B)Traceback (most recent call last):...
ValueError: number of columns of self must equal number of columnsof right-hand side>>> from sage.all import *>>> A = matrix([(Integer(3), -Integer(1), Integer(0), Integer(0)),␣
˓→(Integer(1), Integer(1), -Integer(2), Integer(0)), (Integer(0), Integer(0),␣
˓→Integer(0), -Integer(3))])>>> B = matrix(QQ, Integer(3), Integer(1), [Integer(0), Integer(0), ˓→Integer(1)])>>> A.solve_left(B)Traceback (most recent call last):...
ValueError: number of columns of self must equal number of columnsof right-hand side

Over the reals:
sage: A = matrix(RDF, 3,3, [1,2,5,7.6,2.3,1,1,2,-1]); A[ 1.0 2.0 5.0]
[ 7.6 2.3 1.0]
[ 1.0 2.0 -1.0]
sage: b = vector(RDF,[1,2,3])
sage: x = A.solve_left(b); x.zero_at(2e-17) # fix noisy zeroes
˓→needs scipy(0.666666666..., 0.0, 0.333333333...)sage: x.parent()
˓→needs scipy
Vector space of dimension 3 over Real Double Field
sage: x*A # tol 1e-14
˓→needs scipy(0.9999999999999999, 1.9999999999999998, 3.0)

#␣

#␣

#␣

>>> from sage.all import *>>> A = matrix(RDF, Integer(3),Integer(3), [Integer(1),Integer(2),Integer(5),˓→RealNumber( 7.6 ),RealNumber( 2.3 ),Integer(1),Integer(1),Integer(2),˓→Integer(1)]); A[ 1.0 2.0 5.0]
[ 7.6 2.3 1.0]
[ 1.0 2.0 -1.0]>>> b = vector(RDF,[Integer(1),Integer(2),Integer(3)])>>> x = A.solve_left(b); x.zero_at(RealNumber( 2e-17 )) # fix noisy zeroes ␣˓→# needs scipy(0.666666666..., 0.0, 0.333333333...)>>> x.parent()#␣˓→needs scipy
Vector space of dimension 3 over Real Double Field>>> x*A # tol 1e-14#␣˓→needs scipy(continues on next page)549

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)(0.9999999999999999, 1.9999999999999998, 3.0)

Over the complex numbers:
sage: # needs sage.rings.complex_double sage.symbolic
sage: A = matrix(CDF, [[0, -1 + 2*I, 1 - 3*I,
I],
....:
[2 + 4*I, -2 + 3*I, -1 + 2*I,
-1 - I],....:[ 2 + I,
1 - I,
-1,
5],
....:
[
3*I,
-1 - I,-1 + I,-3 + I]])
sage: b = vector(CDF, [2 -3*I, 3, -2 + 3*I, 8])
sage: x = A.solve_left(b); x
˓→needs scipy(-1.55765124... - 0.644483985...*I, 0.183274021... + 0.286476868...*I,
0.270818505... + 0.246619217...*I, -1.69003558... - 0.828113879...*I)
sage: x.parent()
˓→needs scipy
Vector space of dimension 4 over Complex Double Field
sage: abs(x*A - b) < 1e-14
˓→needs scipy
True

#␣

#␣

#␣

>>> from sage.all import *>>> # needs sage.rings.complex_double sage.symbolic>>> A = matrix(CDF, [[Integer(0), -Integer(1) + Integer(2)*I, ␣
˓→Integer(1) - Integer(3)*I,
I],...
[Integer(2) + Integer(4)*I, -Integer(2) + Integer(3)*I, ˓→Integer(1) + Integer(2)*I,-Integer(1) - I],...
[ Integer(2) + I,
Integer(1) - I,
-Integer(1),␣
˓→
Integer(5)],...
[Integer(3)*I,-Integer(1) - I,
-Integer(1) + I,␣˓→-Integer(3) + I]])>>> b = vector(CDF, [Integer(2) -Integer(3)*I, Integer(3), -Integer(2) +␣˓→Integer(3)*I, Integer(8)])>>> x = A.solve_left(b); x#␣˓→needs scipy(-1.55765124... - 0.644483985...*I, 0.183274021... + 0.286476868...*I,
0.270818505... + 0.246619217...*I, -1.69003558... - 0.828113879...*I)>>> x.parent()#␣˓→needs scipy
Vector space of dimension 4 over Complex Double Field>>> abs(x*A - b) < RealNumber( 1e-14 )␣˓→# needs scipy
True

If b is given as a matrix, the result will be a matrix, as well:sage: A = matrix(RDF, 3, 3, [2, 5, 0, 7, 7, -2, -4.3, 0, 1])
sage: b = matrix(RDF, 2, 3, [2, -4, -5, 1, 1, 0.1])
sage: A.solve_left(b) # tol 1e-14
˓→needs scipy[ -6.495454545454545
4.068181818181818
3.1363636363636354][ 0.5277272727272727 -0.2340909090909091 -0.36818181818181817]#␣

>>> from sage.all import *>>> A = matrix(RDF, Integer(3), Integer(3), [Integer(2), Integer(5),␣
˓→Integer(0), Integer(7), Integer(7), -Integer(2), -RealNumber( 4.3 ),␣
(continues on next page)

550

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Integer(0), Integer(1)])>>> b = matrix(RDF, Integer(2), Integer(3), [Integer(2), -Integer(4), ˓→Integer(5), Integer(1), Integer(1), RealNumber( 0.1 )])>>> A.solve_left(b) # tol 1e-14
˓→needs scipy[ -6.495454545454545
4.068181818181818
3.1363636363636354][ 0.5277272727272727 -0.2340909090909091 -0.36818181818181817]
˓→#␣

If 𝐴 is a non-square matrix, the result is a least-squares solution. For a tall matrix, this may give a solution
with a least-squares error of almost zero:sage: A = matrix(RDF, 3, 2, [1, 3, 4, 2, 0, -3])
sage: b = vector(RDF, [5, 6])
sage: x = A.solve_left(b)˓→needs scipy
sage: (x * A - b).norm() < 1e-14
˓→needs scipy
True>>> from sage.all import *>>> A = matrix(RDF, Integer(3), Integer(2), [Integer(1), Integer(3),␣
˓→Integer(4), Integer(2), Integer(0), -Integer(3)])>>> b = vector(RDF, [Integer(5), Integer(6)])>>> x = A.solve_left(b)˓→needs scipy>>> (x * A - b).norm() < RealNumber( 1e-14 )˓→# needs scipy
True

#␣
#␣

#␣
␣

For a wide matrix 𝐴, the error is usually not small:sage: A = matrix(RDF, 2, 3, [1, 3, 4, 2, 0, -3])
sage: b = vector(RDF, [5, 6, 1])
sage: x = A.solve_left(b)˓→needs scipy
sage: (x * A - b).norm() # tol 1e-14
˓→needs scipy
0.9723055853282466>>> from sage.all import *>>> A = matrix(RDF, Integer(2), Integer(3), [Integer(1), Integer(3),␣
˓→Integer(4), Integer(2), Integer(0), -Integer(3)])>>> b = vector(RDF, [Integer(5), Integer(6), Integer(1)])>>> x = A.solve_left(b)˓→needs scipy>>> (x * A - b).norm() # tol 1e-14
˓→needs scipy
0.9723055853282466

#␣
#␣

#␣
#␣

solve_right(B, check=True, extend=True)
Try to find a solution 𝑋 to the equation 𝐴𝑋 = 𝐵.
If self is a matrix 𝐴, then this function returns a vector or matrix 𝑋 such that 𝐴𝑋 = 𝐵. If 𝐵 is a vector
then 𝑋 is a vector and if 𝐵 is a matrix, then 𝑋 is a matrix.
Over inexact rings, the output of this function may not be an exact solution. For example, over the real orcomplex double field, this method computes a least-squares solution if the system is not square.
551

Matrices and Spaces of Matrices, Release 10.4

INPUT:• B – a matrix or vector• extend – boolean (default: True); when set to True, some solvers will return solutions over a larger
ring than the base ring of the inputs (a typical case are rational solutions for integer linear systems).
When set to False, a solution over the base ring is returned, with a ValueError being raised if none
exists.
• check – boolean (default: True); verify the answer if the system is non-square or rank-deficient, andif its entries lie in an exact ring. Meaningless over most inexact rings, or when the system is square andof full rank.
OUTPUT:
If the system is square and has full rank, the unique solution is returned, and no check is done on the answer.
Over inexact rings, you should expect this answer to be inexact. Moreover, due to the numerical issues
involved, an error may be thrown in this case – specifically if the system is singular but if SageMath fails to
notice that.
If the system is not square or does not have full rank, then a solution is attempted via other means. For
example, over RDF or CDF a least-squares solution is returned, as with MATLAB’s “backslash” operator.
For most inexact rings, the check parameter is ignored because an approximate solution will be returned inany case. Over exact rings, on the other hand, setting the check parameter results in an additional test to
determine whether or not the answer actually solves the system exactly. If a symbolic system involves only
exact elements, its solution can still be checked.
If 𝐵 is a vector, the result is returned as a vector, as well, and as a matrix, otherwise.
See also:
solve_left()
EXAMPLES:
sage: A = matrix(QQ, 3, [1,2,3,-1,2,5,2,3,1])
sage: b = vector(QQ, [1,2,3])
sage: x = A.solve_right(b); x(-13/12, 23/12, -7/12)
sage: A * x(1, 2, 3)>>> from sage.all import *>>> A = matrix(QQ, Integer(3), [Integer(1),Integer(2),Integer(3),-Integer(1),˓→Integer(2),Integer(5),Integer(2),Integer(3),Integer(1)])>>> b = vector(QQ, [Integer(1),Integer(2),Integer(3)])>>> x = A.solve_right(b); x(-13/12, 23/12, -7/12)>>> A * x
(1, 2, 3)

We solve with A nonsquare:
sage: A = matrix(QQ, 2,4, [0, -1, 1, 0, -2, 2, 1, 0])
sage: B = matrix(QQ, 2,2, [1, 0, 1, -1])
sage: X = A.solve_right(B); X[-3/2 1/2]
[ -1
0]
[
0
0]
[
0
0]
(continues on next page)

552

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: A*X == B
True>>> from sage.all import *>>> A = matrix(QQ, Integer(2),Integer(4), [Integer(0), -Integer(1),␣
˓→Integer(1), Integer(0), -Integer(2), Integer(2), Integer(1), Integer(0)])>>> B = matrix(QQ, Integer(2),Integer(2), [Integer(1), Integer(0), Integer(1),˓→ -Integer(1)])>>> X = A.solve_right(B); X[-3/2 1/2]
[ -1
0]
[
0
0]
[
0
0]
>>> A*X == B
True

Another nonsingular example:
sage: A = matrix(QQ,2,3, [1,2,3,2,4,6]); v = vector([-1/2,-1])
sage: x = A.solve_right(v); x(-1/2, 0, 0)
sage: A*x == v
True>>> from sage.all import *>>> A = matrix(QQ,Integer(2),Integer(3), [Integer(1),Integer(2),Integer(3),˓→Integer(2),Integer(4),Integer(6)]); v = vector([-Integer(1)/Integer(2),˓→Integer(1)])>>> x = A.solve_right(v); x(-1/2, 0, 0)>>> A*x == v
True

Same example but over Z:
sage: A = matrix(ZZ,2,3, [1,2,3,2,4,6]); v = vector([-1,-2])
sage: A.solve_right(v)(-1, 0, 0)>>> from sage.all import *>>> A = matrix(ZZ,Integer(2),Integer(3), [Integer(1),Integer(2),Integer(3),˓→Integer(2),Integer(4),Integer(6)]); v = vector([-Integer(1),-Integer(2)])>>> A.solve_right(v)(-1, 0, 0)

An example in which there is no solution:
sage: A = matrix(QQ,2,3, [1,2,3,2,4,6]); v = vector([1,1])
sage: A.solve_right(v)Traceback (most recent call last):...
ValueError: matrix equation has no solutions>>> from sage.all import *>>> A = matrix(QQ,Integer(2),Integer(3), [Integer(1),Integer(2),Integer(3),(continues on next page)553

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Integer(2),Integer(4),Integer(6)]); v = vector([Integer(1),Integer(1)])>>> A.solve_right(v)Traceback (most recent call last):...
ValueError: matrix equation has no solutions
˓→A ValueError is raised if the input is invalid:
sage: A = matrix(QQ, 4,2, [0, -1, 1, 0, -2, 2, 1, 0])
sage: B = matrix(QQ, 2,2, [1, 0, 1, -1])
sage: X = A.solve_right(B)Traceback (most recent call last):...
ValueError: number of rows of self must equal number of rows ofright-hand side>>> from sage.all import *>>> A = matrix(QQ, Integer(4),Integer(2), [Integer(0), -Integer(1),␣
˓→Integer(1), Integer(0), -Integer(2), Integer(2), Integer(1), Integer(0)])>>> B = matrix(QQ, Integer(2),Integer(2), [Integer(1), Integer(0), Integer(1),˓→ -Integer(1)])>>> X = A.solve_right(B)Traceback (most recent call last):...
ValueError: number of rows of self must equal number of rows ofright-hand side

We solve with A singular:
sage: A = matrix(QQ, 2,3, [1,2,3,2,4,6]); B = matrix(QQ, 2,2, [6, -6, 12, ˓→12])sage: X = A.solve_right(B); X[ 6 -6][ 0 0][ 0 0]
sage: A*X == B
True>>> from sage.all import *>>> A = matrix(QQ, Integer(2),Integer(3), [Integer(1),Integer(2),Integer(3),˓→Integer(2),Integer(4),Integer(6)]); B = matrix(QQ, Integer(2),Integer(2),␣
˓→[Integer(6), -Integer(6), Integer(12), -Integer(12)])>>> X = A.solve_right(B); X[ 6 -6][ 0 0][ 0 0]>>> A*X == BTrue

We illustrate left associativity, etc., of the solve_right operator.
sage: A = matrix(QQ, 2, [1,2,3,4])
sage: A.solve_right(A)
[1 0]
[0 1]
sage: (A.solve_right(A)).solve_right(A)(continues on next page)

554

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[1 2]
[3 4]
sage: A.parent()(1).solve_right(A)
[1 2]
[3 4]
sage: A.solve_right(A.solve_right(A))[ -2
1][ 3/2 -1/2]
sage: X = A.solve_right(A - 2); X[ 5 -2][-3 2]
sage: A * X[-1 2][ 3 2]>>> from sage.all import *>>> A = matrix(QQ, Integer(2), [Integer(1),Integer(2),Integer(3),Integer(4)])>>> A.solve_right(A)
[1 0]
[0 1]
>>> (A.solve_right(A)).solve_right(A)
[1 2]
[3 4]
>>> A.parent()(Integer(1)).solve_right(A)
[1 2]
[3 4]
>>> A.solve_right(A.solve_right(A))[ -2
1][ 3/2 -1/2]>>> X = A.solve_right(A - Integer(2)); X[ 5 -2][-3 2]>>> A * X[-1 2][ 3 2]

Solving over a polynomial ring:sage: x = polygen(QQ, x )sage: A = matrix(2, [x, 2*x, -5*x^2 + 1, 3])
sage: v = vector([3, 4*x - 2])sage: X = A.solve_right(v)sage: X((-4/5*x^2 + 2/5*x + 9/10)/(x^3 + 1/10*x),(19/10*x^2 - 1/5*x - 3/10)/(x^3 + 1/10*x))
sage: A * X == v
True>>> from sage.all import *>>> x = polygen(QQ, x )>>> A = matrix(Integer(2), [x, Integer(2)*x, -Integer(5)*x**Integer(2) +␣˓→Integer(1), Integer(3)])>>> v = vector([Integer(3), Integer(4)*x - Integer(2)])>>> X = A.solve_right(v)>>> X((-4/5*x^2 + 2/5*x + 9/10)/(x^3 + 1/10*x),(continues on next page)555

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)(19/10*x^2 - 1/5*x - 3/10)/(x^3 + 1/10*x))>>> A * X == v
True

Solving some systems over Z/𝑛Z:
sage: # needs sage.libs.pari
sage: A = Matrix(Zmod(6), 3, 2, [1,2,3,4,5,6])
sage: B = vector(Zmod(6), [1,1,1])
sage: A.solve_right(B)(5, 1)
sage: B = vector(Zmod(6), [5,1,1])
sage: A.solve_right(B)Traceback (most recent call last):...
ValueError: matrix equation has no solutions
sage: A = Matrix(Zmod(128), 2, 3, [23,11,22,4,1,0])
sage: B = Matrix(Zmod(128), 2, 1, [1,0])
sage: A.solve_right(B)
[ 5]
[108]
[127]
sage: B = B.column(0)sage: A.solve_right(B)(5, 108, 127)
sage: A = Matrix(Zmod(15), 3,4, range(12))
sage: B = Matrix(Zmod(15), 3,3, range(3,12))
sage: X = A.solve_right(B)sage: A*X == B
True>>> from sage.all import *>>> # needs sage.libs.pari>>> A = Matrix(Zmod(Integer(6)), Integer(3), Integer(2), [Integer(1),˓→Integer(2),Integer(3),Integer(4),Integer(5),Integer(6)])>>> B = vector(Zmod(Integer(6)), [Integer(1),Integer(1),Integer(1)])>>> A.solve_right(B)(5, 1)>>> B = vector(Zmod(Integer(6)), [Integer(5),Integer(1),Integer(1)])>>> A.solve_right(B)Traceback (most recent call last):...
ValueError: matrix equation has no solutions>>> A = Matrix(Zmod(Integer(128)), Integer(2), Integer(3), [Integer(23),
˓→Integer(11),Integer(22),Integer(4),Integer(1),Integer(0)])>>> B = Matrix(Zmod(Integer(128)), Integer(2), Integer(1), [Integer(1),˓→Integer(0)])>>> A.solve_right(B)
[ 5]
[108]
[127]
>>> B = B.column(Integer(0))>>> A.solve_right(B)(5, 108, 127)>>> A = Matrix(Zmod(Integer(15)), Integer(3),Integer(4), range(Integer(12)))>>> B = Matrix(Zmod(Integer(15)), Integer(3),Integer(3), range(Integer(3),(continues on next page)

556

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Integer(12)))>>> X = A.solve_right(B)>>> A*X == B
True˓→Solving a system over the p-adics:
sage: # needs sage.rings.padics
sage: k = Qp(5, 4)
sage: a = matrix(k, 3, [1,7,3, 2,5,4, 1,1,2]); a[
1 + O(5^4) 2 + 5 + O(5^4)
3 + O(5^4)][
2 + O(5^4)
5 + O(5^5)
4 + O(5^4)][
1 + O(5^4)
1 + O(5^4)
2 + O(5^4)]sage: v = vector(k, 3, [1,2,3])
sage: x = a.solve_right(v); x(4 + 5 + 5^2 + 3*5^3 + O(5^4), 2 + 5 + 3*5^2 + 5^3 + O(5^4), 1 + 5 + O(5^4))sage: a * x == v
True>>> from sage.all import *>>> # needs sage.rings.padics>>> k = Qp(Integer(5), Integer(4))>>> a = matrix(k, Integer(3), [Integer(1),Integer(7),Integer(3), Integer(2),˓→Integer(5),Integer(4), Integer(1),Integer(1),Integer(2)]); a[
1 + O(5^4) 2 + 5 + O(5^4)
3 + O(5^4)][
2 + O(5^4)
5 + O(5^5)
4 + O(5^4)][
1 + O(5^4)
1 + O(5^4)
2 + O(5^4)]>>> v = vector(k, Integer(3), [Integer(1),Integer(2),Integer(3)])>>> x = a.solve_right(v); x(4 + 5 + 5^2 + 3*5^3 + O(5^4), 2 + 5 + 3*5^2 + 5^3 + O(5^4), 1 + 5 + O(5^4))>>> a * x == v
True

Solving a system of linear equations symbolically using symbolic matrices:sage: # needs sage.symbolic
sage: var( a,b,c,d,x,y )(a, b, c, d, x, y)
sage: A = matrix(SR, 2, [a,b,c,d]); A
[a b]
[c d]
sage: result = vector(SR, [3,5]); result(3, 5)
sage: soln = A.solve_right(result); soln(-b*(3*c/a - 5)/(a*(b*c/a - d)) + 3/a, (3*c/a - 5)/(b*c/a - d))sage: (a*x + b*y).subs(x=soln[0], y=soln[1]).simplify_full()
3
sage: (c*x + d*y).subs(x=soln[0], y=soln[1]).simplify_full()5
sage: (A*soln).apply_map(lambda x: x.simplify_full())(3, 5)>>> from sage.all import *>>> # needs sage.symbolic>>> var( a,b,c,d,x,y )(a, b, c, d, x, y)(continues on next page)557

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> A = matrix(SR, Integer(2), [a,b,c,d]); A
[a b]
[c d]
>>> result = vector(SR, [Integer(3),Integer(5)]); result(3, 5)>>> soln = A.solve_right(result); soln(-b*(3*c/a - 5)/(a*(b*c/a - d)) + 3/a, (3*c/a - 5)/(b*c/a - d))>>> (a*x + b*y).subs(x=soln[Integer(0)], y=soln[Integer(1)]).simplify_full()3>>> (c*x + d*y).subs(x=soln[Integer(0)], y=soln[Integer(1)]).simplify_full()5>>> (A*soln).apply_map(lambda x: x.simplify_full())(3, 5)

Over inexact rings, the output of this function may not be an exact solution. For example, over the real orcomplex double field, this computes a least-squares solution:
sage: A = matrix(RDF, 3, 2, [1, 3, 4, 2, 0, -3])
sage: b = vector(RDF, [5, 6, 1])
sage: A.solve_right(b) # tol 1e-14
˓→needs scipy(1.4782608695652177, 0.35177865612648235)
sage: ~(A.T * A) * A.T * b # closed form solution, tol 1e-14
˓→needs scipy(1.4782608695652177, 0.35177865612648235)#␣#␣>>> from sage.all import *>>> A = matrix(RDF, Integer(3), Integer(2), [Integer(1), Integer(3),␣
˓→Integer(4), Integer(2), Integer(0), -Integer(3)])>>> b = vector(RDF, [Integer(5), Integer(6), Integer(1)])>>> A.solve_right(b) # tol 1e-14
˓→needs scipy(1.4782608695652177, 0.35177865612648235)>>> ~(A.T * A) * A.T * b # closed form solution, tol 1e-14
˓→needs scipy(1.4782608695652177, 0.35177865612648235)#␣#␣Over the reals:
sage: A = matrix(RDF, 3,3, [1,2,5,7.6,2.3,1,1,2,-1]); A[ 1.0 2.0 5.0]
[ 7.6 2.3 1.0]
[ 1.0 2.0 -1.0]
sage: b = vector(RDF, [1,2,3])
sage: x = A.solve_right(b); x # tol 1e-14
˓→needs scipy(-0.1136950904392765, 1.3901808785529717, -0.33333333333333337)
sage: x.parent()
˓→needs scipy
Vector space of dimension 3 over Real Double Field
sage: A*x # tol 1e-14
˓→needs scipy(1.0, 1.9999999999999996, 3.0000000000000004)

#␣

#␣

#␣

>>> from sage.all import *>>> A = matrix(RDF, Integer(3),Integer(3), [Integer(1),Integer(2),Integer(5),(continues on next page)

558

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

RealNumber( 7.6 ),RealNumber( 2.3 ),Integer(1),Integer(1),Integer(2),˓→Integer(1)]); A[ 1.0 2.0 5.0]
[ 7.6 2.3 1.0]
[ 1.0 2.0 -1.0]>>> b = vector(RDF, [Integer(1),Integer(2),Integer(3)])>>> x = A.solve_right(b); x # tol 1e-14
˓→needs scipy(-0.1136950904392765, 1.3901808785529717, -0.33333333333333337)>>> x.parent()
˓→needs scipy
Vector space of dimension 3 over Real Double Field>>> A*x # tol 1e-14
˓→needs scipy(1.0, 1.9999999999999996, 3.0000000000000004)
˓→

#␣

#␣

#␣

Over the complex numbers:
sage: # needs sage.rings.complex_double sage.symbolic
sage: A = matrix(CDF, [[0, -1 + 2*I, 1 - 3*I,
I],
....:
[2 + 4*I, -2 + 3*I, -1 + 2*I,
-1 - I],....:[ 2 + I,
1 - I,
-1,
5],
....:
[
3*I,
-1 - I,-1 + I,-3 + I]])
sage: b = vector(CDF, [2 - 3*I, 3, -2 + 3*I, 8])
sage: x = A.solve_right(b); x
˓→needs scipy(1.96841637... - 1.07606761...*I, -0.614323843... + 1.68416370...*I,
0.0733985765... + 1.73487544...*I, -1.6018683... + 0.524021352...*I)
sage: x.parent()
˓→needs scipy
Vector space of dimension 4 over Complex Double Field
sage: abs(A*x - b) < 1e-14
˓→needs scipy
True

#␣

#␣

#␣

>>> from sage.all import *>>> # needs sage.rings.complex_double sage.symbolic>>> A = matrix(CDF, [[Integer(0), -Integer(1) + Integer(2)*I, ␣
˓→Integer(1) - Integer(3)*I,
I],...
[Integer(2) + Integer(4)*I, -Integer(2) + Integer(3)*I, ˓→Integer(1) + Integer(2)*I,-Integer(1) - I],...
[ Integer(2) + I,
Integer(1) - I,
-Integer(1),␣
˓→
Integer(5)],...
[Integer(3)*I,-Integer(1) - I,
-Integer(1) + I,␣˓→-Integer(3) + I]])>>> b = vector(CDF, [Integer(2) - Integer(3)*I, Integer(3), -Integer(2) +␣˓→Integer(3)*I, Integer(8)])>>> x = A.solve_right(b); x#␣˓→needs scipy(1.96841637... - 1.07606761...*I, -0.614323843... + 1.68416370...*I,
0.0733985765... + 1.73487544...*I, -1.6018683... + 0.524021352...*I)>>> x.parent()#␣˓→needs scipy
Vector space of dimension 4 over Complex Double Field>>> abs(A*x - b) < RealNumber( 1e-14 )␣˓→# needs scipy
True

559

Matrices and Spaces of Matrices, Release 10.4

If b is given as a matrix, the result will be a matrix, as well:sage: A = matrix(RDF, 3, 3, [1, 2, 2, 3, 4, 5, 2, 2, 2])
sage: b = matrix(RDF, 3, 2, [3, 2, 3, 2, 3, 2])
sage: A.solve_right(b) # tol 1e-14
˓→needs scipy[ 0.0 0.0]
[ 4.5 3.0][-3.0 -2.0]#␣>>> from sage.all import *>>> A = matrix(RDF, Integer(3), Integer(3), [Integer(1), Integer(2),␣
˓→Integer(2), Integer(3), Integer(4), Integer(5), Integer(2), Integer(2),␣
˓→Integer(2)])>>> b = matrix(RDF, Integer(3), Integer(2), [Integer(3), Integer(2),␣
˓→Integer(3), Integer(2), Integer(3), Integer(2)])>>> A.solve_right(b) # tol 1e-14#␣˓→needs scipy[ 0.0 0.0]
[ 4.5 3.0][-3.0 -2.0]

If 𝐴 is a non-square matrix, the result is a least-squares solution. For a wide matrix, this may give a solution
with a least-squares error of almost zero:sage: A = matrix(RDF, 2, 3, [1, 3, 4, 2, 0, -3])
sage: b = vector(RDF, [5, 6])
sage: x = A.solve_right(b)˓→needs scipy
sage: (A * x - b).norm() < 1e-14
˓→needs scipy
True

#␣
#␣

>>> from sage.all import *>>> A = matrix(RDF, Integer(2), Integer(3), [Integer(1), Integer(3),␣
˓→Integer(4), Integer(2), Integer(0), -Integer(3)])>>> b = vector(RDF, [Integer(5), Integer(6)])>>> x = A.solve_right(b)˓→needs scipy>>> (A * x - b).norm() < RealNumber( 1e-14 )˓→# needs scipy
True

#␣
␣

For a tall matrix 𝐴, the error is usually not small:sage: A = matrix(RDF, 3, 2, [1, 3, 4, 2, 0, -3])
sage: b = vector(RDF, [5, 6, 1])
sage: x = A.solve_right(b)˓→needs scipy
sage: (A * x - b).norm() # tol 1e-14
˓→needs scipy
3.2692119900020438#␣#␣>>> from sage.all import *>>> A = matrix(RDF, Integer(3), Integer(2), [Integer(1), Integer(3),␣
˓→Integer(4), Integer(2), Integer(0), -Integer(3)])>>> b = vector(RDF, [Integer(5), Integer(6), Integer(1)])(continues on next page)

560

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> x = A.solve_right(b)˓→needs scipy>>> (A * x - b).norm() # tol 1e-14
˓→needs scipy
3.2692119900020438#␣#␣

subdivide(row_lines=None, col_lines=None)
Divides self into logical submatrices which can then be queried and extracted.
If a subdivision already exists, this method forgets the previous subdivision and flushes the cache.
INPUT:• row_lines – None, an integer, or a list of integers (lines at which self must be split)• col_lines – None, an integer, or a list of integers (columns at which self must be split)
OUTPUT: None but changes self
Note: One may also pass a tuple into the first argument which will be interpreted as (row_lines,
col_lines).
EXAMPLES:
sage: # needs sage.libs.pari
sage: M = matrix(5, 5, prime_range(100))
sage: M.subdivide(2,3); M[ 2 3 5| 7 11][13 17 19|23 29][--------+-----][31 37 41|43 47][53 59 61|67 71][73 79 83|89 97]
sage: M.subdivision(0,0)[ 2 3 5]
[13 17 19]
sage: M.subdivision(1,0)[31 37 41][53 59 61][73 79 83]
sage: M.subdivision_entry(1,0,0,0)31
sage: M.subdivisions()([2], [3])sage: M.subdivide(None, [1,3]); M[ 2| 3 5| 7 11][13|17 19|23 29][31|37 41|43 47][53|59 61|67 71][73|79 83|89 97]>>> from sage.all import *>>> # needs sage.libs.pari>>> M = matrix(Integer(5), Integer(5), prime_range(Integer(100)))>>> M.subdivide(Integer(2),Integer(3)); M[ 2 3 5| 7 11](continues on next page)561

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[13 17 19|23 29][--------+-----][31 37 41|43 47][53 59 61|67 71][73 79 83|89 97]>>> M.subdivision(Integer(0),Integer(0))[ 2 3 5]
[13 17 19]>>> M.subdivision(Integer(1),Integer(0))[31 37 41][53 59 61][73 79 83]>>> M.subdivision_entry(Integer(1),Integer(0),Integer(0),Integer(0))
31>>> M.subdivisions()([2], [3])>>> M.subdivide(None, [Integer(1),Integer(3)]); M[ 2| 3 5| 7 11][13|17 19|23 29][31|37 41|43 47][53|59 61|67 71][73|79 83|89 97]

Degenerate cases work too:sage: # needs sage.libs.pari
sage: M.subdivide([2,5], [0,1,3]); M[| 2| 3 5| 7 11][|13|17 19|23 29][+--+-----+-----][|31|37 41|43 47][|53|59 61|67 71][|73|79 83|89 97][+--+-----+-----]
sage: M.subdivision(0,0)[]
sage: M.subdivision(0,1)
[ 2]
[13]
sage: M.subdivide([2,2,3], [0,0,1,1]); M[|| 2|| 3 5 7 11][||13||17 19 23 29][++--++-----------][++--++-----------][||31||37 41 43 47][++--++-----------][||53||59 61 67 71][||73||79 83 89 97]
sage: M.subdivision(0,0)[]
sage: M.subdivision(2,4)[37 41 43 47]>>> from sage.all import *>>> # needs sage.libs.pari>>> M.subdivide([Integer(2),Integer(5)], [Integer(0),Integer(1),Integer(3)]);␣
(continues on next page)

562

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)M[| 2| 3 5| 7 11][|13|17 19|23 29][+--+-----+-----][|31|37 41|43 47][|53|59 61|67 71][|73|79 83|89 97][+--+-----+-----]>>> M.subdivision(Integer(0),Integer(0))[]>>> M.subdivision(Integer(0),Integer(1))
[ 2]
[13]
>>> M.subdivide([Integer(2),Integer(2),Integer(3)], [Integer(0),Integer(0),˓→Integer(1),Integer(1)]); M[|| 2|| 3 5 7 11][||13||17 19 23 29][++--++-----------][++--++-----------][||31||37 41 43 47][++--++-----------][||53||59 61 67 71][||73||79 83 89 97]>>> M.subdivision(Integer(0),Integer(0))[]>>> M.subdivision(Integer(2),Integer(4))[37 41 43 47]
˓→Indices do not need to be in the right order (Issue #14064):
sage: M.subdivide([4, 2], [3, 1]); M˓→needs sage.libs.pari[ 2| 3 5| 7 11][13|17 19|23 29][--+-----+-----][31|37 41|43 47][53|59 61|67 71][--+-----+-----][73|79 83|89 97]>>> from sage.all import *>>> M.subdivide([Integer(4), Integer(2)], [Integer(3), Integer(1)]); M˓→# needs sage.libs.pari[ 2| 3 5| 7 11][13|17 19|23 29][--+-----+-----][31|37 41|43 47][53|59 61|67 71][--+-----+-----][73|79 83|89 97]#␣␣

subdivision(i, j)
Returns an immutable copy of the (i,j)th submatrix of self, according to a previously set subdivision.
Before a subdivision is set, the only valid arguments are (0,0) which returns self.
EXAMPLES:

563

Matrices and Spaces of Matrices, Release 10.4

sage: M = matrix(3, 4, range(12))
sage: M.subdivide(1,2); M[ 0 1| 2 3][-----+-----][ 4 5| 6 7]
[ 8 9|10 11]
sage: M.subdivision(0,0)[0 1]
sage: M.subdivision(0,1)[2 3]
sage: M.subdivision(1,0)
[4 5]
[8 9]
>>> from sage.all import *>>> M = matrix(Integer(3), Integer(4), range(Integer(12)))>>> M.subdivide(Integer(1),Integer(2)); M[ 0 1| 2 3][-----+-----][ 4 5| 6 7]
[ 8 9|10 11]>>> M.subdivision(Integer(0),Integer(0))[0 1]>>> M.subdivision(Integer(0),Integer(1))[2 3]>>> M.subdivision(Integer(1),Integer(0))
[4 5]
[8 9]

It handles size-zero subdivisions as well.
sage: M = matrix(3, 4, range(12))
sage: M.subdivide([0],[0,2,2,4]); M[+-----++-----+][| 0 1|| 2 3|][| 4 5|| 6 7|][| 8 9||10 11|]sage: M.subdivision(0,0)[]
sage: M.subdivision(1,1)
[0 1]
[4 5]
[8 9]
sage: M.subdivision(1,2)[]
sage: M.subdivision(1,0)[]
sage: M.subdivision(0,1)[]>>> from sage.all import *>>> M = matrix(Integer(3), Integer(4), range(Integer(12)))>>> M.subdivide([Integer(0)],[Integer(0),Integer(2),Integer(2),Integer(4)]); M[+-----++-----+][| 0 1|| 2 3|][| 4 5|| 6 7|][| 8 9||10 11|](continues on next page)

564

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> M.subdivision(Integer(0),Integer(0))[]>>> M.subdivision(Integer(1),Integer(1))
[0 1]
[4 5]
[8 9]
>>> M.subdivision(Integer(1),Integer(2))[]>>> M.subdivision(Integer(1),Integer(0))[]>>> M.subdivision(Integer(0),Integer(1))[]

subdivision_entry(i, j, x, y)
Returns the x,y entry of the i,j submatrix of self.
EXAMPLES:
sage: M = matrix(5, 5, range(25))
sage: M.subdivide(3,3); M[ 0 1 2| 3 4]
[ 5 6 7| 8 9]
[10 11 12|13 14][--------+-----][15 16 17|18 19][20 21 22|23 24]
sage: M.subdivision_entry(0,0,1,2)
7
sage: M.subdivision(0,0)[1,2]7sage: M.subdivision_entry(0,1,0,0)3
sage: M.subdivision_entry(1,0,0,0)
15
sage: M.subdivision_entry(1,1,1,1)
24>>> from sage.all import *>>> M = matrix(Integer(5), Integer(5), range(Integer(25)))>>> M.subdivide(Integer(3),Integer(3)); M[ 0 1 2| 3 4]
[ 5 6 7| 8 9]
[10 11 12|13 14][--------+-----][15 16 17|18 19][20 21 22|23 24]>>> M.subdivision_entry(Integer(0),Integer(0),Integer(1),Integer(2))
7>>> M.subdivision(Integer(0),Integer(0))[Integer(1),Integer(2)]7>>> M.subdivision_entry(Integer(0),Integer(1),Integer(0),Integer(0))
3>>> M.subdivision_entry(Integer(1),Integer(0),Integer(0),Integer(0))
15>>> M.subdivision_entry(Integer(1),Integer(1),Integer(1),Integer(1))
24565Matrices and Spaces of Matrices, Release 10.4

Even though this entry exists in the matrix, the index is invalid for the submatrix.
sage: M.subdivision_entry(0,0,4,0)
Traceback (most recent call last):...
IndexError: Submatrix 0,0 has no entry 4,0>>> from sage.all import *>>> M.subdivision_entry(Integer(0),Integer(0),Integer(4),Integer(0))
Traceback (most recent call last):...
IndexError: Submatrix 0,0 has no entry 4,0

subdivisions()
Returns the current subdivision of self.
EXAMPLES:
sage: M = matrix(5, 5, range(25))
sage: M.subdivisions()([], [])
sage: M.subdivide(2,3)
sage: M.subdivisions()([2], [3])sage: N = M.parent()(1)
sage: N.subdivide(M.subdivisions()); N[1 0 0|0 0][0 1 0|0 0][-----+---][0 0 1|0 0][0 0 0|1 0][0 0 0|0 1]>>> from sage.all import *>>> M = matrix(Integer(5), Integer(5), range(Integer(25)))>>> M.subdivisions()([], [])>>> M.subdivide(Integer(2),Integer(3))>>> M.subdivisions()([2], [3])>>> N = M.parent()(Integer(1))>>> N.subdivide(M.subdivisions()); N[1 0 0|0 0][0 1 0|0 0][-----+---][0 0 1|0 0][0 0 0|1 0][0 0 0|0 1]

subs(*args, **kwds)
Substitute values to the variables in that matrix.
All the arguments are transmitted unchanged to the method subs of the coefficients.
EXAMPLES:
sage: # needs sage.symbolic
sage: var( a,b,d,e )(continues on next page)

566

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)(a, b, d, e)
sage: m = matrix([[a,b], [d,e]])sage: m.substitute(a=1)
[1 b]
[d e]
sage: m.subs(a=b, b=d)
[b d]
[d e]
sage: m.subs({a: 3, b: 2, d: 1, e: -1})
[ 3 2][ 1 -1]>>> from sage.all import *>>> # needs sage.symbolic>>> var( a,b,d,e )(a, b, d, e)>>> m = matrix([[a,b], [d,e]])>>> m.substitute(a=Integer(1))
[1 b]
[d e]
>>> m.subs(a=b, b=d)
[b d]
[d e]
>>> m.subs({a: Integer(3), b: Integer(2), d: Integer(1), e: -Integer(1)})[ 3 2][ 1 -1]The parent of the newly created matrix might be different from the initial one. It depends on what the method.subs does on coefficients (see Issue #19045):
sage: x = polygen(ZZ)
sage: m = matrix([[x]])sage: m2 = m.subs(x=2)
sage: m2.parent()
Full MatrixSpace of 1 by 1 dense matrices over Integer Ringsage: m1 = m.subs(x=RDF(1))
sage: m1.parent()
Full MatrixSpace of 1 by 1 dense matrices over Real Double Field>>> from sage.all import *>>> x = polygen(ZZ)>>> m = matrix([[x]])>>> m2 = m.subs(x=Integer(2))>>> m2.parent()
Full MatrixSpace of 1 by 1 dense matrices over Integer Ring>>> m1 = m.subs(x=RDF(Integer(1)))>>> m1.parent()
Full MatrixSpace of 1 by 1 dense matrices over Real Double Field

However, sparse matrices remain sparse:
sage: m = matrix({(3,2): -x, (59,38): x^2 + 2}, nrows=1000, ncols=1000)
sage: m1 = m.subs(x=1)
sage: m1.is_sparse()
True

567

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> m = matrix({(Integer(3),Integer(2)): -x, (Integer(59),Integer(38)):␣
˓→x**Integer(2) + Integer(2)}, nrows=Integer(1000), ncols=Integer(1000))>>> m1 = m.subs(x=Integer(1))>>> m1.is_sparse()
True

symplectic_form()
Find a symplectic form for self if self is an anti-symmetric, alternating matrix defined over a field.
Returns a pair (F, C) such that the rows of C form a symplectic basis for self and F = C * self * C.transpose().
Raises a ValueError if not over a field, or self is not anti-symmetric, or self is not alternating.
Anti-symmetric means that 𝑀 = −𝑀 𝑡 . Alternating means that the diagonal of 𝑀 is identically zero.
A symplectic basis is a basis of the form 𝑒1 , . . . , 𝑒𝑗 , 𝑓1 , . . . 𝑓𝑗 , 𝑧1 , . . . , 𝑧𝑘 such that• 𝑧𝑖 𝑀 𝑣 𝑡 = 0 for all vectors 𝑣• 𝑒𝑖 𝑀 𝑒𝑗 𝑡 = 0 for all 𝑖, 𝑗
• 𝑓𝑖 𝑀 𝑓𝑗 𝑡 = 0 for all 𝑖, 𝑗
• 𝑒𝑖 𝑀 𝑓𝑖 𝑡 = 1 for all 𝑖• 𝑒𝑖 𝑀 𝑓𝑗 𝑡 = 0 for all 𝑖 not equal 𝑗.
See the example for a pictorial description of such a basis.
EXAMPLES:
sage: E = matrix(QQ, 8, 8, [0, -1/2, -2, 1/2, 2, 0, -2, 1, 1/2, 0, -1, -3, 0,␣
˓→2, 5/2, -3, 2, 1, 0, 3/2, -1, 0, -1, -2, -1/2, 3, -3/2, 0, 1, 3/2, -1/2, -1/
˓→2, -2, 0, 1, -1, 0, 0, 1, -1, 0, -2, 0, -3/2, 0, 0, 1/2, -2, 2, -5/2, 1, 1/
˓→2, -1, -1/2, 0, -1, -1, 3, 2, 1/2, 1, 2, 1, 0]); E[
0 -1/2-2 1/2
2
0
-2
1]
[ 1/2
0
-1
-3
0
2 5/2
-3]
[
2
1
0 3/2
-1
0
-1
-2]
[-1/2
3 -3/20
1 3/2 -1/2 -1/2]
[ -2
0
1
-1
0
0
1
-1]
[
0
-2
0 -3/2
0
0 1/2
-2]
[
2 -5/2
1 1/2-1 -1/2
0
-1]
[ -1
3
2 1/2
1
2
1
0]
sage: F, C = E.symplectic_form(); F[ 0 0 0 0 1 0 0 0]
[ 0 0 0 0 0 1 0 0]
[ 0 0 0 0 0 0 1 0]
[ 0 0 0 0 0 0 0 1][-1 0 0 0 0 0 0 0]
[ 0 -1 0 0 0 0 0 0]
[ 0 0 -1 0 0 0 0 0]
[ 0 0 0 -1 0 0 0 0]
sage: F == C * E * C.transpose()True>>> from sage.all import *>>> E = matrix(QQ, Integer(8), Integer(8), [Integer(0), -Integer(1)/˓→Integer(2), -Integer(2), Integer(1)/Integer(2), Integer(2), Integer(0), ˓→Integer(2), Integer(1), Integer(1)/Integer(2), Integer(0), -Integer(1), ˓→Integer(3), Integer(0), Integer(2), Integer(5)/Integer(2), -Integer(3),␣
(continues on next page)

568

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Integer(2), Integer(1), Integer(0), Integer(3)/Integer(2), -Integer(1),␣
˓→Integer(0), -Integer(1), -Integer(2), -Integer(1)/Integer(2), Integer(3), ˓→Integer(3)/Integer(2), Integer(0), Integer(1), Integer(3)/Integer(2), ˓→Integer(1)/Integer(2), -Integer(1)/Integer(2), -Integer(2), Integer(0),␣
˓→Integer(1), -Integer(1), Integer(0), Integer(0), Integer(1), -Integer(1),␣
˓→Integer(0), -Integer(2), Integer(0), -Integer(3)/Integer(2), Integer(0),␣
˓→Integer(0), Integer(1)/Integer(2), -Integer(2), Integer(2), -Integer(5)/˓→Integer(2), Integer(1), Integer(1)/Integer(2), -Integer(1), -Integer(1)/˓→Integer(2), Integer(0), -Integer(1), -Integer(1), Integer(3), Integer(2),␣
˓→Integer(1)/Integer(2), Integer(1), Integer(2), Integer(1), Integer(0)]); E[
0 -1/2-2 1/2
2
0
-2
1]
[ 1/2
0
-1
-3
0
2 5/2
-3]
[
2
1
0 3/2
-1
0
-1
-2]
[-1/2
3 -3/20
1 3/2 -1/2 -1/2]
[ -2
0
1
-1
0
0
1
-1]
[
0
-2
0 -3/2
0
0 1/2
-2]
[
2 -5/2
1 1/2-1 -1/2
0
-1]
[ -1
3
2 1/2
1
2
1
0]
>>> F, C = E.symplectic_form(); F[ 0 0 0 0 1 0 0 0]
[ 0 0 0 0 0 1 0 0]
[ 0 0 0 0 0 0 1 0]
[ 0 0 0 0 0 0 0 1][-1 0 0 0 0 0 0 0]
[ 0 -1 0 0 0 0 0 0]
[ 0 0 -1 0 0 0 0 0]
[ 0 0 0 -1 0 0 0 0]>>> F == C * E * C.transpose()True˓→tensor_product(A, subdivide=True)
Returns the tensor product of two matrices.
INPUT:• A – a matrix• subdivide – (default: True); whether or not to return natural subdivisions with the matrix
OUTPUT:
Replace each element of self by a copy of A, but first create a scalar multiple of A by the element it replaces.
So if self is an 𝑚 × 𝑛 matrix and A is a 𝑝 × 𝑞 matrix, then the tensor product is an 𝑚𝑝 × 𝑛𝑞 matrix. By
default, the matrix will be subdivided into submatrices of size 𝑝 × 𝑞.
EXAMPLES:
sage: M1=Matrix(QQ,[[-1,0],[-1/2,-1]])
sage: M2=Matrix(ZZ,[[1,-1,2],[-2,4,8]])
sage: M1.tensor_product(M2)
[ -1
1
-2|
0
0
0]
[
2
-4
-8|
0
0
0]
[--------------+--------------][-1/2 1/2
-1| -1
1
-2]
[
1
-2
-4|
2
-4
-8]
sage: M2.tensor_product(M1)
[ -1
0|
1
0| -2
0]
[-1/2
-1| 1/2
1| -1-2](continues on next page)569

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[---------+---------+---------]
[
2
0| -4
0| -8
0]
[
1
2| -2
-4| -4-8]>>> from sage.all import *>>> M1=Matrix(QQ,[[-Integer(1),Integer(0)],[-Integer(1)/Integer(2),˓→Integer(1)]])>>> M2=Matrix(ZZ,[[Integer(1),-Integer(1),Integer(2)],[-Integer(2),Integer(4),˓→Integer(8)]])>>> M1.tensor_product(M2)
[ -1
1
-2|
0
0
0]
[
2
-4
-8|
0
0
0]
[--------------+--------------][-1/2 1/2
-1| -1
1
-2]
[
1
-2
-4|
2
-4
-8]
>>> M2.tensor_product(M1)
[ -1
0|
1
0| -2
0]
[-1/2
-1| 1/2
1| -1-2][---------+---------+---------]
[
2
0| -4
0| -8
0]
[
1
2| -2
-4| -4-8]

Subdivisions can be optionally suppressed.
sage: M1.tensor_product(M2, subdivide=False)
[ -1
1
-2
0
0
0]
[
2
-4
-8
0
0
0]
[-1/2 1/2
-1
-1
1
-2]
[
1
-2
-4
2
-4
-8]
>>> from sage.all import *>>> M1.tensor_product(M2, subdivide=False)
[ -1
1
-2
0
0
0]
[
2
-4
-8
0
0
0]
[-1/2 1/2
-1
-1
1
-2]
[
1
-2
-4
2
-4
-8]

Different base rings are handled sensibly.
sage: A = matrix(ZZ, 2, 3, range(6))
sage: B = matrix(FiniteField(23), 3, 4, range(12))
sage: C = matrix(FiniteField(29), 4, 5, range(20))
sage: D = A.tensor_product(B)sage: D.parent()
Full MatrixSpace of 6 by 12 dense matrices over Finite Field of size 23
sage: E = C.tensor_product(B)Traceback (most recent call last):...
TypeError: unsupported operand parent(s) for *:Finite Field of size 29 andFull MatrixSpace of 3 by 4 dense matrices over Finite Field of size 23>>> from sage.all import *>>> A = matrix(ZZ, Integer(2), Integer(3), range(Integer(6)))>>> B = matrix(FiniteField(Integer(23)), Integer(3), Integer(4),␣
(continues on next page)

570

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

range(Integer(12)))>>> C = matrix(FiniteField(Integer(29)), Integer(4), Integer(5),␣
˓→range(Integer(20)))>>> D = A.tensor_product(B)>>> D.parent()
Full MatrixSpace of 6 by 12 dense matrices over Finite Field of size 23>>> E = C.tensor_product(B)Traceback (most recent call last):...
TypeError: unsupported operand parent(s) for *:Finite Field of size 29 andFull MatrixSpace of 3 by 4 dense matrices over Finite Field of size 23
˓→The input is checked to be sure it is a matrix.
sage: A = matrix(QQ, 2, 2, range(4))
sage: A.tensor_product( junk )Traceback (most recent call last):...
TypeError: tensor product requires a second matrix, not junk>>> from sage.all import *>>> A = matrix(QQ, Integer(2), Integer(2), range(Integer(4)))>>> A.tensor_product( junk )Traceback (most recent call last):...
TypeError: tensor product requires a second matrix, not junktrace()
Return the trace of self, which is the sum of the diagonal entries of self.
INPUT:• self – a square matrix
OUTPUT: element of the base ring of self
EXAMPLES:
sage: a = matrix(3, 3, range(9)); a[0 1 2][3 4 5][6 7 8]sage: a.trace()12sage: a = matrix({(1,1): 10, (2,1): -3, (2,2): 4/3}); a[ 000][ 0 100][ 0 -3 4/3]
sage: a.trace()
34/3>>> from sage.all import *>>> a = matrix(Integer(3), Integer(3), range(Integer(9))); a[0 1 2][3 4 5][6 7 8](continues on next page)571

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> a.trace()12>>> a = matrix({(Integer(1),Integer(1)): Integer(10), (Integer(2),˓→Integer(1)): -Integer(3), (Integer(2),Integer(2)): Integer(4)/Integer(3)});␣
˓→a
[ 0
0
0]
[ 0 100][ 0 -3 4/3]>>> a.trace()
34/3

trace_of_product(other)
Returns the trace of self * other without computing the entire product.
EXAMPLES:
sage: M = random_matrix(ZZ, 10, 20)
sage: N = random_matrix(ZZ, 20, 10)
sage: M.trace_of_product(N) == (M*N).trace()
True>>> from sage.all import *>>> M = random_matrix(ZZ, Integer(10), Integer(20))>>> N = random_matrix(ZZ, Integer(20), Integer(10))>>> M.trace_of_product(N) == (M*N).trace()
True

visualize_structure(maxsize=512)
Visualize the non-zero entries
White pixels are put at positions with zero entries. If ‘maxsize’ is given, then the maximal dimension in either
x or y direction is set to ‘maxsize’ depending on which is bigger. If the image is scaled, the darkness of the
pixel reflects how many of the represented entries are nonzero. So if e.g. one image pixel actually represents
a 2x2 submatrix, the dot is darker the more of the four values are nonzero.
INPUT:• maxsize – integer (default: 512). Maximal dimension in either x or y direction of the resulting image.
If None or a maxsize larger than max(self.nrows(),self.ncols()) is given the image will
have the same pixelsize as the matrix dimensions.
OUTPUT:
Bitmap image as an instance of Image.
EXAMPLES:
sage: # needs sage.rings.real_mpfr
sage: M = random_matrix(CC, 5, 7)
sage: for i in range(5): M[i,i] = 0
sage: M[4, 0] = M[0, 6] = M[4, 6] = 0
sage: img = M.visualize_structure(); img
˓→needs pillow
7x5px 24-bit RGB image#␣>>> from sage.all import *>>> # needs sage.rings.real_mpfr(continues on next page)

572

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> M = random_matrix(CC, Integer(5), Integer(7))>>> for i in range(Integer(5)): M[i,i] = Integer(0)>>> M[Integer(4), Integer(0)] = M[Integer(0), Integer(6)] = M[Integer(4),␣
˓→Integer(6)] = Integer(0)>>> img = M.visualize_structure(); img#␣˓→needs pillow
7x5px 24-bit RGB image

You can use save() to save the resulting image:
sage: # needs pillow sage.rings.real_mpfr
sage: filename = tmp_filename(ext= .png )sage: img.save(filename)sage: with open(filename, rb ) as fobj:....:
fobj.read().startswith(b \x89PNG )True>>> from sage.all import *>>> # needs pillow sage.rings.real_mpfr>>> filename = tmp_filename(ext= .png )>>> img.save(filename)>>> with open(filename, rb ) as fobj:...
fobj.read().startswith(b \x89PNG )True

wiedemann(i, t=0)
Application of Wiedemann’s algorithm to the i-th standard basis vector.
INPUT:• i – an integer• t – an integer (default: 0) if t is nonzero, use only the first t linear recurrence relations.
IMPLEMENTATION: This is a toy implementation.
EXAMPLES:
sage: t = matrix(QQ, 3, 3, range(9)); t[0 1 2][3 4 5][6 7 8]sage: t.wiedemann(0)x^2 - 12*x - 18sage: t.charpoly()
˓→needs sage.libs.parix^3 - 12*x^2 - 18*x>>> from sage.all import *>>> t = matrix(QQ, Integer(3), Integer(3), range(Integer(9))); t[0 1 2][3 4 5][6 7 8]>>> t.wiedemann(Integer(0))
x^2 - 12*x - 18>>> t.charpoly()
˓→needs sage.libs.parix^3 - 12*x^2 - 18*x

#␣

#␣

573

Matrices and Spaces of Matrices, Release 10.4

zigzag_form(subdivide=True, transformation=False)
Find a matrix in ZigZag form that is similar to self.
INPUT:• self – a square matrix with entries from an exact field.
• transformation – (default: False); if True return a change-of-basis matrix relating the matrix
and its ZigZag form.
• subdivide – (default: True); if True the ZigZag form matrix is subdivided according to the companion matrices described in the output section below.
OUTPUT:
A matrix in ZigZag form has blocks on the main diagonal that are companion matrices. The first companion
matrix has ones just below the main diagonal. The last column has the negatives of coefficients of a monicpolynomial, but not the leading one. Low degree monomials have their coefficients in the earlier rows. The
second companion matrix is like the first only transposed. The third is like the first. The fourth is like thesecond. And so on.
These blocks on the main diagonal define blocks just off the diagonal. To the right of the first companion
matrix, and above the second companion matrix is a block that is totally zero, except the entry of the first row
and first column may be a one. Below the second block and to the left of the third block is a block that is
totally zero, except the entry of the first row and first column may be one. This alternating pattern continues.
It may now be apparent how this form gets its name. Any other entry of the matrix is zero. So this form isreminiscent of rational canonical form and is a good precursor to that form.
If transformation is True, then the output is a pair of matrices. The first is the form Z and the second
is an invertible matrix U such that U.inverse()*self*U equals Z. In other words, the representation ofself with respect to the columns of U will be Z.
If subdivide is True then the matrix returned as the form is partitioned according to the companion matrices
and these may be manipulated by several different matrix methods.
For output that may be more useful as input to other routines, see the helper method _zigzag_form().
Note: An effort has been made to optimize computation of the form, but no such work has been done forthe computation of the transformation matrix, so for fastest results do not request the transformation matrix.
ALGORITHM:
ZigZag form, and its computation, are due to Arne Storjohann and are described in [Sto2000] and [Sto1998],
where the former is more representative of the code here.
EXAMPLES:
Two examples that illustrate ZigZag form well. Notice that this is not a canonical form. The two matrices
below are similar, since they have equal Jordan canonical forms, yet their ZigZag forms are quite different. In
other words, while the computation of the form is deterministic, the final result, when viewed as a property
of a linear transformation, is dependent on the basis used for the matrix representation.
sage: A = matrix(QQ, [[-68,69, -27, -11, -65,
9, -181, -32],
....:
[-52,
52, -27, -8, -52, -16, -133, -14],....:[ 92, -97, 47, 14, 90, 32, 241, 18],....:
[139, -144, 60, 18, 148, -10, 362, 77],....:
[ 40, -41, 12,6, 45, -24, 105, 42],
....:
[-46,
48, -20, -7, -47,
0, -122, -22],
....:
[-26,
27, -13, -4, -29, -6, -66, -14],(continues on next page)

574

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

....:
[-33,
34, -13, -5, -35,
sage: Z, U = A.zigzag_form(transformation=True)
sage: Z[ 000 40| 1
0| 0
0]
[ 1
0
0 52| 0
0| 0
0]
[ 0
1
0 18| 0
0| 0
0]
[ 0
0
1 -1| 00| 00][---------------+-------+-------]
[ 0
0
0
0| 0
1| 0
0]
[ 0
0
0
0|-25 10| 00][---------------+-------+-------]
[ 0
0
0
0| 1
0| 0 -4]
[ 0
0
0
0| 0
0| 1 -4]
sage: U.inverse()*A*U == Z
True

7,

-87, -23]])

sage: B = matrix(QQ, [[ 16, 69, -13,
2, -52, 143,
90, -3],....:[ 26, 54,6, -5, -28,
73,
73, -48],....:[-16, -79, 12, -10, 64, -142, -115, 41],....:
[ 27, -7, 21, -33, 39, -20, -42, 43],....:
[ 8, -75, 34, -32, 86, -156, -130, 42],....:
[ 2, -17,
7, -8, 20, -33, -31, 16],....:[-24, -80,
7, -3, 56, -136, -112, 42],....:
[ -6, -19,
0, -1, 13, -28, -27, 15]])
sage: Z, U = B.zigzag_form(transformation=True)
sage: Z[00000 1000|
0|
0]
[
1
0
0
0
0 900|
0|
0]
[
0
1
0
0
0 -30|
0|
0]
[
0
0
1
0
0 -153|
0|
0]
[
0
0
0
1
0
3|
0|
0]
[
0
0
0
0
1
9|
0|
0]
[-----------------------------+----+----]
[
0
0
0
0
0
0| -2|
0][-----------------------------+----+----]
[
0
0
0
0
0
0|
1| -2]
sage: U.inverse()*B*U == Z
True
sage: A.jordan_form() == B.jordan_form()
˓→needs sage.combinat sage.libs.pari
True

#␣

>>> from sage.all import *>>> A = matrix(QQ, [[-Integer(68),Integer(69), -Integer(27), -Integer(11),␣
˓→-Integer(65),Integer(9), -Integer(181), -Integer(32)],...
[-Integer(52),Integer(52), -Integer(27), -Integer(8),␣
˓→-Integer(52), -Integer(16), -Integer(133), -Integer(14)],...
[ Integer(92), -Integer(97), Integer(47), Integer(14),␣
˓→ Integer(90),Integer(32), Integer(241), Integer(18)],...
[Integer(139), -Integer(144), Integer(60), Integer(18),␣
˓→Integer(148), -Integer(10),Integer(362), Integer(77)],...
[ Integer(40), -Integer(41), Integer(12),Integer(6),␣
˓→ Integer(45), -Integer(24),Integer(105), Integer(42)],...
[-Integer(46),Integer(48), -Integer(20), -Integer(7),␣
˓→-Integer(47),Integer(0), -Integer(122), -Integer(22)],(continues on next page)575

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
[-Integer(26),Integer(27), -Integer(13),˓→-Integer(29),-Integer(6), -Integer(66), -Integer(14)],...
[-Integer(33),Integer(34), -Integer(13),˓→-Integer(35),Integer(7), -Integer(87), -Integer(23)]])>>> Z, U = A.zigzag_form(transformation=True)
>>> Z
[ 0
0
0 40| 1
0| 0
0]
[ 1
0
0 52| 0
0| 0
0]
[ 0
1
0 18| 0
0| 0
0]
[ 0
0
1 -1| 00| 00][---------------+-------+-------]
[ 0
0
0
0| 0
1| 0
0]
[ 0
0
0
0|-25 10| 00][---------------+-------+-------]
[ 0
0
0
0| 1
0| 0 -4]
[ 0
0
0
0| 0
0| 1 -4]>>> U.inverse()*A*U == Z
True

-Integer(4),␣
-Integer(5),␣

>>> B = matrix(QQ, [[ Integer(16), Integer(69), -Integer(13),Integer(2), ˓→Integer(52),Integer(143),
Integer(90), -Integer(3)],...
[ Integer(26), Integer(54),Integer(6), -Integer(5), ˓→Integer(28),Integer(73),Integer(73), -Integer(48)],...
[-Integer(16), -Integer(79), Integer(12), -Integer(10), ␣
˓→Integer(64), -Integer(142), -Integer(115),
Integer(41)],...
[ Integer(27), -Integer(7), Integer(21), -Integer(33), ␣
˓→Integer(39),-Integer(20), -Integer(42), Integer(43)],...
[ Integer(8), -Integer(75), Integer(34), -Integer(32), ␣
˓→Integer(86), -Integer(156), -Integer(130),
Integer(42)],...
[ Integer(2), -Integer(17),Integer(7), -Integer(8), ␣
˓→Integer(20),-Integer(33), -Integer(31), Integer(16)],...
[-Integer(24), -Integer(80),Integer(7), -Integer(3), ␣
˓→Integer(56), -Integer(136), -Integer(112),
Integer(42)],...
[ -Integer(6), -Integer(19),Integer(0), -Integer(1), ␣
˓→Integer(13),-Integer(28), -Integer(27), Integer(15)]])>>> Z, U = B.zigzag_form(transformation=True)
>>> Z
[
0
0
0
0
0 1000|
0|
0]
[
1
0
0
0
0 900|
0|
0]
[
0
1
0
0
0 -30|
0|
0]
[
0
0
1
0
0 -153|
0|
0]
[
0
0
0
1
0
3|
0|
0]
[
0
0
0
0
1
9|
0|
0]
[-----------------------------+----+----]
[
0
0
0
0
0
0| -2|
0][-----------------------------+----+----]
[
0
0
0
0
0
0|
1| -2]>>> U.inverse()*B*U == Z
True>>> A.jordan_form() == B.jordan_form()
˓→needs sage.combinat sage.libs.pari
True

#␣

Two more examples, illustrating the two extremes of the zig-zag nature of this form. The first has a one ineach of the off-diagonal blocks, the second has all zeros in each off-diagonal block. Notice again that the two
matrices are similar, since their Jordan canonical forms are equal.

576

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

sage: C = matrix(QQ, [[2, 31, -10, -9, -125, 13, 62, -12],....:[0, 48, -16, -16, -188, 20, 92, -16],
....:
[0,
9, -1,
2, -33,
5, 18,
0],....:[0, 15, -5,
0, -59,7, 30, -4],....:
[0, -21,7,
2,84, -10, -42,
5],
....:
[0, -42, 14,
8, 167, -17, -84, 13],....:[0, -50, 17, 10, 199, -23, -98, 14],....:[0, 15, -5, -2, -59,
7, 30, -2]])
sage: Z, U = C.zigzag_form(transformation=True)
sage: Z
[2|1|0|0|0|0|0|0][-+-+-+-+-+-+-+-][0|2|0|0|0|0|0|0][-+-+-+-+-+-+-+-][0|1|2|1|0|0|0|0][-+-+-+-+-+-+-+-][0|0|0|2|0|0|0|0][-+-+-+-+-+-+-+-][0|0|0|1|2|1|0|0][-+-+-+-+-+-+-+-][0|0|0|0|0|2|0|0][-+-+-+-+-+-+-+-][0|0|0|0|0|1|2|1][-+-+-+-+-+-+-+-][0|0|0|0|0|0|0|2]
sage: U.inverse()*C*U == Z
True
sage: D = matrix(QQ, [[ -4,3,
7,2, -4,
5,
7,
-3],
....:
[ -6,
5,
7,
2, -4,
5,
7,
-3],
....:
[ 21, -12,
89, 25,8, 27,
98, -95],
....:
[ -9,
5, -44, -11, -3, -13, -48,
47],
....:
[ 23, -13,
74, 21, 12, 22,
85, -84],....:[ 31, -18, 135, 38, 12, 47, 155, -147],....:[-33, 19, -138, -39, -13, -45, -156, 151],
....:
[ -7,
4, -29, -8, -3, -10, -34, 34]])
sage: Z, U = D.zigzag_form(transformation=True)
sage: Z[ 0 -4| 0 0| 0 0| 0 0]
[ 1 4| 0 0| 0 0| 0 0][-----+-----+-----+-----][ 0 0| 0 1| 0 0| 0 0]
[ 0 0|-4 4| 0 0| 0 0][-----+-----+-----+-----][ 0 0| 0 0| 0 -4| 0 0]
[ 0 0| 0 0| 1 4| 0 0][-----+-----+-----+-----][ 0 0| 0 0| 0 0| 0 1]
[ 0 0| 0 0| 0 0|-4 4]sage: U.inverse()*D*U == Z
True
sage: C.jordan_form() == D.jordan_form()
˓→needs sage.combinat sage.libs.pari
True

#␣

>>> from sage.all import *(continues on next page)577

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> C = matrix(QQ, [[Integer(2), Integer(31), -Integer(10), -Integer(9), ˓→Integer(125),
Integer(13), Integer(62), -Integer(12)],...
[Integer(0), Integer(48), -Integer(16), -Integer(16), ˓→Integer(188),
Integer(20), Integer(92), -Integer(16)],...
[Integer(0),Integer(9), -Integer(1),Integer(2), ˓→Integer(33),Integer(5), Integer(18),Integer(0)],...
[Integer(0), Integer(15), -Integer(5),Integer(0), ˓→Integer(59),Integer(7), Integer(30), -Integer(4)],...
[Integer(0), -Integer(21),Integer(7),Integer(2), ␣
˓→Integer(84), -Integer(10), -Integer(42),Integer(5)],...
[Integer(0), -Integer(42), Integer(14),Integer(8), ␣
˓→Integer(167), -Integer(17), -Integer(84),Integer(13)],...
[Integer(0), -Integer(50), Integer(17), Integer(10), ␣
˓→Integer(199), -Integer(23), -Integer(98),Integer(14)],...
[Integer(0), Integer(15), -Integer(5), -Integer(2), ˓→Integer(59),Integer(7), Integer(30), -Integer(2)]])>>> Z, U = C.zigzag_form(transformation=True)>>> Z[2|1|0|0|0|0|0|0][-+-+-+-+-+-+-+-][0|2|0|0|0|0|0|0][-+-+-+-+-+-+-+-][0|1|2|1|0|0|0|0][-+-+-+-+-+-+-+-][0|0|0|2|0|0|0|0][-+-+-+-+-+-+-+-][0|0|0|1|2|1|0|0][-+-+-+-+-+-+-+-][0|0|0|0|0|2|0|0][-+-+-+-+-+-+-+-][0|0|0|0|0|1|2|1][-+-+-+-+-+-+-+-][0|0|0|0|0|0|0|2]>>> U.inverse()*C*U == Z
True>>> D = matrix(QQ, [[ -Integer(4),Integer(3),Integer(7),Integer(2),␣
˓→ -Integer(4),Integer(5),Integer(7),-Integer(3)],...
[ -Integer(6),Integer(5),Integer(7),Integer(2),␣
˓→ -Integer(4),Integer(5),Integer(7),-Integer(3)],...
[ Integer(21), -Integer(12),Integer(89), Integer(25),␣
˓→
Integer(8), Integer(27),Integer(98), -Integer(95)],...
[ -Integer(9),Integer(5), -Integer(44), -Integer(11),␣
˓→ -Integer(3), -Integer(13),-Integer(48),Integer(47)],...
[ Integer(23), -Integer(13),Integer(74), Integer(21),␣
˓→ Integer(12),Integer(22),Integer(85), -Integer(84)],...
[ Integer(31), -Integer(18), Integer(135), Integer(38),␣
˓→ Integer(12),Integer(47), Integer(155), -Integer(147)],...
[-Integer(33), Integer(19), -Integer(138), -Integer(39),␣
˓→-Integer(13), -Integer(45), -Integer(156),
Integer(151)],...
[ -Integer(7),Integer(4), -Integer(29), -Integer(8),␣
˓→ -Integer(3), -Integer(10),-Integer(34), Integer(34)]])>>> Z, U = D.zigzag_form(transformation=True)>>> Z[ 0 -4| 0 0| 0 0| 0 0]
[ 1 4| 0 0| 0 0| 0 0][-----+-----+-----+-----](continues on next page)

578

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 0 0| 0 1| 0 0| 0 0]
[ 0 0|-4 4| 0 0| 0 0][-----+-----+-----+-----][ 0 0| 0 0| 0 -4| 0 0]
[ 0 0| 0 0| 1 4| 0 0][-----+-----+-----+-----][ 0 0| 0 0| 0 0| 0 1]
[ 0 0| 0 0| 0 0|-4 4]>>> U.inverse()*D*U == Z
True>>> C.jordan_form() == D.jordan_form()
˓→needs sage.combinat sage.libs.pari
True

#␣

ZigZag form is achieved entirely with the operations of the field, so while the eigenvalues may lie outside thefield, this does not impede the computation of the form.
sage: # needs sage.rings.finite_rings
sage: F.<a> = GF(5^4)
sage: A = matrix(F, [[a,0, 0, a + 3],....:[0,a^2 + 1, 0,
0],
....:
[
0,
0,a^3,
0],....:[a^2 +4 ,0,0,a + 2]])sage: A.zigzag_form()[
0 a^3 + 2*a^2 + 2*a + 2|
0|
␣
˓→
0]
[
1
2*a + 2|0|␣˓→0][-------------------------------------------+---------------------+----------˓→----------]
[
0
0|
a^3|
␣
˓→
0]
[-------------------------------------------+---------------------+----------˓→----------]
[
0
0|
0|
␣
˓→
a^2 + 1]
sage: A.eigenvalues()
Traceback (most recent call last):...
NotImplementedError: algebraic closures of finite fields are only implemented␣
˓→for prime fields>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> F = GF(Integer(5)**Integer(4), names=( a ,)); (a,) = F._first_ngens(1)>>> A = matrix(F, [[a,Integer(0), Integer(0), a + Integer(3)],...
[Integer(0),a**Integer(2) + Integer(1), Integer(0), ␣˓→Integer(0)],...
[Integer(0),Integer(0),a**Integer(3),␣˓→Integer(0)],...
[a**Integer(2) +Integer(4) ,Integer(0),Integer(0),˓→a + Integer(2)]])>>> A.zigzag_form()[
0 a^3 + 2*a^2 + 2*a + 2|
0|
␣
˓→
0]
(continues on next page)579

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[1

2*a + 2|0|
␣0][-------------------------------------------+---------------------+----------˓→----------]
[
0
0|
a^3|
␣
˓→
0]
[-------------------------------------------+---------------------+----------˓→----------]
[
0
0|
0|
␣
˓→
a^2 + 1]>>> A.eigenvalues()
Traceback (most recent call last):...
NotImplementedError: algebraic closures of finite fields are only implemented␣
˓→for prime fields
˓→Subdivisions are optional.
sage: F.<a> = GF(5^4)˓→needs sage.rings.finite_rings
sage: A = matrix(F, [[a,0, 0, a + 3],
˓→needs sage.rings.finite_rings....:[0,a^2 + 1, 0,
0],
....:
[
0,
0,a^3,
0],....:[a^2 +4 ,0,0,a + 2]])sage: A.zigzag_form(subdivide=False)
˓→needs sage.rings.finite_rings[
0 a^3 + 2*a^2 + 2*a + 2
˓→
0]
[
1
2*a + 2
˓→
0]
[
0
0
˓→
0]
[
0
0
˓→
a^2 + 1]

#␣
#␣

#␣
0

␣

0

␣

a^3

␣

0

␣

>>> from sage.all import *>>> F = GF(Integer(5)**Integer(4), names=( a ,)); (a,) = F._first_ngens(1)#␣
˓→needs sage.rings.finite_rings>>> A = matrix(F, [[a,Integer(0), Integer(0), a + Integer(3)],␣˓→# needs sage.rings.finite_rings...
[
Integer(0),a**Integer(2) + Integer(1), Integer(0), ␣˓→Integer(0)],...
[Integer(0),Integer(0),a**Integer(3),␣˓→Integer(0)],...
[a**Integer(2) +Integer(4) ,Integer(0),Integer(0),˓→a + Integer(2)]])>>> A.zigzag_form(subdivide=False)#␣˓→needs sage.rings.finite_rings[
0 a^3 + 2*a^2 + 2*a + 2
0
␣
˓→
0]
[
1
2*a + 2
0
␣
˓→
0]
[
0
0
a^3
␣
˓→
0]
[
0
0
0
␣
˓→
a^2 + 1]580

Chapter 8. Base class for matrices, part 2

Matrices and Spaces of Matrices, Release 10.4

exception sage.matrix.matrix2.NotFullRankError
Bases: ValueError
An error that indicates that a matrix is not of full rank.
The fact that a square system is rank-deficient sometimes only becomes apparent while attempting tosolve it. The methods Matrix.solve_left() and Matrix.solve_right() defer to Matrix.
_solve_right_nonsingular_square() for square systems, and that method raises this error if the system turns out to be singular.
sage.matrix.matrix2.decomp_seq(v)This function is used internally be the decomposition matrix method. It takes a list of tuples and produces a sequencethat is correctly sorted and prints with carriage returns.
EXAMPLES:
sage: from sage.matrix.matrix2 import decomp_seq
sage: V = [(QQ^3, 2), (QQ^2, 1)]
sage: decomp_seq(V)[(Vector space of dimension 2 over Rational Field, 1),(Vector space of dimension 3 over Rational Field, 2)]>>> from sage.all import *>>> from sage.matrix.matrix2 import decomp_seq>>> V = [(QQ**Integer(3), Integer(2)), (QQ**Integer(2), Integer(1))]>>> decomp_seq(V)[(Vector space of dimension 2 over Rational Field, 1),(Vector space of dimension 3 over Rational Field, 2)]

sage.matrix.matrix2.ideal_or_fractional(R, *args)

581

Matrices and Spaces of Matrices, Release 10.4

582

Chapter 8. Base class for matrices, part 2

CHAPTER

NINE

GENERIC ASYMPTOTICALLY FAST STRASSEN ALGORITHMS

Sage implements asymptotically fast echelon form and matrix multiplication algorithms.
class sage.matrix.strassen.int_range(indices=None, range=None)
Bases: object
Represent a list of integers as a list of integer intervals.
Note: Repetitions are not considered.
Useful class for dealing with pivots in the strassen echelon, could have much more general application
INPUT:
It can be one of the following:• indices – integer, start of the unique interval• range – integer, length of the unique intervalOR• indices – list of integers, the integers to wrap into intervals
OR• indices – None (default), shortcut for an empty list
OUTPUT:
An instance of int_range, i.e. a list of pairs (start, length).
EXAMPLES:
From a pair of integers:
sage: from sage.matrix.strassen import int_range
sage: int_range(2, 4)[(2, 4)]>>> from sage.all import *>>> from sage.matrix.strassen import int_range>>> int_range(Integer(2), Integer(4))[(2, 4)]

Default:

583

Matrices and Spaces of Matrices, Release 10.4

sage: int_range()[]>>> from sage.all import *>>> int_range()[]

From a list of integers:
sage: int_range([1,2,3,4])[(1, 4)]sage: int_range([1,2,3,4,6,7,8])[(1, 4), (6, 3)]
sage: int_range([1,2,3,4,100,101,102])[(1, 4), (100, 3)]
sage: int_range([1,1000,2,101,3,4,100,102])[(1, 4), (100, 3), (1000, 1)]>>> from sage.all import *>>> int_range([Integer(1),Integer(2),Integer(3),Integer(4)])[(1, 4)]>>> int_range([Integer(1),Integer(2),Integer(3),Integer(4),Integer(6),Integer(7),˓→Integer(8)])[(1, 4), (6, 3)]>>> int_range([Integer(1),Integer(2),Integer(3),Integer(4),Integer(100),
˓→Integer(101),Integer(102)])[(1, 4), (100, 3)]>>> int_range([Integer(1),Integer(1000),Integer(2),Integer(101),Integer(3),˓→Integer(4),Integer(100),Integer(102)])[(1, 4), (100, 3), (1000, 1)]

Repetitions are not considered:
sage: int_range([1,2,3])[(1, 3)]sage: int_range([1,1,1,1,2,2,2,3])[(1, 3)]>>> from sage.all import *>>> int_range([Integer(1),Integer(2),Integer(3)])[(1, 3)]>>> int_range([Integer(1),Integer(1),Integer(1),Integer(1),Integer(2),Integer(2),˓→Integer(2),Integer(3)])[(1, 3)]AUTHORS:• Robert Bradshaw
intervals()
Return the list of intervals.
OUTPUT:
A list of pairs of integers.
EXAMPLES:

584

Chapter 9. Generic Asymptotically Fast Strassen Algorithms

Matrices and Spaces of Matrices, Release 10.4

sage: from sage.matrix.strassen import int_range
sage: I = int_range([4,5,6,20,21,22,23])
sage: I.intervals()[(4, 3), (20, 4)]
sage: type(I.intervals())<... list >>>> from sage.all import *>>> from sage.matrix.strassen import int_range>>> I = int_range([Integer(4),Integer(5),Integer(6),Integer(20),Integer(21),
˓→Integer(22),Integer(23)])>>> I.intervals()[(4, 3), (20, 4)]>>> type(I.intervals())<... list >to_list()Return the (sorted) list of integers represented by this object.
OUTPUT:
A list of integers.
EXAMPLES:
sage: from sage.matrix.strassen import int_range
sage: I = int_range([6,20,21,4,5,22,23])
sage: I.to_list()[4, 5, 6, 20, 21, 22, 23]>>> from sage.all import *>>> from sage.matrix.strassen import int_range>>> I = int_range([Integer(6),Integer(20),Integer(21),Integer(4),Integer(5),˓→Integer(22),Integer(23)])>>> I.to_list()[4, 5, 6, 20, 21, 22, 23]
sage: I = int_range(34, 9)
sage: I.to_list()[34, 35, 36, 37, 38, 39, 40, 41, 42]>>> from sage.all import *>>> I = int_range(Integer(34), Integer(9))>>> I.to_list()[34, 35, 36, 37, 38, 39, 40, 41, 42]

Repetitions are not considered:
sage: I = int_range([1,1,1,1,2,2,2,3])
sage: I.to_list()[1, 2, 3]>>> from sage.all import *>>> I = int_range([Integer(1),Integer(1),Integer(1),Integer(1),Integer(2),˓→Integer(2),Integer(2),Integer(3)])>>> I.to_list()[1, 2, 3]585

Matrices and Spaces of Matrices, Release 10.4

sage.matrix.strassen.strassen_echelon(A, cutoff)
Compute echelon form, in place. Internal function, call with M.echelonize(algorithm=”strassen”) Based on workof Robert Bradshaw and David Harvey at MSRI workshop in 2006.
INPUT:• A – matrix window• cutoff – size at which algorithm reverts to naive Gaussian elimination and multiplication must be at least
1.
OUTPUT: The list of pivot columns
EXAMPLES:
sage: A = matrix(QQ, 7, [5, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 3, 1,␣
˓→0, -1, 0, 0, -1, 0, 1, 2, -1, 1, 0, -1, 0, 1, 3, -1, 1, 0, 0, -2, 0, 2, 0, 1, 0,
˓→ 0, -1, 0, 1, 0, 1])
sage: B = A.__copy__(); B._echelon_strassen(1); B[ 1 0 0 0 0 0 0]
[ 0 1 0 -1 0 1 0]
[ 0 0 1 0 0 0 0]
[ 0 0 0 0 1 0 0]
[ 0 0 0 0 0 0 1]
[ 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0]
sage: C = A.__copy__(); C._echelon_strassen(2); C == B
True
sage: C = A.__copy__(); C._echelon_strassen(4); C == B
True>>> from sage.all import *>>> A = matrix(QQ, Integer(7), [Integer(5), Integer(0), Integer(0), Integer(0),␣
˓→Integer(0), Integer(0), -Integer(1), Integer(0), Integer(0), Integer(1),␣
˓→Integer(0), Integer(0), Integer(0), Integer(0), Integer(0), -Integer(1),␣
˓→Integer(3), Integer(1), Integer(0), -Integer(1), Integer(0), Integer(0), ˓→Integer(1), Integer(0), Integer(1), Integer(2), -Integer(1), Integer(1),␣
˓→Integer(0), -Integer(1), Integer(0), Integer(1), Integer(3), -Integer(1),␣
˓→Integer(1), Integer(0), Integer(0), -Integer(2), Integer(0), Integer(2),␣
˓→Integer(0), Integer(1), Integer(0), Integer(0), -Integer(1), Integer(0),␣
˓→Integer(1), Integer(0), Integer(1)])>>> B = A.__copy__(); B._echelon_strassen(Integer(1)); B[ 1 0 0 0 0 0 0]
[ 0 1 0 -1 0 1 0]
[ 0 0 1 0 0 0 0]
[ 0 0 0 0 1 0 0]
[ 0 0 0 0 0 0 1]
[ 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0]>>> C = A.__copy__(); C._echelon_strassen(Integer(2)); C == B
True>>> C = A.__copy__(); C._echelon_strassen(Integer(4)); C == B
True
sage: n = 32; A = matrix(Integers(389),n,range(n^2))
sage: B = A.__copy__(); B._echelon_in_place_classical()sage: C = A.__copy__(); C._echelon_strassen(2)sage: B == C
True

586

Chapter 9. Generic Asymptotically Fast Strassen Algorithms

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> n = Integer(32); A = matrix(Integers(Integer(389)),n,range(n**Integer(2)))>>> B = A.__copy__(); B._echelon_in_place_classical()>>> C = A.__copy__(); C._echelon_strassen(Integer(2))>>> B == C
True

AUTHORS:• Robert Bradshaw
sage.matrix.strassen.strassen_window_multiply(C, A, B, cutoff)
Multiplies the submatrices specified by A and B, places result in C. Assumes that A and B have compatible dimensions to be multiplied, and that C is the correct size to receive the product, and that they are all defined overthe same ring.
Uses strassen multiplication at high levels and then uses MatrixWindow methods at low levels. EXAMPLES: The
following matrix dimensions are chosen especially to exercise the eight possible parity combinations that could
occur while subdividing the matrix in the strassen recursion. The base case in both cases will be a (4x5) matrix
times a (5x6) matrix.
sage: A = MatrixSpace(Integers(2^65), 64, 83).random_element()
sage: B = MatrixSpace(Integers(2^65), 83, 101).random_element()
sage: A._multiply_classical(B) == A._multiply_strassen(B, 3) #indirect doctest
True>>> from sage.all import *>>> A = MatrixSpace(Integers(Integer(2)**Integer(65)), Integer(64), Integer(83)).
˓→random_element()>>> B = MatrixSpace(Integers(Integer(2)**Integer(65)), Integer(83), Integer(101)).
˓→random_element()>>> A._multiply_classical(B) == A._multiply_strassen(B, Integer(3)) #indirect␣
˓→doctest
True

AUTHORS:• David Harvey• Simon King (2011-07): Improve memory efficiency; Issue #11610
sage.matrix.strassen.test(n, m, R, c=2)
INPUT:• n – integer• m – integer• R – ring• c – integer (default:2)
EXAMPLES:
sage: from sage.matrix.strassen import test
sage: for n in range(5):....:print("{} {}".format(n, test(2*n,n,Frac(QQ[ x ]),2)))0 True1 True2 True(continues on next page)587

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)3 True4 True>>> from sage.all import *>>> from sage.matrix.strassen import test>>> for n in range(Integer(5)):...
print("{} {}".format(n, test(Integer(2)*n,n,Frac(QQ[ x ]),Integer(2))))0 True1 True2 True3 True4 True588

Chapter 9. Generic Asymptotically Fast Strassen Algorithms

CHAPTERTENMINIMAL POLYNOMIALS OF LINEAR RECURRENCE SEQUENCES

AUTHORS:• William Steinsage.matrix.berlekamp_massey.berlekamp_massey(a)Use the Berlekamp-Massey algorithm to find the minimal polynomial of a linear recurrence sequence 𝑎.
The minimal polynomial of a linear recurrence {𝑎𝑟 } is by definition the unique monic polynomial 𝑔, such that
if {𝑎𝑟 } satisfies a linear recurrence 𝑎𝑗+𝑘 + 𝑏𝑗−1 𝑎𝑗−1+𝑘 + · · · + 𝑏0 𝑎𝑘 = 0 (for all 𝑘 ≥ 0), then 𝑔 divides the∑︀𝑗−1polynomial 𝑥𝑗 + 𝑖=0 𝑏𝑖 𝑥𝑖 .
INPUT:• a – a list of even length of elements of a field (or domain)
OUTPUT:the minimal polynomial of the sequence, as a polynomial over the field in which the entries of 𝑎 live
Warning: The result is only guaranteed to be correct on the full sequence if there exists a linear recurrenceof length less than half the length of 𝑎.
EXAMPLES:
sage: from sage.matrix.berlekamp_massey import berlekamp_massey
sage: berlekamp_massey([1,2,1,2,1,2])x^2 - 1
sage: berlekamp_massey([GF(7)(1), 19, 1, 19])x^2 + 6sage: berlekamp_massey([2,2,1,2,1,191,393,132])x^4 - 36727/11711*x^3 + 34213/5019*x^2 + 7024942/35133*x - 335813/1673
sage: berlekamp_massey(prime_range(2, 38))
˓→needs sage.libs.parix^6 - 14/9*x^5 - 7/9*x^4 + 157/54*x^3 - 25/27*x^2 - 73/18*x + 37/9

#␣>>> from sage.all import *>>> from sage.matrix.berlekamp_massey import berlekamp_massey>>> berlekamp_massey([Integer(1),Integer(2),Integer(1),Integer(2),Integer(1),˓→Integer(2)])
x^2 - 1>>> berlekamp_massey([GF(Integer(7))(Integer(1)), Integer(19), Integer(1),␣
˓→Integer(19)])x^2 + 6
(continues on next page)589

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> berlekamp_massey([Integer(2),Integer(2),Integer(1),Integer(2),Integer(1),˓→Integer(191),Integer(393),Integer(132)])x^4 - 36727/11711*x^3 + 34213/5019*x^2 + 7024942/35133*x - 335813/1673>>> berlekamp_massey(prime_range(Integer(2), Integer(38)))˓→# needs sage.libs.parix^6 - 14/9*x^5 - 7/9*x^4 + 157/54*x^3 - 25/27*x^2 - 73/18*x + 37/9

590

␣Chapter 10. Minimal Polynomials of Linear Recurrence Sequences

CHAPTERELEVENBASE CLASS FOR DENSE MATRICES

class sage.matrix.matrix_dense.Matrix_dense
Bases: Matrix
antitranspose()
Returns the antitranspose of self, without changing self.
EXAMPLES:
sage: A = matrix(2,3,range(6)); A[0 1 2][3 4 5]sage: A.antitranspose()
[5 2]
[4 1]
[3 0]
>>> from sage.all import *>>> A = matrix(Integer(2),Integer(3),range(Integer(6))); A[0 1 2][3 4 5]>>> A.antitranspose()
[5 2]
[4 1]
[3 0]
sage: A.subdivide(1,2); A[0 1|2][---+-][3 4|5]sage: A.antitranspose()
[5|2]
[-+-]
[4|1]
[3|0]
>>> from sage.all import *>>> A.subdivide(Integer(1),Integer(2)); A[0 1|2][---+-][3 4|5]>>> A.antitranspose()
[5|2]
[-+-]
(continues on next page)591

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[4|1]
[3|0]

transpose()
Returns 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,
sage: A = M([1,2,3,4])
sage: B = A.transpose()sage: print(B)
[1 3]
[2 4]
sage: print(A)
[1 2]
[3 4]

2)

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

.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]
sage: A.subdivide(None, 1); A
[1|2]
[3|4]
sage: A.transpose()
[1 3]
[---]
[2 4]
>>> from sage.all import *>>> A.subdivide(None, Integer(1)); A
[1|2]
[3|4]
>>> A.transpose()
[1 3]
[---]
[2 4]

592

Chapter 11. Base class for dense matrices

CHAPTERTWELVE

BASE CLASS FOR SPARSE MATRICES

class sage.matrix.matrix_sparse.Matrix_sparse
Bases: Matrix
antitranspose()
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]

See also:
transpose()
apply_map(phi, R=None, sparse=True)
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 – (default: True) whether to return a sparse or a dense matrix
OUTPUT: a matrix over R
EXAMPLES:

593

Matrices and Spaces of Matrices, Release 10.4

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

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

If we did not specify the codomain, the resulting matrix in the above case ends up over Z again:
sage: n = m.apply_map(lambda x: x%3)
sage: n.parent()
Full MatrixSpace of 10000 by 10000 sparse matrices over Integer Ringsage: 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)]2594

Chapter 12. Base class for sparse matrices

Matrices and Spaces of Matrices, Release 10.4

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]

If the map sends zero to a non-zero 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 Ringsage: 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

apply_morphism(phi)Apply the morphism phi to the coefficients of this sparse matrix.
The resulting matrix is over the codomain of phi.
INPUT:

595

Matrices and Spaces of Matrices, Release 10.4

• phi – a morphism, so phi is callable andphi.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

augment(right, subdivide=False)
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]
(continues on next page)

596

Chapter 12. Base class for sparse matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[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]

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]

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]change_ring(ring)
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:

597

Matrices and Spaces of Matrices, Release 10.4

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]

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][-------------------------------------]

charpoly(var='x', **kwds)
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 becomputed 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^2598

Chapter 12. Base class for sparse matrices

Matrices and Spaces of Matrices, Release 10.4>>> 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

density()
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()0sage: 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

determinant(**kwds)
Return the determinant of this matrix.
Note: the generic sparse determinant implementation in Sage is to just compute the determinant of thecorresponding 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

matrix_from_rows_and_columns(rows, columns)
Return the matrix constructed from self from the given rows and columns.
EXAMPLES:

599

Matrices and Spaces of Matrices, Release 10.4

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]

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]

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]

We can efficiently extract large submatrices:sage: A = random_matrix(ZZ, 100000, density=.00005, sparse=True)
˓→(4s on sage.math, 2012)
sage: B = A[50000:,:50000]# long time
sage: count = 0# long time␣(continues on next page)

600

Chapter 12. Base class for sparse matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

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 timeTrue>>> 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 timeTrue

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

AUTHORS:• Jaap Spies (2006-02-18)• Didier Deshommes: some Pyrex speedups implemented• Jason Grout: sparse matrix optimizationstranspose()
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.

601

Matrices and Spaces of Matrices, Release 10.4

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]

.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]

See also:
antitranspose()

602

Chapter 12. Base class for sparse matrices

CHAPTERTHIRTEEN

DENSE MATRICES OVER A GENERAL RING

class sage.matrix.matrix_generic_dense.Matrix_generic_dense
Bases: Matrix_dense
The Matrix_generic_dense class derives from Matrix, and defines functionality for dense matrices overany base ring. Matrices are represented by a list of elements in the base ring, and element access operations are
implemented in this class.
EXAMPLES:
sage: A = random_matrix(Integers(25)[ x ], 2)
sage: type(A)<class sage.matrix.matrix_generic_dense.Matrix_generic_dense >sage: TestSuite(A).run(skip= _test_minpoly )>>> from sage.all import *>>> A = random_matrix(Integers(Integer(25))[ x ], Integer(2))>>> type(A)<class sage.matrix.matrix_generic_dense.Matrix_generic_dense >>>> TestSuite(A).run(skip= _test_minpoly )Test comparisons:sage: A = random_matrix(Integers(25)[ x ], 2)
sage: A == A
True
sage: A < A + 1 or A[0, 0].coefficients()[0] == 24
True
sage: A+1 < A and A[0, 0].coefficients()[0] != 24
False>>> from sage.all import *>>> A = random_matrix(Integers(Integer(25))[ x ], Integer(2))>>> A == A
True>>> A < A + Integer(1) or A[Integer(0), Integer(0)].coefficients()[Integer(0)] ==␣
˓→Integer(24)True>>> A+Integer(1) < A and A[Integer(0), Integer(0)].coefficients()[Integer(0)] !=␣
˓→Integer(24)
False

Test hashing:603

Matrices and Spaces of Matrices, Release 10.4

sage: A = random_matrix(Integers(25)[ x ], 2)
sage: hash(A)Traceback (most recent call last):...
TypeError: mutable matrices are unhashable
sage: A.set_immutable()sage: H = hash(A)>>> from sage.all import *>>> A = random_matrix(Integers(Integer(25))[ x ], Integer(2))>>> hash(A)Traceback (most recent call last):...
TypeError: mutable matrices are unhashable>>> A.set_immutable()>>> H = hash(A)604

Chapter 13. Dense Matrices over a general ring

CHAPTERFOURTEENSPARSE MATRICES OVER A GENERAL RING

EXAMPLES:
sage: R.<x> = PolynomialRing(QQ)
sage: M = MatrixSpace(QQ[ x ], 2, 3, sparse=True); M
Full MatrixSpace of 2 by 3 sparse matrices over
Univariate Polynomial Ring in x over Rational Field
sage: a = M(range(6)); a[0 1 2][3 4 5]sage: b = M([x^n for n in range(6)]); b[ 1x x^2][x^3 x^4 x^5]
sage: a * b.transpose()[2*x^2 + x
2*x^5 + x^4][
5*x^2 + 4*x + 3 5*x^5 + 4*x^4 + 3*x^3]
sage: pari(a)*pari(b.transpose())˓→needs sage.libs.pari[2*x^2 + x, 2*x^5 + x^4; 5*x^2 + 4*x + 3, 5*x^5 + 4*x^4 + 3*x^3]
sage: c = copy(b); c[ 1
x x^2][x^3 x^4 x^5]
sage: c[0,0] = 5; c
[ 5x x^2][x^3 x^4 x^5]
sage: b[0,0]1sage: c.dict(){(0, 0): 5, (0, 1): x, (0, 2): x^2, (1, 0): x^3, (1, 1): x^4, (1, 2): x^5}
sage: c.list()[5, x, x^2, x^3, x^4, x^5]
sage: c.rows()[(5, x, x^2), (x^3, x^4, x^5)]
sage: TestSuite(c).run()sage: d = c.change_ring(CC[ x ]); d[5.00000000000000
x
x^2]
[
x^3
x^4
x^5]
sage: latex(c)\left(\begin{array}{rrr}
5 & x & x^{2} \\x^{3} & x^{4} & x^{5}\end{array}\right)
sage: c.sparse_rows()[(5, x, x^2), (x^3, x^4, x^5)]
sage: d = c.dense_matrix(); d#␣(continues on next page)605

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 5
x x^2][x^3 x^4 x^5]
sage: parent(d)Full MatrixSpace of 2 by 3 dense matrices
over Univariate Polynomial Ring in x over Rational Field
sage: c.sparse_matrix() is cTrue
sage: c.is_sparse()
True>>> from sage.all import *>>> R = PolynomialRing(QQ, names=( x ,)); (x,) = R._first_ngens(1)>>> M = MatrixSpace(QQ[ x ], Integer(2), Integer(3), sparse=True); M
Full MatrixSpace of 2 by 3 sparse matrices over
Univariate Polynomial Ring in x over Rational Field>>> a = M(range(Integer(6))); a[0 1 2][3 4 5]>>> b = M([x**n for n in range(Integer(6))]); b[ 1x x^2][x^3 x^4 x^5]>>> a * b.transpose()[2*x^2 + x
2*x^5 + x^4][
5*x^2 + 4*x + 3 5*x^5 + 4*x^4 + 3*x^3]>>> pari(a)*pari(b.transpose())˓→needs sage.libs.pari[2*x^2 + x, 2*x^5 + x^4; 5*x^2 + 4*x + 3, 5*x^5 + 4*x^4 + 3*x^3]>>> c = copy(b); c[ 1
x x^2][x^3 x^4 x^5]>>> c[Integer(0),Integer(0)] = Integer(5); c[ 5x x^2][x^3 x^4 x^5]>>> b[Integer(0),Integer(0)]1>>> c.dict(){(0, 0): 5, (0, 1): x, (0, 2): x^2, (1, 0): x^3, (1, 1): x^4, (1, 2): x^5}>>> c.list()[5, x, x^2, x^3, x^4, x^5]>>> c.rows()[(5, x, x^2), (x^3, x^4, x^5)]>>> TestSuite(c).run()>>> d = c.change_ring(CC[ x ]); d[5.00000000000000
x
x^2]
[
x^3
x^4
x^5]
>>> latex(c)\left(\begin{array}{rrr}
5 & x & x^{2} \\x^{3} & x^{4} & x^{5}\end{array}\right)>>> c.sparse_rows()[(5, x, x^2), (x^3, x^4, x^5)]>>> d = c.dense_matrix(); d[ 5x x^2][x^3 x^4 x^5]>>> parent(d)#␣(continues on next page)

606

Chapter 14. Sparse Matrices over a general ring

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Full MatrixSpace of 2 by 3 dense matrices
over Univariate Polynomial Ring in x over Rational Field>>> c.sparse_matrix() is c
True>>> c.is_sparse()
Trueclass sage.matrix.matrix_generic_sparse.Matrix_generic_sparse
Bases: Matrix_sparse
Generic sparse matrix.
The Matrix_generic_sparse class derives from Matrix_sparse, and defines functionality for sparse
matrices over any base ring. A generic sparse matrix is represented using a dictionary whose keys are pairs ofintegers (𝑖, 𝑗) and values in the base ring. The values of the dictionary must never be zero.
EXAMPLES:
sage: R.<a,b> = PolynomialRing(ZZ, a,b )sage: M = MatrixSpace(R,5,5,sparse=True)
sage: M({(0,0):5*a+2*b, (3,4): -a})
[5*a + 2*b
0
0
0
0]
[
0
0
0
0
0]
[
0
0
0
0
0]
[
0
0
0
0
-a]
[
0
0
0
0
0]
sage: M(3)[3 0 0 0 0]
[0 3 0 0 0]
[0 0 3 0 0]
[0 0 0 3 0]
[0 0 0 0 3]
sage: V = FreeModule(ZZ, 5,sparse=True)
sage: m = M([V({0:3}), V({2:2, 4:-1}), V(0), V(0), V({1:2})])sage: m[ 3 0 0 0 0]
[ 0 0 2 0 -1][ 0 0 0 0 0]
[ 0 0 0 0 0]
[ 0 2 0 0 0]>>> from sage.all import *>>> R = PolynomialRing(ZZ, a,b , names=( a , b ,)); (a, b,) = R._first_ngens(2)>>> M = MatrixSpace(R,Integer(5),Integer(5),sparse=True)>>> M({(Integer(0),Integer(0)):Integer(5)*a+Integer(2)*b, (Integer(3),˓→Integer(4)): -a})
[5*a + 2*b
0
0
0
0]
[
0
0
0
0
0]
[
0
0
0
0
0]
[
0
0
0
0
-a]
[
0
0
0
0
0]
>>> M(Integer(3))[3 0 0 0 0]
[0 3 0 0 0]
[0 0 3 0 0]
[0 0 0 3 0]
[0 0 0 0 3]
(continues on next page)607

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> V = FreeModule(ZZ, Integer(5),sparse=True)>>> m = M([V({Integer(0):Integer(3)}), V({Integer(2):Integer(2), Integer(4):˓→Integer(1)}), V(Integer(0)), V(Integer(0)), V({Integer(1):Integer(2)})])>>> m[ 3 0 0 0 0]
[ 0 0 2 0 -1][ 0 0 0 0 0]
[ 0 0 0 0 0]
[ 0 2 0 0 0]

Note: The datastructure can potentially be optimized. Firstly, as noticed in Issue #17663, we lose time in using
2-tuples to store indices. Secondly, there is no fast way to access non-zero elements in a given row/column.
sage.matrix.matrix_generic_sparse.Matrix_sparse_from_rows(X)INPUT:• X – nonempty list of SparseVector rows
OUTPUT: Sparse_matrix with those rows.
EXAMPLES:
sage: V = VectorSpace(QQ,20,sparse=True)
sage: v = V(0)sage: v[9] = 4
sage: from sage.matrix.matrix_generic_sparse import Matrix_sparse_from_rows
sage: Matrix_sparse_from_rows([v])[0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0]
sage: Matrix_sparse_from_rows([v, v, v, V(0)])[0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]>>> from sage.all import *>>> V = VectorSpace(QQ,Integer(20),sparse=True)>>> v = V(Integer(0))>>> v[Integer(9)] = Integer(4)>>> from sage.matrix.matrix_generic_sparse import Matrix_sparse_from_rows>>> Matrix_sparse_from_rows([v])[0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0]>>> Matrix_sparse_from_rows([v, v, v, V(Integer(0))])[0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]608

Chapter 14. Sparse Matrices over a general ring

CHAPTERFIFTEEN

DENSE MATRICES OVER THE INTEGER RINGAUTHORS:• William Stein• Robert Bradshaw• Marc Masdeu (August 2014). Implemented using FLINT, see Issue #16803.
• Jeroen Demeyer (October 2014): lots of fixes, see Issue #17090 and Issue #17094.
• Vincent Delecroix (February 2015): make it faster, see Issue #17822.
• Vincent Delecroix (May 2017): removed duplication of entries and cleaner linbox interface
EXAMPLES:
sage: a = matrix(ZZ, 3,3, range(9)); a[0 1 2][3 4 5][6 7 8]sage: a.det()0
sage: a[0,0] = 10; a.det()-30
sage: a.charpoly()x^3 - 22*x^2 + 102*x + 30
sage: b = -3*asage: a == b
False
sage: b < aTrue>>> from sage.all import *>>> a = matrix(ZZ, Integer(3),Integer(3), range(Integer(9))); a[0 1 2][3 4 5][6 7 8]>>> a.det()0>>> a[Integer(0),Integer(0)] = Integer(10); a.det()-30>>> a.charpoly()x^3 - 22*x^2 + 102*x + 30>>> b = -Integer(3)*a>>> a == b
False
(continues on next page)609

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> b < aTrueclass sage.matrix.matrix_integer_dense.Matrix_integer_dense
Bases: Matrix_dense
Matrix over the integers, implemented using FLINT.
On a 32-bit machine, they can have at most 232 − 1 rows or columns. On a 64-bit machine, matrices can have at
most 264 − 1 rows or columns.
EXAMPLES:
sage: a = MatrixSpace(ZZ,3)(2); a[2 0 0][0 2 0][0 0 2]sage: a = matrix(ZZ,1,3, [1,2,-3]); a[ 1 2 -3]
sage: a = MatrixSpace(ZZ,2,4)(2); a
Traceback (most recent call last):...
TypeError: nonzero scalar matrix must be square>>> from sage.all import *>>> a = MatrixSpace(ZZ,Integer(3))(Integer(2)); a[2 0 0][0 2 0][0 0 2]>>> a = matrix(ZZ,Integer(1),Integer(3), [Integer(1),Integer(2),-Integer(3)]); a[ 1 2 -3]>>> a = MatrixSpace(ZZ,Integer(2),Integer(4))(Integer(2)); a
Traceback (most recent call last):...
TypeError: nonzero scalar matrix must be square

BKZ(delta=None, algorithm='fpLLL', fp=None, block_size=10, prune=0, use_givens=False, precision=0,
proof=None, **kwds)
Return the result of running Block Korkin-Zolotarev reduction on self interpreted as a lattice.
INPUT:• delta – (default: 0.99) LLL parameter• algorithm – (default: "fpLLL") "fpLLL" or "NTL"• fp – floating point number implementation– None – NTL’s exact reduction or fpLLL’s wrapper (default)–

fp – double precision: NTL’s FP or fpLLL’s double–

ld – long doubles (fpLLL only)–

qd – NTL’s QP- qd1 – quad doubles: Uses quad_float precision
to compute Gram-Schmidt, but uses double precision in the search phase of the block reduction algorithm. This seems adequate for most purposes, and is faster than qd , which uses
quad_float precision uniformly throughout (NTL only).
610

Chapter 15. Dense matrices over the integer ring

Matrices and Spaces of Matrices, Release 10.4–

xd – extended exponent: NTL’s XD or fpLLL’s dpe–

rr – arbitrary precision: NTL’RR or fpLLL’s MPFR

• block_size – (default: 10) Specifies the size of the blocks in the reduction. High values yield shorter
vectors, but the running time increases double exponentially with block_size. block_size should
be between 2 and the number of rows of self.
• proof – (default: same as proof.linear_algebra()) Insist on full BKZ reduction. If disabled
and fplll is called, reduction is much faster but the result is not fully BKZ reduced.
NTL SPECIFIC INPUT:• prune – (default: 0) The optional parameter prune can be set to any positive number to invoke
the Volume Heuristic from [SH1995]. This can significantly reduce the running time, and hence allow
much bigger block size, but the quality of the reduction is of course not as good in general. Higher
values of prune mean better quality, and slower running time. When prune is 0, pruning is disabled.
Recommended usage: for block_size==30, set 10 <= prune <=15.
• use_givens – Use Givens orthogonalization. Only applies to approximate reduction using NTL. Thisis a bit slower, but generally much more stable, and is really the preferred orthogonalization strategy. For
a nice description of this, see Chapter 5 of [GL1996].
fpLLL SPECIFIC INPUT:• precision – (default: 0 for automatic choice) bit precision to use if fp= rr is set• **kwds – keywords to be passed to fpylll. See fpylll.BKZ.Param for details.
Also, if the verbose level is at least 2, some output is printed during the computation.
EXAMPLES:
sage: A = Matrix(ZZ,3,3,range(1,10))
sage: A.BKZ()[ 0 0 0][ 2 1 0][-1 1 3]sage: A = Matrix(ZZ,3,3,range(1,10))
sage: A.BKZ(use_givens=True)[ 0 0 0][ 2 1 0][-1 1 3]sage: A = Matrix(ZZ,3,3,range(1,10))
sage: A.BKZ(fp="fp")[ 0 0 0][ 2 1 0][-1 1 3]>>> from sage.all import *>>> A = Matrix(ZZ,Integer(3),Integer(3),range(Integer(1),Integer(10)))>>> A.BKZ()[ 0 0 0][ 2 1 0][-1 1 3]>>> A = Matrix(ZZ,Integer(3),Integer(3),range(Integer(1),Integer(10)))>>> A.BKZ(use_givens=True)(continues on next page)611

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[ 0
[ 2
[-1

0
1
1

0]
0]
3]

>>> A = Matrix(ZZ,Integer(3),Integer(3),range(Integer(1),Integer(10)))>>> A.BKZ(fp="fp")[ 0 0 0][ 2 1 0][-1 1 3]

ALGORITHM:
Calls either NTL or fpLLL.
LLL(delta=None, eta=None, algorithm='fpLLL:wrapper', fp=None, prec=0, early_red=False, use_givens=False,
use_siegel=False, transformation=False, **kwds)
Return LLL-reduced or approximated LLL reduced matrix 𝑅 of the lattice generated by the rows of self.
A set of vectors (𝑏1 , 𝑏2 , ..., 𝑏𝑑 ) is (𝛿, 𝜂)-LLL-reduced if the two following conditions hold:• For any 𝑖 > 𝑗, we have |𝜇𝑖,𝑗 | ≤ 𝜂.
• For any 𝑖 < 𝑑, we have 𝛿|𝑏*𝑖 |2 ≤ |𝑏*𝑖+1 + 𝜇𝑖+1,𝑖 𝑏*𝑖 |2 ,where 𝜇𝑖,𝑗 = ⟨𝑏𝑖 , 𝑏*𝑗 ⟩/⟨𝑏*𝑗 , 𝑏*𝑗 ⟩ and 𝑏*𝑖 is the 𝑖-th vector of the Gram-Schmidt orthogonalisation of(𝑏1 , 𝑏2 , ..., 𝑏𝑑 ).
The default reduction parametersare 𝛿 = 0.99 and 𝜂 = 0.501. The parameters 𝛿 and 𝜂 must satisfy 0.25 <√𝛿 ≤ 1.0 and 0.5 ≤ 𝜂 < 𝛿. Polynomial time complexity is only guaranteed for 𝛿 < 1. Not every algorithm
admits the case 𝛿 = 1.
If the matrix has a nonzero kernel, the LLL-reduced matrix will contain zero rows, so that the output has thesame dimensions as the input. The transformation matrix is always invertible over the integers.
Also the rank of self is cached if it is computed during the reduction. Note that in general this only happens
when self.rank() == self.ncols() and the exact algorithm is used.
INPUT:• delta – (default: 0.99) 𝛿 parameter as described above, ignored by pari• eta – (default: 0.501) 𝜂 parameter as described above, ignored by NTL and pari
• algorithm – string; one of the algorithms listed below (default: "fpLLL:wrapper").
• fp – floating point number implementation, ignored by pari:– None – NTL’s exact reduction or fpLLL’s wrapper–

fp – double precision: NTL’s FP or fpLLL’s double–

ld – long doubles (fpLLL only)–

qd – NTL’s QP–

xd – extended exponent: NTL’s XD or fpLLL’s dpe–

rr – arbitrary precision: NTL’s RR or fpLLL’s MPFR

• prec – (default: auto choose) precision, ignored by NTL and pari
• early_red – (default: False) perform early reduction, ignored by NTL and pari
• use_givens – (default: False) use Givens orthogonalization. Only applies to approximate reduction
using NTL. This is slower but generally more stable.
612

Chapter 15. Dense matrices over the integer ring

Matrices and Spaces of Matrices, Release 10.4

• use_siegel – (default: False) use Siegel’s condition instead of Lovász’s condition, ignored by NTL
and pari• transformation – (default: False) also return transformation
matrix.
• **kwds – keywords to be passed to fpylll. See fpylll.LLL.reduction() for details.
Also, if the verbose level is at least 2, some output is printed during the computation.
AVAILABLE ALGORITHMS:•

NTL:LLL – NTL’s LLL + choice of fp.

•

fpLLL:heuristic – fpLLL’s heuristic + choice of fp.

•

fpLLL:fast – fpLLL’s fast + choice of fp.

•

fpLLL:proved – fpLLL’s proved + choice of fp.

•

fpLLL:wrapper – fpLLL’s automatic choice (default).

•

pari – pari’s qflll.

OUTPUT:
A matrix over the integers.
EXAMPLES:
sage: A = Matrix(ZZ,3,3,range(1,10))
sage: A.LLL()[ 0 0 0][ 2 1 0][-1 1 3]>>> from sage.all import *>>> A = Matrix(ZZ,Integer(3),Integer(3),range(Integer(1),Integer(10)))>>> A.LLL()[ 0 0 0][ 2 1 0][-1 1 3]

We compute the extended GCD of a list of integers using LLL, this example is from the Magma handbook:
sage: Q = [ 67015143, 248934363018, 109210, 25590011055, 74631449,....:
10230248, 709487, 68965012139, 972065, 864972271 ]sage: n = len(Q)sage: S = 100
sage: X = Matrix(ZZ, n, n + 1)
sage: for i in range(n):....:X[i, i + 1] = 1
sage: for i in range(n):....:X[i, 0] = S * Q[i]sage: L = X.LLL()
sage: M = L.row(n-1).list()[1:]sage: M[-3, -1, 13, -1, -4, 2, 3, 4, 5, -1]
sage: add(Q[i]*M[i] for i in range(n))-1613Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> Q = [ Integer(67015143), Integer(248934363018), Integer(109210),␣
˓→Integer(25590011055), Integer(74631449),...
Integer(10230248), Integer(709487), Integer(68965012139),␣
˓→Integer(972065), Integer(864972271) ]>>> n = len(Q)>>> S = Integer(100)>>> X = Matrix(ZZ, n, n + Integer(1))>>> for i in range(n):...
X[i, i + Integer(1)] = Integer(1)>>> for i in range(n):...
X[i, Integer(0)] = S * Q[i]>>> L = X.LLL()>>> M = L.row(n-Integer(1)).list()[Integer(1):]>>> M[-3, -1, 13, -1, -4, 2, 3, 4, 5, -1]>>> add(Q[i]*M[i] for i in range(n))-1The case 𝛿 = 1 is not always supported:
sage: L = X.LLL(delta=2)
Traceback (most recent call last):...
TypeError: delta must be <= 1sage: L = X.LLL(delta=1)# not tested, will eat lots of ram
Traceback (most recent call last):...
RuntimeError: infinite loop in LLL
sage: L = X.LLL(delta=1, algorithm= NTL:LLL )sage: L[-1](-100, -3, -1, 13, -1, -4, 2, 3, 4, 5, -1)>>> from sage.all import *>>> L = X.LLL(delta=Integer(2))
Traceback (most recent call last):...
TypeError: delta must be <= 1>>> L = X.LLL(delta=Integer(1))# not tested, will eat lots of ram
Traceback (most recent call last):...
RuntimeError: infinite loop in LLL>>> L = X.LLL(delta=Integer(1), algorithm= NTL:LLL )>>> L[-Integer(1)](-100, -3, -1, 13, -1, -4, 2, 3, 4, 5, -1)

We return the transformation matrix:
sage: A = random_matrix(ZZ, 10, 20)
sage: R, U = A.LLL(transformation=True)
sage: U * A == R
True
sage: R, U = A.LLL(algorithm="NTL:LLL", transformation=True)
sage: U * A == R
True(continues on next page)

614

Chapter 15. Dense matrices over the integer ring

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: R, U = A.LLL(algorithm="pari", transformation=True)
sage: U * A == R
True>>> from sage.all import *>>> A = random_matrix(ZZ, Integer(10), Integer(20))>>> R, U = A.LLL(transformation=True)>>> U * A == R
True>>> R, U = A.LLL(algorithm="NTL:LLL", transformation=True)>>> U * A == R
True>>> R, U = A.LLL(algorithm="pari", transformation=True)>>> U * A == R
True

Example with a nonzero kernel:
sage: M = matrix(4,3,[1,2,3,2,4,6,7,0,1,-1,-2,-3])
sage: M.LLL()[0:2][0 0 0][0 0 0]sage: M.LLL(algorithm="NTL:LLL")[0:2][0 0 0][0 0 0]sage: M.LLL(algorithm="pari")[0:2][0 0 0][0 0 0]>>> from sage.all import *>>> M = matrix(Integer(4),Integer(3),[Integer(1),Integer(2),Integer(3),˓→Integer(2),Integer(4),Integer(6),Integer(7),Integer(0),Integer(1),˓→Integer(1),-Integer(2),-Integer(3)])>>> M.LLL()[Integer(0):Integer(2)][0 0 0][0 0 0]>>> M.LLL(algorithm="NTL:LLL")[Integer(0):Integer(2)][0 0 0][0 0 0]>>> M.LLL(algorithm="pari")[Integer(0):Integer(2)][0 0 0][0 0 0]Note: See sage.libs.ntl.ntl_mat_ZZ.ntl_mat_ZZ.LLL and fpylll.fplll.lll for details on the algorithms used.
Although LLL is a deterministic algorithm, the output for different implementations and CPUs (32-bit vs.
64-bit) may vary, while still being correct.

615

Matrices and Spaces of Matrices, Release 10.4

antitranspose()
Return the antitranspose of self, without changing self.
EXAMPLES:
sage: A = matrix(2,3,range(6))
sage: type(A)<class sage.matrix.matrix_integer_dense.Matrix_integer_dense >sage: A.antitranspose()
[5 2]
[4 1]
[3 0]
sage: A[0 1 2][3 4 5]sage: A.subdivide(1,2); A[0 1|2][---+-][3 4|5]sage: A.antitranspose()
[5|2]
[-+-]
[4|1]
[3|0]
>>> from sage.all import *>>> A = matrix(Integer(2),Integer(3),range(Integer(6)))>>> type(A)<class sage.matrix.matrix_integer_dense.Matrix_integer_dense >>>> A.antitranspose()
[5 2]
[4 1]
[3 0]
>>> A
[0 1 2][3 4 5]>>> A.subdivide(Integer(1),Integer(2)); A[0 1|2][---+-][3 4|5]>>> A.antitranspose()
[5|2]
[-+-]
[4|1]
[3|0]

augment(right, subdivide=False)
Return a new matrix formed by appending the matrix (or vector) right on the right side of self.
INPUT:• right – a matrix, vector or free module element, whose dimensions are compatible with self.
• subdivide – default: False – request the resulting matrix to have a new subdivision, separating
self from right.
OUTPUT:

616

Chapter 15. Dense matrices over the integer ring

Matrices and Spaces of Matrices, Release 10.4

A new matrix formed by appending right onto the right side of self. If right is a vector (or free module
element) then in this context it is appropriate to consider it as a column vector. (The code first converts a vector
to a 1-column matrix.)
EXAMPLES:
sage: A = matrix(ZZ, 4, 5, range(20))
sage: B = matrix(ZZ, 4, 3, range(12))
sage: A.augment(B)[ 0 1 2 3 4 0 1 2]
[ 5 6 7 8 9 3 4 5]
[10 11 12 13 14 6 7 8]
[15 16 17 18 19 9 10 11]>>> from sage.all import *>>> A = matrix(ZZ, Integer(4), Integer(5), range(Integer(20)))>>> B = matrix(ZZ, Integer(4), Integer(3), range(Integer(12)))>>> A.augment(B)[ 0 1 2 3 4 0 1 2]
[ 5 6 7 8 9 3 4 5]
[10 11 12 13 14 6 7 8]
[15 16 17 18 19 9 10 11]

A vector may be augmented to a matrix.
sage: A = matrix(ZZ, 3, 5, range(15))
sage: v = vector(ZZ, 3, range(3))
sage: A.augment(v)[ 0 1 2 3 4 0]
[ 5 6 7 8 9 1]
[10 11 12 13 14 2]>>> from sage.all import *>>> A = matrix(ZZ, Integer(3), Integer(5), range(Integer(15)))>>> v = vector(ZZ, Integer(3), range(Integer(3)))>>> A.augment(v)[ 0 1 2 3 4 0]
[ 5 6 7 8 9 1]
[10 11 12 13 14 2]

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(ZZ, 3, 5, range(15))
sage: B = matrix(ZZ, 3, 3, range(9))
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(ZZ, Integer(3), Integer(5), range(Integer(15)))>>> B = matrix(ZZ, Integer(3), Integer(3), range(Integer(9)))>>> 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]617

Matrices and Spaces of Matrices, Release 10.4

Errors are raised if the sizes are incompatible.
sage: A = matrix(ZZ, [[1, 2],[3, 4]])sage: B = matrix(ZZ, [[10, 20], [30, 40], [50, 60]])
sage: A.augment(B)Traceback (most recent call last):...
TypeError: number of rows must be the same, not 2 != 3>>> from sage.all import *>>> A = matrix(ZZ, [[Integer(1), Integer(2)],[Integer(3), Integer(4)]])>>> B = matrix(ZZ, [[Integer(10), Integer(20)], [Integer(30), Integer(40)],␣
˓→[Integer(50), Integer(60)]])>>> A.augment(B)Traceback (most recent call last):...
TypeError: number of rows must be the same, not 2 != 3

charpoly(var='x', algorithm=None)
Note: The characteristic polynomial is defined as det(𝑥𝐼 − 𝐴).
INPUT:• var – a variable name• algorithm – (optional) either ‘generic’, ‘flint’ or ‘linbox’. Default is set to ‘linbox’.
EXAMPLES:
sage: A = matrix(ZZ,6, range(36))
sage: f = A.charpoly(); fx^6 - 105*x^5 - 630*x^4
sage: f(A) == 0
True
sage: g = A.charpoly(algorithm= flint )sage: f == gTruesage: n=20; A = Mat(ZZ,n)(range(n^2))
sage: A.charpoly()x^20 - 3990*x^19 - 266000*x^18
sage: A.minpoly()x^3 - 3990*x^2 - 266000*x>>> from sage.all import *>>> A = matrix(ZZ,Integer(6), range(Integer(36)))>>> f = A.charpoly(); fx^6 - 105*x^5 - 630*x^4>>> f(A) == Integer(0)True>>> g = A.charpoly(algorithm= flint )>>> f == g
True>>> n=Integer(20); A = Mat(ZZ,n)(range(n**Integer(2)))>>> A.charpoly()x^20 - 3990*x^19 - 266000*x^18(continues on next page)

618

Chapter 15. Dense matrices over the integer ring

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> A.minpoly()x^3 - 3990*x^2 - 266000*x

On non square matrices, this method raises an ArithmeticError:
sage: matrix(ZZ, 2, 1).charpoly()
Traceback (most recent call last):...
ArithmeticError: only valid for square matrix>>> from sage.all import *>>> matrix(ZZ, Integer(2), Integer(1)).charpoly()
Traceback (most recent call last):...
ArithmeticError: only valid for square matrix

column(i, from_list=False)
Return the i-th column of this matrix as a dense vector.
INPUT:• i – integer• from_list – ignored
EXAMPLES:
sage: m = matrix(ZZ, 3, 2, [1, -2, 3, 4, -1, 0])
sage: m.column(1)(-2, 4, 0)
sage: m.column(1, from_list=True)(-2, 4, 0)
sage: m.column(-1)(-2, 4, 0)
sage: m.column(-2)(1, 3, -1)
sage: m.column(2)Traceback (most recent call last):...
IndexError: column index out of range
sage: m.column(-3)
Traceback (most recent call last):...
IndexError: column index out of range>>> from sage.all import *>>> m = matrix(ZZ, Integer(3), Integer(2), [Integer(1), -Integer(2),␣
˓→Integer(3), Integer(4), -Integer(1), Integer(0)])>>> m.column(Integer(1))(-2, 4, 0)>>> m.column(Integer(1), from_list=True)(-2, 4, 0)>>> m.column(-Integer(1))(-2, 4, 0)>>> m.column(-Integer(2))(1, 3, -1)(continues on next page)619

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> m.column(Integer(2))
Traceback (most recent call last):...
IndexError: column index out of range>>> m.column(-Integer(3))
Traceback (most recent call last):...
IndexError: column index out of range

decomposition(**kwds)
Return the decomposition of the free module on which this matrix A acts from the right (i.e., the action is x
goes to x A), along with whether this matrix acts irreducibly on each factor. The factors are guaranteed to besorted in the same way as the corresponding factors of the characteristic polynomial, and are saturated as ZZ
modules.
INPUT:• self – a matrix over the integers• **kwds – these are passed onto to the decomposition over QQ command.
EXAMPLES:
sage: t = ModularSymbols(11,sign=1).hecke_matrix(2)sage: w = t.change_ring(ZZ)
sage: w
[ 3 -2][ 0 -2]sage: w.charpoly().factor()(x - 3) * (x + 2)
sage: w.decomposition()[(Free module of degree 2 and rank 1 over Integer Ring
Echelon basis matrix:[ 5 -2], True),(Free module of degree 2 and rank 1 over Integer Ring
Echelon basis matrix:[0 1], True)]>>> from sage.all import *>>> t = ModularSymbols(Integer(11),sign=Integer(1)).hecke_matrix(Integer(2))>>> w = t.change_ring(ZZ)>>> w[ 3 -2][ 0 -2]>>> w.charpoly().factor()(x - 3) * (x + 2)>>> w.decomposition()[(Free module of degree 2 and rank 1 over Integer Ring
Echelon basis matrix:[ 5 -2], True),(Free module of degree 2 and rank 1 over Integer Ring
Echelon basis matrix:[0 1], True)(continues on next page)

620

Chapter 15. Dense matrices over the integer ring

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)]

determinant(algorithm='default', proof=None, stabilize=2)
Return the determinant of this matrix.
INPUT:• algorithm–

default – use flint–

flint – let flint do the determinant–

padic – uses a p-adic / multimodular algorithm that relies on code in IML and linbox–

linbox – calls linbox det (you must set proof=False to use this!)–

ntl – calls NTL’s det function–

pari – uses PARI

• proof – bool or None; if None use proof.linear_algebra(); only relevant for the padic algorithm.
Note: It would be VERY VERY hard for det to fail even with proof=False.
• stabilize – if proof is False, require det to be the same for this many CRT primes in a row. Ignored
if proof is True.
ALGORITHM: The p-adic algorithm works by first finding a random vector v, then solving 𝐴𝑥 = 𝑣 andtaking the denominator 𝑑. This gives a divisor of the determinant. Then we compute det(𝐴)/𝑑 using a
multimodular algorithm and the Hadamard bound, skipping primes that divide 𝑑.
EXAMPLES:
sage: A = matrix(ZZ,8,8,[3..66])
sage: A.determinant()
0>>> from sage.all import *>>> A = matrix(ZZ,Integer(8),Integer(8),(ellipsis_range(Integer(3),Ellipsis,
˓→Integer(66))))>>> A.determinant()
0sage: A = random_matrix(ZZ,20,20)
sage: D1 = A.determinant()
sage: A._clear_cache()sage: D2 = A.determinant(algorithm= ntl )sage: D1 == D2
True>>> from sage.all import *>>> A = random_matrix(ZZ,Integer(20),Integer(20))>>> D1 = A.determinant()>>> A._clear_cache()>>> D2 = A.determinant(algorithm= ntl )>>> D1 == D2
True

621

Matrices and Spaces of Matrices, Release 10.4

We have a special-case algorithm for 4 x 4 determinants:
sage: A = matrix(ZZ,4,[1,2,3,4,4,3,2,1,0,5,0,1,9,1,2,3])
sage: A.determinant()
270>>> from sage.all import *>>> A = matrix(ZZ,Integer(4),[Integer(1),Integer(2),Integer(3),Integer(4),˓→Integer(4),Integer(3),Integer(2),Integer(1),Integer(0),Integer(5),˓→Integer(0),Integer(1),Integer(9),Integer(1),Integer(2),Integer(3)])>>> A.determinant()
270

Next we try the Linbox det. Note that we must have proof=False.
sage: A = matrix(ZZ,5,[1,2,3,4,5,4,6,3,2,1,7,9,7,5,2,1,4,6,7,8,3,2,4,6,7])
sage: A.determinant(algorithm= linbox )Traceback (most recent call last):...
RuntimeError: you must pass the proof=False option to the determinant command␣˓→to use LinBox s det algorithm
sage: A.determinant(algorithm= linbox , proof=False)-21
sage: A._clear_cache()sage: A.determinant()-21>>> from sage.all import *>>> A = matrix(ZZ,Integer(5),[Integer(1),Integer(2),Integer(3),Integer(4),˓→Integer(5),Integer(4),Integer(6),Integer(3),Integer(2),Integer(1),˓→Integer(7),Integer(9),Integer(7),Integer(5),Integer(2),Integer(1),˓→Integer(4),Integer(6),Integer(7),Integer(8),Integer(3),Integer(2),˓→Integer(4),Integer(6),Integer(7)])>>> A.determinant(algorithm= linbox )Traceback (most recent call last):...
RuntimeError: you must pass the proof=False option to the determinant command␣˓→to use LinBox s det algorithm>>> A.determinant(algorithm= linbox , proof=False)-21>>> A._clear_cache()>>> A.determinant()-21

Try the other algorithms on the same example:
sage: A._clear_cache(); A.determinant(algorithm= padic )-21
sage: A._clear_cache(); A.determinant(algorithm= pari )-21
sage: A._clear_cache(); A.determinant(algorithm= ntl )-21
sage: A._clear_cache(); A.determinant(algorithm= padic )-21>>> from sage.all import *>>> A._clear_cache(); A.determinant(algorithm= padic )(continues on next page)

622

Chapter 15. Dense matrices over the integer ring

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)-21>>> A._clear_cache(); A.determinant(algorithm= pari )-21>>> A._clear_cache(); A.determinant(algorithm= ntl )-21>>> A._clear_cache(); A.determinant(algorithm= padic )-21

A bigger example:
sage: A = random_matrix(ZZ,30)
sage: d = A.determinant()
sage: A._clear_cache()sage: A.determinant(algorithm= linbox ,proof=False) == dTrue>>> from sage.all import *>>> A = random_matrix(ZZ,Integer(30))>>> d = A.determinant()>>> A._clear_cache()>>> A.determinant(algorithm= linbox ,proof=False) == dTrueechelon_form(algorithm='default', proof=None, include_zero_rows=True, transformation=False, D=None)
Return the echelon form of this matrix over the integers, also known as the hermite normal form (HNF).
INPUT:• algorithm – String. The algorithm to use. Valid options are:–default – Let Sage pick an algorithm (default). Up to 75 rows or columns with no transformation matrix, use pari with flag 0; otherwise, use flint.

–

flint – use flint–

ntl – use NTL (only works for square matrices of full rank!)–

padic – an asymptotically fast p-adic modular algorithm, If your matrix has large coefficientsand is small, you may also want to try this.

–pari – use PARI with flag 1–

pari0 – use PARI with flag 0–

pari1 – use PARI with flag 1–

pari4 – use PARI with flag 4 (use heuristic LLL)

• proof – (default: True); if proof=False certain determinants are computed using a randomized hybrid p-adic multimodular strategy until it stabilizes twice (instead of up to the Hadamard bound). It is
incredibly unlikely that one would ever get an incorrect result with proof=False.
• include_zero_rows – (default: True) if False, don’t include zero rows
• transformation – if given, also compute transformation matrix; only valid for flint and padic algorithm• D – (default: None) if given and the algorithm is ‘ntl’, then D must be a multiple of the determinant andthis function will use that fact.

623

Matrices and Spaces of Matrices, Release 10.4

OUTPUT:
The Hermite normal form (=echelon form over Z) of self as an immutable matrix.
EXAMPLES:
sage: A = MatrixSpace(ZZ,2)([1,2,3,4])
sage: A.echelon_form()
[1 0]
[0 2]
sage: A = MatrixSpace(ZZ,5)(range(25))
sage: A.echelon_form()[ 5
0 -5 -10 -15]
[ 0
1
2
3
4]
[ 0
0
0
0
0]
[ 0
0
0
0
0]
[ 0
0
0
0
0]
>>> from sage.all import *>>> A = MatrixSpace(ZZ,Integer(2))([Integer(1),Integer(2),Integer(3),˓→Integer(4)])>>> A.echelon_form()
[1 0]
[0 2]
>>> A = MatrixSpace(ZZ,Integer(5))(range(Integer(25)))>>> A.echelon_form()[ 5
0 -5 -10 -15]
[ 0
1
2
3
4]
[ 0
0
0
0
0]
[ 0
0
0
0
0]
[ 0
0
0
0
0]

Getting a transformation matrix in the nonsquare case:sage: A = matrix(ZZ,5,3,[1..15])
sage: H, U = A.hermite_form(transformation=True, include_zero_rows=False)
sage: H[1 2 3][0 3 6]sage: U
[ 0
0
0
4 -3]
[ 0
0
0 13 -10]
sage: U*A == H
True>>> from sage.all import *>>> A = matrix(ZZ,Integer(5),Integer(3),(ellipsis_range(Integer(1),Ellipsis,
˓→Integer(15))))>>> H, U = A.hermite_form(transformation=True, include_zero_rows=False)>>> H[1 2 3][0 3 6]
>>> U
[ 0
0
0
4 -3]
[ 0
0
0 13 -10]>>> U*A == H
True

624

Chapter 15. Dense matrices over the integer ring

Matrices and Spaces of Matrices, Release 10.4

Note: If ‘ntl’ is chosen for a non square matrix this function raises a ValueError.
Special cases: 0 or 1 rows:
sage: a = matrix(ZZ, 1,2,[0,-1])
sage: a.hermite_form()[0 1]
sage: a.pivots()(1,)
sage: a = matrix(ZZ, 1,2,[0,0])
sage: a.hermite_form()[0 0]
sage: a.pivots()()
sage: a = matrix(ZZ,1,3); a[0 0 0]sage: a.echelon_form(include_zero_rows=False)[]
sage: a.echelon_form(include_zero_rows=True)[0 0 0]>>> from sage.all import *>>> a = matrix(ZZ, Integer(1),Integer(2),[Integer(0),-Integer(1)])>>> a.hermite_form()[0 1]>>> a.pivots()(1,)>>> a = matrix(ZZ, Integer(1),Integer(2),[Integer(0),Integer(0)])>>> a.hermite_form()[0 0]>>> a.pivots()()>>> a = matrix(ZZ,Integer(1),Integer(3)); a[0 0 0]>>> a.echelon_form(include_zero_rows=False)[]>>> a.echelon_form(include_zero_rows=True)[0 0 0]Illustrate using various algorithms.:
sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm= pari )[1 2 3][0 3 6][0 0 0]sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm= pari0 )[1 2 3][0 3 6][0 0 0]sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm= pari4 )[1 2 3][0 3 6][0 0 0]sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm= padic )[1 2 3][0 3 6](continues on next page)625

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 0 0]sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm= default )[1 2 3][0 3 6][0 0 0]>>> from sage.all import *>>> matrix(ZZ,Integer(3),(ellipsis_range(Integer(1),Ellipsis,Integer(9)))).
˓→hermite_form(algorithm= pari )[1 2 3][0 3 6][0 0 0]>>> matrix(ZZ,Integer(3),(ellipsis_range(Integer(1),Ellipsis,Integer(9)))).
˓→hermite_form(algorithm= pari0 )[1 2 3][0 3 6][0 0 0]>>> matrix(ZZ,Integer(3),(ellipsis_range(Integer(1),Ellipsis,Integer(9)))).
˓→hermite_form(algorithm= pari4 )[1 2 3][0 3 6][0 0 0]>>> matrix(ZZ,Integer(3),(ellipsis_range(Integer(1),Ellipsis,Integer(9)))).
˓→hermite_form(algorithm= padic )[1 2 3][0 3 6][0 0 0]>>> matrix(ZZ,Integer(3),(ellipsis_range(Integer(1),Ellipsis,Integer(9)))).
˓→hermite_form(algorithm= default )[1 2 3][0 3 6][0 0 0]The ‘ntl’ algorithm doesn’t work on matrices that do not have full rank.:
sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm= ntl )Traceback (most recent call last):...
ValueError: ntl only computes HNF for square matrices of full rank.
sage: matrix(ZZ,3,[0] +[2..9]).hermite_form(algorithm= ntl )[1 0 0][0 1 0][0 0 3]>>> from sage.all import *>>> matrix(ZZ,Integer(3),(ellipsis_range(Integer(1),Ellipsis,Integer(9)))).
˓→hermite_form(algorithm= ntl )Traceback (most recent call last):...
ValueError: ntl only computes HNF for square matrices of full rank.
>>> matrix(ZZ,Integer(3),[Integer(0)] +(ellipsis_range(Integer(2),Ellipsis,
˓→Integer(9)))).hermite_form(algorithm= ntl )[1 0 0][0 1 0][0 0 3]elementary_divisors(algorithm='pari')
626

Chapter 15. Dense matrices over the integer ring

Matrices and Spaces of Matrices, Release 10.4

Return the elementary divisors of self, in order.
Warning: This is MUCH faster than the smith_form() function.
The elementary divisors are the invariants of the finite abelian group that is the cokernel of left multiplicationof this matrix. They are ordered in reverse by divisibility.
INPUT:• self – matrix• algorithm – (default: ‘pari’)–pari : works robustly, but is slower.

–

linbox – use linbox (currently off, broken)

OUTPUT: list of integers
Note: These are the invariants of the cokernel of left multiplication:
sage: M = Matrix([[3,0,1],[0,1,0]])
sage: M
[3 0 1][0 1 0]sage: M.elementary_divisors()[1, 1]
sage: M.transpose().elementary_divisors()[1, 1, 0]>>> from sage.all import *>>> M = Matrix([[Integer(3),Integer(0),Integer(1)],[Integer(0),Integer(1),˓→Integer(0)]])>>> M[3 0 1][0 1 0]>>> M.elementary_divisors()[1, 1]>>> M.transpose().elementary_divisors()[1, 1, 0]

EXAMPLES:
sage: matrix(3, range(9)).elementary_divisors()[1, 3, 0]
sage: matrix(3, range(9)).elementary_divisors(algorithm= pari )[1, 3, 0]
sage: C = MatrixSpace(ZZ,4)([3,4,5,6,7,3,8,10,14,5,6,7,2,2,10,9])
sage: C.elementary_divisors()[1, 1, 1, 687]>>> from sage.all import *>>> matrix(Integer(3), range(Integer(9))).elementary_divisors()[1, 3, 0](continues on next page)627

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> matrix(Integer(3), range(Integer(9))).elementary_divisors(algorithm= pari˓→ )[1, 3, 0]>>> C = MatrixSpace(ZZ,Integer(4))([Integer(3),Integer(4),Integer(5),˓→Integer(6),Integer(7),Integer(3),Integer(8),Integer(10),Integer(14),
˓→Integer(5),Integer(6),Integer(7),Integer(2),Integer(2),Integer(10),
˓→Integer(9)])>>> C.elementary_divisors()[1, 1, 1, 687]
sage: M = matrix(ZZ, 3, [1,5,7, 3,6,9, 0,1,2])
sage: M.elementary_divisors()[1, 1, 6]>>> from sage.all import *>>> M = matrix(ZZ, Integer(3), [Integer(1),Integer(5),Integer(7), Integer(3),˓→Integer(6),Integer(9), Integer(0),Integer(1),Integer(2)])>>> M.elementary_divisors()[1, 1, 6]This returns a copy, which is safe to change:
sage: edivs = M.elementary_divisors()
sage: edivs.pop()
6
sage: M.elementary_divisors()[1, 1, 6]>>> from sage.all import *>>> edivs = M.elementary_divisors()>>> edivs.pop()
6>>> M.elementary_divisors()[1, 1, 6]

See also:smith_form()frobenius(*args, **kwds)
Deprecated: Use frobenius_form() instead. See Issue #36396 for details.
frobenius_form(flag=0, var='x')
Return the Frobenius form (rational canonical form) of this matrix.
INPUT:• flag – 0 (default), 1 or 2 as follows:– 0 – (default) return the Frobenius form of this matrix.
– 1 – return only the elementary divisor polynomials, as polynomials in var.
– 2 – return a two-components vector [F,B] where F is the Frobenius form and B is the basis change
so that 𝑀 = 𝐵 −1 𝐹 𝐵.
• var – a string (default: ‘x’)

628

Chapter 15. Dense matrices over the integer ring

Matrices and Spaces of Matrices, Release 10.4

ALGORITHM: uses PARI’s pari:matfrobenius
EXAMPLES:
sage: A = MatrixSpace(ZZ, 3)(range(9))
sage: A.frobenius_form(0)[ 0 0 0]
[ 1 0 18]
[ 0 1 12]sage: A.frobenius_form(1)[x^3 - 12*x^2 - 18*x]
sage: A.frobenius_form(1, var= y )[y^3 - 12*y^2 - 18*y]sage: F, B = A.frobenius_form(2)sage: A == B^(-1)*F*B
True
sage: a=matrix([])
sage: a.frobenius_form(2)([], [])
sage: a.frobenius_form(0)[]sage: a.frobenius_form(1)[]sage: B = random_matrix(ZZ,2,3)
sage: B.frobenius_form()
Traceback (most recent call last):...
ArithmeticError: frobenius matrix of non-square matrix not defined.
>>> from sage.all import *>>> A = MatrixSpace(ZZ, Integer(3))(range(Integer(9)))>>> A.frobenius_form(Integer(0))[ 0 0 0]
[ 1 0 18]
[ 0 1 12]>>> A.frobenius_form(Integer(1))[x^3 - 12*x^2 - 18*x]>>> A.frobenius_form(Integer(1), var= y )[y^3 - 12*y^2 - 18*y]>>> F, B = A.frobenius_form(Integer(2))>>> A == B**(-Integer(1))*F*B
True>>> a=matrix([])>>> a.frobenius_form(Integer(2))([], [])>>> a.frobenius_form(Integer(0))[]>>> a.frobenius_form(Integer(1))[]>>> B = random_matrix(ZZ,Integer(2),Integer(3))>>> B.frobenius_form()
Traceback (most recent call last):...
ArithmeticError: frobenius matrix of non-square matrix not defined.

AUTHORS:• Martin Albrecht (2006-04-02)629

Matrices and Spaces of Matrices, Release 10.4

TODO: - move this to work for more general matrices than just over Z. This will require fixing how PARI
polynomials are coerced to Sage polynomials.
gcd()
Return the gcd of all entries of self; very fast.
EXAMPLES:
sage: a = matrix(ZZ,2, [6,15,-6,150])
sage: a.gcd()3>>> from sage.all import *>>> a = matrix(ZZ,Integer(2), [Integer(6),Integer(15),-Integer(6),˓→Integer(150)])>>> a.gcd()3

height()Return the height of this matrix, i.e., the max absolute value of the entries of the matrix.
OUTPUT: A nonnegative integer.
EXAMPLES:
sage: a = Mat(ZZ,3)(range(9))
sage: a.height()
8
sage: a = Mat(ZZ,2,3)([-17,3,-389,15,-1,0]); a[ -17
3 -389][ 15-10]
sage: a.height()
389>>> from sage.all import *>>> a = Mat(ZZ,Integer(3))(range(Integer(9)))>>> a.height()
8>>> a = Mat(ZZ,Integer(2),Integer(3))([-Integer(17),Integer(3),-Integer(389),
˓→Integer(15),-Integer(1),Integer(0)]); a[ -17
3 -389][ 15-1
0]>>> a.height()
389

hermite_form(algorithm='default', proof=None, include_zero_rows=True, transformation=False, D=None)
Return the echelon form of this matrix over the integers, also known as the hermite normal form (HNF).
INPUT:• algorithm – String. The algorithm to use. Valid options are:630–

default – Let Sage pick an algorithm (default). Up to 75 rows or columns with no transformation matrix, use pari with flag 0; otherwise, use flint.

–

flint – use flint–

ntl – use NTL (only works for square matrices of full rank!)–

padic – an asymptotically fast p-adic modular algorithm, If your matrix has large coefficientsand is small, you may also want to try this.
Chapter 15. Dense matrices over the integer ring

Matrices and Spaces of Matrices, Release 10.4–

pari – use PARI with flag 1–

pari0 – use PARI with flag 0–

pari1 – use PARI with flag 1–

pari4 – use PARI with flag 4 (use heuristic LLL)

• proof – (default: True); if proof=False certain determinants are computed using a randomized hybrid p-adic multimodular strategy until it stabilizes twice (instead of up to the Hadamard bound). It is
incredibly unlikely that one would ever get an incorrect result with proof=False.
• include_zero_rows – (default: True) if False, don’t include zero rows
• transformation – if given, also compute transformation matrix; only valid for flint and padic algorithm• D – (default: None) if given and the algorithm is ‘ntl’, then D must be a multiple of the determinant andthis function will use that fact.
OUTPUT:
The Hermite normal form (=echelon form over Z) of self as an immutable matrix.
EXAMPLES:
sage: A = MatrixSpace(ZZ,2)([1,2,3,4])
sage: A.echelon_form()
[1 0]
[0 2]
sage: A = MatrixSpace(ZZ,5)(range(25))
sage: A.echelon_form()[ 5
0 -5 -10 -15]
[ 0
1
2
3
4]
[ 0
0
0
0
0]
[ 0
0
0
0
0]
[ 0
0
0
0
0]
>>> from sage.all import *>>> A = MatrixSpace(ZZ,Integer(2))([Integer(1),Integer(2),Integer(3),˓→Integer(4)])>>> A.echelon_form()
[1 0]
[0 2]
>>> A = MatrixSpace(ZZ,Integer(5))(range(Integer(25)))>>> A.echelon_form()[ 5
0 -5 -10 -15]
[ 0
1
2
3
4]
[ 0
0
0
0
0]
[ 0
0
0
0
0]
[ 0
0
0
0
0]

Getting a transformation matrix in the nonsquare case:sage: A = matrix(ZZ,5,3,[1..15])
sage: H, U = A.hermite_form(transformation=True, include_zero_rows=False)
sage: H[1 2 3][0 3 6]sage: U
[ 0
0
0
4 -3]
(continues on next page)631

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 0
0
0 13 -10]
sage: U*A == H
True>>> from sage.all import *>>> A = matrix(ZZ,Integer(5),Integer(3),(ellipsis_range(Integer(1),Ellipsis,
˓→Integer(15))))>>> H, U = A.hermite_form(transformation=True, include_zero_rows=False)>>> H[1 2 3][0 3 6]
>>> U
[ 0
0
0
4 -3]
[ 0
0
0 13 -10]>>> U*A == H
True

Note: If ‘ntl’ is chosen for a non square matrix this function raises a ValueError.
Special cases: 0 or 1 rows:
sage: a = matrix(ZZ, 1,2,[0,-1])
sage: a.hermite_form()[0 1]
sage: a.pivots()(1,)
sage: a = matrix(ZZ, 1,2,[0,0])
sage: a.hermite_form()[0 0]
sage: a.pivots()()
sage: a = matrix(ZZ,1,3); a[0 0 0]sage: a.echelon_form(include_zero_rows=False)[]
sage: a.echelon_form(include_zero_rows=True)[0 0 0]>>> from sage.all import *>>> a = matrix(ZZ, Integer(1),Integer(2),[Integer(0),-Integer(1)])>>> a.hermite_form()[0 1]>>> a.pivots()(1,)>>> a = matrix(ZZ, Integer(1),Integer(2),[Integer(0),Integer(0)])>>> a.hermite_form()[0 0]>>> a.pivots()()>>> a = matrix(ZZ,Integer(1),Integer(3)); a[0 0 0]>>> a.echelon_form(include_zero_rows=False)[]>>> a.echelon_form(include_zero_rows=True)(continues on next page)

632

Chapter 15. Dense matrices over the integer ring

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 0 0]Illustrate using various algorithms.:
sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm= pari )[1 2 3][0 3 6][0 0 0]sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm= pari0 )[1 2 3][0 3 6][0 0 0]sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm= pari4 )[1 2 3][0 3 6][0 0 0]sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm= padic )[1 2 3][0 3 6][0 0 0]sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm= default )[1 2 3][0 3 6][0 0 0]>>> from sage.all import *>>> matrix(ZZ,Integer(3),(ellipsis_range(Integer(1),Ellipsis,Integer(9)))).
˓→hermite_form(algorithm= pari )[1 2 3][0 3 6][0 0 0]>>> matrix(ZZ,Integer(3),(ellipsis_range(Integer(1),Ellipsis,Integer(9)))).
˓→hermite_form(algorithm= pari0 )[1 2 3][0 3 6][0 0 0]>>> matrix(ZZ,Integer(3),(ellipsis_range(Integer(1),Ellipsis,Integer(9)))).
˓→hermite_form(algorithm= pari4 )[1 2 3][0 3 6][0 0 0]>>> matrix(ZZ,Integer(3),(ellipsis_range(Integer(1),Ellipsis,Integer(9)))).
˓→hermite_form(algorithm= padic )[1 2 3][0 3 6][0 0 0]>>> matrix(ZZ,Integer(3),(ellipsis_range(Integer(1),Ellipsis,Integer(9)))).
˓→hermite_form(algorithm= default )[1 2 3][0 3 6][0 0 0]The ‘ntl’ algorithm doesn’t work on matrices that do not have full rank.:
sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm= ntl )Traceback (most recent call last):(continues on next page)633

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
ValueError: ntl only computes HNF for square matrices of full rank.
sage: matrix(ZZ,3,[0] +[2..9]).hermite_form(algorithm= ntl )[1 0 0][0 1 0][0 0 3]>>> from sage.all import *>>> matrix(ZZ,Integer(3),(ellipsis_range(Integer(1),Ellipsis,Integer(9)))).
˓→hermite_form(algorithm= ntl )Traceback (most recent call last):...
ValueError: ntl only computes HNF for square matrices of full rank.
>>> matrix(ZZ,Integer(3),[Integer(0)] +(ellipsis_range(Integer(2),Ellipsis,
˓→Integer(9)))).hermite_form(algorithm= ntl )[1 0 0][0 1 0][0 0 3]index_in_saturation(proof=None)
Return the index of self in its saturation.
INPUT:• proof – (default: use proof.linear_algebra()); if False, the determinant calculations are done with
proof=False.
OUTPUT:• positive integer – the index of the row span of this matrix in its saturation
ALGORITHM: Use Hermite normal form twice to find an invertible matrix whose inverse transforms a matrix
with the same row span as self to its saturation, then compute the determinant of that matrix.
EXAMPLES:
sage: A = matrix(ZZ, 2,3, [1..6]); A[1 2 3][4 5 6]sage: A.index_in_saturation()3
sage: A.saturation()[1 2 3][1 1 1]>>> from sage.all import *>>> A = matrix(ZZ, Integer(2),Integer(3), (ellipsis_range(Integer(1),Ellipsis,
˓→Integer(6)))); A[1 2 3][4 5 6]>>> A.index_in_saturation()3>>> A.saturation()[1 2 3][1 1 1]

insert_row(index, row)
Create a new matrix from self with.
634

Chapter 15. Dense matrices over the integer ring

Matrices and Spaces of Matrices, Release 10.4

INPUT:• index – integer• row – a vector
EXAMPLES:
sage: X = matrix(ZZ,3,range(9)); X[0 1 2][3 4 5][6 7 8]sage: X.insert_row(1, [1,5,-10])
[ 0
1
2]
[ 1
5 -10]
[ 3
4
5]
[ 6
7
8]
sage: X.insert_row(0, [1,5,-10])[ 1
5 -10]
[ 0
1
2]
[ 3
4
5]
[ 6
7
8]
sage: X.insert_row(3, [1,5,-10])
[ 0
1
2]
[ 3
4
5]
[ 6
7
8]
[ 1
5 -10]>>> from sage.all import *>>> X = matrix(ZZ,Integer(3),range(Integer(9))); X[0 1 2][3 4 5][6 7 8]>>> X.insert_row(Integer(1), [Integer(1),Integer(5),-Integer(10)])
[ 0
1
2]
[ 1
5 -10]
[ 3
4
5]
[ 6
7
8]
>>> X.insert_row(Integer(0), [Integer(1),Integer(5),-Integer(10)])[ 1
5 -10]
[ 0
1
2]
[ 3
4
5]
[ 6
7
8]
>>> X.insert_row(Integer(3), [Integer(1),Integer(5),-Integer(10)])
[ 0
1
2]
[ 3
4
5]
[ 6
7
8]
[ 1
5 -10]

integer_valued_polynomials_generators()
Determine the generators of the ring of integer valued polynomials on this matrix.
OUTPUT:
A pair (mu_B, P) where P is a list of polynomials in{𝑓 ∈[𝑋] such that[𝑋] | 𝑓 (𝐵) ∈ 𝑀𝑛 (Z)} = 𝜇𝐵 [𝑋] +

∑︁

𝑔Z[𝑋]

𝑔∈𝑃

where 𝐵 is this matrix.
635

Matrices and Spaces of Matrices, Release 10.4

EXAMPLES:
sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]])sage: B.integer_valued_polynomials_generators()(x^3 + x^2 - 12*x - 20, [1, 1/4*x^2 + 3/4*x + 1/2])>>> from sage.all import *>>> B = matrix(ZZ, [[Integer(1), Integer(0), Integer(1)], [Integer(1), ˓→Integer(2), -Integer(1)], [Integer(10), Integer(0), Integer(0)]])>>> B.integer_valued_polynomials_generators()(x^3 + x^2 - 12*x - 20, [1, 1/4*x^2 + 3/4*x + 1/2])

See also:
compute_J_ideal, integer_valued_polynomials_generators()
inverse_of_unit()
If self is a matrix with determinant 1 or −1 return the inverse of self as a matrix over 𝑍𝑍.
EXAMPLES:
sage: m = matrix(ZZ, 2, [2,1,1,1]).inverse_of_unit()
sage: m[ 1 -1][-1 2]
sage: parent(m)Full MatrixSpace of 2 by 2 dense matrices over Integer Ringsage: matrix(2, [2,1,0,1]).inverse_of_unit()
Traceback (most recent call last):...
ArithmeticError: non-invertible matrix>>> from sage.all import *>>> m = matrix(ZZ, Integer(2), [Integer(2),Integer(1),Integer(1),Integer(1)]).
˓→inverse_of_unit()>>> m[ 1 -1][-1 2]>>> parent(m)Full MatrixSpace of 2 by 2 dense matrices over Integer Ring>>> matrix(Integer(2), [Integer(2),Integer(1),Integer(0),Integer(1)]).inverse_
˓→of_unit()
Traceback (most recent call last):...
ArithmeticError: non-invertible matrix

is_LLL_reduced(delta=None, eta=None)
Return True if this lattice is (𝛿, 𝜂)-LLL reduced. See self.LLL for a definition of LLL reduction.
INPUT:• delta – (default: 0.99) parameter 𝛿 as described above• eta – (default: 0.501) parameter 𝜂 as described above
EXAMPLES:

636

Chapter 15. Dense matrices over the integer ring

Matrices and Spaces of Matrices, Release 10.4

sage: A = random_matrix(ZZ, 10, 10)
sage: L = A.LLL()
sage: A.is_LLL_reduced()
False
sage: L.is_LLL_reduced()True>>> from sage.all import *>>> A = random_matrix(ZZ, Integer(10), Integer(10))>>> L = A.LLL()>>> A.is_LLL_reduced()
False>>> L.is_LLL_reduced()
True

is_one()Test whether self is the identity matrix.
EXAMPLES:
sage: matrix(2, [1,0,0,1]).is_one()True
sage: matrix(2, [1,1,0,1]).is_one()False
sage: matrix(2, 3, [1,0,0,0,1,0]).is_one()
False>>> from sage.all import *>>> matrix(Integer(2), [Integer(1),Integer(0),Integer(0),Integer(1)]).is_one()True>>> matrix(Integer(2), [Integer(1),Integer(1),Integer(0),Integer(1)]).is_one()
False>>> matrix(Integer(2), Integer(3), [Integer(1),Integer(0),Integer(0),˓→Integer(0),Integer(1),Integer(0)]).is_one()
False

is_primitive()
Test whether the matrix is primitive.
An integral matrix 𝐴 is primitive if all its entries are non-negative and for some positive integer 𝑛 the matrix
𝐴𝑛 has all its entries positive.
EXAMPLES:
sage: m = matrix(3, [1,1,0,0,0,1,1,0,0])
sage: m.is_primitive()
True
sage: m**4
[3 2 1][1 1 1][2 1 1]
sage: m = matrix(4, [[1,1,0,0],[0,0,1,0],[0,0,0,1],[1,0,0,0]])
sage: m.is_primitive()
True
sage: m**6
[4 3 2 1](continues on next page)637

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[1 1 1 1][2 1 1 1][3 2 1 1]
sage: m = matrix(4, [[0,1,0,1],[1,0,1,0],[0,1,0,1],[1,0,1,0]])
sage: m.is_primitive()
False>>> from sage.all import *>>> m = matrix(Integer(3), [Integer(1),Integer(1),Integer(0),Integer(0),˓→Integer(0),Integer(1),Integer(1),Integer(0),Integer(0)])>>> m.is_primitive()
True>>> m**Integer(4)[3 2 1][1 1 1][2 1 1]>>> m = matrix(Integer(4), [[Integer(1),Integer(1),Integer(0),Integer(0)],˓→[Integer(0),Integer(0),Integer(1),Integer(0)],[Integer(0),Integer(0),˓→Integer(0),Integer(1)],[Integer(1),Integer(0),Integer(0),Integer(0)]])>>> m.is_primitive()
True>>> m**Integer(6)[4 3 2 1][1 1 1 1][2 1 1 1][3 2 1 1]>>> m = matrix(Integer(4), [[Integer(0),Integer(1),Integer(0),Integer(1)],
˓→[Integer(1),Integer(0),Integer(1),Integer(0)],[Integer(0),Integer(1),˓→Integer(0),Integer(1)],[Integer(1),Integer(0),Integer(1),Integer(0)]])>>> m.is_primitive()
False

Testing extremal matrices:sage: def matrix1(d):....:m = matrix(d)....:m[0,0] = 1....:
for i in range(d-1):....:m[i,i+1] = m[i+1,i] = 1....:
return m
sage: all(matrix1(d).is_primitive() for d in range(2,20))
True
sage: def matrix2(d):....:m = matrix(d)....:for i in range(d-1):....:m[i,i+1] = 1....:
m[d-1,0] = m[d-1,1] = 1....:
return m
sage: all(matrix2(d).is_primitive() for d in range(2,20))
True

638

Chapter 15. Dense matrices over the integer ring

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> def matrix1(d):...
m = matrix(d)...
m[Integer(0),Integer(0)] = Integer(1)...
for i in range(d-Integer(1)):...
m[i,i+Integer(1)] = m[i+Integer(1),i] = Integer(1)...
return m>>> all(matrix1(d).is_primitive() for d in range(Integer(2),Integer(20)))True>>> def matrix2(d):...
m = matrix(d)...
for i in range(d-Integer(1)):...
m[i,i+Integer(1)] = Integer(1)...
m[d-Integer(1),Integer(0)] = m[d-Integer(1),Integer(1)] = Integer(1)...
return m>>> all(matrix2(d).is_primitive() for d in range(Integer(2),Integer(20)))
True

Non-primitive families:
sage: def matrix3(d):....:m = matrix(d)....:m[0,0] = 1....:
for i in range(d-1):....:m[i,i+1] = 1....:
return m
sage: any(matrix3(d).is_primitive() for d in range(2,20))
False>>> from sage.all import *>>> def matrix3(d):...
m = matrix(d)...
m[Integer(0),Integer(0)] = Integer(1)...
for i in range(d-Integer(1)):...
m[i,i+Integer(1)] = Integer(1)...
return m>>> any(matrix3(d).is_primitive() for d in range(Integer(2),Integer(20)))
False

minpoly(var='x', algorithm=None)
INPUT:• var – a variable name• algorithm – (optional) either ‘linbox’ (default) or ‘generic’
EXAMPLES:
sage: A = matrix(ZZ, 6, range(36))
sage: A.minpoly()x^3 - 105*x^2 - 630*x
sage: A = Mat(ZZ, 6)([k^2 for k in range(36)])
sage: A.minpoly(algorithm= linbox )x^4 - 2695*x^3 - 257964*x^2 + 1693440*x
sage: A.minpoly(algorithm= generic )x^4 - 2695*x^3 - 257964*x^2 + 1693440*x

639

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = matrix(ZZ, Integer(6), range(Integer(36)))>>> A.minpoly()x^3 - 105*x^2 - 630*x>>> A = Mat(ZZ, Integer(6))([k**Integer(2) for k in range(Integer(36))])>>> A.minpoly(algorithm= linbox )x^4 - 2695*x^3 - 257964*x^2 + 1693440*x>>> A.minpoly(algorithm= generic )x^4 - 2695*x^3 - 257964*x^2 + 1693440*x

On non square matrices, this method raises an ArithmeticError:
sage: matrix(ZZ, 2, 1).minpoly()
Traceback (most recent call last):...
ArithmeticError: only valid for square matrix>>> from sage.all import *>>> matrix(ZZ, Integer(2), Integer(1)).minpoly()
Traceback (most recent call last):...
ArithmeticError: only valid for square matrix

null_ideal(b=0)
Return the (𝑏)-ideal of this matrix.
Let 𝐵 be a 𝑛 × 𝑛 matrix. The null ideal modulo 𝑏, or (𝑏)-ideal, is𝑁(𝑏) (𝐵) = {𝑓 ∈ Z[𝑋] | 𝑓 (𝐵) ∈ 𝑀𝑛 (𝑏Z)}.
INPUT:• b – an element of Z (default: 0)
OUTPUT:
An ideal in Z[𝑋].
EXAMPLES:
sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]])sage: B.null_ideal()
Principal ideal (x^3 + x^2 - 12*x - 20) of
Univariate Polynomial Ring in x over Integer Ringsage: B.null_ideal(8)Ideal (8, x^3 + x^2 - 12*x - 20, 2*x^2 + 6*x + 4) ofUnivariate Polynomial Ring in x over Integer Ringsage: B.null_ideal(6)Ideal (6, 2*x^3 + 2*x^2 - 24*x - 40, 3*x^2 + 3*x) of
Univariate Polynomial Ring in x over Integer Ring>>> from sage.all import *>>> B = matrix(ZZ, [[Integer(1), Integer(0), Integer(1)], [Integer(1), ˓→Integer(2), -Integer(1)], [Integer(10), Integer(0), Integer(0)]])>>> B.null_ideal()
Principal ideal (x^3 + x^2 - 12*x - 20) of
Univariate Polynomial Ring in x over Integer Ring
(continues on next page)

640

Chapter 15. Dense matrices over the integer ring

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> B.null_ideal(Integer(8))
Ideal (8, x^3 + x^2 - 12*x - 20, 2*x^2 + 6*x + 4) ofUnivariate Polynomial Ring in x over Integer Ring>>> B.null_ideal(Integer(6))
Ideal (6, 2*x^3 + 2*x^2 - 24*x - 40, 3*x^2 + 3*x) of
Univariate Polynomial Ring in x over Integer Ring

See also:
compute_J_ideal, null_ideal()p_minimal_polynomials(p, s_max=None)
Compute (𝑝𝑠 )-minimal polynomials 𝜈𝑠 of this matrix.
For 𝑠 ≥ 0, a (𝑝𝑠 )-minimal polynomial of a matrix 𝐵 is a monic polynomial 𝑓 ∈ Z[𝑋] of minimal degreesuch that all entries of 𝑓 (𝐵) are divisible by 𝑝𝑠 .
Compute a finite subset 𝒮 of the positive integers and (𝑝𝑠 )-minimal polynomials 𝜈𝑠 for 𝑠 ∈ 𝒮.
For 0 < 𝑡 ≤ max 𝒮, a (𝑝𝑡 )-minimal polynomial is given by 𝜈𝑠 where 𝑠 = min{𝑟 ∈ 𝒮 | 𝑟 ≥ 𝑡}. For
𝑡 > max 𝒮, the minimal polynomial of 𝐵 is also a (𝑝𝑡 )-minimal polynomial.
INPUT:• p – a prime in Z
• s_max – a positive integer (default: None); if set, only (𝑝𝑠 )-minimal polynomials for s <= s_max
are computed (see below for details)
OUTPUT:
A dictionary. Keys are the finite set 𝒮, the values are the associated (𝑝𝑠 )-minimal polynomials 𝜈𝑠 , 𝑠 ∈ 𝒮.
Setting s_max only affects the output if s_max is at most max 𝒮 where 𝒮 denotes the full set. In that case,only those 𝜈𝑠 with s <= s_max are returned where s_max is always included even if it is not included in
the full set 𝒮.
EXAMPLES:
sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]])sage: B.p_minimal_polynomials(2){2: x^2 + 3*x + 2}>>> from sage.all import *>>> B = matrix(ZZ, [[Integer(1), Integer(0), Integer(1)], [Integer(1), ˓→Integer(2), -Integer(1)], [Integer(10), Integer(0), Integer(0)]])>>> B.p_minimal_polynomials(Integer(2)){2: x^2 + 3*x + 2}

See also:
compute_J_ideal, p_minimal_polynomials()
pivots()Return the pivot column positions of this matrix.
OUTPUT: a tuple of Python integers: the position of the first nonzero entry in each row of the echelon form.
EXAMPLES:

641

Matrices and Spaces of Matrices, Release 10.4

sage: n = 3; A = matrix(ZZ,n,range(n^2)); A[0 1 2][3 4 5][6 7 8]sage: A.pivots()(0, 1)
sage: A.echelon_form()[ 3 0 -3]
[ 0 1 2][ 0 0 0]>>> from sage.all import *>>> n = Integer(3); A = matrix(ZZ,n,range(n**Integer(2))); A[0 1 2][3 4 5][6 7 8]>>> A.pivots()(0, 1)>>> A.echelon_form()[ 3 0 -3]
[ 0 1 2][ 0 0 0]

prod_of_row_sums(cols)
Return the product of the sums of the entries in the submatrix of self with given columns.
INPUT:• cols – a list (or set) of integers representing columns of self
OUTPUT: an integer
EXAMPLES:
sage: a = matrix(ZZ,2,3,[1..6]); a[1 2 3][4 5 6]sage: a.prod_of_row_sums([0,2])40
sage: (1+3)*(4+6)
40
sage: a.prod_of_row_sums(set([0,2]))40>>> from sage.all import *>>> a = matrix(ZZ,Integer(2),Integer(3),(ellipsis_range(Integer(1),Ellipsis,
˓→Integer(6)))); a[1 2 3][4 5 6]>>> a.prod_of_row_sums([Integer(0),Integer(2)])
40>>> (Integer(1)+Integer(3))*(Integer(4)+Integer(6))
40>>> a.prod_of_row_sums(set([Integer(0),Integer(2)]))40

randomize(density=1, x=None, y=None, distribution=None, nonzero=False)
Randomize density proportion of the entries of this matrix, leaving the rest unchanged.
642

Chapter 15. Dense matrices over the integer ring

Matrices and Spaces of Matrices, Release 10.4

The parameters are the same as the ones for the integer ring’s random_element function.
If x and y are given, randomized entries of this matrix have to be between x and y and have density 1.
INPUT:• self – a mutable matrix over ZZ• density – a float between 0 and 1• x, y – if not None, these are passed to the ZZ.random_element function as the upper and lower
endpoints in the uniform distribution• distribution – would also be passed into ZZ.random_element if given• nonzero – bool (default: False); whether the new entries are guaranteed to be zero
OUTPUT:• None, the matrix is modified in-place
EXAMPLES:
sage: A = matrix(ZZ, 2,3, [1..6])
sage: ranks = [True, True, True]
sage: while any(ranks):....:A.randomize()....:ranks[A.rank()] = False
sage: mini = 0
sage: maxi = 0
sage: while mini != -30 and maxi != 30:....:
A.randomize(x=-30, y=30)....:
mini = min(min(A.list()), mini)....:
maxi = min(min(A.list()), maxi)>>> from sage.all import *>>> A = matrix(ZZ, Integer(2),Integer(3), (ellipsis_range(Integer(1),Ellipsis,
˓→Integer(6))))>>> ranks = [True, True, True]>>> while any(ranks):...
A.randomize()...
ranks[A.rank()] = False>>> mini = Integer(0)>>> maxi = Integer(0)>>> while mini != -Integer(30) and maxi != Integer(30):...
A.randomize(x=-Integer(30), y=Integer(30))...
mini = min(min(A.list()), mini)...
maxi = min(min(A.list()), maxi)rank(algorithm='modp')
Return the rank of this matrix.
INPUT:• algorithm – either modp (default) or flint or linbox
OUTPUT:• a nonnegative integer – the rank

643

Matrices and Spaces of Matrices, Release 10.4

Note: The rank is cached.
ALGORITHM:
If set to modp , first check if the matrix has maximum possible rank by working modulo one random
prime. If not, call LinBox’s rank function.
EXAMPLES:
sage: a = matrix(ZZ,2,3,[1..6]); a[1 2 3][4 5 6]sage: a.rank()
2sage: a = matrix(ZZ,3,3,[1..9]); a[1 2 3][4 5 6][7 8 9]sage: a.rank()
2>>> from sage.all import *>>> a = matrix(ZZ,Integer(2),Integer(3),(ellipsis_range(Integer(1),Ellipsis,
˓→Integer(6)))); a[1 2 3][4 5 6]>>> a.rank()2>>> a = matrix(ZZ,Integer(3),Integer(3),(ellipsis_range(Integer(1),Ellipsis,
˓→Integer(9)))); a[1 2 3][4 5 6][7 8 9]>>> a.rank()
2

Here is a bigger example - the rank is of course still 2:
sage: a = matrix(ZZ,100,[1..100^2]); a.rank()
2>>> from sage.all import *>>> a = matrix(ZZ,Integer(100),(ellipsis_range(Integer(1),Ellipsis,
˓→Integer(100)**Integer(2)))); a.rank()
2

rational_reconstruction(N)Use rational reconstruction to lift self to a matrix over the rational numbers (if possible), where we view self
as a matrix modulo N.
INPUT:• N – an integer
OUTPUT:• matrix – over QQ or raise a ValueError

644

Chapter 15. Dense matrices over the integer ring

Matrices and Spaces of Matrices, Release 10.4

EXAMPLES: We create a random 4x4 matrix over ZZ.
sage: A = matrix(ZZ, 4, [4, -4, 7, 1, -1, 1, -1, -12, -1, -1, 1, -1, -3, 1, 5,
˓→ -1])>>> from sage.all import *>>> A = matrix(ZZ, Integer(4), [Integer(4), -Integer(4), Integer(7),␣
˓→Integer(1), -Integer(1), Integer(1), -Integer(1), -Integer(12), -Integer(1),˓→ -Integer(1), Integer(1), -Integer(1), -Integer(3), Integer(1), Integer(5),␣
˓→-Integer(1)])

There isn’t a unique rational reconstruction of it:
sage: A.rational_reconstruction(11)Traceback (most recent call last):...
ValueError: rational reconstruction does not exist>>> from sage.all import *>>> A.rational_reconstruction(Integer(11))
Traceback (most recent call last):...
ValueError: rational reconstruction does not exist

We throw in a denominator and reduce the matrix modulo 389 - it does rationally reconstruct.
sage: B = (A/3 % 389).change_ring(ZZ)
sage: B.rational_reconstruction(389) == A/3
True>>> from sage.all import *>>> B = (A/Integer(3) % Integer(389)).change_ring(ZZ)>>> B.rational_reconstruction(Integer(389)) == A/Integer(3)Truerow(i, from_list=False)
Return the i-th row of this matrix as a dense vector.
INPUT:• i – integer• from_list – ignored
EXAMPLES:
sage: m = matrix(ZZ, 2, [1, -2, 3, 4])
sage: m.row(0)(1, -2)sage: m.row(1)(3, 4)
sage: m.row(1, from_list=True)(3, 4)
sage: m.row(-2)(1, -2)sage: m.row(2)Traceback (most recent call last):(continues on next page)645

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
IndexError: row index out of range
sage: m.row(-3)
Traceback (most recent call last):...
IndexError: row index out of range>>> from sage.all import *>>> m = matrix(ZZ, Integer(2), [Integer(1), -Integer(2), Integer(3),␣
˓→Integer(4)])>>> m.row(Integer(0))(1, -2)>>> m.row(Integer(1))(3, 4)>>> m.row(Integer(1), from_list=True)(3, 4)>>> m.row(-Integer(2))(1, -2)>>> m.row(Integer(2))
Traceback (most recent call last):...
IndexError: row index out of range>>> m.row(-Integer(3))
Traceback (most recent call last):...
IndexError: row index out of range

saturation(p=0, proof=None, max_dets=5)
Return a saturation matrix of self, which is a matrix whose rows span the saturation of the row span of self.
This is not unique.
The saturation of a Z module 𝑀 embedded in Z𝑛 is a module 𝑆 that contains 𝑀 with finite index such that
Z𝑛 /𝑆 is torsion free. This function takes the row span 𝑀 of self, and finds another matrix of full rank withrow span the saturation of 𝑀 .
INPUT:• p – (default: 0); if nonzero given, saturate only at the prime 𝑝, i.e., return a matrix whose row span is a
Z-module 𝑆 that contains self and such that the index of 𝑆 in its saturation is coprime to 𝑝. If 𝑝 is None,
return full saturation of self.
• proof – (default: use proof.linear_algebra()); if False, the determinant calculations are done with
proof=False.
• max_dets – (default: 5); technical parameter - max number of determinant to compute when bounding
prime divisor of self in its saturation.
OUTPUT:• matrix – a matrix over ZZ
Note: The result is not cached.
ALGORITHM: 1. Replace input by a matrix of full rank got from a subset of the rows. 2. Divide out
any common factors from rows. 3. Check max_dets random dets of submatrices to see if their GCD (with646

Chapter 15. Dense matrices over the integer ring

Matrices and Spaces of Matrices, Release 10.4p) is 1 - if so matrix is saturated and we’re done. 4. Finally, use that if A is a matrix of full rank, thenℎ𝑛𝑓 (𝑡𝑟𝑎𝑛𝑠𝑝𝑜𝑠𝑒(𝐴))−1 * 𝐴 is a saturation of A.
EXAMPLES:
sage: A = matrix(ZZ, 3, 5, [-51, -1509, -71, -109, -593, -19, -341, 4, 86, 98,
˓→ 0, -246, -11, 65, 217])
sage: A.echelon_form()
[
1
5
2262
20364
56576][
0
635653 320873 891313][
0042993 386937 1074825]
sage: S = A.saturation(); S[ -51 -1509-71 -109 -593][ -19 -341
4
86
98]
[
35
994
43
51
347]
>>> from sage.all import *>>> A = matrix(ZZ, Integer(3), Integer(5), [-Integer(51), -Integer(1509), ˓→Integer(71), -Integer(109), -Integer(593), -Integer(19), -Integer(341),␣
˓→Integer(4), Integer(86), Integer(98), Integer(0), -Integer(246), ˓→Integer(11), Integer(65), Integer(217)])>>> A.echelon_form()
[
1
5
2262
20364
56576][
0
635653 320873 891313][
0042993 386937 1074825]>>> S = A.saturation(); S[ -51 -1509-71 -109 -593][ -19 -341
4
86
98]
[
35
994
43
51
347]

Notice that the saturation spans a different module than A.
sage: S.echelon_form()[ 1 2 0 8 32][ 0 3 0 -2 -6][ 0 0 1 9 25]
sage: V = A.row_space(); W = S.row_space()sage: V.is_submodule(W)True
sage: V.index_in(W)85986
sage: V.index_in_saturation()
85986>>> from sage.all import *>>> S.echelon_form()[ 1 2 0 8 32][ 0 3 0 -2 -6][ 0 0 1 9 25]>>> V = A.row_space(); W = S.row_space()>>> V.is_submodule(W)
True>>> V.index_in(W)85986>>> V.index_in_saturation()
85986

We illustrate each option:
647

Matrices and Spaces of Matrices, Release 10.4

sage: S = A.saturation(p=2)
sage: S = A.saturation(proof=False)
sage: S = A.saturation(max_dets=2)>>> from sage.all import *>>> S = A.saturation(p=Integer(2))>>> S = A.saturation(proof=False)>>> S = A.saturation(max_dets=Integer(2))

smith_form(transformation=True, integral=None)
Return the smith normal form of this matrix, that is the diagonal matrix 𝑆 with diagonal entries the orderedelementary divisors of this matrix.
INPUT:• transformation – a boolean (default: True); whether to return the transformation matrices 𝑈 and𝑉 such that 𝑆 = 𝑈 · 𝑠𝑒𝑙𝑓 · 𝑉 .
• integral – a subring of the base ring or True (default: None); ignored for matrices with integer
entries.
Note: The elementary_divisors() function, which returns the diagonal entries of 𝑆, is VASTLY
faster than this function.
The elementary divisors are the invariants of the finite abelian group that is the cokernel of this matrix. They
are ordered in reverse by divisibility.
EXAMPLES:
sage: A = MatrixSpace(IntegerRing(), 3)(range(9))
sage: D, U, V = A.smith_form()
sage: D
[1 0 0][0 3 0][0 0 0]sage: U[ 0 2 -1]
[ 0 -1 1][ 1 -2 1]
sage: V[ 0 0 1][-1 2 -2]
[ 1 -1 1]
sage: U*A*V[1 0 0][0 3 0][0 0 0]>>> from sage.all import *>>> A = MatrixSpace(IntegerRing(), Integer(3))(range(Integer(9)))>>> D, U, V = A.smith_form()>>> D[1 0 0][0 3 0][0 0 0]>>> U(continues on next page)

648

Chapter 15. Dense matrices over the integer ring

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 0 2 -1]
[ 0 -1 1][ 1 -2 1]>>> V[ 0 0 1][-1 2 -2]
[ 1 -1 1]>>> U*A*V[1 0 0][0 3 0][0 0 0]It also makes sense for nonsquare matrices:sage: A = Matrix(ZZ,3,2,range(6))
sage: D, U, V = A.smith_form()
sage: D
[1 0]
[0 2]
[0 0]
sage: U[ 0 2 -1]
[ 0 -1 1][ 1 -2 1]
sage: V[-1 1][ 1 0]
sage: U * A * V
[1 0]
[0 2]
[0 0]
>>> from sage.all import *>>> A = Matrix(ZZ,Integer(3),Integer(2),range(Integer(6)))>>> D, U, V = A.smith_form()
>>> D
[1 0]
[0 2]
[0 0]
>>> U
[ 0 2 -1]
[ 0 -1 1][ 1 -2 1]>>> V[-1 1][ 1 0]>>> U * A * V
[1 0]
[0 2]
[0 0]

Empty matrices are handled sensibly (see Issue #3068):
sage: m = MatrixSpace(ZZ, 2,0)(0); d,u,v = m.smith_form(); u*m*v == dTruesage: m = MatrixSpace(ZZ, 0,2)(0); d,u,v = m.smith_form(); u*m*v == d(continues on next page)649

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)True
sage: m = MatrixSpace(ZZ, 0,0)(0); d,u,v = m.smith_form(); u*m*v == dTrue>>> from sage.all import *>>> m = MatrixSpace(ZZ, Integer(2),Integer(0))(Integer(0)); d,u,v = m.smith_
˓→form(); u*m*v == dTrue>>> m = MatrixSpace(ZZ, Integer(0),Integer(2))(Integer(0)); d,u,v = m.smith_
˓→form(); u*m*v == dTrue>>> m = MatrixSpace(ZZ, Integer(0),Integer(0))(Integer(0)); d,u,v = m.smith_
˓→form(); u*m*v == dTrue

See also:
elementary_divisors()
symplectic_form()
Find a symplectic basis for self if self is an anti-symmetric, alternating matrix.
Return a pair (F, C) such that the rows of C form a symplectic basis for self and F = C * self *C.transpose().
Raise a ValueError if self is not anti-symmetric, or self is not alternating.
Anti-symmetric means that 𝑀 = −𝑀 𝑡 . Alternating means that the diagonal of 𝑀 is identically zero.
A symplectic basis is a basis of the form 𝑒1 , . . . , 𝑒𝑗 , 𝑓1 , . . . 𝑓𝑗 , 𝑧1 , . . . , 𝑧𝑘 such that• 𝑧𝑖 𝑀 𝑣 𝑡 = 0 for all vectors 𝑣• 𝑒𝑖 𝑀 𝑒𝑗 𝑡 = 0 for all 𝑖, 𝑗
• 𝑓𝑖 𝑀 𝑓𝑗 𝑡 = 0 for all 𝑖, 𝑗
• 𝑒𝑖 𝑀 𝑓𝑖 𝑡 = 1 for all 𝑖• 𝑒𝑖 𝑀 𝑓𝑗 𝑡 = 0 for all 𝑖 not equal𝑗.
The ordering for the factors 𝑑𝑖 |𝑑𝑖+1 and for the placement of zeroes was chosen to agree with the output ofsmith_form().
See the example for a pictorial description of such a basis.
EXAMPLES:
sage: E = matrix(ZZ, 5, 5, [0, 14, 0, -8, -2, -14, 0, -3, -11, 4, 0, 3, 0, 0,␣
˓→0, 8, 11, 0, 0, 8, 2, -4, 0, -8, 0]); E[ 0 140 -8 -2][-14
0 -3 -11
4]
[ 0
3
0
0
0]
[ 8 110
0
8][ 2 -40 -8
0]sage: F, C = E.symplectic_form()
sage: F[ 0 0 1 0 0]
[ 0 0 0 2 0][-1 0 0 0 0](continues on next page)

650

Chapter 15. Dense matrices over the integer ring

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 0 -2 0 0 0]
[ 0 0 0 0 0]
sage: F == C * E * C.transpose()True
sage: E.smith_form()[0][1 0 0 0 0]
[0 1 0 0 0]
[0 0 2 0 0]
[0 0 0 2 0]
[0 0 0 0 0]>>> from sage.all import *>>> E = matrix(ZZ, Integer(5), Integer(5), [Integer(0), Integer(14),␣
˓→Integer(0), -Integer(8), -Integer(2), -Integer(14), Integer(0), -Integer(3),˓→ -Integer(11), Integer(4), Integer(0), Integer(3), Integer(0), Integer(0),␣
˓→Integer(0), Integer(8), Integer(11), Integer(0), Integer(0), Integer(8),␣
˓→Integer(2), -Integer(4), Integer(0), -Integer(8), Integer(0)]); E[ 0 140 -8 -2][-14
0 -3 -11
4]
[ 0
3
0
0
0]
[ 8 110
0
8][ 2 -40 -8
0]>>> F, C = E.symplectic_form()>>> F[ 0 0 1 0 0]
[ 0 0 0 2 0][-1 0 0 0 0]
[ 0 -2 0 0 0]
[ 0 0 0 0 0]>>> F == C * E * C.transpose()
True>>> E.smith_form()[Integer(0)][1 0 0 0 0]
[0 1 0 0 0]
[0 0 2 0 0]
[0 0 0 2 0]
[0 0 0 0 0]transpose()
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: A = matrix(ZZ, 2, 3, range(6))
sage: type(A)<class sage.matrix.matrix_integer_dense.Matrix_integer_dense >sage: B = A.transpose()sage: print(B)
[0 3]
[1 4]
[2 5]
sage: print(A)[0 1 2][3 4 5]651

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = matrix(ZZ, Integer(2), Integer(3), range(Integer(6)))>>> type(A)<class sage.matrix.matrix_integer_dense.Matrix_integer_dense >>>> B = A.transpose()>>> print(B)
[0 3]
[1 4]
[2 5]
>>> print(A)[0 1 2][3 4 5].T is a convenient shortcut for the transpose:
sage: A.T
[0 3]
[1 4]
[2 5]
>>> from sage.all import *>>> A.T
[0 3]
[1 4]
[2 5]
sage: A.subdivide(None, 1); A[0|1 2][3|4 5]sage: A.transpose()
[0 3]
[---]
[1 4]
[2 5]
>>> from sage.all import *>>> A.subdivide(None, Integer(1)); A[0|1 2][3|4 5]>>> A.transpose()
[0 3]
[---]
[1 4]
[2 5]

652

Chapter 15. Dense matrices over the integer ring

CHAPTERSIXTEENSPARSE INTEGER MATRICESAUTHORS:• William Stein (2007-02-21)• Soroosh Yazdani (2007-02-21)class sage.matrix.matrix_integer_sparse.Matrix_integer_sparse
Bases: Matrix_sparse
Create a sparse matrix over the integers.
INPUT:• parent – a matrix space over ZZ• entries – see matrix()• copy – ignored (for backwards compatibility)• coerce – if False, assume without checking that the entries are of type Integer.
charpoly(var='x', algorithm=None)
Return the characteristic polynomial of this matrix.
INPUT:• var – (default: x ) the name of the variable of the polynomial• algorithm – (default: None) one of None, linbox , or an algorithm accepted by sage.
matrix.matrix_sparse.Matrix_sparse.charpoly()
EXAMPLES:
sage: M = MatrixSpace(ZZ, 4, sparse=True)
sage: m = M()sage: m[0,0] = m[1,2] = m[2,3] = m[3,3] = 1
sage: m[0,2] = m[1,3] = m[2,0] = m[3,0] = -3
sage: m[1,1] = 2
sage: m[ 1 0 -3 0][ 0 2 1 -3][-3 0 0 1][-3 0 0 1]
sage: m.charpoly()x^4 - 4*x^3 - 4*x^2 + 16*x

653

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> M = MatrixSpace(ZZ, Integer(4), sparse=True)>>> m = M()>>> m[Integer(0),Integer(0)] = m[Integer(1),Integer(2)] = m[Integer(2),˓→Integer(3)] = m[Integer(3),Integer(3)] = Integer(1)>>> m[Integer(0),Integer(2)] = m[Integer(1),Integer(3)] = m[Integer(2),˓→Integer(0)] = m[Integer(3),Integer(0)] = -Integer(3)>>> m[Integer(1),Integer(1)] = Integer(2)>>> m[ 1 0 -3 0][ 0 2 1 -3][-3 0 0 1][-3 0 0 1]>>> m.charpoly()x^4 - 4*x^3 - 4*x^2 + 16*x

elementary_divisors(algorithm='pari')
Return the elementary divisors of self, in order.
The elementary divisors are the invariants of the finite abelian group that is the cokernel of left multiplicationby this matrix. They are ordered in reverse by divisibility.
INPUT:• self – matrix• algorithm – (default: ‘pari’)– ‘pari’: works robustly, but is slower.
– ‘linbox’ – use linbox (currently off, broken)
OUTPUT:
list of integers
EXAMPLES:
sage: matrix(3, range(9),sparse=True).elementary_divisors()[1, 3, 0]
sage: M = matrix(ZZ, 3, [1,5,7, 3,6,9, 0,1,2], sparse=True)
sage: M.elementary_divisors()[1, 1, 6]>>> from sage.all import *>>> matrix(Integer(3), range(Integer(9)),sparse=True).elementary_divisors()[1, 3, 0]>>> M = matrix(ZZ, Integer(3), [Integer(1),Integer(5),Integer(7), Integer(3),˓→Integer(6),Integer(9), Integer(0),Integer(1),Integer(2)], sparse=True)>>> M.elementary_divisors()[1, 1, 6]This returns a copy, which is safe to change:
sage: edivs = M.elementary_divisors()
sage: edivs.pop()
6
sage: M.elementary_divisors()[1, 1, 6]654

Chapter 16. Sparse integer matrices

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> edivs = M.elementary_divisors()>>> edivs.pop()
6>>> M.elementary_divisors()[1, 1, 6]

See also:smith_form()
hermite_form(algorithm='default', cutoff=0, **kwds)
Return the echelon form of self.
Note: This row reduction does not use division if the matrix is not over a field (e.g., if the matrix is over the
integers). If you want to calculate the echelon form using division, then use rref(), which assumes that thematrix entries are in a field (specifically, the field of fractions of the base ring of the matrix).
INPUT:• algorithm – string. Which algorithm to use. Choices are–default : Let Sage choose an algorithm (default).

–classical : Gauss elimination.

–

partial_pivoting : Gauss elimination, using partial pivoting (if base ring has absolutevalue)–

scaled_partial_pivoting : Gauss elimination, using scaled partial pivoting (if base ringhas absolute value)–

scaled_partial_pivoting_valuation : Gauss elimination, using scaled partial pivoting (if base ring has valuation)–strassen : use a Strassen divide and conquer algorithm (if available)• cutoff – integer. Only used if the Strassen algorithm is selected.
• transformation – boolean. Whether to also return the transformation matrix. Some matrix backends do not provide this information, in which case this option is ignored.
OUTPUT:The reduced row echelon form of self, as an immutable matrix. Note that self is not changed by thiscommand. Use echelonize() to change self in place.
If the optional parameter transformation=True is specified, the output consists of a pair (𝐸, 𝑇 ) of
matrices where 𝐸 is the echelon form of self and 𝑇 is the transformation matrix.
EXAMPLES:
sage: MS = MatrixSpace(GF(19), 2, 3)
sage: C = MS.matrix([1,2,3,4,5,6])
sage: C.rank()
2sage: C.nullity()0sage: C.echelon_form()[ 1 0 18]
[ 0 1 2]655

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> MS = MatrixSpace(GF(Integer(19)), Integer(2), Integer(3))>>> C = MS.matrix([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5),˓→Integer(6)])>>> C.rank()
2>>> C.nullity()0>>> C.echelon_form()[ 1 0 18]
[ 0 1 2]The matrix library used for Z/𝑝-matrices does not return the transformation matrix, so the transformation option is ignored:sage: C.echelon_form(transformation=True)[ 1 0 18]
[ 0 1 2]sage: D = matrix(ZZ, 2, 3, [1,2,3,4,5,6])
sage: D.echelon_form(transformation=True)([1 2 3] [ 1 0]
[0 3 6], [ 4 -1])
sage: E, T = D.echelon_form(transformation=True)
sage: T*D == E
True>>> from sage.all import *>>> C.echelon_form(transformation=True)[ 1 0 18]
[ 0 1 2]>>> D = matrix(ZZ, Integer(2), Integer(3), [Integer(1),Integer(2),Integer(3),˓→Integer(4),Integer(5),Integer(6)])>>> D.echelon_form(transformation=True)([1 2 3] [ 1 0]
[0 3 6], [ 4 -1])>>> E, T = D.echelon_form(transformation=True)>>> T*D == E
True

minpoly(var='x', algorithm=None)
Return the minimal polynomial of this matrix.
INPUT:• var – (default: x ) the name of the variable of the polynomial• algorithm – (default: None) one of None, linbox , or an algorithm accepted by sage.
matrix.matrix_sparse.Matrix_sparse.minpoly()
EXAMPLES:

656

Chapter 16. Sparse integer matrices

Matrices and Spaces of Matrices, Release 10.4

sage: M = MatrixSpace(ZZ, 4, sparse=True)
sage: m = M({(0, 0):2, (1, 1):1, (2, 1):-8, (2, 2):2, (2, 3):-1, (3, 3):1})
sage: m[ 2 0 0 0]
[ 0 1 0 0]
[ 0 -8 2 -1][ 0 0 0 1]
sage: m.minpoly()x^2 - 3*x + 2>>> from sage.all import *>>> M = MatrixSpace(ZZ, Integer(4), sparse=True)>>> m = M({(Integer(0), Integer(0)):Integer(2), (Integer(1),␣
˓→Integer(1)):Integer(1), (Integer(2), Integer(1)):-Integer(8), (Integer(2),␣
˓→Integer(2)):Integer(2), (Integer(2), Integer(3)):-Integer(1), (Integer(3),␣
˓→Integer(3)):Integer(1)})>>> m[ 2 0 0 0]
[ 0 1 0 0]
[ 0 -8 2 -1][ 0 0 0 1]>>> m.minpoly()x^2 - 3*x + 2

rank(algorithm=None)
Compute the rank of this matrix.
INPUT:• algorithm – (optional) one of None, linbox or generic
EXAMPLES:
sage: M = MatrixSpace(ZZ, 3, 2, sparse=True)
sage: m = M([1, 0, 2, 3, -1, 0])
sage: m.rank()
2>>> from sage.all import *>>> M = MatrixSpace(ZZ, Integer(3), Integer(2), sparse=True)>>> m = M([Integer(1), Integer(0), Integer(2), Integer(3), -Integer(1),␣
˓→Integer(0)])>>> m.rank()
2

rational_reconstruction(N)Use rational reconstruction to lift self to a matrix over the rational numbers (if possible), where we view
self as a matrix modulo 𝑁 .
EXAMPLES:
sage: A = matrix(ZZ, 3, 4, [(1/3)%500, 2, 3, (-4)%500,....:
7, 2, 2, 3,....:
4, 3, 4, (5/7)%500], sparse=True)
sage: A.rational_reconstruction(500)
[1/3
2
3 -4]
[ 7
2
2
3]
[ 4
3
4 5/7]

657

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = matrix(ZZ, Integer(3), Integer(4), [(Integer(1)/Integer(3))˓→%Integer(500), Integer(2), Integer(3), (-Integer(4))%Integer(500),...
Integer(7), Integer(2), Integer(2), Integer(3),...
Integer(4), Integer(3), Integer(4), (Integer(5)/˓→Integer(7))%Integer(500)], sparse=True)>>> A.rational_reconstruction(Integer(500))
[1/3
2
3 -4]
[ 7
2
2
3]
[ 4
3
4 5/7]

smith_form(transformation=True, integral=None)
Return the smith normal form of this matrix, that is the diagonal matrix 𝑆 with diagonal entries the orderedelementary divisors of this matrix.
INPUT:• transformation – a boolean (default: True); whether to return the transformation matrices 𝑈 and𝑉 such that 𝑆 = 𝑈 · 𝑠𝑒𝑙𝑓 · 𝑉 .
• integral – a subring of the base ring or True (default: None); ignored for matrices with integer
entries.
This version is for sparse matrices and simply makes the matrix dense and calls the version for dense integer
matrices.
Note: The elementary_divisors() function, which returns the diagonal entries of S, is VASTLY
faster than this function.
The elementary divisors are the invariants of the finite abelian group that is the cokernel of this matrix. They
are ordered in reverse by divisibility.
EXAMPLES:
sage: A = MatrixSpace(IntegerRing(), 3, sparse=True)(range(9))
sage: D, U, V = A.smith_form()
sage: D
[1 0 0][0 3 0][0 0 0]sage: U[ 0 2 -1]
[ 0 -1 1][ 1 -2 1]
sage: V[ 0 0 1][-1 2 -2]
[ 1 -1 1]
sage: U*A*V[1 0 0][0 3 0][0 0 0]>>> from sage.all import *>>> A = MatrixSpace(IntegerRing(), Integer(3), sparse=True)(range(Integer(9)))>>> D, U, V = A.smith_form()(continues on next page)

658

Chapter 16. Sparse integer matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> D[1 0 0][0 3 0][0 0 0]>>> U[ 0 2 -1]
[ 0 -1 1][ 1 -2 1]>>> V[ 0 0 1][-1 2 -2]
[ 1 -1 1]>>> U*A*V[1 0 0][0 3 0][0 0 0]It also makes sense for nonsquare matrices:sage: A = Matrix(ZZ,3,2,range(6), sparse=True)
sage: D, U, V = A.smith_form()
sage: D
[1 0]
[0 2]
[0 0]
sage: U[ 0 2 -1]
[ 0 -1 1][ 1 -2 1]
sage: V[-1 1][ 1 0]
sage: U * A * V
[1 0]
[0 2]
[0 0]
>>> from sage.all import *>>> A = Matrix(ZZ,Integer(3),Integer(2),range(Integer(6)), sparse=True)>>> D, U, V = A.smith_form()
>>> D
[1 0]
[0 2]
[0 0]
>>> U
[ 0 2 -1]
[ 0 -1 1][ 1 -2 1]>>> V[-1 1][ 1 0]>>> U * A * V
[1 0]
[0 2]
[0 0]

The examples above show that Issue #10626 has been implemented.
659

Matrices and Spaces of Matrices, Release 10.4

See also:
elementary_divisors()

660

Chapter 16. Sparse integer matrices

CHAPTERSEVENTEEN

MODULAR ALGORITHM TO COMPUTE HERMITE NORMAL FORMS
OF INTEGER MATRICESAUTHORS:• Clement Pernet and William Stein (2008-02-07): initial version
sage.matrix.matrix_integer_dense_hnf.add_column(B, H_B, a, proof)
The add column procedure.
INPUT:• B – a square matrix (may be singular)• H_B – the Hermite normal form of B
• a – an n x 1 matrix, where B has n rows
• proof – bool; whether to prove result correct, in case we use fallback method.
OUTPUT:• x – a vector such that H’ = H_B.augment(x) is the HNF of A = B.augment(a).
EXAMPLES:
sage: B = matrix(ZZ, 3, 3, [1,2,5, 0,-5,3, 1,1,2])
sage: H_B = B.echelon_form()
sage: a = matrix(ZZ, 3, 1, [1,8,-2])
sage: import sage.matrix.matrix_integer_dense_hnf as hnf
sage: x = hnf.add_column(B, H_B, a, True); x
[18]
[ 3]
[23]
sage: H_B.augment(x)[ 1 0 17 18][ 0 1 3 3]
[ 0 0 18 23]
sage: B.augment(a).echelon_form()[ 1 0 17 18][ 0 1 3 3]
[ 0 0 18 23]>>> from sage.all import *>>> B = matrix(ZZ, Integer(3), Integer(3), [Integer(1),Integer(2),Integer(5),␣
˓→Integer(0),-Integer(5),Integer(3), Integer(1),Integer(1),Integer(2)])>>> H_B = B.echelon_form()>>> a = matrix(ZZ, Integer(3), Integer(1), [Integer(1),Integer(8),-Integer(2)])(continues on next page)661

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> import sage.matrix.matrix_integer_dense_hnf as hnf>>> x = hnf.add_column(B, H_B, a, True); x
[18]
[ 3]
[23]
>>> H_B.augment(x)[ 1 0 17 18][ 0 1 3 3]
[ 0 0 18 23]>>> B.augment(a).echelon_form()[ 1 0 17 18][ 0 1 3 3]
[ 0 0 18 23]

sage.matrix.matrix_integer_dense_hnf.add_column_fallback(B, a, proof)
Simplistic version of add_column, in case the powerful clever one fails (e.g., B is singular).
INPUT:
B – a square matrix (may be singular) a – an n x 1 matrix, where B has n rows proof – bool; whether toprove result correct
OUTPUT:x – a vector such that H’ = H_B.augment(x) is the HNF of A = B.augment(a).
EXAMPLES:
sage: B = matrix(ZZ,3, [-1, -1, 1, -3, 8, -2, -1, -1, -1])
sage: a = matrix(ZZ,3,1, [1,2,3])
sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
sage: matrix_integer_dense_hnf.add_column_fallback(B, a, True)
[-3]
[-7]
[-2]
sage: matrix_integer_dense_hnf.add_column_fallback(B, a, False)
[-3]
[-7]
[-2]
sage: B.augment(a).hermite_form()[ 1 1 1 -3][ 0 11 1 -7][ 0 0 2 -2]>>> from sage.all import *>>> B = matrix(ZZ,Integer(3), [-Integer(1), -Integer(1), Integer(1), -Integer(3),␣
˓→Integer(8), -Integer(2), -Integer(1), -Integer(1), -Integer(1)])>>> a = matrix(ZZ,Integer(3),Integer(1), [Integer(1),Integer(2),Integer(3)])>>> import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf>>> matrix_integer_dense_hnf.add_column_fallback(B, a, True)
[-3]
[-7]
[-2]
>>> matrix_integer_dense_hnf.add_column_fallback(B, a, False)
[-3]
[-7]
[-2]
>>> B.augment(a).hermite_form()(continues on next page)

662

Chapter 17. Modular algorithm to compute Hermite normal forms of integer matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 1 1[ 0 11
[ 0 0

1 -3]
1 -7]
2 -2]

sage.matrix.matrix_integer_dense_hnf.add_row(A, b, pivots, include_zero_rows)
The add row procedure.
INPUT:• A – a matrix in Hermite normal form with n column• b – an n x 1 row matrix• pivots – sorted list of integers; the pivot positions of A.
OUTPUT:• H – the Hermite normal form of A.stack(b).
• new_pivots – the pivot columns of H.
EXAMPLES:
sage: import sage.matrix.matrix_integer_dense_hnf as hnf
sage: A = matrix(ZZ, 2, 3, [-21, -7, 5, 1,20,-7])
sage: b = matrix(ZZ, 1,3, [-1,1,-1])
sage: hnf.add_row(A, b, A.pivots(), True)([ 1 6 29]
[ 0 7 28]
[ 0 0 46], [0, 1, 2])
sage: A.stack(b).echelon_form()[ 1 6 29]
[ 0 7 28]
[ 0 0 46]>>> from sage.all import *>>> import sage.matrix.matrix_integer_dense_hnf as hnf>>> A = matrix(ZZ, Integer(2), Integer(3), [-Integer(21), -Integer(7), Integer(5),˓→ Integer(1),Integer(20),-Integer(7)])>>> b = matrix(ZZ, Integer(1),Integer(3), [-Integer(1),Integer(1),-Integer(1)])>>> hnf.add_row(A, b, A.pivots(), True)([ 1 6 29]
[ 0 7 28]
[ 0 0 46], [0, 1, 2])>>> A.stack(b).echelon_form()[ 1 6 29]
[ 0 7 28]
[ 0 0 46]

sage.matrix.matrix_integer_dense_hnf.benchmark_hnf(nrange, bits=4)
Run benchmark program.
EXAMPLES:

663

Matrices and Spaces of Matrices, Release 10.4

sage: import sage.matrix.matrix_integer_dense_hnf as hnf
sage: hnf.benchmark_hnf([10,25],32)( sage , 10, 32, ...),( sage , 25, 32, ...),>>> from sage.all import *>>> import sage.matrix.matrix_integer_dense_hnf as hnf>>> hnf.benchmark_hnf([Integer(10),Integer(25)],Integer(32))( sage , 10, 32, ...),( sage , 25, 32, ...),

sage.matrix.matrix_integer_dense_hnf.benchmark_magma_hnf(nrange, bits=4)
EXAMPLES:
sage: import sage.matrix.matrix_integer_dense_hnf as hnf
sage: hnf.benchmark_magma_hnf([50,100],32)# optional - magma( magma , 50, 32, ...),( magma , 100, 32, ...),>>> from sage.all import *>>> import sage.matrix.matrix_integer_dense_hnf as hnf>>> hnf.benchmark_magma_hnf([Integer(50),Integer(100)],Integer(32))
˓→optional - magma( magma , 50, 32, ...),( magma , 100, 32, ...),#␣sage.matrix.matrix_integer_dense_hnf.det_from_modp_and_divisor(A, d, p, z_mod,
moduli, z_so_far=1,
N_so_far=1)
This is used for internal purposes for computing determinants quickly (with the hybrid p-adic / multimodular
algorithm).
INPUT:• A – a square matrix• d – a divisor of the determinant of A
• p – a prime• z_mod – values of det/d (mod …)• moduli – the moduli so far• z_so_far – for a modulus p in the list moduli, (z_so_far mod p) is the determinant of A modulo p.
• N_so_far – N_so_far is the product over the primes in the list moduli.
OUTPUT:• A triple (det bound, new z_so_far, new N_so_far).
EXAMPLES:
sage: a = matrix(ZZ, 3, [6, 1, 2, -56, -2, -1, -11, 2, -3])
sage: factor(a.det())-1 * 13 * 29
sage: d = 13
sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf(continues on next page)

664

Chapter 17. Modular algorithm to compute Hermite normal forms of integer matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: matrix_integer_dense_hnf.det_from_modp_and_divisor(a, d, 97, [], [])(-377, -29, 97)
sage: a.det()-377>>> from sage.all import *>>> a = matrix(ZZ, Integer(3), [Integer(6), Integer(1), Integer(2), -Integer(56),␣
˓→-Integer(2), -Integer(1), -Integer(11), Integer(2), -Integer(3)])>>> factor(a.det())-1 * 13 * 29>>> d = Integer(13)>>> import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf>>> matrix_integer_dense_hnf.det_from_modp_and_divisor(a, d, Integer(97), [], [])(-377, -29, 97)>>> a.det()-377

sage.matrix.matrix_integer_dense_hnf.det_given_divisor(A, d, proof=True, stabilize=2)
Given a divisor d of the determinant of A, compute the determinant of A.
INPUT:• A – a square integer matrix• d – a nonzero integer that is assumed to divide the determinant of A
• proof – bool (default: True) compute det modulo enough primes so that the determinant is computed provably correctly (via the Hadamard bound). It would be VERY hard for det() to fail even with proof=False.
• stabilize – int (default: 2) if proof = False, then compute the determinant modulo 𝑝 until stabilize
successive modulo determinant computations stabilize.
OUTPUT:
integer – determinant
EXAMPLES:
sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
sage: a = matrix(ZZ,3,[-1, -1, -1, -20, 4, 1, -1, 1, 2])
sage: matrix_integer_dense_hnf.det_given_divisor(a, 3)-30
sage: matrix_integer_dense_hnf.det_given_divisor(a, 3, proof=False)-30
sage: matrix_integer_dense_hnf.det_given_divisor(a, 3, proof=False, stabilize=1)-30
sage: a.det()-30>>> from sage.all import *>>> import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf>>> a = matrix(ZZ,Integer(3),[-Integer(1), -Integer(1), -Integer(1), -Integer(20),
˓→ Integer(4), Integer(1), -Integer(1), Integer(1), Integer(2)])>>> matrix_integer_dense_hnf.det_given_divisor(a, Integer(3))-30>>> matrix_integer_dense_hnf.det_given_divisor(a, Integer(3), proof=False)-30>>> matrix_integer_dense_hnf.det_given_divisor(a, Integer(3), proof=False,␣
(continues on next page)665

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)stabilize=Integer(1))-30>>> a.det()-30
˓→Here we illustrate proof=False giving a wrong answer:
sage: p = matrix_integer_dense_hnf.max_det_prime(2)sage: q = previous_prime(p)sage: a = matrix(ZZ, 2, [p, 0, 0, q])
sage: p * q
70368442188091
sage: matrix_integer_dense_hnf.det_given_divisor(a, 1, proof=False, stabilize=2)0>>> from sage.all import *>>> p = matrix_integer_dense_hnf.max_det_prime(Integer(2))>>> q = previous_prime(p)>>> a = matrix(ZZ, Integer(2), [p, Integer(0), Integer(0), q])>>> p * q70368442188091>>> matrix_integer_dense_hnf.det_given_divisor(a, Integer(1), proof=False,␣
˓→stabilize=Integer(2))
0This still works, because we do not work modulo primes that divide the determinant bound, which is found usinga p-adic algorithm:
sage: a.det(proof=False, stabilize=2)70368442188091>>> from sage.all import *>>> a.det(proof=False, stabilize=Integer(2))
70368442188091

3 primes is enough:sage: matrix_integer_dense_hnf.det_given_divisor(a, 1, proof=False, stabilize=3)70368442188091
sage: matrix_integer_dense_hnf.det_given_divisor(a, 1, proof=False, stabilize=5)70368442188091
sage: matrix_integer_dense_hnf.det_given_divisor(a, 1, proof=True)
70368442188091>>> from sage.all import *>>> matrix_integer_dense_hnf.det_given_divisor(a, Integer(1), proof=False,␣
˓→stabilize=Integer(3))
70368442188091>>> matrix_integer_dense_hnf.det_given_divisor(a, Integer(1), proof=False,␣
˓→stabilize=Integer(5))
70368442188091>>> matrix_integer_dense_hnf.det_given_divisor(a, Integer(1), proof=True)
70368442188091

sage.matrix.matrix_integer_dense_hnf.det_padic(A, proof=True, stabilize=2)
Return the determinant of A, computed using a p-adic/multimodular algorithm.
666

Chapter 17. Modular algorithm to compute Hermite normal forms of integer matrices

Matrices and Spaces of Matrices, Release 10.4

INPUT:• A – a square matrix• proof – boolean• stabilize (default: 2) – if proof False, number of successive primes so that CRT det must stabilize.
EXAMPLES:
sage: import sage.matrix.matrix_integer_dense_hnf as hsage: a = matrix(ZZ, 3, [1..9])sage: h.det_padic(a)0sage: a = matrix(ZZ, 3, [1,2,5,-7,8,10,192,5,18])
sage: h.det_padic(a)-3669
sage: a.determinant(algorithm= ntl )-3669>>> from sage.all import *>>> import sage.matrix.matrix_integer_dense_hnf as h>>> a = matrix(ZZ, Integer(3), (ellipsis_range(Integer(1),Ellipsis,Integer(9))))>>> h.det_padic(a)0>>> a = matrix(ZZ, Integer(3), [Integer(1),Integer(2),Integer(5),-Integer(7),˓→Integer(8),Integer(10),Integer(192),Integer(5),Integer(18)])>>> h.det_padic(a)-3669>>> a.determinant(algorithm= ntl )-3669

sage.matrix.matrix_integer_dense_hnf.double_det(A, b, c, proof)
Compute the determinants of the stacked integer matrices A.stack(b) and A.stack(c).
INPUT:• A – an (n-1) x n matrix• b – a 1 x n matrix• c – a 1 x n matrix• proof – whether or not to compute the det modulo enough times to provably compute the determinant.
OUTPUT:• a pair of two integers.
EXAMPLES:
sage: from sage.matrix.matrix_integer_dense_hnf import double_det
sage: A = matrix(ZZ, 2, 3, [1,2,3, 4,-2,5])
sage: b = matrix(ZZ, 1, 3, [1,-2,5])
sage: c = matrix(ZZ, 1, 3, [8,2,10])
sage: A.stack(b).det()-48
sage: A.stack(c).det()
42
sage: double_det(A, b, c, False)(-48, 42)667

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> from sage.matrix.matrix_integer_dense_hnf import double_det>>> A = matrix(ZZ, Integer(2), Integer(3), [Integer(1),Integer(2),Integer(3),␣
˓→Integer(4),-Integer(2),Integer(5)])>>> b = matrix(ZZ, Integer(1), Integer(3), [Integer(1),-Integer(2),Integer(5)])>>> c = matrix(ZZ, Integer(1), Integer(3), [Integer(8),Integer(2),Integer(10)])>>> A.stack(b).det()-48>>> A.stack(c).det()
42>>> double_det(A, b, c, False)(-48, 42)

sage.matrix.matrix_integer_dense_hnf.extract_ones_data(H, pivots)
Compute ones data and corresponding submatrices of H.
This is used to optimized the add_row() function.
INPUT:• H – a matrix in HNF• pivots – list of all pivot column positions of H
OUTPUT:C, D, E, onecol, onerow, non_onecol, non_onerow where onecol, onerow, non_onecol, non_onerow are as for theones function, and C, D, E are matrices:• C – submatrix of all non-onecol columns and onecol rows
• D – all non-onecol columns and other rows
• E – inverse of D
If D is not invertible or there are 0 or more than 2 non onecols, then C, D, and E are set to None.
EXAMPLES:
sage: H = matrix(ZZ, 3, 4, [1, 0, 0, 7, 0, 1, 5, 2, 0, 0, 6, 6])
sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
sage: matrix_integer_dense_hnf.extract_ones_data(H, [0,1,2])([0][5], [6], [1/6], [0, 1], [0, 1], [2], [2])>>> from sage.all import *>>> H = matrix(ZZ, Integer(3), Integer(4), [Integer(1), Integer(0), Integer(0),␣
˓→Integer(7), Integer(0), Integer(1), Integer(5), Integer(2), Integer(0),␣
˓→Integer(0), Integer(6), Integer(6)])>>> import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf>>> matrix_integer_dense_hnf.extract_ones_data(H, [Integer(0),Integer(1),˓→Integer(2)])([0][5], [6], [1/6], [0, 1], [0, 1], [2], [2])Here we get None’s since the (2,2) position submatrix is not invertible.
sage: H = matrix(ZZ, 3, 5, [1, 0, 0, 45, -36, 0, 1, 0, 131, -107, 0, 0, 0, 178, -145]); H [ 1 0 0 45 -36] [ 0 1 0
668

Chapter 17. Modular algorithm to compute Hermite normal forms of integer matrices

Matrices and Spaces of Matrices, Release 10.4

131 -107] [ 0 0 0 178 -145] sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
sage: matrix_integer_dense_hnf.extract_ones_data(H, [0,1,3]) (None, None, None, [0, 1], [0, 1], [2], [2])sage.matrix.matrix_integer_dense_hnf.hnf(A, include_zero_rows=True, proof=True)
Return the Hermite Normal Form of a general integer matrix A, along with the pivot columns.
INPUT:• A – an n x m matrix A over the integers.
• include_zero_rows – bool (default: True) whether or not to include zero rows in the output matrix• proof – whether or not to prove the result correct.
OUTPUT:• matrix – the Hermite normal form of A
• pivots – the pivot column positions of A
EXAMPLES:
sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
sage: a = matrix(ZZ,3,5,[-2, -6, -3, -17, -1, 2, -1, -1, -2, -1, -2, -2, -6, 9,␣
˓→2])
sage: matrix_integer_dense_hnf.hnf(a)([2
0
26 -75 -10][
01
27 -73-9][0
0
37 -106 -13], [0, 1, 2])
sage: matrix_integer_dense_hnf.hnf(a.transpose())([1 0 0][0 1 0][0 0 1][0 0 0][0 0 0], [0, 1, 2])
sage: matrix_integer_dense_hnf.hnf(a.transpose(), include_zero_rows=False)([1 0 0][0 1 0][0 0 1], [0, 1, 2])>>> from sage.all import *>>> import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf>>> a = matrix(ZZ,Integer(3),Integer(5),[-Integer(2), -Integer(6), -Integer(3), ˓→Integer(17), -Integer(1), Integer(2), -Integer(1), -Integer(1), -Integer(2), ˓→Integer(1), -Integer(2), -Integer(2), -Integer(6), Integer(9), Integer(2)])>>> matrix_integer_dense_hnf.hnf(a)([2
0
26 -75 -10][
01
27 -73-9][0
0
37 -106 -13], [0, 1, 2])>>> matrix_integer_dense_hnf.hnf(a.transpose())([1 0 0](continues on next page)669

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 1 0][0 0 1][0 0 0][0 0 0], [0, 1, 2])>>> matrix_integer_dense_hnf.hnf(a.transpose(), include_zero_rows=False)([1 0 0][0 1 0][0 0 1], [0, 1, 2])

sage.matrix.matrix_integer_dense_hnf.hnf_square(A, proof)
INPUT:• a nonsingular n x n matrix A over the integers.
OUTPUT:• the Hermite normal form of A.
EXAMPLES:
sage: import sage.matrix.matrix_integer_dense_hnf as hnf
sage: A = matrix(ZZ, 3, [-21, -7, 5, 1,20,-7, -1,1,-1])
sage: hnf.hnf_square(A, False)[ 1 6 29]
[ 0 7 28]
[ 0 0 46]
sage: A.echelon_form()[ 1 6 29]
[ 0 7 28]
[ 0 0 46]>>> from sage.all import *>>> import sage.matrix.matrix_integer_dense_hnf as hnf>>> A = matrix(ZZ, Integer(3), [-Integer(21), -Integer(7), Integer(5), Integer(1),˓→Integer(20),-Integer(7), -Integer(1),Integer(1),-Integer(1)])>>> hnf.hnf_square(A, False)[ 1 6 29]
[ 0 7 28]
[ 0 0 46]>>> A.echelon_form()[ 1 6 29]
[ 0 7 28]
[ 0 0 46]

sage.matrix.matrix_integer_dense_hnf.hnf_with_transformation(A, proof=True)
Compute the HNF H of A along with a transformation matrix U such that U*A = H.
INPUT:• A – an n x m matrix A over the integers.
• proof – whether or not to prove the result correct.
OUTPUT:• matrix – the Hermite normal form H of A

670

Chapter 17. Modular algorithm to compute Hermite normal forms of integer matrices

Matrices and Spaces of Matrices, Release 10.4

• U – a unimodular matrix such that U * A = H
EXAMPLES:
sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
sage: A = matrix(ZZ, 2, [1, -5, -10, 1, 3, 197]); A[ 1 -5 -10]
[ 1
3 197]
sage: H, U = matrix_integer_dense_hnf.hnf_with_transformation(A)sage: H[ 1
3 197][ 0
8 207]
sage: U[ 0 1][-1 1]
sage: U*A
[ 1
3 197][ 0
8 207]>>> from sage.all import *>>> import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf>>> A = matrix(ZZ, Integer(2), [Integer(1), -Integer(5), -Integer(10), Integer(1),˓→ Integer(3), Integer(197)]); A[ 1 -5 -10]
[ 1
3 197]>>> H, U = matrix_integer_dense_hnf.hnf_with_transformation(A)
>>> H
[ 1
3 197][ 0
8 207]>>> U[ 0 1][-1 1]>>> U*A[ 1
3 197][ 0
8 207]

sage.matrix.matrix_integer_dense_hnf.hnf_with_transformation_tests(n=10, m=5,
trials=10)
Use this to randomly test that hnf with transformation matrix is working.
EXAMPLES:
sage: from sage.matrix.matrix_integer_dense_hnf import hnf_with_transformation_
˓→tests
sage: hnf_with_transformation_tests(n=15, m=10, trials=10)
0 1 2 3 4 5 6 7 8 9>>> from sage.all import *>>> from sage.matrix.matrix_integer_dense_hnf import hnf_with_transformation_tests>>> hnf_with_transformation_tests(n=Integer(15), m=Integer(10),␣
˓→trials=Integer(10))
0 1 2 3 4 5 6 7 8 9sage.matrix.matrix_integer_dense_hnf.interleave_matrices(A, B, cols1, cols2)
INPUT:• A, B – matrices with the same number of rows
• cols1, cols2 – disjoint lists of integers
671

Matrices and Spaces of Matrices, Release 10.4

OUTPUT:
construct a new matrix C by sticking the columns of A at the positions specified by cols1 and the columns of B at
the positions specified by cols2.
EXAMPLES:
sage: A = matrix(ZZ, 2, [1,2,3,4]); B = matrix(ZZ, 2, [-1,5,2,3])
sage: A
[1 2]
[3 4]
sage: B[-1 5][ 2 3]
sage: import sage.matrix.matrix_integer_dense_hnf as hnf
sage: hnf.interleave_matrices(A, B, [1,3], [0,2])[-1 1 5 2]
[ 2 3 3 4]>>> from sage.all import *>>> A = matrix(ZZ, Integer(2), [Integer(1),Integer(2),Integer(3),Integer(4)]); B␣
˓→= matrix(ZZ, Integer(2), [-Integer(1),Integer(5),Integer(2),Integer(3)])
>>> A
[1 2]
[3 4]
>>> B
[-1 5][ 2 3]>>> import sage.matrix.matrix_integer_dense_hnf as hnf>>> hnf.interleave_matrices(A, B, [Integer(1),Integer(3)], [Integer(0),˓→Integer(2)])[-1 1 5 2]
[ 2 3 3 4]

sage.matrix.matrix_integer_dense_hnf.is_in_hnf_form(H, pivots)
Return whether the matrix H is in Hermite normal form with given pivot columns.
INPUT:• H – matrix• pivots – sorted list of integers
OUTPUT:boolean
EXAMPLES:
sage: a = matrix(ZZ,3,5,[-2, -6, -3, -17, -1, 2, -1, -1, -2, -1, -2, -2, -6, 9,␣
˓→2])
sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
sage: matrix_integer_dense_hnf.is_in_hnf_form(a,range(3))
False
sage: e = a.hermite_form(); p = a.pivots()
sage: matrix_integer_dense_hnf.is_in_hnf_form(e, p)
True>>> from sage.all import *>>> a = matrix(ZZ,Integer(3),Integer(5),[-Integer(2), -Integer(6), -Integer(3), (continues on next page)

672

Chapter 17. Modular algorithm to compute Hermite normal forms of integer matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Integer(17), -Integer(1), Integer(2), -Integer(1), -Integer(1), -Integer(2), ˓→Integer(1), -Integer(2), -Integer(2), -Integer(6), Integer(9), Integer(2)])>>> import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf>>> matrix_integer_dense_hnf.is_in_hnf_form(a,range(Integer(3)))
False>>> e = a.hermite_form(); p = a.pivots()>>> matrix_integer_dense_hnf.is_in_hnf_form(e, p)True˓→sage.matrix.matrix_integer_dense_hnf.max_det_prime(n)Return the largest prime so that it is reasonably efficient to compute modulo that prime with n x n matrices in
LinBox.
INPUT:• n – a positive integer
OUTPUT:a prime number
EXAMPLES:
sage: from sage.matrix.matrix_integer_dense_hnf import max_det_prime
sage: max_det_prime(10000)
8388593sage: max_det_prime(1000)
8388593sage: max_det_prime(10)8388593>>> from sage.all import *>>> from sage.matrix.matrix_integer_dense_hnf import max_det_prime>>> max_det_prime(Integer(10000))
8388593>>> max_det_prime(Integer(1000))
8388593>>> max_det_prime(Integer(10))
8388593sage.matrix.matrix_integer_dense_hnf.ones(H, pivots)
Find all 1 pivot columns of the matrix H in Hermite form, along with the corresponding rows, and also the non 1
pivot columns and non-pivot rows. Here a 1 pivot column is a pivot column so that the leading bottom entry is 1.
INPUT:• H – matrix in Hermite form
• pivots – list of integers (all pivot positions of H).
OUTPUT:
4-tuple of integer lists: onecol, onerow, non_oneol, non_onerow
EXAMPLES:
sage: H = matrix(ZZ, 3, 5, [1, 0, 0, 45, -36, 0, 1, 0, 131, -107, 0, 0, 0, 178, ˓→145]); H[
100
45 -36](continues on next page)673

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[01
0 131 -107][
000 178 -145]
sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
sage: matrix_integer_dense_hnf.ones(H, [0,1,3])([0, 1], [0, 1], [2], [2])>>> from sage.all import *>>> H = matrix(ZZ, Integer(3), Integer(5), [Integer(1), Integer(0), Integer(0),␣
˓→Integer(45), -Integer(36), Integer(0), Integer(1), Integer(0), Integer(131), ˓→Integer(107), Integer(0), Integer(0), Integer(0), Integer(178), -Integer(145)]);
˓→ H
[
1
0
0
45 -36][0
1
0 131 -107][
000 178 -145]>>> import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf>>> matrix_integer_dense_hnf.ones(H, [Integer(0),Integer(1),Integer(3)])([0, 1], [0, 1], [2], [2])sage.matrix.matrix_integer_dense_hnf.pad_zeros(A, nrows)
Add zeros to the bottom of A so that the resulting matrix has nrows.
INPUT:• A – a matrix• nrows – an integer that is at least as big as the number of rows of A.
OUTPUT:a matrix with nrows rows.
EXAMPLES:
sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
sage: a = matrix(ZZ, 2, 4, [1, 0, 0, 7, 0, 1, 5, 2])
sage: matrix_integer_dense_hnf.pad_zeros(a, 4)[1 0 0 7][0 1 5 2][0 0 0 0][0 0 0 0]
sage: matrix_integer_dense_hnf.pad_zeros(a, 2)[1 0 0 7][0 1 5 2]>>> from sage.all import *>>> import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf>>> a = matrix(ZZ, Integer(2), Integer(4), [Integer(1), Integer(0), Integer(0),␣
˓→Integer(7), Integer(0), Integer(1), Integer(5), Integer(2)])>>> matrix_integer_dense_hnf.pad_zeros(a, Integer(4))[1 0 0 7][0 1 5 2][0 0 0 0][0 0 0 0]>>> matrix_integer_dense_hnf.pad_zeros(a, Integer(2))[1 0 0 7][0 1 5 2]674

Chapter 17. Modular algorithm to compute Hermite normal forms of integer matrices

Matrices and Spaces of Matrices, Release 10.4

sage.matrix.matrix_integer_dense_hnf.pivots_of_hnf_matrix(H)Return the pivot columns of a matrix H assumed to be in HNF.
INPUT:• H – a matrix that must be HNF
OUTPUT:• list – list of pivots
EXAMPLES:
sage: H = matrix(ZZ, 3, 5, [1, 0, 0, 45, -36, 0, 1, 0, 131, -107, 0, 0, 0, 178, ˓→145]); H[
100
45 -36][0
1
0 131 -107][
000 178 -145]
sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
sage: matrix_integer_dense_hnf.pivots_of_hnf_matrix(H)[0, 1, 3]>>> from sage.all import *>>> H = matrix(ZZ, Integer(3), Integer(5), [Integer(1), Integer(0), Integer(0),␣
˓→Integer(45), -Integer(36), Integer(0), Integer(1), Integer(0), Integer(131), ˓→Integer(107), Integer(0), Integer(0), Integer(0), Integer(178), -Integer(145)]);
˓→ H
[
1
0
0
45 -36][0
1
0 131 -107][
000 178 -145]>>> import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf>>> matrix_integer_dense_hnf.pivots_of_hnf_matrix(H)[0, 1, 3]

sage.matrix.matrix_integer_dense_hnf.probable_hnf(A, include_zero_rows, proof)
Return the HNF of A or raise an exception if something involving the randomized nature of the algorithm goes
wrong along the way.
Calling this function again a few times should result it in it working, at least if proof=True.
INPUT:• A – a matrix• include_zero_rows – bool
• proof – bool
OUTPUT:
the Hermite normal form of A. cols – pivot columns
EXAMPLES:
sage: a = matrix(ZZ,4,3,[-1, -1, -1, -20, 4, 1, -1, 1, 2,1,2,3])
sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
sage: matrix_integer_dense_hnf.probable_hnf(a, True, True)([1 0 0][0 1 0][0 0 1](continues on next page)675

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 0 0], [0, 1, 2])
sage: matrix_integer_dense_hnf.probable_hnf(a, False, True)([1 0 0][0 1 0][0 0 1], [0, 1, 2])
sage: matrix_integer_dense_hnf.probable_hnf(a, False, False)([1 0 0][0 1 0][0 0 1], [0, 1, 2])>>> from sage.all import *>>> a = matrix(ZZ,Integer(4),Integer(3),[-Integer(1), -Integer(1), -Integer(1), ˓→Integer(20), Integer(4), Integer(1), -Integer(1), Integer(1), Integer(2),˓→Integer(1),Integer(2),Integer(3)])>>> import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf>>> matrix_integer_dense_hnf.probable_hnf(a, True, True)([1 0 0][0 1 0][0 0 1][0 0 0], [0, 1, 2])>>> matrix_integer_dense_hnf.probable_hnf(a, False, True)([1 0 0][0 1 0][0 0 1], [0, 1, 2])>>> matrix_integer_dense_hnf.probable_hnf(a, False, False)([1 0 0][0 1 0][0 0 1], [0, 1, 2])

sage.matrix.matrix_integer_dense_hnf.probable_pivot_columns(A)INPUT:• A – a matrix
OUTPUT:a tuple of integers
EXAMPLES:
sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
sage: a = matrix(ZZ,3,[0, -1, -1, 0, -20, 1, 0, 1, 2])
sage: a[ 0 -1 -1][ 0 -201][ 0
12](continues on next page)

676

Chapter 17. Modular algorithm to compute Hermite normal forms of integer matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: matrix_integer_dense_hnf.probable_pivot_columns(a)(1, 2)>>> from sage.all import *>>> import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf>>> a = matrix(ZZ,Integer(3),[Integer(0), -Integer(1), -Integer(1), Integer(0), ˓→Integer(20), Integer(1), Integer(0), Integer(1), Integer(2)])>>> a[ 0 -1 -1][ 0 -20
1][ 0
1
2]>>> matrix_integer_dense_hnf.probable_pivot_columns(a)(1, 2)

sage.matrix.matrix_integer_dense_hnf.probable_pivot_rows(A)Return rows of A that are very likely to be pivots.
This really finds the pivots of A modulo a random prime.
INPUT:• A – a matrix
OUTPUT:a tuple of integers
EXAMPLES:
sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
sage: a = matrix(ZZ,3,[0, -1, -1, 0, -20, 1, 0, 1, 2])
sage: a[ 0 -1 -1][ 0 -201][ 0
12]
sage: matrix_integer_dense_hnf.probable_pivot_rows(a)(0, 1)>>> from sage.all import *>>> import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf>>> a = matrix(ZZ,Integer(3),[Integer(0), -Integer(1), -Integer(1), Integer(0), ˓→Integer(20), Integer(1), Integer(0), Integer(1), Integer(2)])>>> a[ 0 -1 -1][ 0 -20
1][ 0
1
2]>>> matrix_integer_dense_hnf.probable_pivot_rows(a)(0, 1)

sage.matrix.matrix_integer_dense_hnf.sanity_checks(times=50, n=8, m=5, proof=True,
stabilize=2, check_using_magma=True)
Run random sanity checks on the modular p-adic HNF with tall and wide matrices both dense and sparse.
INPUT:• times – number of times to randomly try matrices with each shape• n – number of rows

677

Matrices and Spaces of Matrices, Release 10.4

• m – number of columns• proof – test with proof true• stabilize – parameter to pass to hnf algorithm when proof is False• check_using_magma – if True use Magma instead of PARI to check correctness of computed HNF’s. Since
PARI’s HNF is buggy and slow (as of 2008-02-16 non-pivot entries sometimes are not normalized to benonnegative) the default is Magma.
EXAMPLES:
sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf
sage: matrix_integer_dense_hnf.sanity_checks(times=5, check_using_magma=False)
small 8 x 5
0 1 2 3 4 (done)
big 8 x 5
0 1 2 3 4 (done)
small 5 x 8
0 1 2 3 4 (done)
big 5 x 8
0 1 2 3 4 (done)sparse 8 x 5
0 1 2 3 4 (done)sparse 5 x 8
0 1 2 3 4 (done)
ill conditioned -- 1000*A -- 8 x 5
0 1 2 3 4 (done)
ill conditioned -- 1000*A but one row -- 8 x 5
0 1 2 3 4 (done)>>> from sage.all import *>>> import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf>>> matrix_integer_dense_hnf.sanity_checks(times=Integer(5), check_using_
˓→magma=False)
small 8 x 5
0 1 2 3 4 (done)
big 8 x 5
0 1 2 3 4 (done)
small 5 x 8
0 1 2 3 4 (done)
big 5 x 8
0 1 2 3 4 (done)sparse 8 x 5
0 1 2 3 4 (done)sparse 5 x 8
0 1 2 3 4 (done)
ill conditioned -- 1000*A -- 8 x 5
0 1 2 3 4 (done)
ill conditioned -- 1000*A but one row -- 8 x 5
0 1 2 3 4 (done)

sage.matrix.matrix_integer_dense_hnf.solve_system_with_difficult_last_row(B, a)
Solve B*x = a when the last row of 𝐵 contains huge entries using a clever trick that reduces the problem to solve C*x= a where 𝐶 is 𝐵 but with the last row replaced by something small, along with one easy null space computation.
The latter are both solved 𝑝-adically.
INPUT:• B – a square n x n nonsingular matrix with painful big bottom row.
678

Chapter 17. Modular algorithm to compute Hermite normal forms of integer matrices

Matrices and Spaces of Matrices, Release 10.4

• a – an n x 1 column matrix
OUTPUT:• the unique solution to B*x = a.
EXAMPLES:
sage: from sage.matrix.matrix_integer_dense_hnf import solve_system_with_
˓→difficult_last_row
sage: B = matrix(ZZ, 3, [1,2,4, 3,-4,7, 939082,2930982,132902384098234])
sage: a = matrix(ZZ,3,1, [1,2,5])
sage: z = solve_system_with_difficult_last_row(B, a)sage: z[ 106321906985474/132902379815497][132902385037291/1329023798154970][-5221794/664511899077485]
sage: B*z
[1]
[2]
[5]
>>> from sage.all import *>>> from sage.matrix.matrix_integer_dense_hnf import solve_system_with_difficult_˓→last_row>>> B = matrix(ZZ, Integer(3), [Integer(1),Integer(2),Integer(4), Integer(3),˓→Integer(4),Integer(7), Integer(939082),Integer(2930982),
˓→Integer(132902384098234)])>>> a = matrix(ZZ,Integer(3),Integer(1), [Integer(1),Integer(2),Integer(5)])>>> z = solve_system_with_difficult_last_row(B, a)>>> z[ 106321906985474/132902379815497][132902385037291/1329023798154970][-5221794/664511899077485]>>> B*z
[1]
[2]
[5]

679

Matrices and Spaces of Matrices, Release 10.4

680

Chapter 17. Modular algorithm to compute Hermite normal forms of integer matrices

CHAPTEREIGHTEEN

SATURATION OVER ZZ

sage.matrix.matrix_integer_dense_saturation.index_in_saturation(A, proof=True)
The index of A in its saturation.
INPUT:• A – matrix over Z• proof – boolean (True or False)
OUTPUT:
An integer
EXAMPLES:
sage: from sage.matrix.matrix_integer_dense_saturation import index_in_saturation
sage: A = matrix(ZZ, 2, 2, [3,2,3,4]); B = matrix(ZZ, 2,3,[1,2,3,4,5,6]); C = A*B;
˓→ C
[11 16 21][19 26 33]
sage: index_in_saturation(C)18
sage: W = C.row_space()sage: S = W.saturation()sage: W.index_in(S)18>>> from sage.all import *>>> from sage.matrix.matrix_integer_dense_saturation import index_in_saturation>>> A = matrix(ZZ, Integer(2), Integer(2), [Integer(3),Integer(2),Integer(3),˓→Integer(4)]); B = matrix(ZZ, Integer(2),Integer(3),[Integer(1),Integer(2),˓→Integer(3),Integer(4),Integer(5),Integer(6)]); C = A*B; C[11 16 21][19 26 33]>>> index_in_saturation(C)18>>> W = C.row_space()>>> S = W.saturation()>>> W.index_in(S)18

For any zero matrix the index in its saturation is 1 (see Issue #13034):
sage: m = matrix(ZZ, 3)
sage: m(continues on next page)681

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 0 0][0 0 0][0 0 0]sage: m.index_in_saturation()1
sage: m = matrix(ZZ, 2, 3)
sage: m[0 0 0][0 0 0]sage: m.index_in_saturation()1>>> from sage.all import *>>> m = matrix(ZZ, Integer(3))>>> m[0 0 0][0 0 0][0 0 0]>>> m.index_in_saturation()1>>> m = matrix(ZZ, Integer(2), Integer(3))>>> m[0 0 0][0 0 0]>>> m.index_in_saturation()1

sage.matrix.matrix_integer_dense_saturation.p_saturation(A, p, proof=True)
INPUT:• A – a matrix over ZZ• p – a prime• proof – bool (default: True)OUTPUT:
The p-saturation of the matrix A, i.e., a new matrix in Hermite form whose row span a ZZ-module that is
p-saturated.
EXAMPLES:
sage: from sage.matrix.matrix_integer_dense_saturation import p_saturation
sage: A = matrix(ZZ, 2, 2, [3,2,3,4]); B = matrix(ZZ, 2,3,[1,2,3,4,5,6])
sage: A.det()6
sage: C = A*B; C[11 16 21][19 26 33]
sage: C2 = p_saturation(C, 2); C2[ 1 8 15]
[ 0 9 18]
sage: C2.index_in_saturation()9
sage: C3 = p_saturation(C, 3); C3[ 1 0 -1]
[ 0 2 4]
(continues on next page)682

Chapter 18. Saturation over ZZ

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: C3.index_in_saturation()2>>> from sage.all import *>>> from sage.matrix.matrix_integer_dense_saturation import p_saturation>>> A = matrix(ZZ, Integer(2), Integer(2), [Integer(3),Integer(2),Integer(3),˓→Integer(4)]); B = matrix(ZZ, Integer(2),Integer(3),[Integer(1),Integer(2),˓→Integer(3),Integer(4),Integer(5),Integer(6)])>>> A.det()6>>> C = A*B; C[11 16 21][19 26 33]>>> C2 = p_saturation(C, Integer(2)); C2[ 1 8 15]
[ 0 9 18]>>> C2.index_in_saturation()
9>>> C3 = p_saturation(C, Integer(3)); C3[ 1 0 -1]
[ 0 2 4]>>> C3.index_in_saturation()2

sage.matrix.matrix_integer_dense_saturation.random_sublist_of_size(k, n)
INPUT:• k – an integer• n – an integer
OUTPUT:a randomly chosen sublist of range(k) of size n.
EXAMPLES:
sage: import sage.matrix.matrix_integer_dense_saturation as ssage: l = s.random_sublist_of_size(10, 3)
sage: len(l)3sage: l_check = [-1] + l + [10]sage: all(l_check[i] < l_check[i+1] for i in range(4))
True
sage: l = s.random_sublist_of_size(10, 7)
sage: len(l)7sage: l_check = [-1] + l + [10]sage: all(l_check[i] < l_check[i+1] for i in range(8))
True>>> from sage.all import *>>> import sage.matrix.matrix_integer_dense_saturation as s>>> l = s.random_sublist_of_size(Integer(10), Integer(3))>>> len(l)3>>> l_check = [-Integer(1)] + l + [Integer(10)](continues on next page)683

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> all(l_check[i] < l_check[i+Integer(1)] for i in range(Integer(4)))
True>>> l = s.random_sublist_of_size(Integer(10), Integer(7))>>> len(l)7>>> l_check = [-Integer(1)] + l + [Integer(10)]>>> all(l_check[i] < l_check[i+Integer(1)] for i in range(Integer(8)))
Truesage.matrix.matrix_integer_dense_saturation.saturation(A, proof=True, p=0, max_dets=5)
Compute a saturation matrix of A.
INPUT:• A – a matrix over ZZ• proof – bool (default: True)• p – int (default: 0); if not 0 only guarantees that output is p-saturated• max_dets – int (default: 4) max number of dets of submatrices to compute.
OUTPUT:
matrix – saturation of the matrix A.
EXAMPLES:
sage: from sage.matrix.matrix_integer_dense_saturation import saturation
sage: A = matrix(ZZ, 2, 2, [3,2,3,4]); B = matrix(ZZ, 2,3,[1,2,3,4,5,6]); C = A*B
sage: C
[11 16 21][19 26 33]
sage: C.index_in_saturation()18
sage: S = saturation(C); S[11 16 21][-2 -3 -4]
sage: S.index_in_saturation()1
sage: saturation(C, proof=False)[11 16 21][-2 -3 -4]
sage: saturation(C, p=2)
[11 16 21][-2 -3 -4]
sage: saturation(C, p=2, max_dets=1)[11 16 21][-2 -3 -4]>>> from sage.all import *>>> from sage.matrix.matrix_integer_dense_saturation import saturation>>> A = matrix(ZZ, Integer(2), Integer(2), [Integer(3),Integer(2),Integer(3),˓→Integer(4)]); B = matrix(ZZ, Integer(2),Integer(3),[Integer(1),Integer(2),˓→Integer(3),Integer(4),Integer(5),Integer(6)]); C = A*B>>> C[11 16 21][19 26 33]>>> C.index_in_saturation()(continues on next page)

684

Chapter 18. Saturation over ZZ

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)18>>> S = saturation(C); S[11 16 21][-2 -3 -4]>>> S.index_in_saturation()1>>> saturation(C, proof=False)[11 16 21][-2 -3 -4]>>> saturation(C, p=Integer(2))[11 16 21][-2 -3 -4]>>> saturation(C, p=Integer(2), max_dets=Integer(1))[11 16 21][-2 -3 -4]

sage.matrix.matrix_integer_dense_saturation.solve_system_with_difficult_last_row(B,A)
Solve the matrix equation B*Z = A when the last row of 𝐵 contains huge entries.
INPUT:• B – a square n x n nonsingular matrix with painful big bottom row.
• A – an n x k matrix.
OUTPUT:the unique solution to B*Z = A.
EXAMPLES:
sage: from sage.matrix.matrix_integer_dense_saturation import solve_system_with_
˓→difficult_last_row
sage: B = matrix(ZZ, 3, [1,2,3, 3,-1,2,939239082,39202803080,2939028038402834]);␣˓→A = matrix(ZZ,3,2,[1,2,4,3,-1,0])
sage: X = solve_system_with_difficult_last_row(B, A); X[ 290668794698843/226075992027744
468068726971/409557956572][-226078357385539/1582531944194208
1228691305937/2866905696004][
2365357795/1582531944194208-17436221/2866905696004]
sage: B*X == A
True>>> from sage.all import *>>> from sage.matrix.matrix_integer_dense_saturation import solve_system_with_
˓→difficult_last_row>>> B = matrix(ZZ, Integer(3), [Integer(1),Integer(2),Integer(3), Integer(3),˓→Integer(1),Integer(2),Integer(939239082),Integer(39202803080),
˓→Integer(2939028038402834)]); A = matrix(ZZ,Integer(3),Integer(2),[Integer(1),˓→Integer(2),Integer(4),Integer(3),-Integer(1),Integer(0)])>>> X = solve_system_with_difficult_last_row(B, A); X[ 290668794698843/226075992027744
468068726971/409557956572][-226078357385539/1582531944194208
1228691305937/2866905696004][
2365357795/1582531944194208-17436221/2866905696004]>>> B*X == A
True

685

Matrices and Spaces of Matrices, Release 10.4

686

Chapter 18. Saturation over ZZ

CHAPTERNINETEEN

DENSE MATRICES OVER THE RATIONAL FIELD

EXAMPLES:
We create a 3x3 matrix with rational entries and do some operations with it.
sage: a = matrix(QQ, 3,3, [1,2/3, -4/5, 1,1,1, 8,2, -3/19]); a[1
2/3 -4/5]
[
1
1
1]
[
8
2 -3/19]sage: a.det()
2303/285
sage: a.charpoly()x^3 - 35/19*x^2 + 1259/285*x - 2303/285
sage: b = a^(-1); b[ -615/2303 -426/2303
418/2303][ 2325/2303 1779/2303 -513/2303][-1710/2303
950/2303
95/2303]
sage: b.det()
285/2303
sage: a == b
False
sage: a < bFalse
sage: b < aTruesage: a > b
Truesage: a*b
[1 0 0][0 1 0][0 0 1]>>> from sage.all import *>>> a = matrix(QQ, Integer(3),Integer(3), [Integer(1),Integer(2)/Integer(3), ˓→Integer(4)/Integer(5), Integer(1),Integer(1),Integer(1), Integer(8),Integer(2), ˓→Integer(3)/Integer(19)]); a[1
2/3 -4/5]
[
1
1
1]
[
8
2 -3/19]>>> a.det()
2303/285>>> a.charpoly()x^3 - 35/19*x^2 + 1259/285*x - 2303/285>>> b = a**(-Integer(1)); b[ -615/2303 -426/2303
418/2303](continues on next page)687

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 2325/2303[-1710/2303>>> b.det()
285/2303>>> a == b
False>>> a < b
False>>> b < aTrue>>> a > b
True>>> a*b[1 0 0][0 1 0][0 0 1]

1779/2303
950/2303-513/2303]
95/2303]

class sage.matrix.matrix_rational_dense.MatrixWindow
Bases: object
class sage.matrix.matrix_rational_dense.Matrix_rational_dense
Bases: Matrix_dense
INPUT:• parent – a matrix space over QQ• entries – see matrix()• copy – ignored (for backwards compatibility)• coerce – if False, assume without checking that the entries are of type Rational.
BKZ(*args, **kwargs)
Return the result of running Block Korkin-Zolotarev reduction on self interpreted as a lattice.
The arguments *args and **kwargs are passed onto sage.matrix.matrix_integer_dense.
Matrix_integer_dense.BKZ(), see there for more details.
EXAMPLES:
sage: A = Matrix(QQ, 3, 3, [1/n for n in range(1, 10)])sage: A.BKZ()[ 1/28 -1/40 -1/18][ 1/28 -1/40 1/18][-1/14 -1/40
0]
sage: A = random_matrix(QQ, 10, 10)
sage: d = lcm(a.denom() for a in A.list())
sage: A.BKZ() == (A * d).change_ring(ZZ).BKZ() / d
True>>> from sage.all import *>>> A = Matrix(QQ, Integer(3), Integer(3), [Integer(1)/n for n in␣˓→range(Integer(1), Integer(10))])>>> A.BKZ()[ 1/28 -1/40 -1/18][ 1/28 -1/40 1/18](continues on next page)

688

Chapter 19. Dense matrices over the rational fieldMatrices and Spaces of Matrices, Release 10.4

(continued from previous page)[-1/14 -1/40

0]>>> A = random_matrix(QQ, Integer(10), Integer(10))>>> d = lcm(a.denom() for a in A.list())>>> A.BKZ() == (A * d).change_ring(ZZ).BKZ() / dTrue

LLL(*args, **kwargs)
Return an LLL reduced or approximated LLL reduced lattice for self interpreted as a lattice.
The arguments *args and **kwargs are passed onto sage.matrix.matrix_integer_dense.
Matrix_integer_dense.LLL(), see there for more details.
EXAMPLES:
sage: A = Matrix(QQ, 3, 3, [1/n for n in range(1, 10)])sage: A.LLL()[ 1/28 -1/40 -1/18][ 1/28 -1/40 1/18][
0 -3/400]
sage: A = random_matrix(QQ, 10, 10)
sage: d = lcm(a.denom() for a in A.list())
sage: A.LLL() == (A * d).change_ring(ZZ).LLL() / d
True>>> from sage.all import *>>> A = Matrix(QQ, Integer(3), Integer(3), [Integer(1)/n for n in␣˓→range(Integer(1), Integer(10))])>>> A.LLL()[ 1/28 -1/40 -1/18][ 1/28 -1/40 1/18][
0 -3/400]>>> A = random_matrix(QQ, Integer(10), Integer(10))>>> d = lcm(a.denom() for a in A.list())>>> A.LLL() == (A * d).change_ring(ZZ).LLL() / dTrue

add_to_entry(i, j, elt)
Add elt to the entry at position (i,j)
EXAMPLES:
sage: m = matrix(QQ, 2, 2)
sage: m.add_to_entry(0, 0, -1/3)
sage: m
[-1/3
0]
[
0
0]
>>> from sage.all import *>>> m = matrix(QQ, Integer(2), Integer(2))>>> m.add_to_entry(Integer(0), Integer(0), -Integer(1)/Integer(3))
>>> m
[-1/3
0]
[
0
0]

689

Matrices and Spaces of Matrices, Release 10.4

antitranspose()
Returns the antitranspose of self, without changing self.
EXAMPLES:
sage: A = matrix(QQ,2,3,range(6))
sage: type(A)<class sage.matrix.matrix_rational_dense.Matrix_rational_dense >sage: A.antitranspose()
[5 2]
[4 1]
[3 0]
sage: A[0 1 2][3 4 5]sage: A.subdivide(1,2); A[0 1|2][---+-][3 4|5]sage: A.antitranspose()
[5|2]
[-+-]
[4|1]
[3|0]
>>> from sage.all import *>>> A = matrix(QQ,Integer(2),Integer(3),range(Integer(6)))>>> type(A)<class sage.matrix.matrix_rational_dense.Matrix_rational_dense >>>> A.antitranspose()
[5 2]
[4 1]
[3 0]
>>> A
[0 1 2][3 4 5]>>> A.subdivide(Integer(1),Integer(2)); A[0 1|2][---+-][3 4|5]>>> A.antitranspose()
[5|2]
[-+-]
[4|1]
[3|0]

change_ring(R)Create the matrix over R with entries the entries of self coerced into R.
EXAMPLES:
sage: a = matrix(QQ,2,[1/2,-1,2,3])
sage: a.change_ring(GF(3))
[2 2]
[2 0]
sage: a.change_ring(ZZ)(continues on next page)

690

Chapter 19. Dense matrices over the rational fieldMatrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Traceback (most recent call last):...
TypeError: matrix has denominators so can...t change to ZZ
sage: b = a.change_ring(QQ[ x ]); b[1/2 -1][ 2
3]
sage: b.parent()
Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in␣˓→x over Rational Field>>> from sage.all import *>>> a = matrix(QQ,Integer(2),[Integer(1)/Integer(2),-Integer(1),Integer(2),˓→Integer(3)])>>> a.change_ring(GF(Integer(3)))
[2 2]
[2 0]
>>> a.change_ring(ZZ)
Traceback (most recent call last):...
TypeError: matrix has denominators so can...t change to ZZ>>> b = a.change_ring(QQ[ x ]); b[1/2 -1][ 2
3]>>> b.parent()
Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in␣˓→x over Rational Field

charpoly(var='x', algorithm=None)
Return the characteristic polynomial of this matrix.
Note: The characteristic polynomial is defined as det(𝑥𝐼 − 𝐴).
INPUT:• var – (optional) name of the variable as a string• algorithm – an optional specification of an algorithm. It can be one of:– None: (default) will use flint for small dimensions and linbox otherwise–

flint : uses flint library–linbox : uses linbox library–generic : uses Sage generic implementation

OUTPUT: a polynomial over the rational numbers.
EXAMPLES:
sage: a = matrix(QQ, 3, [4/3, 2/5, 1/5, 4, -3/2, 0, 0, -2/3, 3/4])
sage: f = a.charpoly(); fx^3 - 7/12*x^2 - 149/40*x + 97/30
sage: f(a)[0 0 0][0 0 0][0 0 0]691

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> a = matrix(QQ, Integer(3), [Integer(4)/Integer(3), Integer(2)/Integer(5),␣
˓→Integer(1)/Integer(5), Integer(4), -Integer(3)/Integer(2), Integer(0),␣
˓→Integer(0), -Integer(2)/Integer(3), Integer(3)/Integer(4)])>>> f = a.charpoly(); fx^3 - 7/12*x^2 - 149/40*x + 97/30>>> f(a)[0 0 0][0 0 0][0 0 0]column(i, from_list=False)
Return the i-th column of this matrix as a dense vector.
INPUT:• i – integer• from_list – ignored
EXAMPLES:
sage: m = matrix(QQ, 3, 2, [1/5,-2/3,3/4,4/9,-1,0])
sage: m.column(1)(-2/3, 4/9, 0)
sage: m.column(1,from_list=True)(-2/3, 4/9, 0)
sage: m.column(-1)(-2/3, 4/9, 0)
sage: m.column(-2)(1/5, 3/4, -1)
sage: m.column(2)Traceback (most recent call last):...
IndexError: column index out of range
sage: m.column(-3)
Traceback (most recent call last):...
IndexError: column index out of range>>> from sage.all import *>>> m = matrix(QQ, Integer(3), Integer(2), [Integer(1)/Integer(5),-Integer(2)/˓→Integer(3),Integer(3)/Integer(4),Integer(4)/Integer(9),-Integer(1),˓→Integer(0)])>>> m.column(Integer(1))(-2/3, 4/9, 0)>>> m.column(Integer(1),from_list=True)(-2/3, 4/9, 0)>>> m.column(-Integer(1))(-2/3, 4/9, 0)>>> m.column(-Integer(2))(1/5, 3/4, -1)>>> m.column(Integer(2))
Traceback (most recent call last):...
IndexError: column index out of range(continues on next page)

692

Chapter 19. Dense matrices over the rational fieldMatrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> m.column(-Integer(3))
Traceback (most recent call last):...
IndexError: column index out of range

decomposition(is_diagonalizable=False, dual=False, algorithm=None, height_guess=None, proof=None)
Returns the decomposition of the free module on which this matrix A acts from the right (i.e., the action is x
goes to x A), along with whether this matrix acts irreducibly on each factor. The factors are guaranteed to besorted in the same way as the corresponding factors of the characteristic polynomial.
Let A be the matrix acting from the on the vector space V of column vectors. Assume that A is square.
This function computes maximal subspaces W_1, …, W_n corresponding to Galois conjugacy classes of
eigenvalues of A. More precisely, let f(X) be the characteristic polynomial of A. This function computes thesubspace 𝑊𝑖 = 𝑘𝑒𝑟(𝑔( 𝐴)𝑛 ), where g_i(X) is an irreducible factor of f(X) and g_i(X) exactly divides f(X).
If the optional parameter is_diagonalizable is True, then we let W_i = ker(g(A)), since then we know thatker(g(A)) = 𝑘𝑒𝑟(𝑔(𝐴)𝑛 ).
If dual is True, also returns the corresponding decomposition of V under the action of the transpose of A.
The factors are guaranteed to correspond.
INPUT:• is_diagonalizable – ignored• dual – whether to also return decompositions for the dual
• algorithm – an optional specification of an algorithm– None – (default) use default algorithm for computing Echelon forms– ‘multimodular’: much better if the answers factors have small height• height_guess – positive integer; only used by the multimodular algorithm• proof – bool or None (default: None, see proof.linear_algebra or sage.structure.proof); only used by
the multimodular algorithm. Note that the Sage global default is proof=True.
Note: IMPORTANT: If you expect that the subspaces in the answer are spanned by vectors with small height
coordinates, use algorithm=’multimodular’ and height_guess=1; this is potentially much faster than the default.
If you know for a fact the answer will be very small, use algorithm=’multimodular’, height_guess=bound onheight, proof=False.
You can get very very fast decomposition with proof=False.
EXAMPLES:
sage: a = matrix(QQ,3,[1..9])sage: a.decomposition()[(Vector space of degree 3 and dimension 1 over Rational Field
Basis matrix:[ 1 -2 1], True),(Vector space of degree 3 and dimension 2 over Rational Field
Basis matrix:[ 1 0 -1]
[ 0 1 2], True)]

693

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> a = matrix(QQ,Integer(3),(ellipsis_range(Integer(1),Ellipsis,Integer(9))))>>> a.decomposition()[(Vector space of degree 3 and dimension 1 over Rational Field
Basis matrix:[ 1 -2 1], True),(Vector space of degree 3 and dimension 2 over Rational Field
Basis matrix:[ 1 0 -1]
[ 0 1 2], True)]

denominator()
Return the denominator of this matrix.
OUTPUT: a Sage Integer
EXAMPLES:
sage: b = matrix(QQ,2,range(6)); b[0,0]=-5007/293; b[-5007/293
1
2]
[
3
4
5]
sage: b.denominator()
293
sage: matrix(QQ, 2, [1/2, 1/3, 1/4, 1/5]).denominator()
60>>> from sage.all import *>>> b = matrix(QQ,Integer(2),range(Integer(6))); b[Integer(0),Integer(0)]=˓→Integer(5007)/Integer(293); b[-5007/293
1
2]
[
3
4
5]
>>> b.denominator()
293>>> matrix(QQ, Integer(2), [Integer(1)/Integer(2), Integer(1)/Integer(3),␣
˓→Integer(1)/Integer(4), Integer(1)/Integer(5)]).denominator()
60

determinant(algorithm=None, proof=None)
Return the determinant of this matrix.
INPUT:• algorithm – an optional specification of an algorithm. It can be one of– None: (default) uses flint–

flint : uses flint library–pari : uses PARI library–

integer : removes denominator and call determinant on the corresponding
integer matrix–

generic : calls the generic Sage implementation• proof – bool or None; if None use proof.linear_algebra(); only relevant for the padic algorithm.

694

Chapter 19. Dense matrices over the rational fieldMatrices and Spaces of Matrices, Release 10.4

Note: It would be VERY VERY hard for det to fail even with proof=False.
EXAMPLES:
sage: m = matrix(QQ,3,[1,2/3,4/5, 2,2,2, 5,3,2/5])
sage: m.determinant()-34/15sage: m.charpoly()x^3 - 17/5*x^2 - 122/15*x + 34/15
sage: m = matrix(QQ, 3, [(1/i)**j for i in range(2,5) for j in range(3)])
sage: m.determinant(algorithm="flint")-1/288sage: m = matrix(QQ, 4, [(-1)**n/n for n in range(1,17)])
sage: m.determinant(algorithm="pari")
2/70945875
sage: m = matrix(QQ, 5, [1/(i+j+1) for i in range(5) for j in range(5)])
sage: m.determinant(algorithm="integer")
1/266716800000>>> from sage.all import *>>> m = matrix(QQ,Integer(3),[Integer(1),Integer(2)/Integer(3),Integer(4)/˓→Integer(5), Integer(2),Integer(2),Integer(2), Integer(5),Integer(3),˓→Integer(2)/Integer(5)])>>> m.determinant()-34/15>>> m.charpoly()x^3 - 17/5*x^2 - 122/15*x + 34/15>>> m = matrix(QQ, Integer(3), [(Integer(1)/i)**j for i in range(Integer(2),˓→Integer(5)) for j in range(Integer(3))])>>> m.determinant(algorithm="flint")-1/288>>> m = matrix(QQ, Integer(4), [(-Integer(1))**n/n for n in range(Integer(1),˓→Integer(17))])>>> m.determinant(algorithm="pari")
2/70945875>>> m = matrix(QQ, Integer(5), [Integer(1)/(i+j+Integer(1)) for i in␣
˓→range(Integer(5)) for j in range(Integer(5))])>>> m.determinant(algorithm="integer")
1/266716800000

On non-square matrices, the method raises a ValueError:
sage: matrix(QQ, 2, 3).determinant(algorithm= flint )Traceback (most recent call last):...
ValueError: non square matrix
sage: matrix(QQ, 2, 3).determinant(algorithm= pari )Traceback (most recent call last):...
ValueError: non square matrix(continues on next page)695

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: matrix(QQ, 2, 3).determinant(algorithm= integer )Traceback (most recent call last):...
ValueError: non square matrix
sage: matrix(QQ, 2, 3).determinant(algorithm= generic )Traceback (most recent call last):...
ValueError: non square matrix>>> from sage.all import *>>> matrix(QQ, Integer(2), Integer(3)).determinant(algorithm= flint )Traceback (most recent call last):...
ValueError: non square matrix>>> matrix(QQ, Integer(2), Integer(3)).determinant(algorithm= pari )Traceback (most recent call last):...
ValueError: non square matrix>>> matrix(QQ, Integer(2), Integer(3)).determinant(algorithm= integer )Traceback (most recent call last):...
ValueError: non square matrix>>> matrix(QQ, Integer(2), Integer(3)).determinant(algorithm= generic )Traceback (most recent call last):...
ValueError: non square matrix

echelon_form(algorithm=None, height_guess=None, proof=None, **kwds)
Return the echelon form of this matrix.
The (row) echelon form of a matrix, see Wikipedia article Row_echelon_form, is the matrix obtained by
performing Gauss elimination on the rows of the matrix.
INPUT: See echelonize() for the options.
EXAMPLES:
sage: a = matrix(QQ, 4, range(16)); a[0,0] = 1/19; a[0,1] = 1/5; a[1/19 1/5
2
3]
[
4
5
6
7]
[
8
9
10
11]
[ 12
13
14
15]
sage: a.echelon_form()[
1
0
0 -76/157][
01
0 -5/157][
001 238/157]
[
0
0
0
0]
sage: a.echelon_form(algorithm= multimodular )[10
0 -76/157][
01
0 -5/157][
001 238/157]
[
0
0
0
0]
>>> from sage.all import *>>> a = matrix(QQ, Integer(4), range(Integer(16))); a[Integer(0),Integer(0)]␣
˓→= Integer(1)/Integer(19); a[Integer(0),Integer(1)] = Integer(1)/Integer(5);␣
˓→a(continues on next page)

696

Chapter 19. Dense matrices over the rational fieldMatrices and Spaces of Matrices, Release 10.4

(continued from previous page)[1/19 1/5
2
3]
[
4
5
6
7]
[
8
9
10
11]
[ 12
13
14
15]
>>> a.echelon_form()[
1
0
0 -76/157][
01
0 -5/157][
001 238/157]
[
0
0
0
0]
>>> a.echelon_form(algorithm= multimodular )[10
0 -76/157][
01
0 -5/157][
001 238/157]
[
0
0
0
0]

The result is an immutable matrix, so if you want to modify the result then you need to make a copy. This
checks that Issue #10543 is fixed.:
sage: A = matrix(QQ, 2, range(6))
sage: E = A.echelon_form()
sage: E.is_mutable()False
sage: F = copy(E)sage: F[0,0] = 50
sage: F[50 0 -1]
[ 0 1 2]>>> from sage.all import *>>> A = matrix(QQ, Integer(2), range(Integer(6)))>>> E = A.echelon_form()>>> E.is_mutable()
False>>> F = copy(E)>>> F[Integer(0),Integer(0)] = Integer(50)>>> F[50 0 -1]
[ 0 1 2]echelonize(algorithm=None, height_guess=None, proof=None, **kwds)
Transform the matrix self into reduced row echelon form in place.
INPUT:• algorithm – an optional specification of an algorithm. One of• None: (default) uses flint for small dimension and multimodular otherwise•

flint : use the flint library,•padic : an algorithm based on the IML p-adic solver,•

multimodular : uses a multimodular algorithm the uses linbox modulo many primes (likely to befaster when coefficients are huge),•classical : just clear each column using Gauss elimination.

• height_guess, **kwds – all passed to the multimodular algorithm; ignored by other algorithms.

697

Matrices and Spaces of Matrices, Release 10.4

• proof – bool or None (default: None, see proof.linear_algebra or sage.structure.proof). Passed to themultimodular algorithm. Note that the Sage global default is proof=True.
EXAMPLES:
sage: a = matrix(QQ, 4, range(16)); a[0,0] = 1/19; a[0,1] = 1/5; a[1/19 1/5
2
3]
[
4
5
6
7]
[
8
9
10
11]
[ 12
13
14
15]
sage: a.echelonize()
sage: a[1
0
0 -76/157][
01
0 -5/157][
001 238/157]
[
0
0
0
0]
>>> from sage.all import *>>> a = matrix(QQ, Integer(4), range(Integer(16))); a[Integer(0),Integer(0)]␣
˓→= Integer(1)/Integer(19); a[Integer(0),Integer(1)] = Integer(1)/Integer(5);␣
˓→a[1/19 1/5
2
3]
[
4
5
6
7]
[
8
9
10
11]
[ 12
13
14
15]
>>> a.echelonize()
>>> a
[
1
0
0 -76/157][
01
0 -5/157][
001 238/157]
[
0
0
0
0]
sage: a = matrix(QQ, 4, range(16)); a[0,0] = 1/19; a[0,1] = 1/5
sage: a.echelonize(algorithm= multimodular )sage: a[1
0
0 -76/157][
01
0 -5/157][
001 238/157]
[
0
0
0
0]
>>> from sage.all import *>>> a = matrix(QQ, Integer(4), range(Integer(16))); a[Integer(0),Integer(0)]␣
˓→= Integer(1)/Integer(19); a[Integer(0),Integer(1)] = Integer(1)/Integer(5)>>> a.echelonize(algorithm= multimodular )
>>> a
[
1
0
0 -76/157][
01
0 -5/157][
001 238/157]
[
0
0
0
0]

height()Return the height of this matrix, which is the maximum of the absolute values of all numerators and denominators of entries in this matrix.
OUTPUT: an Integer
EXAMPLES:

698

Chapter 19. Dense matrices over the rational fieldMatrices and Spaces of Matrices, Release 10.4

sage: b = matrix(QQ,2,range(6)); b[0,0]=-5007/293; b[-5007/293
1
2]
[
3
4
5]
sage: b.height()
5007>>> from sage.all import *>>> b = matrix(QQ,Integer(2),range(Integer(6))); b[Integer(0),Integer(0)]=˓→Integer(5007)/Integer(293); b[-5007/293
1
2]
[
3
4
5]
>>> b.height()
5007

inverse(algorithm=None, check_invertible=True)
Return the inverse of this matrix
INPUT:• algorithm – an optional specification of an algorithm. It can be one of– None: (default) uses flint–

flint : uses flint library–pari : uses PARI library–iml : uses IML library• check_invertible – only used when algorithm=iml. Whether to check that matrix is invertible
EXAMPLES:
sage: a = matrix(QQ,3,[1,2,5,3,2,1,1,1,1,])
sage: a.inverse()[1/2 3/2 -4][ -1 -2
7][1/2 1/2 -2]
sage: a = matrix(QQ, 2, [1, 5, 17, 3])
sage: a.inverse(algorithm="flint")[-3/82 5/82][17/82 -1/82]
sage: a.inverse(algorithm="flint") * a
[1 0]
[0 1]
sage: a = matrix(QQ, 2, [-1, 5, 12, -3])
sage: a.inverse(algorithm="iml")[1/19 5/57][4/19 1/57]
sage: a.inverse(algorithm="iml") * a
[1 0]
[0 1]
sage: a = matrix(QQ, 4, primes_first_n(16))
sage: a.inverse(algorithm="pari")[
3/11 -12/55
-1/5
2/11]
(continues on next page)699

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ -5/11-2/55[ -13/22 307/440[ 15/22 -37/88

3/10
-1/10
0

-3/22]-9/88]
7/88]>>> from sage.all import *>>> a = matrix(QQ,Integer(3),[Integer(1),Integer(2),Integer(5),Integer(3),˓→Integer(2),Integer(1),Integer(1),Integer(1),Integer(1),])>>> a.inverse()[1/2 3/2 -4][ -1 -2
7][1/2 1/2 -2]>>> a = matrix(QQ, Integer(2), [Integer(1), Integer(5), Integer(17),␣
˓→Integer(3)])>>> a.inverse(algorithm="flint")[-3/82 5/82][17/82 -1/82]>>> a.inverse(algorithm="flint") * a
[1 0]
[0 1]
>>> a = matrix(QQ, Integer(2), [-Integer(1), Integer(5), Integer(12), ˓→Integer(3)])>>> a.inverse(algorithm="iml")[1/19 5/57][4/19 1/57]>>> a.inverse(algorithm="iml") * a
[1 0]
[0 1]
>>> a = matrix(QQ, Integer(4), primes_first_n(Integer(16)))>>> a.inverse(algorithm="pari")[
3/11 -12/55
-1/5
2/11]
[ -5/11-2/55
3/10-3/22][ -13/22 307/440-1/10-9/88][ 15/22 -37/88
0
7/88]

On singular matrices this method raises a ZeroDivisionError:
sage: a = matrix(QQ, 2)
sage: a.inverse(algorithm="flint")
Traceback (most recent call last):...
ZeroDivisionError: input matrix must be nonsingularsage: a.inverse(algorithm="iml")
Traceback (most recent call last):...
ZeroDivisionError: input matrix must be nonsingularsage: a.inverse(algorithm="pari")
Traceback (most recent call last):...
ZeroDivisionError: input matrix must be nonsingular>>> from sage.all import *>>> a = matrix(QQ, Integer(2))>>> a.inverse(algorithm="flint")(continues on next page)

700

Chapter 19. Dense matrices over the rational fieldMatrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Traceback (most recent call last):...
ZeroDivisionError: input matrix must be nonsingular>>> a.inverse(algorithm="iml")
Traceback (most recent call last):...
ZeroDivisionError: input matrix must be nonsingular>>> a.inverse(algorithm="pari")
Traceback (most recent call last):...
ZeroDivisionError: input matrix must be nonsingular

is_LLL_reduced(delta=None, eta=None)
Return True if this lattice is (𝛿, 𝜂)-LLL reduced. For a definition of LLL reduction, see sage.matrix.
matrix_integer_dense.Matrix_integer_dense.LLL().
EXAMPLES:
sage: A = random_matrix(QQ, 10, 10)
sage: L = A.LLL()
sage: A.is_LLL_reduced()
False
sage: L.is_LLL_reduced()True>>> from sage.all import *>>> A = random_matrix(QQ, Integer(10), Integer(10))>>> L = A.LLL()>>> A.is_LLL_reduced()
False>>> L.is_LLL_reduced()Truematrix_from_columns(columns)
Return the matrix constructed from self using columns with indices in the columns list.
EXAMPLES:
sage: A = matrix(QQ, 3, range(9))
sage: A[0 1 2][3 4 5][6 7 8]sage: A.matrix_from_columns([2,1])
[2 1]
[5 4]
[8 7]
sage: A.matrix_from_columns((2,1,0,2))[2 1 0 2][5 4 3 5][8 7 6 8]>>> from sage.all import *>>> A = matrix(QQ, Integer(3), range(Integer(9)))>>> A[0 1 2](continues on next page)701

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[3 4 5][6 7 8]>>> A.matrix_from_columns([Integer(2),Integer(1)])
[2 1]
[5 4]
[8 7]
>>> A.matrix_from_columns((Integer(2),Integer(1),Integer(0),Integer(2)))[2 1 0 2][5 4 3 5][8 7 6 8]

minpoly(var='x', algorithm=None)
Return the minimal polynomial of this matrix
INPUT:• var – (optional) the variable name as a string (default is ‘x’)
• algorithm – an optional specification of an algorithm. It can be one of– None: (default) will use linbox–

linbox : uses the linbox library–generic : uses the generic Sage implementation

OUTPUT: a polynomial over the rationals
EXAMPLES:
sage: a = matrix(QQ, 3, [4/3, 2/5, 1/5, 4, -3/2, 0, 0, -2/3, 3/4])
sage: f = a.minpoly(); fx^3 - 7/12*x^2 - 149/40*x + 97/30
sage: a = Mat(ZZ,4)(range(16))
sage: f = a.minpoly(); f.factor()x * (x^2 - 30*x - 80)
sage: f(a) == 0
True>>> from sage.all import *>>> a = matrix(QQ, Integer(3), [Integer(4)/Integer(3), Integer(2)/Integer(5),␣
˓→Integer(1)/Integer(5), Integer(4), -Integer(3)/Integer(2), Integer(0),␣
˓→Integer(0), -Integer(2)/Integer(3), Integer(3)/Integer(4)])>>> f = a.minpoly(); fx^3 - 7/12*x^2 - 149/40*x + 97/30>>> a = Mat(ZZ,Integer(4))(range(Integer(16)))>>> f = a.minpoly(); f.factor()x * (x^2 - 30*x - 80)>>> f(a) == Integer(0)Truesage: a = matrix(QQ, 4, [1..4^2])sage: factor(a.minpoly())
x * (x^2 - 34*x - 80)
sage: factor(a.minpoly( y ))y * (y^2 - 34*y - 80)
sage: factor(a.charpoly())
x^2 * (x^2 - 34*x - 80)(continues on next page)702

Chapter 19. Dense matrices over the rational fieldMatrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: b = matrix(QQ, 4, [-1, 2, 2, 0, 0, 4, 2, 2, 0, 0, -1, -2, 0, -4, 0, 4])
sage: a = matrix(QQ, 4, [1, 1, 0,0, 0,1,0,0, 0,0,5,0, 0,0,0,5])
sage: c = b^(-1)*a*b
sage: factor(c.minpoly())(x - 5) * (x - 1)^2
sage: factor(c.charpoly())(x - 5)^2 * (x - 1)^2>>> from sage.all import *>>> a = matrix(QQ, Integer(4), (ellipsis_range(Integer(1),Ellipsis,
˓→Integer(4)**Integer(2))))>>> factor(a.minpoly())
x * (x^2 - 34*x - 80)>>> factor(a.minpoly( y ))y * (y^2 - 34*y - 80)>>> factor(a.charpoly())
x^2 * (x^2 - 34*x - 80)>>> b = matrix(QQ, Integer(4), [-Integer(1), Integer(2), Integer(2),␣
˓→Integer(0), Integer(0), Integer(4), Integer(2), Integer(2), Integer(0),␣
˓→Integer(0), -Integer(1), -Integer(2), Integer(0), -Integer(4), Integer(0),␣
˓→Integer(4)])>>> a = matrix(QQ, Integer(4), [Integer(1), Integer(1), Integer(0),Integer(0),˓→ Integer(0),Integer(1),Integer(0),Integer(0), Integer(0),Integer(0),˓→Integer(5),Integer(0), Integer(0),Integer(0),Integer(0),Integer(5)])>>> c = b**(-Integer(1))*a*b>>> factor(c.minpoly())(x - 5) * (x - 1)^2>>> factor(c.charpoly())(x - 5)^2 * (x - 1)^2

Check consistency:
sage: for _ in range(100):....:
dim = randint(0, 10)....:m = random_matrix(QQ, dim, num_bound=8, den_bound=8)....:
p_linbox = m.charpoly(algorithm= linbox ); m._clear_cache()....:p_generic = m.charpoly(algorithm= generic )....:assert p_linbox == p_generic>>> from sage.all import *>>> for _ in range(Integer(100)):...
dim = randint(Integer(0), Integer(10))...
m = random_matrix(QQ, dim, num_bound=Integer(8), den_bound=Integer(8))...
p_linbox = m.charpoly(algorithm= linbox ); m._clear_cache()...
p_generic = m.charpoly(algorithm= generic )...
assert p_linbox == p_generic

prod_of_row_sums(cols)
randomize(density=1, num_bound=2, den_bound=2, distribution=None, nonzero=False)
Randomize density proportion of the entries of this matrix, leaving the rest unchanged.
If x and y are given, randomized entries of this matrix have numerators and denominators bounded by x andy and have density 1.
INPUT:

703

Matrices and Spaces of Matrices, Release 10.4

• density – number between 0 and 1 (default: 1)• num_bound – numerator bound (default: 2)• den_bound – denominator bound (default: 2)• distribution – None or ‘1/n’ (default: None); if ‘1/n’ then num_bound, den_bound are ignored
and numbers are chosen using the GMP function mpq_randomize_entry_recip_uniform
OUTPUT:• None, the matrix is modified in-space
EXAMPLES:
The default distribution:
sage: from collections import defaultdict
sage: total_count = 0
sage: dic = defaultdict(Integer)
sage: def add_samples(distribution=None):....:
global dic, total_count....:for _ in range(100):....:
A = Matrix(QQ, 2, 4, 0)....:
A.randomize(distribution=distribution)....:
for a in A.list():....:dic[a] += 1....:
total_count += 1.0
sage: expected = {-2: 1/9, -1: 3/18, -1/2: 1/18, 0: 3/9,....:
1/2: 1/18, 1: 3/18, 2: 1/9}
sage: add_samples()sage: while not all(abs(dic[a]/total_count - expected[a]) < 0.001 for a in␣˓→dic):....:
add_samples()>>> from sage.all import *>>> from collections import defaultdict>>> total_count = Integer(0)>>> dic = defaultdict(Integer)>>> def add_samples(distribution=None):...
global dic, total_count...
for _ in range(Integer(100)):...
A = Matrix(QQ, Integer(2), Integer(4), Integer(0))...
A.randomize(distribution=distribution)...
for a in A.list():...
dic[a] += Integer(1)...
total_count += RealNumber( 1.0 )>>> expected = {-Integer(2): Integer(1)/Integer(9), -Integer(1): Integer(3)/˓→Integer(18), -Integer(1)/Integer(2): Integer(1)/Integer(18), Integer(0):␣
˓→Integer(3)/Integer(9),...
Integer(1)/Integer(2): Integer(1)/Integer(18), Integer(1):␣
˓→Integer(3)/Integer(18), Integer(2): Integer(1)/Integer(9)}>>> add_samples()>>> while not all(abs(dic[a]/total_count - expected[a]) < RealNumber( 0.001 )␣
˓→for a in dic):...
add_samples()The distribution 1/n :704

Chapter 19. Dense matrices over the rational fieldMatrices and Spaces of Matrices, Release 10.4

sage: def mpq_randomize_entry_recip_uniform():....:
r = 2*random() - 1....:
if r == 0: r = 1....:
num = int(4/(5*r))....:
r = random()....:
if r == 0: r = 1....:
den = int(1/random())....:
return Integer(num)/Integer(den)sage: total_count = 0
sage: dic = defaultdict(Integer)
sage: dic2 = defaultdict(Integer)
sage: add_samples( 1/n )sage: for _ in range(8):....:dic2[mpq_randomize_entry_recip_uniform()] += 1
sage: while not all(abs(dic[a] - dic2[a])/total_count < 0.005 for a in dic):....:
add_samples( 1/n )....:for _ in range(800):....:
dic2[mpq_randomize_entry_recip_uniform()] += 1>>> from sage.all import *>>> def mpq_randomize_entry_recip_uniform():...
r = Integer(2)*random() - Integer(1)...
if r == Integer(0): r = Integer(1)...
num = int(Integer(4)/(Integer(5)*r))...
r = random()...
if r == Integer(0): r = Integer(1)...
den = int(Integer(1)/random())...
return Integer(num)/Integer(den)>>> total_count = Integer(0)>>> dic = defaultdict(Integer)>>> dic2 = defaultdict(Integer)>>> add_samples( 1/n )>>> for _ in range(Integer(8)):...
dic2[mpq_randomize_entry_recip_uniform()] += Integer(1)>>> while not all(abs(dic[a] - dic2[a])/total_count < RealNumber( 0.005 ) for␣
˓→a in dic):...
add_samples( 1/n )...
for _ in range(Integer(800)):...
dic2[mpq_randomize_entry_recip_uniform()] += Integer(1)The default can be used to obtain matrices of different rank:
sage: ranks = [False]*11
sage: while not all(ranks):....:
for dens in (0.05, 0.1, 0.2, 0.5):....:
A = Matrix(QQ, 10, 10, 0)....:
A.randomize(dens)....:
ranks[A.rank()] = True>>> from sage.all import *>>> ranks = [False]*Integer(11)>>> while not all(ranks):...
for dens in (RealNumber( 0.05 ), RealNumber( 0.1 ), RealNumber( 0.2 ),˓→ RealNumber( 0.5 )):...
A = Matrix(QQ, Integer(10), Integer(10), Integer(0))(continues on next page)705

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

...
...

A.randomize(dens)
ranks[A.rank()] = True

The default density is 6/9:
sage: def add_sample(density, num_rows, num_cols):....:
global density_sum, total_count....:total_count += 1.0....:
A = Matrix(QQ, num_rows, num_cols, 0)....:
A.randomize(density)....:
density_sum += float(A.density())
sage: density_sum = 0.0
sage: total_count = 0.0
sage: expected_density = 6/9
sage: add_sample(1.0, 100, 100)
sage: while abs(density_sum/total_count - expected_density) > 0.001:....:
add_sample(1.0, 100, 100)>>> from sage.all import *>>> def add_sample(density, num_rows, num_cols):...
global density_sum, total_count...
total_count += RealNumber( 1.0 )...
A = Matrix(QQ, num_rows, num_cols, Integer(0))...
A.randomize(density)...
density_sum += float(A.density())>>> density_sum = RealNumber( 0.0 )>>> total_count = RealNumber( 0.0 )>>> expected_density = Integer(6)/Integer(9)>>> add_sample(RealNumber( 1.0 ), Integer(100), Integer(100))>>> while abs(density_sum/total_count - expected_density) > RealNumber( 0.001
˓→ ):
...
add_sample(RealNumber( 1.0 ), Integer(100), Integer(100))

The modified density depends on the number of columns:
sage: density_sum = 0.0
sage: total_count = 0.0
sage: expected_density = 6/9*0.5
sage: add_sample(0.5, 100, 2)
sage: while abs(density_sum/total_count - expected_density) > 0.001:....:
add_sample(0.5, 100, 2)
sage: density_sum = 0.0
sage: total_count = 0.0
sage: expected_density = 6/9*(1.0 - (99/100)^50)
sage: expected_density
0.263...
sage: add_sample(0.5, 100, 100)
sage: while abs(density_sum/total_count - expected_density) > 0.001:....:
add_sample(0.5, 100, 100)>>> from sage.all import *>>> density_sum = RealNumber( 0.0 )(continues on next page)

706

Chapter 19. Dense matrices over the rational fieldMatrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> total_count = RealNumber( 0.0 )>>> expected_density = Integer(6)/Integer(9)*RealNumber( 0.5 )>>> add_sample(RealNumber( 0.5 ), Integer(100), Integer(2))>>> while abs(density_sum/total_count - expected_density) > RealNumber( 0.001
˓→ ):
...
add_sample(RealNumber( 0.5 ), Integer(100), Integer(2))>>> density_sum = RealNumber( 0.0 )>>> total_count = RealNumber( 0.0 )>>> expected_density = Integer(6)/Integer(9)*(RealNumber( 1.0 ) -␣
˓→(Integer(99)/Integer(100))**Integer(50))>>> expected_density
0.263...
>>> add_sample(RealNumber( 0.5 ), Integer(100), Integer(100))>>> while abs(density_sum/total_count - expected_density) > RealNumber( 0.001
˓→ ):
...
add_sample(RealNumber( 0.5 ), Integer(100), Integer(100))

Modifying the bounds for numerator and denominator:
sage: num_dic = defaultdict(Integer)
sage: den_dic = defaultdict(Integer)
sage: while not (all(num_dic[i] for i in range(-200, 201))....:
and all(den_dic[i] for i in range(1, 101))):....:
a = matrix(QQ, 2, 4)....:
a.randomize(num_bound=200, den_bound=100)....:
for q in a.list():....:num_dic[q.numerator()] += 1....:
den_dic[q.denominator()] += 1
sage: len(num_dic)
401
sage: len(den_dic)
100>>> from sage.all import *>>> num_dic = defaultdict(Integer)>>> den_dic = defaultdict(Integer)>>> while not (all(num_dic[i] for i in range(-Integer(200), Integer(201)))...
and all(den_dic[i] for i in range(Integer(1), Integer(101)))):...
a = matrix(QQ, Integer(2), Integer(4))...
a.randomize(num_bound=Integer(200), den_bound=Integer(100))...
for q in a.list():...
num_dic[q.numerator()] += Integer(1)...
den_dic[q.denominator()] += Integer(1)>>> len(num_dic)
401>>> len(den_dic)
100rank(algorithm=None)
Return the rank of this matrix.
INPUT:• algorithm – an optional specification of an algorithm. One of– None: (default) will use flint
707

Matrices and Spaces of Matrices, Release 10.4–

flint : uses the flint library–pari : uses the PARI library–

integer : eliminate denominators and calls the rank function on the corresponding integer
matrixEXAMPLES:
sage: matrix(QQ,3,[1..9]).rank()
2sage: matrix(QQ,100,[1..100^2]).rank()
2>>> from sage.all import *>>> matrix(QQ,Integer(3),(ellipsis_range(Integer(1),Ellipsis,Integer(9)))).
˓→rank()2>>> matrix(QQ,Integer(100),(ellipsis_range(Integer(1),Ellipsis,
˓→Integer(100)**Integer(2)))).rank()2

row(i, from_list=False)
Return the i-th row of this matrix as a dense vector.
INPUT:• i – integer• from_list – ignored
EXAMPLES:
sage: m = matrix(QQ, 2, [1/5, -2/3, 3/4, 4/9])
sage: m.row(0)(1/5, -2/3)
sage: m.row(1)(3/4, 4/9)
sage: m.row(1, from_list=True)(3/4, 4/9)
sage: m.row(-2)(1/5, -2/3)
sage: m.row(2)Traceback (most recent call last):...
IndexError: row index out of range
sage: m.row(-3)
Traceback (most recent call last):...
IndexError: row index out of range>>> from sage.all import *>>> m = matrix(QQ, Integer(2), [Integer(1)/Integer(5), -Integer(2)/Integer(3),˓→ Integer(3)/Integer(4), Integer(4)/Integer(9)])>>> m.row(Integer(0))(1/5, -2/3)>>> m.row(Integer(1))(3/4, 4/9)
(continues on next page)

708

Chapter 19. Dense matrices over the rational fieldMatrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> m.row(Integer(1), from_list=True)(3/4, 4/9)>>> m.row(-Integer(2))(1/5, -2/3)>>> m.row(Integer(2))
Traceback (most recent call last):...
IndexError: row index out of range>>> m.row(-Integer(3))
Traceback (most recent call last):...
IndexError: row index out of range

set_row_to_multiple_of_row(i, j, s)
Set row i equal to s times row j.
EXAMPLES:
sage: a = matrix(QQ,2,3,range(6)); a[0 1 2][3 4 5]sage: a.set_row_to_multiple_of_row(1,0,-3)
sage: a[ 0 1 2][ 0 -3 -6]>>> from sage.all import *>>> a = matrix(QQ,Integer(2),Integer(3),range(Integer(6))); a[0 1 2][3 4 5]>>> a.set_row_to_multiple_of_row(Integer(1),Integer(0),-Integer(3))>>> a[ 0 1 2][ 0 -3 -6]transpose()
Returns 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: A = matrix(QQ, 2, 3, range(6))
sage: type(A)<class sage.matrix.matrix_rational_dense.Matrix_rational_dense >sage: B = A.transpose()sage: print(B)
[0 3]
[1 4]
[2 5]
sage: print(A)[0 1 2][3 4 5]709

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = matrix(QQ, Integer(2), Integer(3), range(Integer(6)))>>> type(A)<class sage.matrix.matrix_rational_dense.Matrix_rational_dense >>>> B = A.transpose()>>> print(B)
[0 3]
[1 4]
[2 5]
>>> print(A)[0 1 2][3 4 5].T is a convenient shortcut for the transpose:
sage: print(A.T)
[0 3]
[1 4]
[2 5]
>>> from sage.all import *>>> print(A.T)
[0 3]
[1 4]
[2 5]
sage: A.subdivide(None, 1); A[0|1 2][3|4 5]sage: A.transpose()
[0 3]
[---]
[1 4]
[2 5]
>>> from sage.all import *>>> A.subdivide(None, Integer(1)); A[0|1 2][3|4 5]>>> A.transpose()
[0 3]
[---]
[1 4]
[2 5]

710

Chapter 19. Dense matrices over the rational fieldCHAPTERTWENTYSPARSE RATIONAL MATRICESAUTHORS:• William Stein (2007-02-21)• Soroosh Yazdani (2007-02-21)class sage.matrix.matrix_rational_sparse.Matrix_rational_sparse
Bases: Matrix_sparse
Create a sparse matrix over the rational numbers.
INPUT:• parent – a matrix space over QQ• entries – see matrix()• copy – ignored (for backwards compatibility)• coerce – if False, assume without checking that the entries are of type Rational.
add_to_entry(i, j, elt)
Add elt to the entry at position (i, j).
EXAMPLES:
sage: m = matrix(QQ, 2, 2, sparse=True)
sage: m.add_to_entry(0, 0, -1/3)
sage: m
[-1/3
0]
[
0
0]
sage: m.add_to_entry(0, 0, 1/3)
sage: m[0 0]
[0 0]
sage: m.nonzero_positions()[]>>> from sage.all import *>>> m = matrix(QQ, Integer(2), Integer(2), sparse=True)>>> m.add_to_entry(Integer(0), Integer(0), -Integer(1)/Integer(3))
>>> m
[-1/3
0]
[
0
0]
>>> m.add_to_entry(Integer(0), Integer(0), Integer(1)/Integer(3))
>>> m
[0 0]
(continues on next page)711

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 0]>>> m.nonzero_positions()[]

denominator()
Return the denominator of this matrix.
OUTPUT:• Sage Integer
EXAMPLES:
sage: b = matrix(QQ,2,range(6)); b[0,0]=-5007/293; b[-5007/293
1
2]
[
3
4
5]
sage: b.denominator()
293>>> from sage.all import *>>> b = matrix(QQ,Integer(2),range(Integer(6))); b[Integer(0),Integer(0)]=˓→Integer(5007)/Integer(293); b[-5007/293
1
2]
[
3
4
5]
>>> b.denominator()
293

dense_matrix()
Return dense version of this matrix.
EXAMPLES:
sage: a = matrix(QQ,2,[1..4],sparse=True); type(a)<class sage.matrix.matrix_rational_sparse.Matrix_rational_sparse >sage: type(a.dense_matrix())<class sage.matrix.matrix_rational_dense.Matrix_rational_dense >sage: a.dense_matrix()
[1 2]
[3 4]
>>> from sage.all import *>>> a = matrix(QQ,Integer(2),(ellipsis_range(Integer(1),Ellipsis,Integer(4))),
˓→sparse=True); type(a)<class sage.matrix.matrix_rational_sparse.Matrix_rational_sparse >>>> type(a.dense_matrix())<class sage.matrix.matrix_rational_dense.Matrix_rational_dense >>>> a.dense_matrix()
[1 2]
[3 4]

Check that subdivisions are preserved when converting between dense and sparse matrices:sage: a.subdivide([1,1], [2])sage: b = a.dense_matrix().sparse_matrix().dense_matrix()
sage: b.subdivisions() == a.subdivisions()
True

712

Chapter 20. Sparse rational matrices

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> a.subdivide([Integer(1),Integer(1)], [Integer(2)])>>> b = a.dense_matrix().sparse_matrix().dense_matrix()>>> b.subdivisions() == a.subdivisions()
Trueechelon_form(algorithm='default', height_guess=None, proof=True, **kwds)
INPUT:
height_guess, proof, **kwds – all passed to the multimodular algorithm; ignored by the p-adic
algorithm.
OUTPUT:
self is no in reduced row echelon form.
EXAMPLES:
sage: a = matrix(QQ, 4, range(16), sparse=True); a[0,0] = 1/19; a[0,1] = 1/5;␣
˓→a[1/19 1/5
2
3]
[
4
5
6
7]
[
8
9
10
11]
[ 12
13
14
15]
sage: a.echelon_form()[
1
0
0 -76/157][
01
0 -5/157][
001 238/157]
[
0
0
0
0]
>>> from sage.all import *>>> a = matrix(QQ, Integer(4), range(Integer(16)), sparse=True); a[Integer(0),˓→Integer(0)] = Integer(1)/Integer(19); a[Integer(0),Integer(1)] = Integer(1)/˓→Integer(5); a[1/19 1/5
2
3]
[
4
5
6
7]
[
8
9
10
11]
[ 12
13
14
15]
>>> a.echelon_form()[
1
0
0 -76/157][
01
0 -5/157][
001 238/157]
[
0
0
0
0]

echelonize(height_guess=None, proof=True, **kwds)
Transform the matrix self into reduced row echelon form in place.
INPUT:
height_guess, proof, **kwds – all passed to the multimodular algorithm; ignored by the p-adic
algorithm.
OUTPUT:
Nothing. The matrix self is transformed into reduced row echelon form in place.
ALGORITHM: a multimodular algorithm.
EXAMPLES:

713

Matrices and Spaces of Matrices, Release 10.4

sage: a = matrix(QQ, 4, range(16), sparse=True); a[0,0] = 1/19; a[0,1] = 1/5;␣
˓→a[1/19 1/5
2
3]
[
4
5
6
7]
[
8
9
10
11]
[ 12
13
14
15]
sage: a.echelonize(); a[10
0 -76/157][
01
0 -5/157][
001 238/157]
[
0
0
0
0]
>>> from sage.all import *>>> a = matrix(QQ, Integer(4), range(Integer(16)), sparse=True); a[Integer(0),˓→Integer(0)] = Integer(1)/Integer(19); a[Integer(0),Integer(1)] = Integer(1)/˓→Integer(5); a[1/19 1/5
2
3]
[
4
5
6
7]
[
8
9
10
11]
[ 12
13
14
15]
>>> a.echelonize(); a[10
0 -76/157][
01
0 -5/157][
001 238/157]
[
0
0
0
0]

Issue #10319 has been fixed:
sage: m = Matrix(QQ, [1], sparse=True); m.echelonize()
sage: m = Matrix(QQ, [1], sparse=True); m.echelonize(); m[1]>>> from sage.all import *>>> m = Matrix(QQ, [Integer(1)], sparse=True); m.echelonize()>>> m = Matrix(QQ, [Integer(1)], sparse=True); m.echelonize(); m[1]height()Return the height of this matrix, which is the least common multiple of all numerators and denominators ofelements of this matrix.
OUTPUT:– Integer
EXAMPLES:
sage: b = matrix(QQ,2,range(6), sparse=True); b[0,0]=-5007/293; b[-5007/293
1
2]
[
3
4
5]
sage: b.height()
5007>>> from sage.all import *>>> b = matrix(QQ,Integer(2),range(Integer(6)), sparse=True); b[Integer(0),˓→Integer(0)]=-Integer(5007)/Integer(293); b[-5007/293
12](continues on next page)714

Chapter 20. Sparse rational matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[3>>> b.height()
5007

4

5]

set_row_to_multiple_of_row(i, j, s)
Set row i equal to s times row j.
EXAMPLES:
sage: a = matrix(QQ,2,3,range(6), sparse=True); a[0 1 2][3 4 5]sage: a.set_row_to_multiple_of_row(1,0,-3)
sage: a[ 0 1 2][ 0 -3 -6]>>> from sage.all import *>>> a = matrix(QQ,Integer(2),Integer(3),range(Integer(6)), sparse=True); a[0 1 2][3 4 5]>>> a.set_row_to_multiple_of_row(Integer(1),Integer(0),-Integer(3))>>> a[ 0 1 2][ 0 -3 -6]715

Matrices and Spaces of Matrices, Release 10.4

716

Chapter 20. Sparse rational matrices

CHAPTERTWENTYONE

DENSE MATRICES USING A NUMPY BACKEND

This serves as a base class for dense matrices over Real Double Field and Complex Double Field.
AUTHORS:• Jason Grout, Sep 2008: switch to NumPy backend, factored out the Matrix_double_dense class• Josh Kantor• William Stein: many bug fixes and touch ups.
EXAMPLES:
sage: b = Mat(RDF,2,3).basis()
sage: b[0,0][1.0 0.0 0.0]
[0.0 0.0 0.0]>>> from sage.all import *>>> b = Mat(RDF,Integer(2),Integer(3)).basis()>>> b[Integer(0),Integer(0)][1.0 0.0 0.0]
[0.0 0.0 0.0]

We deal with the case of zero rows or zero columns:
sage: m = MatrixSpace(RDF,0,3)
sage: m.zero_matrix()[]>>> from sage.all import *>>> m = MatrixSpace(RDF,Integer(0),Integer(3))>>> m.zero_matrix()[]class sage.matrix.matrix_double_dense.Matrix_double_dense
Bases: Matrix_numpy_dense
Base class for matrices over the Real Double Field and the Complex Double Field. These are supposed to be fast
matrix operations using C doubles. Most operations are implemented using numpy which will call the underlying
BLAS on the system.
This class cannot be instantiated on its own. The numpy matrix creation depends on several variables that are set
in the subclasses.
EXAMPLES:

717

Matrices and Spaces of Matrices, Release 10.4

sage: m = Matrix(RDF, [[1,2],[3,4]])
sage: m**2
[ 7.0 10.0][15.0 22.0]
sage: m^(-1)# rel tol 1e-15
˓→needs scipy[-1.9999999999999996 0.9999999999999998][ 1.4999999999999998 -0.4999999999999999]#␣>>> from sage.all import *>>> m = Matrix(RDF, [[Integer(1),Integer(2)],[Integer(3),Integer(4)]])>>> m**Integer(2)[ 7.0 10.0][15.0 22.0]>>> m**(-Integer(1))# rel tol 1e-15
˓→# needs scipy[-1.9999999999999996 0.9999999999999998][ 1.4999999999999998 -0.4999999999999999]

␣

LU()
Return a decomposition of the (row-permuted) matrix as a product of a lower-triangular matrix (“L”) and an
upper-triangular matrix (“U”).
OUTPUT:For an 𝑚 × 𝑛 matrix A this method returns a triple of immutable matrices P, L, U such that
• A = P*L*U• P is a square permutation matrix, of size 𝑚 × 𝑚, so is all zeroes, but with exactly a single one in eachrow and each column.
• L is lower-triangular, square of size 𝑚 × 𝑚, with every diagonal entry equal to one.
• U is upper-triangular with size 𝑚 × 𝑛, i.e. entries below the “diagonal” are all zero.
The computed decomposition is cached and returned on subsequent calls, thus requiring the results to be
immutable.
Effectively, P permutes the rows of A. Then L can be viewed as a sequence of row operations on this matrix, where each operation is adding a multiple of a row to a subsequent row. There is no scaling (thus
1’s on the diagonal of L) and no row-swapping (P does that). As a result U is close to being the result ofGaussian-elimination. However, round-off errors can make it hard to determine the zero entries of U.
Note: The behaviour of LU() has changed in Sage version 9.1. Earlier, LU() returned P,L,U such that
P*A=L*U, where P represents the permutation and is the matrix inverse of the P returned by this method.
The computation of this matrix inverse can be accomplished quickly with just a transpose as the matrix isorthogonal/unitary.
For details see Issue #18365.
EXAMPLES:
sage: m = matrix(RDF,4,range(16))
sage: P,L,U = m.LU()
sage: P*L*U # rel tol 2e-16[ 0.0 1.0 2.0 3.0]
[ 4.0 5.0 6.0 7.0]
(continues on next page)

718

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 8.0 9.0 10.0 11.0][12.0 13.0 14.0 15.0]>>> from sage.all import *>>> m = matrix(RDF,Integer(4),range(Integer(16)))>>> P,L,U = m.LU()>>> P*L*U # rel tol 2e-16[ 0.0 1.0 2.0 3.0]
[ 4.0 5.0 6.0 7.0]
[ 8.0 9.0 10.0 11.0][12.0 13.0 14.0 15.0]

Below example illustrates the change in behaviour of LU().
sage: (m - P*L*U).norm() < 1e-14
True
sage: (P*m - L*U).norm() < 1e-14
False>>> from sage.all import *>>> (m - P*L*U).norm() < RealNumber( 1e-14 )True>>> (P*m - L*U).norm() < RealNumber( 1e-14 )False

Issue #10839 made this routine available for rectangular matrices.
sage: A = matrix(RDF, 5, 6, range(30)); A[ 0.0 1.0 2.0 3.0 4.0 5.0]
[ 6.0 7.0 8.0 9.0 10.0 11.0][12.0 13.0 14.0 15.0 16.0 17.0][18.0 19.0 20.0 21.0 22.0 23.0][24.0 25.0 26.0 27.0 28.0 29.0]
sage: P, L, U = A.LU()
sage: P
[0.0 1.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0 1.0]
[0.0 0.0 1.0 0.0 0.0]
[0.0 0.0 0.0 1.0 0.0]
[1.0 0.0 0.0 0.0 0.0]
sage: L.zero_at(0)# Use zero_at(0) to get rid of signed zeros[ 1.0 0.0 0.0 0.0 0.0]
[ 0.0 1.0 0.0 0.0 0.0]
[ 0.5 0.5 1.0 0.0 0.0]
[0.75 0.25 0.0 1.0 0.0]
[0.25 0.75 0.0 0.0 1.0]
sage: U.zero_at(0)# Use zero_at(0) to get rid of signed zeros[24.0 25.0 26.0 27.0 28.0 29.0][ 0.0 1.0 2.0 3.0 4.0 5.0]
[ 0.0 0.0 0.0 0.0 0.0 0.0]
[ 0.0 0.0 0.0 0.0 0.0 0.0]
[ 0.0 0.0 0.0 0.0 0.0 0.0]
sage: P.transpose()*A-L*U[0.0 0.0 0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0 0.0 0.0]
(continues on next page)719

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0.0 0.0 0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0 0.0 0.0]
sage: P*L*U[ 0.0 1.0 2.0 3.0 4.0 5.0]
[ 6.0 7.0 8.0 9.0 10.0 11.0][12.0 13.0 14.0 15.0 16.0 17.0][18.0 19.0 20.0 21.0 22.0 23.0][24.0 25.0 26.0 27.0 28.0 29.0]>>> from sage.all import *>>> A = matrix(RDF, Integer(5), Integer(6), range(Integer(30))); A[ 0.0 1.0 2.0 3.0 4.0 5.0]
[ 6.0 7.0 8.0 9.0 10.0 11.0][12.0 13.0 14.0 15.0 16.0 17.0][18.0 19.0 20.0 21.0 22.0 23.0][24.0 25.0 26.0 27.0 28.0 29.0]>>> P, L, U = A.LU()>>> P[0.0 1.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0 1.0]
[0.0 0.0 1.0 0.0 0.0]
[0.0 0.0 0.0 1.0 0.0]
[1.0 0.0 0.0 0.0 0.0]>>> L.zero_at(Integer(0))# Use zero_at(0) to get rid of signed zeros[ 1.0 0.0 0.0 0.0 0.0]
[ 0.0 1.0 0.0 0.0 0.0]
[ 0.5 0.5 1.0 0.0 0.0]
[0.75 0.25 0.0 1.0 0.0]
[0.25 0.75 0.0 0.0 1.0]>>> U.zero_at(Integer(0))# Use zero_at(0) to get rid of signed zeros[24.0 25.0 26.0 27.0 28.0 29.0][ 0.0 1.0 2.0 3.0 4.0 5.0]
[ 0.0 0.0 0.0 0.0 0.0 0.0]
[ 0.0 0.0 0.0 0.0 0.0 0.0]
[ 0.0 0.0 0.0 0.0 0.0 0.0]>>> P.transpose()*A-L*U[0.0 0.0 0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0 0.0 0.0]>>> P*L*U[ 0.0 1.0 2.0 3.0 4.0 5.0]
[ 6.0 7.0 8.0 9.0 10.0 11.0][12.0 13.0 14.0 15.0 16.0 17.0][18.0 19.0 20.0 21.0 22.0 23.0][24.0 25.0 26.0 27.0 28.0 29.0]

Trivial cases return matrices of the right size and characteristics.
sage: A = matrix(RDF, 5, 0)
sage: P, L, U = A.LU()
sage: P.parent()
Full MatrixSpace of 5 by 5 dense matrices over Real Double Field
sage: L.parent()
Full MatrixSpace of 5 by 5 dense matrices over Real Double Field(continues on next page)

720

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: U.parent()
Full MatrixSpace of 5 by 0 dense matrices over Real Double Field
sage: A-P*L*U[]>>> from sage.all import *>>> A = matrix(RDF, Integer(5), Integer(0))>>> P, L, U = A.LU()>>> P.parent()
Full MatrixSpace of 5 by 5 dense matrices over Real Double Field>>> L.parent()
Full MatrixSpace of 5 by 5 dense matrices over Real Double Field>>> U.parent()
Full MatrixSpace of 5 by 0 dense matrices over Real Double Field>>> A-P*L*U[]

The results are immutable since they are cached.
sage: P, L, U = matrix(RDF, 2, 2, range(4)).LU()
sage: L[0,0] = 0
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).
sage: P[0,0] = 0
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).
sage: U[0,0] = 0
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).
>>> from sage.all import *>>> P, L, U = matrix(RDF, Integer(2), Integer(2), range(Integer(4))).LU()>>> L[Integer(0),Integer(0)] = Integer(0)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).
>>> P[Integer(0),Integer(0)] = Integer(0)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).
>>> U[Integer(0),Integer(0)] = Integer(0)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).

LU_valid()
Return True if the LU form of this matrix has already been computed.
721

Matrices and Spaces of Matrices, Release 10.4

EXAMPLES:
sage: A = random_matrix(RDF,3) ; A.LU_valid()
False
sage: P, L, U = A.LU()
sage: A.LU_valid()True>>> from sage.all import *>>> A = random_matrix(RDF,Integer(3)) ; A.LU_valid()
False>>> P, L, U = A.LU()>>> A.LU_valid()
True

QR()
Return a factorization into a unitary matrix and an upper-triangular matrix.
INPUT:
Any matrix over RDF or CDF.
OUTPUT:
Q, R – a pair of matrices such that if 𝐴 is the original matrix, then𝐴 = 𝑄𝑅,𝑄* 𝑄 = 𝐼

where 𝑅 is upper-triangular. 𝑄* is the conjugate-transpose in the complex case, and just the transpose in thereal case. So 𝑄 is a unitary matrix (or rather, orthogonal, in the real case), or equivalently 𝑄 has orthogonal
columns. For a matrix of full rank this factorization is unique up to adjustments via multiples of rows andcolumns by multiples with scalars having modulus 1. So in the full-rank case, 𝑅 is unique if the diagonal
entries are required to be positive real numbers.
The resulting decomposition is cached.
ALGORITHM:
Calls scipy.linalg.qr() from SciPy, which is in turn an interface to LAPACK routines.
EXAMPLES:Over the reals, the inverse of Q is its transpose, since including a conjugate has no effect. In the real case, we
say Q is orthogonal.
sage: A = matrix(RDF, [[-2, 0, -4, -1, -1],....:[-2, 1, -6, -3, -1],....:
[1, 1, 7, 4, 5],....:[3, 0, 8, 3, 3],....:[-1, 1, -6, -6, 5]])sage: Q, R = A.QR()>>> from sage.all import *>>> A = matrix(RDF, [[-Integer(2), Integer(0), -Integer(4), -Integer(1), ˓→Integer(1)],...
[-Integer(2), Integer(1), -Integer(6), -Integer(3), ˓→Integer(1)],...
[Integer(1), Integer(1), Integer(7), Integer(4),␣
˓→Integer(5)],...
[Integer(3), Integer(0), Integer(8), Integer(3),␣
(continues on next page)722

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Integer(3)],...
˓→Integer(5)]])>>> Q, R = A.QR()
˓→[-Integer(1), Integer(1), -Integer(6), -Integer(6),␣

At this point, Q is only well-defined up to the signs of its columns, and similarly for R and its rows, so wenormalize them:sage: Qnorm = Q._normalize_columns()
sage: Rnorm = R._normalize_rows()
sage: Qnorm.round(6).zero_at(10^-6)[ 0.458831 0.126051 0.381212 0.394574
0.68744][ 0.458831 -0.47269 -0.051983 -0.717294 0.220963][-0.229416 -0.661766 0.661923 0.180872 -0.196411][-0.688247 -0.189076 -0.204468 -0.09663 0.662889][ 0.229416 -0.535715 -0.609939 0.536422 -0.024551]
sage: Rnorm.round(6).zero_at(10^-6)[ 4.358899 -0.458831 13.076697 6.194225 2.982405][
0.0 1.670172 0.598741 -1.29202 6.207997][
0.0
0.0 5.444402 5.468661 -0.682716]
[
0.0
0.0
0.0 1.027626-3.6193]
[
0.0
0.0
0.0
0.0 0.024551]
sage: (Q*Q.transpose()) # tol 1e-14[0.9999999999999994
0.0
0.0
0.0 ␣
˓→
0.0]
[
0.0
1.0
0.0
0.0 ␣
˓→
0.0]
[
0.0
0.0 0.9999999999999999
0.0 ␣
˓→
0.0]
[
0.0
0.0
0.0 0.9999999999999998 ␣
˓→
0.0]
[
0.0
0.0
0.0
0.0␣
˓→1.0000000000000002]
sage: (Q*R - A).zero_at(10^-14)[0.0 0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0 0.0]>>> from sage.all import *>>> Qnorm = Q._normalize_columns()>>> Rnorm = R._normalize_rows()>>> Qnorm.round(Integer(6)).zero_at(Integer(10)**-Integer(6))[ 0.458831 0.126051 0.381212 0.394574
0.68744][ 0.458831 -0.47269 -0.051983 -0.717294 0.220963][-0.229416 -0.661766 0.661923 0.180872 -0.196411][-0.688247 -0.189076 -0.204468 -0.09663 0.662889][ 0.229416 -0.535715 -0.609939 0.536422 -0.024551]>>> Rnorm.round(Integer(6)).zero_at(Integer(10)**-Integer(6))[ 4.358899 -0.458831 13.076697 6.194225 2.982405][
0.0 1.670172 0.598741 -1.29202 6.207997][
0.0
0.0 5.444402 5.468661 -0.682716]
[
0.0
0.0
0.0 1.027626-3.6193]
[
0.0
0.0
0.0
0.0 0.024551]>>> (Q*Q.transpose()) # tol 1e-14(continues on next page)723

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0.9999999999999994
0.0
0.0
0.0 ␣
˓→
0.0]
[
0.0
1.0
0.0
0.0 ␣
˓→
0.0]
[
0.0
0.0 0.9999999999999999
0.0 ␣
˓→
0.0]
[
0.0
0.0
0.0 0.9999999999999998 ␣
˓→
0.0]
[
0.0
0.0
0.0
0.0␣
˓→1.0000000000000002]>>> (Q*R - A).zero_at(Integer(10)**-Integer(14))[0.0 0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0 0.0]

Now over the complex numbers, demonstrating that the SciPy libraries are (properly) using the Hermitian
inner product, so that Q is a unitary matrix (its inverse is the conjugate-transpose).
sage: A = matrix(CDF, [[-8, 4*I + 1, -I + 2, 2*I + 1],....:[1, -2*I - 1, -I + 3, -I + 1],....:[I + 7, 2*I + 1, -2*I + 7, -I + 1],....:[I + 2, 0, I + 12, -1]])
sage: Q, R = A.QR()
sage: Q._normalize_columns() # tol 1e-6[
0.7302967433402214
0.20705664550556482 + 0.
˓→5383472783144685*I
0.24630498099986423 - 0.07644563587232917*I
0.
˓→23816176831943323 - 0.10365960327796941*I][-0.09128709291752768 -0.20705664550556482 - 0.
˓→37787837804765584*I
0.37865595338630315 - 0.19522214955246678*I
0.
˓→7012444502144682 - 0.36437116509865947*I][ -0.6390096504226938 - 0.09128709291752768*I
0.17082173254209104 + 0.
˓→6677576817554466*I -0.03411475806452064 + 0.040901987417671426*I0.
˓→31401710855067644 - 0.08251917187054114*I][ -0.18257418583505536 - 0.09128709291752768*I -0.03623491296347384 + 0.
˓→07246982592694771*I
0.8632284069415112 + 0.06322839976356195*I -0.
˓→44996948676115206 - 0.01161191812089182*I]
sage: R._normalize_rows().zero_at(1e-15) # tol 1e-6[
10.954451150103322-1.
˓→9170289512680814*I
5.385938482134133 - 2.1908902300206643*I -0.
˓→2738612787525829 - 2.1908902300206643*I][
0.0
4.
˓→8295962564173-0.8696379111233719 - 5.864879483945123*I 0.993871898426711␣
˓→- 0.30540855212070794*I]
[
0.0
␣
˓→
0.0
12.00160760935814 -0.2709533402297273 + 0.
˓→4420629644486325*I]
[
0.0
␣
˓→
0.0
0.0
␣
˓→1.9429639442589917]
sage: (Q.conjugate().transpose()*Q).zero_at(1e-15) # tol 1e-15
[
1.0
0.0
0.0
0.0]
[
0.0 0.9999999999999994
0.0
0.0]
[
0.0
0.0 1.0000000000000002
0.0]
[
0.0
0.0
0.0 1.0000000000000004]
sage: (Q*R - A).zero_at(10^-14)(continues on next page)724

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]>>> from sage.all import *>>> A = matrix(CDF, [[-Integer(8), Integer(4)*I + Integer(1), -I + Integer(2),˓→ Integer(2)*I + Integer(1)],...
[Integer(1), -Integer(2)*I - Integer(1), -I + Integer(3),˓→ -I + Integer(1)],...
[I + Integer(7), Integer(2)*I + Integer(1), ˓→Integer(2)*I + Integer(7), -I + Integer(1)],...
[I + Integer(2), Integer(0), I + Integer(12), ˓→Integer(1)]])>>> Q, R = A.QR()>>> Q._normalize_columns() # tol 1e-6[
0.7302967433402214
0.20705664550556482 + 0.
˓→5383472783144685*I
0.24630498099986423 - 0.07644563587232917*I
0.
˓→23816176831943323 - 0.10365960327796941*I][-0.09128709291752768 -0.20705664550556482 - 0.
˓→37787837804765584*I
0.37865595338630315 - 0.19522214955246678*I
0.
˓→7012444502144682 - 0.36437116509865947*I][ -0.6390096504226938 - 0.09128709291752768*I
0.17082173254209104 + 0.
˓→6677576817554466*I -0.03411475806452064 + 0.040901987417671426*I0.
˓→31401710855067644 - 0.08251917187054114*I][ -0.18257418583505536 - 0.09128709291752768*I -0.03623491296347384 + 0.
˓→07246982592694771*I
0.8632284069415112 + 0.06322839976356195*I -0.
˓→44996948676115206 - 0.01161191812089182*I]>>> R._normalize_rows().zero_at(RealNumber( 1e-15 )) # tol 1e-6[
10.954451150103322-1.
˓→9170289512680814*I
5.385938482134133 - 2.1908902300206643*I -0.
˓→2738612787525829 - 2.1908902300206643*I][
0.0
4.
˓→8295962564173-0.8696379111233719 - 5.864879483945123*I 0.993871898426711␣
˓→- 0.30540855212070794*I]
[
0.0
␣
˓→
0.0
12.00160760935814 -0.2709533402297273 + 0.
˓→4420629644486325*I]
[
0.0
␣
˓→
0.0
0.0
␣
˓→1.9429639442589917]>>> (Q.conjugate().transpose()*Q).zero_at(RealNumber( 1e-15 )) # tol 1e-15
[
1.0
0.0
0.0
0.0]
[
0.0 0.9999999999999994
0.0
0.0]
[
0.0
0.0 1.0000000000000002
0.0]
[
0.0
0.0
0.0 1.0000000000000004]>>> (Q*R - A).zero_at(Integer(10)**-Integer(14))[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]

An example of a rectangular matrix that is also rank-deficient. If you run this example yourself, you may see
a very small, nonzero entries in the third row, in the third column, even though the exact version of the matrix
has rank 2. The final two columns of Q span the left kernel of A (as evidenced by the two zero rows of R).
Different platforms will compute different bases for this left kernel, so we do not exhibit the actual matrix.

725

Matrices and Spaces of Matrices, Release 10.4

sage: Arat = matrix(QQ, [[2, -3, 3],....:[-1, 1, -1],....:[-1, 3, -3],....:[-5, 1, -1]])
sage: Arat.rank()
2sage: A = Arat.change_ring(CDF)
sage: Q, R = A.QR()
sage: R._normalize_rows() # abs tol 1e-14[
5.567764362830022-2.6940795304016243
2.6940795304016243][
0.0
3.5695847775155825-3.5695847775155825][
0.0
0.0 2.4444034681064287e-16]
[
0.0
0.0
0.0]
sage: (Q.conjugate_transpose()*Q) # abs tol 1e-14[
1.0000000000000002 -5.185196889911925e-17 -4.1457180570414476e-17 -2.
˓→909388767229071e-17][ -5.185196889911925e-17
1.0000000000000002 -9.286869233696149e-17 -1.
˓→1035822863186828e-16][-4.1457180570414476e-17 -9.286869233696149e-17
1.0 4.
˓→4159215672155694e-17][ -2.909388767229071e-17 -1.1035822863186828e-16 4.4159215672155694e-17
␣
˓→
1.0]
>>> from sage.all import *>>> Arat = matrix(QQ, [[Integer(2), -Integer(3), Integer(3)],...
[-Integer(1), Integer(1), -Integer(1)],...
[-Integer(1), Integer(3), -Integer(3)],...
[-Integer(5), Integer(1), -Integer(1)]])>>> Arat.rank()
2>>> A = Arat.change_ring(CDF)>>> Q, R = A.QR()>>> R._normalize_rows() # abs tol 1e-14[
5.567764362830022-2.6940795304016243
2.6940795304016243][
0.0
3.5695847775155825-3.5695847775155825][
0.0
0.0 2.4444034681064287e-16]
[
0.0
0.0
0.0]
>>> (Q.conjugate_transpose()*Q) # abs tol 1e-14[
1.0000000000000002 -5.185196889911925e-17 -4.1457180570414476e-17 -2.
˓→909388767229071e-17][ -5.185196889911925e-17
1.0000000000000002 -9.286869233696149e-17 -1.
˓→1035822863186828e-16][-4.1457180570414476e-17 -9.286869233696149e-17
1.0 4.
˓→4159215672155694e-17][ -2.909388767229071e-17 -1.1035822863186828e-16 4.4159215672155694e-17
␣
˓→
1.0]

Results are cached, meaning they are immutable matrices. Make a copy if you need to manipulate a result.
sage: A = random_matrix(CDF, 2, 2)
sage: Q, R = A.QR()
sage: Q.is_mutable()False
sage: R.is_mutable()False
sage: Q[0,0] = 0
Traceback (most recent call last):(continues on next page)

726

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
ValueError: matrix is immutable; please change a copy instead (i.e., use␣˓→copy(M) to change a copy of M).
sage: Qcopy = copy(Q)sage: Qcopy[0,0] = 679
sage: Qcopy[0,0]679.0>>> from sage.all import *>>> A = random_matrix(CDF, Integer(2), Integer(2))>>> Q, R = A.QR()>>> Q.is_mutable()
False>>> R.is_mutable()
False>>> Q[Integer(0),Integer(0)] = Integer(0)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).
>>> Qcopy = copy(Q)>>> Qcopy[Integer(0),Integer(0)] = Integer(679)>>> Qcopy[Integer(0),Integer(0)]
679.0

SVD()
Return the singular value decomposition of this matrix.
The U and V matrices are not unique and may be returned with different values in the future or on different
systems. The S matrix is unique and contains the singular values in descending order.
The computed decomposition is cached and returned on subsequent calls.
INPUT:• A – a matrix
OUTPUT:• U, S, V – immutable matrices such that 𝐴 = 𝑈 *𝑆*𝑉.𝑐𝑜𝑛𝑗().𝑡𝑟𝑎𝑛𝑠𝑝𝑜𝑠𝑒() where U and V are orthogonal
and S is zero off of the diagonal.
Note that if self is m-by-n, then the dimensions of the matrices that this returns are (m,m), (m,n), and (n, n).
Note: If all you need is the singular values of the matrix, see the more convenient singular_values().
EXAMPLES:
sage: m = matrix(RDF,4,range(1,17))
sage: U,S,V = m.SVD()
sage: U*S*V.transpose() # tol 1e-14[0.9999999999999993 1.9999999999999987 3.000000000000001[ 4.999999999999998 5.999999999999998 6.999999999999998[ 8.999999999999998 9.999999999999996 10.999999999999998[12.999999999999998
14.0
15.0

4.000000000000002]
8.0]
12.0]
16.0]

727

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> m = matrix(RDF,Integer(4),range(Integer(1),Integer(17)))>>> U,S,V = m.SVD()>>> U*S*V.transpose() # tol 1e-14[0.9999999999999993 1.9999999999999987 3.000000000000001 4.000000000000002][ 4.999999999999998 5.999999999999998 6.999999999999998
8.0][ 8.999999999999998 9.999999999999996 10.999999999999998
12.0][12.999999999999998
14.0
15.0
16.0]

A non-square example:
sage: m = matrix(RDF, 2, range(1,7)); m[1.0 2.0 3.0]
[4.0 5.0 6.0]
sage: U, S, V = m.SVD()
sage: U*S*V.transpose() # tol 1e-14[0.9999999999999994 1.9999999999999998 2.999999999999999][ 4.000000000000001 5.000000000000002 6.000000000000001]>>> from sage.all import *>>> m = matrix(RDF, Integer(2), range(Integer(1),Integer(7))); m[1.0 2.0 3.0]
[4.0 5.0 6.0]>>> U, S, V = m.SVD()>>> U*S*V.transpose() # tol 1e-14[0.9999999999999994 1.9999999999999998 2.999999999999999][ 4.000000000000001 5.000000000000002 6.000000000000001]

S contains the singular values:
sage: S.round(4)[ 9.508
0.0
0.0][
0.0 0.7729
0.0]
sage: [N(sqrt(abs(x)), digits=4) for x in (S*S.transpose()).eigenvalues()][9.508, 0.7729]>>> from sage.all import *>>> S.round(Integer(4))[ 9.508
0.0
0.0][
0.0 0.7729
0.0]>>> [N(sqrt(abs(x)), digits=Integer(4)) for x in (S*S.transpose()).
˓→eigenvalues()][9.508, 0.7729]

U and V are orthogonal matrices:sage: U # random, SVD is not unique[-0.386317703119 -0.922365780077][-0.922365780077 0.386317703119][-0.274721127897 -0.961523947641][-0.961523947641 0.274721127897]
sage: (U*U.transpose()) # tol 1e-15
[
1.0
0.0]
[
0.0 1.0000000000000004]
sage: V # random, SVD is not unique[-0.428667133549 0.805963908589 0.408248290464][-0.566306918848 0.112382414097 -0.816496580928](continues on next page)

728

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[-0.703946704147 -0.581199080396 0.408248290464]
sage: (V*V.transpose()) # tol 1e-15[0.9999999999999999
0.0
0.0]
[
0.0
1.0
0.0]
[
0.0
0.0 0.9999999999999999]>>> from sage.all import *>>> U # random, SVD is not unique[-0.386317703119 -0.922365780077][-0.922365780077 0.386317703119][-0.274721127897 -0.961523947641][-0.961523947641 0.274721127897]>>> (U*U.transpose()) # tol 1e-15
[
1.0
0.0]
[
0.0 1.0000000000000004]>>> V # random, SVD is not unique[-0.428667133549 0.805963908589 0.408248290464][-0.566306918848 0.112382414097 -0.816496580928][-0.703946704147 -0.581199080396 0.408248290464]>>> (V*V.transpose()) # tol 1e-15[0.9999999999999999
0.0
0.0]
[
0.0
1.0
0.0]
[
0.0
0.0 0.9999999999999999]

cholesky()
Return the Cholesky factorization of a matrix that is real symmetric, or complex Hermitian.
INPUT:
Any square matrix with entries from RDF that is symmetric, or with entries from CDF that is Hermitian. The
matrix must be positive definite for the Cholesky decomposition to exist.
OUTPUT:For a matrix 𝐴 the routine returns a lower triangular matrix 𝐿 such that,
𝐴 = 𝐿𝐿*
where 𝐿* is the conjugate-transpose in the complex case, and just the transpose in the real case. If the matrix
fails to be positive definite (perhaps because it is not symmetric or Hermitian), then this function raises a
ValueError.
IMPLEMENTATION:
The existence of a Cholesky decomposition and the positive definite property are equivalent. So this method
and the is_positive_definite() method compute and cache both the Cholesky decomposition andthe positive-definiteness. So the is_positive_definite() method or catching a ValueError fromthe cholesky() method are equally expensive computationally and if the decomposition exists, it is cached
as a side-effect of either routine.
EXAMPLES:
A real matrix that is symmetric, Hermitian, and positive definite:sage: M = matrix(RDF,[[ 1, 1,
1,....:[ 1, 5,31,....:[ 1, 31, 341,....:
[ 1,121, 1555,

1,
1],
121,
341],
1555, 4681],
7381, 22621],(continues on next page)729

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)....:[ 1,341, 4681, 22621, 69905]])
sage: M.is_symmetric()True
sage: M.is_hermitian()True
sage: L = M.cholesky()
sage: L.round(6).zero_at(10^-10)
[
1.0
0.0
0.0
0.0
0.0]
[
1.0
2.0
0.0
0.0
0.0]
[
1.0
15.0
10.723805
0.0
0.0]
[
1.0
60.0
60.985814
7.792973
0.0][
1.0 170.0 198.623524 39.366567 1.7231]
sage: (L*L.transpose()).round(6).zero_at(10^-10)
[ 1.0
1.0
1.0
1.0
1.0]
[ 1.0
5.0
31.0
121.0
341.0][ 1.0
31.0
341.0 1555.0 4681.0][ 1.0
121.0 1555.0 7381.0 22621.0][ 1.0
341.0 4681.0 22621.0 69905.0]>>> from sage.all import *>>> M = matrix(RDF,[[ Integer(1), Integer(1),Integer(1),Integer(1),␣
˓→
Integer(1)],...
[ Integer(1), Integer(5),Integer(31),Integer(121),␣
˓→
Integer(341)],...
[ Integer(1), Integer(31), Integer(341), Integer(1555),␣
˓→ Integer(4681)],...
[ Integer(1),Integer(121), Integer(1555), Integer(7381),␣
˓→Integer(22621)],...
[ Integer(1),Integer(341), Integer(4681), Integer(22621),␣
˓→Integer(69905)]])>>> M.is_symmetric()
True>>> M.is_hermitian()
True>>> L = M.cholesky()>>> L.round(Integer(6)).zero_at(Integer(10)**-Integer(10))
[
1.0
0.0
0.0
0.0
0.0]
[
1.0
2.0
0.0
0.0
0.0]
[
1.0
15.0
10.723805
0.0
0.0]
[
1.0
60.0
60.985814
7.792973
0.0][
1.0 170.0 198.623524 39.366567 1.7231]>>> (L*L.transpose()).round(Integer(6)).zero_at(Integer(10)**-Integer(10))
[ 1.0
1.0
1.0
1.0
1.0]
[ 1.0
5.0
31.0
121.0
341.0][ 1.0
31.0
341.0 1555.0 4681.0][ 1.0
121.0 1555.0 7381.0 22621.0][ 1.0
341.0 4681.0 22621.0 69905.0]

A complex matrix that is Hermitian and positive definite.
sage: # needs sage.symbolic
sage: A = matrix(CDF, [[23, 17*I + 3, 24*I + 25,
21*I],....:[ -17*I + 3,
38, -69*I + 89, 7*I + 15],....:[-24*I + 25, 69*I + 89,
976, 24*I + 6],....:[-21*I, -7*I + 15, -24*I + 6,28]])
sage: A.is_hermitian()(continues on next page)730

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)True
sage: L = A.cholesky()
sage: L.round(6).zero_at(10^-10)[
4.795832
0.0
0.0
˓→0.0][ 0.625543 - 3.544745*I
5.004346
0.0
˓→0.0][
5.21286 - 5.004346*I 13.588189 + 10.721116*I
24.984023
˓→0.0][-4.378803*I -0.104257 - 0.851434*I -0.21486 + 0.371348*I
˓→811799]
sage: (L*L.conjugate_transpose()).round(6).zero_at(10^-10)[
23.0 3.0 + 17.0*I 25.0 + 24.0*I
21.0*I][ 3.0 - 17.0*I
38.0 89.0 - 69.0*I 15.0 + 7.0*I][25.0 - 24.0*I 89.0 + 69.0*I
976.0 6.0 + 24.0*I][-21.0*I 15.0 - 7.0*I 6.0 - 24.0*I
28.0]

␣
␣
␣
2.

>>> from sage.all import *>>> # needs sage.symbolic>>> A = matrix(CDF, [[Integer(23), Integer(17)*I + Integer(3), ␣
˓→Integer(24)*I + Integer(25),Integer(21)*I],...
[ -Integer(17)*I + Integer(3),Integer(38), ˓→Integer(69)*I + Integer(89), Integer(7)*I + Integer(15)],...
[-Integer(24)*I + Integer(25), Integer(69)*I +␣˓→Integer(89),Integer(976), Integer(24)*I + Integer(6)],...
[-Integer(21)*I, -Integer(7)*I + Integer(15), ˓→Integer(24)*I + Integer(6),Integer(28)]])>>> A.is_hermitian()
True>>> L = A.cholesky()>>> L.round(Integer(6)).zero_at(Integer(10)**-Integer(10))[
4.795832
0.0
0.0
˓→0.0][ 0.625543 - 3.544745*I
5.004346
0.0
˓→0.0][
5.21286 - 5.004346*I 13.588189 + 10.721116*I
24.984023
˓→0.0][-4.378803*I -0.104257 - 0.851434*I -0.21486 + 0.371348*I 2.
˓→811799]>>> (L*L.conjugate_transpose()).round(Integer(6)).zero_at(Integer(10)**˓→Integer(10))[
23.0 3.0 + 17.0*I 25.0 + 24.0*I
21.0*I][ 3.0 - 17.0*I
38.0 89.0 - 69.0*I 15.0 + 7.0*I][25.0 - 24.0*I 89.0 + 69.0*I
976.0 6.0 + 24.0*I][-21.0*I 15.0 - 7.0*I 6.0 - 24.0*I
28.0]

␣
␣
␣

This routine will recognize when the input matrix is not positive definite. The negative eigenvalues are an
equivalent indicator. (Eigenvalues of a Hermitian matrix must be real, so there is no loss in ignoring theimprecise imaginary parts).
sage: A = matrix(RDF, [[ 3, -6,
9,
6, -9],....:[-6, 11, -16, -11, 17],....:
[ 9, -16, 28, 16, -40],....:[ 6, -11, 16,
9, -19],....:[-9, 17, -40, -19, 68]])
sage: A.is_symmetric()(continues on next page)731

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)True
sage: A.eigenvalues()[108.07..., 13.02..., -0.02..., -0.70..., -1.37...]sage: A.cholesky()Traceback (most recent call last):...
ValueError: matrix is not positive definite
sage: # needs sage.symbolic
sage: B = matrix(CDF, [[2, 4 - 2*I, 2 + 2*I],....:[4 + 2*I,
8,
10*I],....:[2 - 2*I,-10*I,-3]])sage: B.is_hermitian()True
sage: [ev.real() for ev in B.eigenvalues()][15.88..., 0.08..., -8.97...]sage: B.cholesky()Traceback (most recent call last):...
ValueError: matrix is not positive definite>>> from sage.all import *>>> A = matrix(RDF, [[ Integer(3), -Integer(6),Integer(9),Integer(6), ␣˓→-Integer(9)],...
[-Integer(6), Integer(11), -Integer(16), -Integer(11), ␣
˓→Integer(17)],...
[ Integer(9), -Integer(16), Integer(28), Integer(16), ˓→Integer(40)],...
[ Integer(6), -Integer(11), Integer(16),Integer(9), ˓→Integer(19)],...
[-Integer(9), Integer(17), -Integer(40), -Integer(19), ␣
˓→Integer(68)]])>>> A.is_symmetric()
True>>> A.eigenvalues()[108.07..., 13.02..., -0.02..., -0.70..., -1.37...]>>> A.cholesky()Traceback (most recent call last):...
ValueError: matrix is not positive definite>>> # needs sage.symbolic>>> B = matrix(CDF, [[Integer(2), Integer(4) - Integer(2)*I, Integer(2)␣
˓→+ Integer(2)*I],...
[Integer(4) + Integer(2)*I,
Integer(8),␣˓→Integer(10)*I],...
[Integer(2) - Integer(2)*I,-Integer(10)*I,
˓→Integer(3)]])>>> B.is_hermitian()True>>> [ev.real() for ev in B.eigenvalues()][15.88..., 0.08..., -8.97...]>>> B.cholesky()Traceback (most recent call last):...
ValueError: matrix is not positive definite

condition(p='frob')
732

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

Return the condition number of a square nonsingular matrix.
Roughly speaking, this is a measure of how sensitive the matrix is to round-off errors in numerical computations. The minimum possible value is 1.0, and larger numbers indicate greater sensitivity.
INPUT:• p – (default: ‘frob’); controls which norm is used to compute the condition number, allowable values are‘frob’ (for the Frobenius norm), integers -2, -1, 1, 2, positive and negative infinity. See output discussion
for specifics.
OUTPUT:The condition number of a matrix is the product of a norm of the matrix times the norm of the inverse of thematrix. This requires that the matrix be square and invertible (nonsingular, full rank).
Returned value is a double precision floating point value in RDF, or Infinity. Row and column sums
described below √are sums of the absolute values of the entries, where the absolute value of the complex
number 𝑎 + 𝑏𝑖 is 𝑎2 + 𝑏2 . Singular values are the “diagonal” entries of the “S” matrix in the singular value
decomposition.
• p = frob : the default norm employed in computing the condition number, the Frobenius norm,
which for a matrix 𝐴 = (𝑎𝑖𝑗 ) computes
⎛
⎞1/2
∑︁
2
⎝
|𝑎𝑖,𝑗 | ⎠
𝑖,𝑗

• p =

sv : the quotient of the maximal and minimal singular value.

• p = Infinity or p = oo: the maximum row sum.
• p = -Infinity or p = -oo: the minimum column sum.
• p = 1: the maximum column sum.
• p = -1: the minimum column sum.
• p = 2: the 2-norm, equal to the maximum singular value.
• p = -2: the minimum singular value.
ALGORITHM:
Computation is performed by the cond() function of the SciPy/NumPy library.
EXAMPLES:First over the reals.
sage: A = matrix(RDF, 4, [(1/4)*x^3 for x in range(16)]); A
[
0.0
0.25
2.0
6.75]
[ 16.0 31.25
54.0 85.75][ 128.0 182.25 250.0 332.75][ 432.0 549.25 686.0 843.75]
sage: A.condition()
9923.88955...
sage: A.condition(p= frob )9923.88955...
sage: A.condition(p=Infinity) # tol 3e-14
22738.50000000045
sage: A.condition(p=-Infinity) # tol 2e-14(continues on next page)733

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)17.50000000000028
sage: A.condition(p=1)
12139.21...
sage: A.condition(p=-1)
550.0000000000093
sage: A.condition(p=2)
9897.8088...
sage: A.condition(p=-2)0.000101032462...

# tol 2e-14>>> from sage.all import *>>> A = matrix(RDF, Integer(4), [(Integer(1)/Integer(4))*x**Integer(3) for x␣˓→in range(Integer(16))]); A
[
0.0
0.25
2.0
6.75]
[ 16.0 31.25
54.0 85.75][ 128.0 182.25 250.0 332.75][ 432.0 549.25 686.0 843.75]>>> A.condition()
9923.88955...
>>> A.condition(p= frob )9923.88955...
>>> A.condition(p=Infinity) # tol 3e-14
22738.50000000045>>> A.condition(p=-Infinity) # tol 2e-14
17.50000000000028>>> A.condition(p=Integer(1))
12139.21...
>>> A.condition(p=-Integer(1)) # tol 2e-14
550.0000000000093>>> A.condition(p=Integer(2))
9897.8088...
>>> A.condition(p=-Integer(2))
0.000101032462...

And over the complex numbers.
sage: B = matrix(CDF, 3, [x + x^2*I for x in range(9)]); B[
0.0 1.0 + 1.0*I 2.0 + 4.0*I][ 3.0 + 9.0*I 4.0 + 16.0*I 5.0 + 25.0*I][6.0 + 36.0*I 7.0 + 49.0*I 8.0 + 64.0*I]
sage: B.condition()
203.851798...
sage: B.condition(p= frob )203.851798...
sage: B.condition(p=Infinity)
369.55630...
sage: B.condition(p=-Infinity)
5.46112969...
sage: B.condition(p=1)
289.251481...
sage: B.condition(p=-1)
20.4566639...
sage: B.condition(p=2)
202.653543...
sage: B.condition(p=-2)
0.00493453005...

734

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> B = matrix(CDF, Integer(3), [x + x**Integer(2)*I for x in␣˓→range(Integer(9))]); B[
0.0 1.0 + 1.0*I 2.0 + 4.0*I][ 3.0 + 9.0*I 4.0 + 16.0*I 5.0 + 25.0*I][6.0 + 36.0*I 7.0 + 49.0*I 8.0 + 64.0*I]>>> B.condition()
203.851798...
>>> B.condition(p= frob )203.851798...
>>> B.condition(p=Infinity)
369.55630...
>>> B.condition(p=-Infinity)
5.46112969...
>>> B.condition(p=Integer(1))
289.251481...
>>> B.condition(p=-Integer(1))
20.4566639...
>>> B.condition(p=Integer(2))
202.653543...
>>> B.condition(p=-Integer(2))
0.00493453005...

Hilbert matrices are famously ill-conditioned, while an identity matrix can hit the minimum with the rightnorm.
sage: A = matrix(RDF, 10, [1/(i+j+1) for i in range(10) for j in range(10)])sage: A.condition() # tol 2e-4
16332197709146.014
sage: id = identity_matrix(CDF, 10)
sage: id.condition(p=1)
1.0>>> from sage.all import *>>> A = matrix(RDF, Integer(10), [Integer(1)/(i+j+Integer(1)) for i in␣
˓→range(Integer(10)) for j in range(Integer(10))])>>> A.condition() # tol 2e-4
16332197709146.014>>> id = identity_matrix(CDF, Integer(10))>>> id.condition(p=Integer(1))
1.0Return values are in 𝑅𝐷𝐹 .
sage: A = matrix(CDF, 2, range(1,5))
sage: A.condition() in RDF
True>>> from sage.all import *>>> A = matrix(CDF, Integer(2), range(Integer(1),Integer(5)))>>> A.condition() in RDF
True

Rectangular and singular matrices raise errors if p is not ‘sv’.
sage: A = matrix(RDF, 2, 3, range(6))
sage: A.condition()(continues on next page)735

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Traceback (most recent call last):...
TypeError: matrix must be square if p is not

sv , not 2 x 3

sage: A.condition( sv )7.34...
sage: A = matrix(QQ, 5, range(25))
sage: A.is_singular()True
sage: B = A.change_ring(CDF)
sage: B.condition()+Infinity>>> from sage.all import *>>> A = matrix(RDF, Integer(2), Integer(3), range(Integer(6)))>>> A.condition()
Traceback (most recent call last):...
TypeError: matrix must be square if p is not sv , not 2 x 3>>> A.condition( sv )7.34...
>>> A = matrix(QQ, Integer(5), range(Integer(25)))>>> A.is_singular()
True>>> B = A.change_ring(CDF)>>> B.condition()+Infinity

Improper values of p are caught.
sage: A = matrix(CDF, 2, range(1,5))
sage: A.condition(p= bogus )Traceback (most recent call last):...
ValueError: condition number p must be +/- infinity, frob , sv or an␣˓→integer, not bogus
sage: A.condition(p=632)
Traceback (most recent call last):...
ValueError: condition number integer values of p must be -2, -1, 1 or 2,␣˓→not 632>>> from sage.all import *>>> A = matrix(CDF, Integer(2), range(Integer(1),Integer(5)))>>> A.condition(p= bogus )Traceback (most recent call last):...
ValueError: condition number p must be +/- infinity, frob , sv or an␣˓→integer, not bogus>>> A.condition(p=Integer(632))
Traceback (most recent call last):...
ValueError: condition number integer values of p must be -2, -1, 1 or 2,␣
(continues on next page)

736

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

not 632˓→

conjugate()
Return the conjugate of this matrix, i.e. the matrix whose entries are the conjugates of the entries of self.
EXAMPLES:
sage: # needs sage.symbolic
sage: A = matrix(CDF, [[1+I, 3-I], [0, 2*I]])sage: A.conjugate()[1.0 - 1.0*I 3.0 + 1.0*I][
0.0-2.0*I]>>> from sage.all import *>>> # needs sage.symbolic>>> A = matrix(CDF, [[Integer(1)+I, Integer(3)-I], [Integer(0),␣
˓→Integer(2)*I]])>>> A.conjugate()[1.0 - 1.0*I 3.0 + 1.0*I][
0.0-2.0*I]

There is a shorthand notation:
sage: A.conjugate() == A.C
˓→needs sage.symbolicTrue>>> from sage.all import *>>> A.conjugate() == A.C
˓→needs sage.symbolic
True

#␣

#␣

Conjugates work (trivially) for real matrices:sage: B = matrix.random(RDF, 3)
sage: B == B.conjugate()
True>>> from sage.all import *>>> B = matrix.random(RDF, Integer(3))>>> B == B.conjugate()
True

determinant()
Return the determinant of self.
ALGORITHM:
Uses scipy.linalg.det().
EXAMPLES:
sage: m = matrix(RDF,2,range(4)); m.det()-2.0
sage: m = matrix(RDF,0,[]); m.det()
1.0(continues on next page)737

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: m = matrix(RDF, 2, range(6)); m.det()Traceback (most recent call last):...
ValueError: self must be a square matrix>>> from sage.all import *>>> m = matrix(RDF,Integer(2),range(Integer(4))); m.det()-2.0>>> m = matrix(RDF,Integer(0),[]); m.det()
1.0>>> m = matrix(RDF, Integer(2), range(Integer(6))); m.det()Traceback (most recent call last):...
ValueError: self must be a square matrix

eigenvalues(other=None, algorithm='default', tol=None, homogeneous=False)
Return a list of ordinary or generalized eigenvalues.
INPUT:• self – a square matrix• other – a square matrix 𝐵 (default: None) in a generalized eigenvalue problem; if None, an ordinary
eigenvalue problem is solved; if algorithm is symmetric or hermitian , 𝐵 must be real
symmetric or hermitian positive definite, respectively• algorithm – default: default•–

default – applicable to any matrix with double-precision floating point entries. Uses theeigvals() function from SciPy.

–symmetric – converts the matrix into a real matrix (i.e. with entries from RDF), then applies the algorithm for Hermitian matrices. This algorithm can be significantly faster than thedefault algorithm.

–

hermitian – uses the eigh() function from SciPy, which applies only to real symmetric or complex Hermitian matrices. Since Hermitian is defined as a matrix equaling its
conjugate-transpose, for a matrix with real entries this property is equivalent to being symmetric.
This algorithm can be significantly faster than the default algorithm.

tol – (default: None); if set to a value other than None, this is interpreted as a small real number
used to aid in grouping eigenvalues that are numerically similar, but is ignored when homogeneous isset. See the output description for more information.

• homogeneous – boolean (default: False); if True, use homogeneous coordinates for the output(see eigenvectors_right() for details)
Warning: When using the symmetric or hermitian algorithms, no check is made on the
input matrix, and only the entries below, and on, the main diagonal are employed in the computation.
Methods such as is_symmetric() and is_hermitian() could be used to verify this beforehand.
OUTPUT:
Default output for a square matrix of size 𝑛 is a list of 𝑛 eigenvalues from the complex double field, CDF.
If the symmetric or hermitian algorithms are chosen, the returned eigenvalues are from the real
double field, RDF.

738

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

If a tolerance is specified, an attempt is made to group eigenvalues that are numerically similar. The returnis then a list of pairs, where each pair is an eigenvalue followed by its multiplicity. The eigenvalue reported
is the mean of the eigenvalues computed, and these eigenvalues are contained in an interval (or disk) whose
radius is less than 5*tol for 𝑛 < 10, 000 in the worst case.
More precisely, for an 𝑛 × 𝑛 matrix, the diameter of the interval containing similar eigenvalues could be aslarge as sum of the reciprocals of the first 𝑛 integers times tol.
Warning: Use caution when using the tol parameter to group eigenvalues. See the examples below to
see how this can go wrong.
EXAMPLES:
sage: m = matrix(RDF, 2, 2, [1,2,3,4])
sage: ev = m.eigenvalues(); ev[-0.372281323..., 5.37228132...]sage: ev[0].parent()
Complex Double Field
sage: m = matrix(RDF, 2, 2, [0,1,-1,0])
sage: m.eigenvalues(algorithm= default )[1.0*I, -1.0*I]
sage: m = matrix(CDF, 2, 2, [I,1,-I,0])
˓→needs sage.symbolic
sage: m.eigenvalues()
˓→needs sage.symbolic[-0.624810533... + 1.30024259...*I, 0.624810533... - 0.30024259...*I]#␣#␣>>> from sage.all import *>>> m = matrix(RDF, Integer(2), Integer(2), [Integer(1),Integer(2),Integer(3),˓→Integer(4)])>>> ev = m.eigenvalues(); ev[-0.372281323..., 5.37228132...]>>> ev[Integer(0)].parent()
Complex Double Field>>> m = matrix(RDF, Integer(2), Integer(2), [Integer(0),Integer(1),˓→Integer(1),Integer(0)])>>> m.eigenvalues(algorithm= default )[1.0*I, -1.0*I]>>> m = matrix(CDF, Integer(2), Integer(2), [I,Integer(1),-I,Integer(0)])␣˓→# needs sage.symbolic>>> m.eigenvalues()#␣˓→needs sage.symbolic[-0.624810533... + 1.30024259...*I, 0.624810533... - 0.30024259...*I]

The adjacency matrix of a graph will be symmetric, and the eigenvalues will be real.
sage: # needs sage.graphs
sage: A = graphs.PetersenGraph().adjacency_matrix()
sage: A = A.change_ring(RDF)
sage: ev = A.eigenvalues(algorithm= symmetric ); ev # tol 1e-14[-2.0, -2.0, -2.0, -2.0, 1.0, 1.0, 1.0, 1.0, 1.0, 3.0]
(continues on next page)739

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: ev[0].parent()
Real Double Field>>> from sage.all import *>>> # needs sage.graphs>>> A = graphs.PetersenGraph().adjacency_matrix()>>> A = A.change_ring(RDF)>>> ev = A.eigenvalues(algorithm= symmetric ); ev # tol 1e-14[-2.0, -2.0, -2.0, -2.0, 1.0, 1.0, 1.0, 1.0, 1.0, 3.0]>>> ev[Integer(0)].parent()
Real Double Field

The matrix A is “random”, but the construction of C provides a positive-definite Hermitian matrix. Notethat the eigenvalues of a Hermitian matrix are real, and the eigenvalues of a positive-definite matrix will bepositive.
sage: # needs sage.symbolic
sage: A = matrix([[ 4*I + 5, 8*I + 1, 7*I + 5, 3*I + 5],....:[ 7*I - 2, -4*I + 7, -2*I + 4, 8*I + 8],....:[-2*I + 1, 6*I + 6, 5*I + 5, -I - 4],....:[ 5*I + 1, 6*I + 2,
I - 4, -I + 3]])sage: C = (A*A.conjugate_transpose()).change_ring(CDF)
sage: ev = C.eigenvalues(algorithm= hermitian ); ev[2.68144025..., 49.5167998..., 274.086188..., 390.71557...]sage: ev[0].parent()
Real Double Field>>> from sage.all import *>>> # needs sage.symbolic>>> A = matrix([[ Integer(4)*I + Integer(5), Integer(8)*I + Integer(1), ␣
˓→Integer(7)*I + Integer(5), Integer(3)*I + Integer(5)],...
[ Integer(7)*I - Integer(2), -Integer(4)*I + Integer(7), ˓→Integer(2)*I + Integer(4), Integer(8)*I + Integer(8)],...
[-Integer(2)*I + Integer(1), Integer(6)*I + Integer(6), ␣
˓→Integer(5)*I + Integer(5),-I - Integer(4)],...
[ Integer(5)*I + Integer(1), Integer(6)*I + Integer(2),˓→- Integer(4), -I + Integer(3)]])>>> C = (A*A.conjugate_transpose()).change_ring(CDF)>>> ev = C.eigenvalues(algorithm= hermitian ); ev[2.68144025..., 49.5167998..., 274.086188..., 390.71557...]>>> ev[Integer(0)].parent()
Real Double FieldI␣

A tolerance can be given to aid in grouping eigenvalues that are similar numerically. However, if the parameteris too small it might split too finely. Too large, and it can go wrong very badly. Use with care.
sage: # needs sage.graphs
sage: G = graphs.PetersenGraph()
sage: G.spectrum()[3, 1, 1, 1, 1, 1, -2, -2, -2, -2]
sage: A = G.adjacency_matrix().change_ring(RDF)
sage: A.eigenvalues(algorithm= symmetric , tol=1.0e-5) # tol 1e-15[(-2.0, 4), (1.0, 5), (3.0, 1)]
sage: A.eigenvalues(algorithm= symmetric , tol=2.5) # tol 1e-15[(-2.0, 4), (1.3333333333333333, 6)]740

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> # needs sage.graphs>>> G = graphs.PetersenGraph()>>> G.spectrum()[3, 1, 1, 1, 1, 1, -2, -2, -2, -2]>>> A = G.adjacency_matrix().change_ring(RDF)>>> A.eigenvalues(algorithm= symmetric , tol=RealNumber( 1.0e-5 )) # tol 1e˓→15[(-2.0, 4), (1.0, 5), (3.0, 1)]>>> A.eigenvalues(algorithm= symmetric , tol=RealNumber( 2.5 )) # tol 1e-15[(-2.0, 4), (1.3333333333333333, 6)]

An (extreme) example of properly grouping similar eigenvalues.
sage: # needs sage.graphs
sage: G = graphs.HigmanSimsGraph()
sage: A = G.adjacency_matrix().change_ring(RDF)
sage: A.eigenvalues(algorithm= symmetric , tol=1.0e-5)[(-8.0, 22), (2.0, 77), (22.0, 1)]# tol 2e-15>>> from sage.all import *>>> # needs sage.graphs>>> G = graphs.HigmanSimsGraph()>>> A = G.adjacency_matrix().change_ring(RDF)>>> A.eigenvalues(algorithm= symmetric , tol=RealNumber( 1.0e-5 ))˓→15[(-8.0, 22), (2.0, 77), (22.0, 1)]# tol 2e-In this generalized eigenvalue problem, the homogeneous coordinates explain the output obtained for the
eigenvalues:
sage: A = matrix.identity(RDF, 2)
sage: B = matrix(RDF, [[3, 5], [6, 10]])sage: A.eigenvalues(B) # tol 1e-14[0.0769230769230769, +infinity]
sage: E = A.eigenvalues(B, homogeneous=True); E # random[(0.9999999999999999, 13.000000000000002), (0.9999999999999999, 0.0)]
sage: [alpha/beta for alpha, beta in E] # tol 1e-14[0.0769230769230769, NaN + NaN*I]>>> from sage.all import *>>> A = matrix.identity(RDF, Integer(2))>>> B = matrix(RDF, [[Integer(3), Integer(5)], [Integer(6), Integer(10)]])>>> A.eigenvalues(B) # tol 1e-14[0.0769230769230769, +infinity]>>> E = A.eigenvalues(B, homogeneous=True); E # random[(0.9999999999999999, 13.000000000000002), (0.9999999999999999, 0.0)]>>> [alpha/beta for alpha, beta in E] # tol 1e-14[0.0769230769230769, NaN + NaN*I]

See also:
eigenvectors_left(),eigenvectors_right(),
Matrix.eigenmatrix_right().

Matrix.eigenmatrix_left(),eigenvectors_left(other=None, homogeneous=False)
Compute the ordinary or generalized left eigenvectors of a matrix of double precision real or complex numbers(i.e. RDF or CDF).
741

Matrices and Spaces of Matrices, Release 10.4

INPUT:• other – a square matrix 𝐵 (default: None) in a generalized eigenvalue problem; if None, an ordinary
eigenvalue problem is solved• homogeneous – boolean (default: False); if True, use homogeneous coordinates for the eigenvalues in the output
OUTPUT:
A list of triples, each of the form (e,[v],1), where e is the eigenvalue, and v is an associated left eigenvector such that𝑣𝐴 = 𝑒𝑣.
If the matrix 𝐴 is of size 𝑛, then there are 𝑛 triples.
If a matrix 𝐵 is passed as optional argument, the output is a solution to the generalized eigenvalue problem
such that𝑣𝐴 = 𝑒𝑣𝐵.
If homogeneous is set, each eigenvalue is returned as a tuple (𝛼, 𝛽) of homogeneous coordinates such that𝛽𝑣𝐴 = 𝛼𝑣𝐵.
The format of the output is designed to match the format for exact results. However, since matrices here
have numerical entries, the resulting eigenvalues will also be numerical. No attempt is made to determine
if two eigenvalues are equal, or if eigenvalues might actually be zero. So the algebraic multiplicity of eacheigenvalue is reported as 1. Decisions about equal eigenvalues or zero eigenvalues should be addressed in thecalling routine.
The SciPy routines used for these computations produce eigenvectors normalized to have length 1, but on
different hardware they may vary by a complex sign. So for doctests we have normalized output by forcing
their eigenvectors to have their first non-zero entry equal to one.
ALGORITHM:
Values are computed with the SciPy library using scipy.linalg.eig().
EXAMPLES:
sage: m = matrix(RDF, [[-5, 3, 2, 8],[10, 2, 4, -2],[-1, -10, -10, -17],[-2,␣˓→7, 6, 13]])sage: m[ -5.03.0
2.0
8.0][ 10.0
2.0
4.0 -2.0][ -1.0 -10.0 -10.0 -17.0][ -2.0
7.0
6.0 13.0]
sage: spectrum = m.left_eigenvectors()
sage: for i in range(len(spectrum)):....:
spectrum[i][1][0] = matrix(RDF, spectrum[i][1]).echelon_form()[0]sage: spectrum[0] # tol 1e-13(2.0, [(1.0, 1.0, 1.0, 1.0)], 1)
sage: spectrum[1] # tol 1e-13(1.0, [(1.0, 0.8, 0.8, 0.6)], 1)
sage: spectrum[2] # tol 1e-13(-2.0, [(1.0, 0.4, 0.6, 0.2)], 1)
sage: spectrum[3] # tol 1e-13(-1.0, [(1.0, 1.0, 2.0, 2.0)], 1)

742

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> m = matrix(RDF, [[-Integer(5), Integer(3), Integer(2), Integer(8)],˓→[Integer(10), Integer(2), Integer(4), -Integer(2)],[-Integer(1), ˓→Integer(10), -Integer(10), -Integer(17)],[-Integer(2), Integer(7),␣
˓→Integer(6), Integer(13)]])>>> m[ -5.03.0
2.0
8.0][ 10.0
2.0
4.0 -2.0][ -1.0 -10.0 -10.0 -17.0][ -2.0
7.0
6.0 13.0]>>> spectrum = m.left_eigenvectors()>>> for i in range(len(spectrum)):...
spectrum[i][Integer(1)][Integer(0)] = matrix(RDF,␣
˓→spectrum[i][Integer(1)]).echelon_form()[Integer(0)]>>> spectrum[Integer(0)] # tol 1e-13(2.0, [(1.0, 1.0, 1.0, 1.0)], 1)>>> spectrum[Integer(1)] # tol 1e-13(1.0, [(1.0, 0.8, 0.8, 0.6)], 1)>>> spectrum[Integer(2)] # tol 1e-13(-2.0, [(1.0, 0.4, 0.6, 0.2)], 1)>>> spectrum[Integer(3)] # tol 1e-13(-1.0, [(1.0, 1.0, 2.0, 2.0)], 1)

A generalized eigenvalue problem:
sage: A = matrix(CDF, [[1+I, -2], [3, 4]])sage: B = matrix(CDF, [[0, 7-I], [2, -3]])
sage: E = A.eigenvectors_left(B)sage: all((v * A - e * v * B).norm() < 1e-14 for e, [v], _ in E)
True>>> from sage.all import *>>> A = matrix(CDF, [[Integer(1)+I, -Integer(2)], [Integer(3), Integer(4)]])>>> B = matrix(CDF, [[Integer(0), Integer(7)-I], [Integer(2), -Integer(3)]])>>> E = A.eigenvectors_left(B)>>> all((v * A - e * v * B).norm() < RealNumber( 1e-14 ) for e, [v], _ in E)
True

In a generalized eigenvalue problem with a singular matrix 𝐵, we can check the eigenvector property using
homogeneous coordinates, even though the quotient 𝛼/𝛽 is not always defined:
sage: A = matrix.identity(CDF, 2)
sage: B = matrix(CDF, [[2, 1+I], [4, 2+2*I]])sage: E = A.eigenvectors_left(B, homogeneous=True)
sage: all((beta * v * A - alpha * v * B).norm() < 1e-14....:
for (alpha, beta), [v], _ in E)
True>>> from sage.all import *>>> A = matrix.identity(CDF, Integer(2))>>> B = matrix(CDF, [[Integer(2), Integer(1)+I], [Integer(4),␣
˓→Integer(2)+Integer(2)*I]])>>> E = A.eigenvectors_left(B, homogeneous=True)>>> all((beta * v * A - alpha * v * B).norm() < RealNumber( 1e-14 )...
for (alpha, beta), [v], _ in E)
True

743

Matrices and Spaces of Matrices, Release 10.4

See also:
eigenvalues(), eigenvectors_right(), Matrix.eigenmatrix_left().
eigenvectors_right(other=None, homogeneous=False)
Compute the ordinary or generalized right eigenvectors of a matrix of double precision real or complex numbers (i.e. RDF or CDF).
INPUT:• other – a square matrix 𝐵 (default: None) in a generalized eigenvalue problem; if None, an ordinary
eigenvalue problem is solved• homogeneous – boolean (default: False); if True, use homogeneous coordinates for the eigenvalues in the output
OUTPUT:
A list of triples, each of the form (e,[v],1), where e is the eigenvalue, and v is an associated righteigenvector such that
𝐴𝑣 = 𝑒𝑣.
If the matrix 𝐴 is of size 𝑛, then there are 𝑛 triples.
If a matrix 𝐵 is passed as optional argument, the output is a solution to the generalized eigenvalue problem
such that
𝐴𝑣 = 𝑒𝐵𝑣.
If homogeneous is set, each eigenvalue is returned as a tuple (𝛼, 𝛽) of homogeneous coordinates such that
𝛽𝐴𝑣 = 𝛼𝐵𝑣.
The format of the output is designed to match the format for exact results. However, since matrices here
have numerical entries, the resulting eigenvalues will also be numerical. No attempt is made to determine
if two eigenvalues are equal, or if eigenvalues might actually be zero. So the algebraic multiplicity of eacheigenvalue is reported as 1. Decisions about equal eigenvalues or zero eigenvalues should be addressed in thecalling routine.
The SciPy routines used for these computations produce eigenvectors normalized to have length 1, but on
different hardware they may vary by a complex sign. So for doctests we have normalized output by forcing
their eigenvectors to have their first non-zero entry equal to one.
ALGORITHM:
Values are computed with the SciPy library using scipy.linalg.eig().
EXAMPLES:
sage: m = matrix(RDF, [[-9, -14, 19, -74],[-1, 2, 4, -11],[-4, -12, 6, -32],
˓→[0, -2, -1, 1]])
sage: m[ -9.0 -14.0 19.0 -74.0][ -1.0
2.0
4.0 -11.0][ -4.0 -12.0
6.0 -32.0][ 0.0 -2.0 -1.0
1.0]
sage: spectrum = m.right_eigenvectors()
sage: for i in range(len(spectrum)):....:
spectrum[i][1][0] = matrix(RDF, spectrum[i][1]).echelon_form()[0]sage: spectrum[0] # tol 1e-13(continues on next page)

744

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)(2.0, [(1.0, -2.0, 3.0, 1.0)], 1)
sage: spectrum[1] # tol 1e-13(1.0, [(1.0, -0.666666666666633, 1.333333333333286, 0.33333333333331555)], 1)
sage: spectrum[2] # tol 1e-13(-2.0, [(1.0, -0.2, 1.0, 0.2)], 1)
sage: spectrum[3] # tol 1e-12(-1.0, [(1.0, -0.5, 2.0, 0.5)], 1)>>> from sage.all import *>>> m = matrix(RDF, [[-Integer(9), -Integer(14), Integer(19), -Integer(74)],[˓→Integer(1), Integer(2), Integer(4), -Integer(11)],[-Integer(4), ˓→Integer(12), Integer(6), -Integer(32)],[Integer(0), -Integer(2), ˓→Integer(1), Integer(1)]])>>> m[ -9.0 -14.0 19.0 -74.0][ -1.0
2.0
4.0 -11.0][ -4.0 -12.0
6.0 -32.0][ 0.0 -2.0 -1.0
1.0]>>> spectrum = m.right_eigenvectors()>>> for i in range(len(spectrum)):...
spectrum[i][Integer(1)][Integer(0)] = matrix(RDF,␣
˓→spectrum[i][Integer(1)]).echelon_form()[Integer(0)]>>> spectrum[Integer(0)] # tol 1e-13(2.0, [(1.0, -2.0, 3.0, 1.0)], 1)>>> spectrum[Integer(1)] # tol 1e-13(1.0, [(1.0, -0.666666666666633, 1.333333333333286, 0.33333333333331555)], 1)>>> spectrum[Integer(2)] # tol 1e-13(-2.0, [(1.0, -0.2, 1.0, 0.2)], 1)>>> spectrum[Integer(3)] # tol 1e-12(-1.0, [(1.0, -0.5, 2.0, 0.5)], 1)

A generalized eigenvalue problem:
sage: A = matrix(CDF, [[1+I, -2], [3, 4]])sage: B = matrix(CDF, [[0, 7-I], [2, -3]])
sage: E = A.eigenvectors_right(B)sage: all((A * v - e * B * v).norm() < 1e-14 for e, [v], _ in E)
True>>> from sage.all import *>>> A = matrix(CDF, [[Integer(1)+I, -Integer(2)], [Integer(3), Integer(4)]])>>> B = matrix(CDF, [[Integer(0), Integer(7)-I], [Integer(2), -Integer(3)]])>>> E = A.eigenvectors_right(B)>>> all((A * v - e * B * v).norm() < RealNumber( 1e-14 ) for e, [v], _ in E)
True

In a generalized eigenvalue problem with a singular matrix 𝐵, we can check the eigenvector property using
homogeneous coordinates, even though the quotient 𝛼/𝛽 is not always defined:
sage: A = matrix.identity(RDF, 2)
sage: B = matrix(RDF, [[3, 5], [6, 10]])sage: E = A.eigenvectors_right(B, homogeneous=True)
sage: all((beta * A * v - alpha * B * v).norm() < 1e-14....:
for (alpha, beta), [v], _ in E)
True

745

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = matrix.identity(RDF, Integer(2))>>> B = matrix(RDF, [[Integer(3), Integer(5)], [Integer(6), Integer(10)]])>>> E = A.eigenvectors_right(B, homogeneous=True)>>> all((beta * A * v - alpha * B * v).norm() < RealNumber( 1e-14 )...
for (alpha, beta), [v], _ in E)
True

See also:
eigenvalues(), eigenvectors_left(), Matrix.eigenmatrix_right().
exp()
Calculate the exponential of this matrix X, which is the matrix
𝑒𝑋 =

∞
∑︁
𝑋𝑘
𝑘=0

𝑘!

.

EXAMPLES:
sage: A = matrix(RDF, 2, [1,2,3,4]); A[1.0 2.0][3.0 4.0]
sage: A.exp() # tol 1e-14[51.968956198705044 74.73656456700327][112.10484685050491 164.07380304920997]
sage: A = matrix(CDF, 2, [1,2+I,3*I,4]); A˓→needs sage.symbolic[
1.0 2.0 + 1.0*I]
[
3.0*I
4.0]
sage: A.exp() # tol 3e-14
˓→needs sage.symbolic[-19.614602953804912 + 12.517743846762578*I
˓→88379930658099*I][ -32.383580980922254 + 21.88423595789845*I
˓→901324827684824*I]#␣#␣
3.7949636449582176 + 28.
2.269633004093535 + 44.

>>> from sage.all import *>>> A = matrix(RDF, Integer(2), [Integer(1),Integer(2),Integer(3),˓→Integer(4)]); A[1.0 2.0][3.0 4.0]>>> A.exp() # tol 1e-14[51.968956198705044 74.73656456700327][112.10484685050491 164.07380304920997]>>> A = matrix(CDF, Integer(2), [Integer(1),Integer(2)+I,Integer(3)*I,
˓→Integer(4)]); A# needs sage.symbolic[
1.0 2.0 + 1.0*I]
[
3.0*I
4.0]
>>> A.exp() # tol 3e-14
˓→needs sage.symbolic[-19.614602953804912 + 12.517743846762578*I
3.7949636449582176 + 28.
˓→88379930658099*I][ -32.383580980922254 + 21.88423595789845*I
2.269633004093535 + 44.
˓→901324827684824*I]#␣

is_hermitian(tol=1e-12, algorithm='naive')
Return True if the matrix is equal to its conjugate-transpose.
746

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

INPUT:• tol – (default: 1e-12); the largest value of the absolute value of the difference between two matrix
entries for which they will still be considered equal.
• algorithm – string (default: “naive”); either “naive” or “orthonormal”
OUTPUT:
True if the matrix is square and equal to the transpose with every entry conjugated, and False otherwise.
Note that if conjugation has no effect on elements of the base ring (such as for integers), then the is_symmetric() method is equivalent and faster.
The tolerance parameter is used to allow for numerical values to be equal if there is a slight difference due toround-off and other imprecisions.
The result is cached, on a per-tolerance and per-algorithm basis.
ALGORITHMS:
The naive algorithm simply compares corresponding entries on either side of the diagonal (and on the diagonal
itself) to see if they are conjugates, with equality controlled by the tolerance parameter.
The orthonormal algorithm first computes a Schur decomposition (via the schur() method) and checks
that the result is a diagonal matrix with real entries.
So the naive algorithm can finish quickly for a matrix that is not Hermitian, while the orthonormal algorithm
will always compute a Schur decomposition before going through a similar check of the matrix entry-by-entry.
EXAMPLES:
sage: # needs sage.symbolic
sage: A = matrix(CDF, [[ 1 + I, 1 - 6*I, -1 - I],....:[-3 - I,
-4*I,
-2],
....:
[-1 + I, -2 - 8*I, 2 + I]])
sage: A.is_hermitian(algorithm= orthonormal )False
sage: A.is_hermitian(algorithm= naive )False
sage: B = A*A.conjugate_transpose()sage: B.is_hermitian(algorithm= orthonormal )Truesage: B.is_hermitian(algorithm= naive )True>>> from sage.all import *>>> # needs sage.symbolic>>> A = matrix(CDF, [[ Integer(1) + I, Integer(1) - Integer(6)*I, ˓→Integer(1) - I],...
[-Integer(3) - I,
-Integer(4)*I,-Integer(2)],...
[-Integer(1) + I, -Integer(2) - Integer(8)*I, ␣
˓→Integer(2) + I]])>>> A.is_hermitian(algorithm= orthonormal )False>>> A.is_hermitian(algorithm= naive )False>>> B = A*A.conjugate_transpose()>>> B.is_hermitian(algorithm= orthonormal )True>>> B.is_hermitian(algorithm= naive )
True

747

Matrices and Spaces of Matrices, Release 10.4

A matrix that is nearly Hermitian, but for one non-real diagonal entry.
sage: # needs sage.symbolic
sage: A = matrix(CDF, [[2,2-I, 1+4*I],....:[ 2+I,
3+I, 2-6*I],....:[1-4*I, 2+6*I,
5]])sage: A.is_hermitian(algorithm= orthonormal )False
sage: A[1,1] = 132
sage: A.is_hermitian(algorithm= orthonormal )True>>> from sage.all import *>>> # needs sage.symbolic>>> A = matrix(CDF, [[Integer(2),Integer(2)-I,␣
˓→Integer(1)+Integer(4)*I],...
[ Integer(2)+I,
Integer(3)+I, Integer(2)˓→Integer(6)*I],...
[Integer(1)-Integer(4)*I, Integer(2)+Integer(6)*I,
˓→Integer(5)]])>>> A.is_hermitian(algorithm= orthonormal )False>>> A[Integer(1),Integer(1)] = Integer(132)>>> A.is_hermitian(algorithm= orthonormal )True␣

We get a unitary matrix from the SVD routine and use this numerical matrix to create a matrix that should
be Hermitian (indeed it should be the identity matrix), but with some imprecision. We use this to illustratethat if the tolerance is set too small, then we can be too strict about the equality of entries and may achieve
the wrong result (depending on the system):sage: # needs sage.symbolic
sage: A = matrix(CDF, [[ 1 + I, 1 - 6*I, -1 - I],....:[-3 - I,
-4*I,
-2],
....:
[-1 + I, -2 - 8*I, 2 + I]])
sage: U, _, _ = A.SVD()
sage: B = U*U.conjugate_transpose()sage: B.is_hermitian(algorithm= naive )Truesage: B.is_hermitian(algorithm= naive , tol=1.0e-17)
False
sage: B.is_hermitian(algorithm= naive , tol=1.0e-15)
True# random>>> from sage.all import *>>> # needs sage.symbolic>>> A = matrix(CDF, [[ Integer(1) + I, Integer(1) - Integer(6)*I, ˓→Integer(1) - I],...
[-Integer(3) - I,
-Integer(4)*I,-Integer(2)],...
[-Integer(1) + I, -Integer(2) - Integer(8)*I, ␣
˓→Integer(2) + I]])>>> U, _, _ = A.SVD()>>> B = U*U.conjugate_transpose()>>> B.is_hermitian(algorithm= naive )True>>> B.is_hermitian(algorithm= naive , tol=RealNumber( 1.0e-17 )) # random
False(continues on next page)

748

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> B.is_hermitian(algorithm= naive , tol=RealNumber( 1.0e-15 ))True

A square, empty matrix is trivially Hermitian.
sage: A = matrix(RDF, 0, 0)
sage: A.is_hermitian()True>>> from sage.all import *>>> A = matrix(RDF, Integer(0), Integer(0))>>> A.is_hermitian()
True

Rectangular matrices are never Hermitian, no matter which algorithm is requested.
sage: A = matrix(CDF, 3, 4)
sage: A.is_hermitian()False>>> from sage.all import *>>> A = matrix(CDF, Integer(3), Integer(4))>>> A.is_hermitian()
False

AUTHOR:• Rob Beezer (2011-03-30)
is_normal(tol=1e-12, algorithm='orthonormal')
Return True if the matrix commutes with its conjugate-transpose.
INPUT:• tol – (default: 1e-12); the largest value of the absolute value of the difference between two matrix
entries for which they will still be considered equal.
• algorithm – (default: ‘orthonormal’); set to ‘orthonormal’ for a stable procedure and set to ‘naive’ fora fast procedure.
OUTPUT:
True if the matrix is square and commutes with its conjugate-transpose, and False otherwise.
Normal matrices are precisely those that can be diagonalized by a unitary matrix.
The tolerance parameter is used to allow for numerical values to be equal if there is a slight difference due toround-off and other imprecisions.
The result is cached, on a per-tolerance and per-algorithm basis.
ALGORITHMS:
The naive algorithm simply compares entries of the two possible products of the matrix with its
conjugate-transpose, with equality controlled by the tolerance parameter.
The orthonormal algorithm first computes a Schur decomposition (via the schur() method) and checks
that the result is a diagonal matrix. An orthonormal diagonalization is equivalent to being normal.

749

Matrices and Spaces of Matrices, Release 10.4

So the naive algorithm can finish fairly quickly for a matrix that is not normal, once the products have been
computed. However, the orthonormal algorithm will compute a Schur decomposition before going through asimilar check of a matrix entry-by-entry.
EXAMPLES:First over the complexes. B is Hermitian, hence normal.
sage: # needs sage.symbolic
sage: A = matrix(CDF, [[ 1 + I, 1 - 6*I, -1 - I],....:[-3 - I,
-4*I,
-2],
....:
[-1 + I, -2 - 8*I, 2 + I]])
sage: B = A*A.conjugate_transpose()sage: B.is_hermitian()True
sage: B.is_normal(algorithm= orthonormal )Truesage: B.is_normal(algorithm= naive )Truesage: B[0,0] = I
sage: B.is_normal(algorithm= orthonormal )False
sage: B.is_normal(algorithm= naive )False>>> from sage.all import *>>> # needs sage.symbolic>>> A = matrix(CDF, [[ Integer(1) + I, Integer(1) - Integer(6)*I, ˓→Integer(1) - I],...
[-Integer(3) - I,
-Integer(4)*I,-Integer(2)],...
[-Integer(1) + I, -Integer(2) - Integer(8)*I, ␣
˓→Integer(2) + I]])>>> B = A*A.conjugate_transpose()>>> B.is_hermitian()
True>>> B.is_normal(algorithm= orthonormal )True>>> B.is_normal(algorithm= naive )True>>> B[Integer(0),Integer(0)] = I>>> B.is_normal(algorithm= orthonormal )False>>> B.is_normal(algorithm= naive )False

Now over the reals. Circulant matrices are normal.
sage: # needs sage.graphs
sage: G = graphs.CirculantGraph(20, [3, 7])
sage: D = digraphs.Circuit(20)sage: A = 3*D.adjacency_matrix() - 5*G.adjacency_matrix()
sage: A = A.change_ring(RDF)
sage: A.is_normal()True
sage: A.is_normal(algorithm= naive )Truesage: A[19,0] = 4.0
sage: A.is_normal()(continues on next page)

750

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

False
sage: A.is_normal(algorithm= naive )False>>> from sage.all import *>>> # needs sage.graphs>>> G = graphs.CirculantGraph(Integer(20), [Integer(3), Integer(7)])>>> D = digraphs.Circuit(Integer(20))>>> A = Integer(3)*D.adjacency_matrix() - Integer(5)*G.adjacency_matrix()>>> A = A.change_ring(RDF)>>> A.is_normal()
True>>> A.is_normal(algorithm= naive )True>>> A[Integer(19),Integer(0)] = RealNumber( 4.0 )>>> A.is_normal()
False>>> A.is_normal(algorithm= naive )False

Skew-Hermitian matrices are normal.
sage: # needs sage.symbolic
sage: A = matrix(CDF, [[ 1 + I, 1 - 6*I, -1 - I],....:[-3 - I,
-4*I,
-2],
....:
[-1 + I, -2 - 8*I, 2 + I]])
sage: B = A - A.conjugate_transpose()sage: B.is_hermitian()False
sage: B.is_normal()True
sage: B.is_normal(algorithm= naive )True>>> from sage.all import *>>> # needs sage.symbolic>>> A = matrix(CDF, [[ Integer(1) + I, Integer(1) - Integer(6)*I, ˓→Integer(1) - I],...
[-Integer(3) - I,
-Integer(4)*I,-Integer(2)],...
[-Integer(1) + I, -Integer(2) - Integer(8)*I, ␣
˓→Integer(2) + I]])>>> B = A - A.conjugate_transpose()>>> B.is_hermitian()
False>>> B.is_normal()
True>>> B.is_normal(algorithm= naive )True

A small matrix that does not fit into any of the usual categories of normal matrices.
sage: A = matrix(RDF, [[1, -1],....:
[1, 1]])
sage: A.is_normal()True
sage: not A.is_hermitian() and not A.is_skew_symmetric()(continues on next page)751

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)True>>> from sage.all import *>>> A = matrix(RDF, [[Integer(1), -Integer(1)],...
[Integer(1), Integer(1)]])>>> A.is_normal()True>>> not A.is_hermitian() and not A.is_skew_symmetric()
True

Sage has several fields besides the entire complex numbers where conjugation is non-trivial.
sage: # needs sage.rings.number_fieldsage: F.<b> = QuadraticField(-7)
sage: C = matrix(F, [[-2*b - 3, 7*b - 6, -b + 3],....:[-2*b - 3, -3*b + 2,
-2*b],....:[
b + 1,
0,-2]])
sage: C = C*C.conjugate_transpose()sage: C.is_normal()True>>> from sage.all import *>>> # needs sage.rings.number_field>>> F = QuadraticField(-Integer(7), names=( b ,)); (b,) = F._first_ngens(1)>>> C = matrix(F, [[-Integer(2)*b - Integer(3), Integer(7)*b - Integer(6), ˓→b + Integer(3)],...
[-Integer(2)*b - Integer(3), -Integer(3)*b + Integer(2), ␣˓→-Integer(2)*b],...
[b + Integer(1),Integer(0),-Integer(2)]])>>> C = C*C.conjugate_transpose()>>> C.is_normal()True

A square, empty matrix is trivially normal.
sage: A = matrix(CDF, 0, 0)
sage: A.is_normal()True>>> from sage.all import *>>> A = matrix(CDF, Integer(0), Integer(0))>>> A.is_normal()
True

Rectangular matrices are never normal, no matter which algorithm is requested.
sage: A = matrix(CDF, 3, 4)
sage: A.is_normal()False>>> from sage.all import *>>> A = matrix(CDF, Integer(3), Integer(4))>>> A.is_normal()
False

AUTHOR:
752

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

• Rob Beezer (2011-03-31)
is_positive_definite()
Determines if a matrix is positive definite.
A matrix 𝐴 is positive definite if it is square, is Hermitian (which reduces to symmetric in the real case), andfor every nonzero vector ⃗𝑥,⃗𝑥* 𝐴⃗𝑥 > 0
where ⃗𝑥* is the conjugate-transpose in the complex case and just the transpose in the real case. Equivalently,
a positive definite matrix has only positive eigenvalues and only positive determinants of leading principal
submatrices.
INPUT:
Any matrix over RDF or CDF.
OUTPUT:
True if and only if the matrix is square, Hermitian, and meets the condition above on the quadratic form.
The result is cached.
IMPLEMENTATION:
The existence of a Cholesky decomposition and the positive definite property are equivalent. So thismethod and the cholesky() method compute and cache both the Cholesky decomposition and thepositive-definiteness. So the is_positive_definite() method or catching a ValueError from thecholesky() method are equally expensive computationally and if the decomposition exists, it is cached asa side-effect of either routine.
EXAMPLES:
A matrix over RDF that is positive definite.
sage: M = matrix(RDF,[[ 1, 1,
1,
1,
1],
....:
[ 1, 5,
31,
121,
341],
....:
[ 1, 31, 341, 1555, 4681],....:[ 1,121, 1555, 7381, 22621],....:[ 1,341, 4681, 22621, 69905]])
sage: M.is_symmetric()True
sage: M.eigenvalues()[77547.66..., 82.44..., 2.41..., 0.46..., 0.011...]
sage: [round(M[:i,:i].determinant()) for i in range(1, M.nrows()+1)][1, 4, 460, 27936, 82944]
sage: M.is_positive_definite()True>>> from sage.all import *>>> M = matrix(RDF,[[ Integer(1), Integer(1),Integer(1),Integer(1),␣
˓→
Integer(1)],...
[ Integer(1), Integer(5),Integer(31),Integer(121),␣
˓→
Integer(341)],...
[ Integer(1), Integer(31), Integer(341), Integer(1555),␣
˓→ Integer(4681)],...
[ Integer(1),Integer(121), Integer(1555), Integer(7381),␣
˓→Integer(22621)],...
[ Integer(1),Integer(341), Integer(4681), Integer(22621),␣
˓→Integer(69905)]])(continues on next page)753

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> M.is_symmetric()
True>>> M.eigenvalues()[77547.66..., 82.44..., 2.41..., 0.46..., 0.011...]>>> [round(M[:i,:i].determinant()) for i in range(Integer(1), M.
˓→nrows()+Integer(1))][1, 4, 460, 27936, 82944]>>> M.is_positive_definite()True

A matrix over CDF that is positive definite.
sage: # needs sage.symbolic
sage: C = matrix(CDF, [[23, 17*I + 3, 24*I + 25,
21*I],....:[ -17*I + 3,
38, -69*I + 89, 7*I + 15],....:[-24*I + 25, 69*I + 89,
976, 24*I + 6],....:[-21*I, -7*I + 15, -24*I + 6,28]])
sage: C.is_hermitian()True
sage: [x.real() for x in C.eigenvalues()][991.46..., 55.96..., 3.69..., 13.87...]sage: [round(C[:i,:i].determinant().real()) for i in range(1, C.nrows()+1)][23, 576, 359540, 2842600]
sage: C.is_positive_definite()True>>> from sage.all import *>>> # needs sage.symbolic>>> C = matrix(CDF, [[Integer(23), Integer(17)*I + Integer(3), ␣
˓→Integer(24)*I + Integer(25),Integer(21)*I],...
[ -Integer(17)*I + Integer(3),Integer(38), ˓→Integer(69)*I + Integer(89), Integer(7)*I + Integer(15)],...
[-Integer(24)*I + Integer(25), Integer(69)*I +␣˓→Integer(89),Integer(976), Integer(24)*I + Integer(6)],...
[-Integer(21)*I, -Integer(7)*I + Integer(15), ˓→Integer(24)*I + Integer(6),Integer(28)]])>>> C.is_hermitian()True>>> [x.real() for x in C.eigenvalues()][991.46..., 55.96..., 3.69..., 13.87...]>>> [round(C[:i,:i].determinant().real()) for i in range(Integer(1), C.
˓→nrows()+Integer(1))][23, 576, 359540, 2842600]>>> C.is_positive_definite()True

A matrix over RDF that is not positive definite.
sage: A = matrix(RDF, [[ 3, -6,
9,
6, -9],....:[-6, 11, -16, -11, 17],....:
[ 9, -16, 28, 16, -40],....:[ 6, -11, 16,
9, -19],....:[-9, 17, -40, -19, 68]])
sage: A.is_symmetric()True
sage: A.eigenvalues()(continues on next page)754

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[108.07..., 13.02..., -0.02..., -0.70..., -1.37...]sage: [round(A[:i,:i].determinant()) for i in range(1, A.nrows()+1)][3, -3, -15, 30, -30]
sage: A.is_positive_definite()
False>>> from sage.all import *>>> A = matrix(RDF, [[ Integer(3), -Integer(6),Integer(9),Integer(6), ␣˓→-Integer(9)],...
[-Integer(6), Integer(11), -Integer(16), -Integer(11), ␣
˓→Integer(17)],...
[ Integer(9), -Integer(16), Integer(28), Integer(16), ˓→Integer(40)],...
[ Integer(6), -Integer(11), Integer(16),Integer(9), ˓→Integer(19)],...
[-Integer(9), Integer(17), -Integer(40), -Integer(19), ␣
˓→Integer(68)]])>>> A.is_symmetric()
True>>> A.eigenvalues()[108.07..., 13.02..., -0.02..., -0.70..., -1.37...]>>> [round(A[:i,:i].determinant()) for i in range(Integer(1), A.
˓→nrows()+Integer(1))][3, -3, -15, 30, -30]>>> A.is_positive_definite()False

A matrix over CDF that is not positive definite.
sage: # needs sage.symbolic
sage: B = matrix(CDF, [[2, 4 - 2*I, 2 + 2*I],....:[4 + 2*I,
8,
10*I],....:[2 - 2*I,-10*I,-3]])sage: B.is_hermitian()True
sage: [ev.real() for ev in B.eigenvalues()][15.88..., 0.08..., -8.97...]sage: [round(B[:i,:i].determinant().real()) for i in range(1, B.nrows()+1)][2, -4, -12]
sage: B.is_positive_definite()
False>>> from sage.all import *>>> # needs sage.symbolic>>> B = matrix(CDF, [[Integer(2), Integer(4) - Integer(2)*I, Integer(2)␣
˓→+ Integer(2)*I],...
[Integer(4) + Integer(2)*I,
Integer(8),␣˓→Integer(10)*I],...
[Integer(2) - Integer(2)*I,-Integer(10)*I,
˓→Integer(3)]])>>> B.is_hermitian()True>>> [ev.real() for ev in B.eigenvalues()][15.88..., 0.08..., -8.97...]>>> [round(B[:i,:i].determinant().real()) for i in range(Integer(1), B.
˓→nrows()+Integer(1))](continues on next page)755

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[2, -4, -12]>>> B.is_positive_definite()False

A large random matrix that is guaranteed by theory to be positive definite.
sage: R = random_matrix(CDF, 200)
sage: H = R.conjugate_transpose()*R
sage: H.is_positive_definite()True>>> from sage.all import *>>> R = random_matrix(CDF, Integer(200))>>> H = R.conjugate_transpose()*R>>> H.is_positive_definite()
True

AUTHOR:• Rob Beezer (2012-05-28)
is_skew_hermitian(tol=1e-12, algorithm='orthonormal')
Return True if the matrix is equal to the negative of its conjugate transpose.
INPUT:• tol – (default: 1e-12); the largest value of the absolute value of the difference between two matrix
entries for which they will still be considered equal.
• algorithm – (default: ‘orthonormal’); set to ‘orthonormal’ for a stable procedure and set to ‘naive’ fora fast procedure.
OUTPUT:
True if the matrix is square and equal to the negative of its conjugate transpose, and False otherwise.
Note that if conjugation has no effect on elements of the base ring (such as for integers), then theis_skew_symmetric() method is equivalent and faster.
The tolerance parameter is used to allow for numerical values to be equal if there is a slight difference due toround-off and other imprecisions.
The result is cached, on a per-tolerance and per-algorithm basis.
ALGORITHMS:
The naive algorithm simply compares corresponding entries on either side of the diagonal (and on the diagonal
itself) to see if they are conjugates, with equality controlled by the tolerance parameter.
The orthonormal algorithm first computes a Schur decomposition (via the schur() method) and checks
that the result is a diagonal matrix with real entries.
So the naive algorithm can finish quickly for a matrix that is not Hermitian, while the orthonormal algorithm
will always compute a Schur decomposition before going through a similar check of the matrix entry-by-entry.
EXAMPLES:
sage: A = matrix(CDF, [[0, -1],....:
[1, 0]])
sage: A.is_skew_hermitian(algorithm= orthonormal )True(continues on next page)

756

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: A.is_skew_hermitian(algorithm= naive )True>>> from sage.all import *>>> A = matrix(CDF, [[Integer(0), -Integer(1)],...
[Integer(1), Integer(0)]])>>> A.is_skew_hermitian(algorithm= orthonormal )True>>> A.is_skew_hermitian(algorithm= naive )True

A matrix that is nearly skew-Hermitian, but for a non-real diagonal entry.
sage: # needs sage.symbolic
sage: A = matrix(CDF, [[ -I, -1, 1-I],....:[
1, 1, -1],....:[-1-I, 1, -I]])
sage: A.is_skew_hermitian()False
sage: A[1,1] = -I
sage: A.is_skew_hermitian()True>>> from sage.all import *>>> # needs sage.symbolic>>> A = matrix(CDF, [[ -I, -Integer(1), Integer(1)-I],...
[
Integer(1), Integer(1), -Integer(1)],...
[-Integer(1)-I, Integer(1), -I]])>>> A.is_skew_hermitian()
False>>> A[Integer(1),Integer(1)] = -I>>> A.is_skew_hermitian()True

We get a unitary matrix from the SVD routine and use this numerical matrix to create a matrix that should
be skew-Hermitian (indeed it should be the identity matrix multiplied by 𝐼), but with some imprecision. We
use this to illustrate that if the tolerance is set too small, then we can be too strict about the equality of entries
and may achieve the wrong result (depending on the system):sage: # needs sage.symbolic
sage: A = matrix(CDF, [[ 1 + I, 1 - 6*I, -1 - I],....:[-3 - I,
-4*I,
-2],
....:
[-1 + I, -2 - 8*I, 2 + I]])
sage: U, _, _ = A.SVD()
sage: B = 1j*U*U.conjugate_transpose()sage: B.is_skew_hermitian(algorithm= naive )Truesage: B.is_skew_hermitian(algorithm= naive , tol=1.0e-17)
False
sage: B.is_skew_hermitian(algorithm= naive , tol=1.0e-15)
True>>> from sage.all import *>>> # needs sage.symbolic>>> A = matrix(CDF, [[ Integer(1) + I,

# randomInteger(1) - Integer(6)*I, (continues on next page)757

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Integer(1) - I],...
[-Integer(3) - I,
-Integer(4)*I,-Integer(2)],...
[-Integer(1) + I, -Integer(2) - Integer(8)*I, ␣
˓→Integer(2) + I]])>>> U, _, _ = A.SVD()>>> B = ComplexNumber(0, 1 )*U*U.conjugate_transpose()>>> B.is_skew_hermitian(algorithm= naive )True>>> B.is_skew_hermitian(algorithm= naive , tol=RealNumber( 1.0e-17 )) #␣˓→random
False>>> B.is_skew_hermitian(algorithm= naive , tol=RealNumber( 1.0e-15 ))True
˓→A square, empty matrix is trivially Hermitian.
sage: A = matrix(RDF, 0, 0)
sage: A.is_skew_hermitian()True>>> from sage.all import *>>> A = matrix(RDF, Integer(0), Integer(0))>>> A.is_skew_hermitian()
True

Rectangular matrices are never Hermitian, no matter which algorithm is requested.
sage: A = matrix(CDF, 3, 4)
sage: A.is_skew_hermitian()False>>> from sage.all import *>>> A = matrix(CDF, Integer(3), Integer(4))>>> A.is_skew_hermitian()
False

AUTHOR:• Rob Beezer (2011-03-30)
is_unitary(tol=1e-12, algorithm='orthonormal')
Return True if the columns of the matrix are an orthonormal basis.
For a matrix with real entries this determines if a matrix is “orthogonal” and for a matrix with complex entries
this determines if the matrix is “unitary.”
INPUT:• tol – (default: 1e-12); the largest value of the absolute value of the difference between two matrix
entries for which they will still be considered equal.
• algorithm – (default: ‘orthonormal’); set to ‘orthonormal’ for a stable procedure and set to ‘naive’ fora fast procedure.
OUTPUT:
True if the matrix is square and its conjugate-transpose is its inverse, and False otherwise. In other words,
a matrix is orthogonal or unitary if the product of its conjugate-transpose times the matrix is the identity
matrix.
758

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

The tolerance parameter is used to allow for numerical values to be equal if there is a slight difference due toround-off and other imprecisions.
The result is cached, on a per-tolerance and per-algorithm basis.
ALGORITHMS:
The naive algorithm simply computes the product of the conjugate-transpose with the matrix and compares
the entries to the identity matrix, with equality controlled by the tolerance parameter.
The orthonormal algorithm first computes a Schur decomposition (via the schur() method) and checks
that the result is a diagonal matrix with entries of modulus 1, which is equivalent to being unitary.
So the naive algorithm might finish fairly quickly for a matrix that is not unitary, once the product has been
computed. However, the orthonormal algorithm will compute a Schur decomposition before going through asimilar check of a matrix entry-by-entry.
EXAMPLES:
A matrix that is far from unitary.
sage: A = matrix(RDF, 4, range(16))
sage: A.conjugate().transpose()*A[224.0 248.0 272.0 296.0][248.0 276.0 304.0 332.0][272.0 304.0 336.0 368.0][296.0 332.0 368.0 404.0]
sage: A.is_unitary()
False
sage: A.is_unitary(algorithm= naive )False
sage: A.is_unitary(algorithm= orthonormal )False>>> from sage.all import *>>> A = matrix(RDF, Integer(4), range(Integer(16)))>>> A.conjugate().transpose()*A[224.0 248.0 272.0 296.0][248.0 276.0 304.0 332.0][272.0 304.0 336.0 368.0][296.0 332.0 368.0 404.0]>>> A.is_unitary()
False>>> A.is_unitary(algorithm= naive )False>>> A.is_unitary(algorithm= orthonormal )False

The QR decomposition will produce a unitary matrix as Q and the SVD decomposition will create two unitarymatrices, U and V.
sage: # needs sage.symbolic
sage: A = matrix(CDF, [[1 - I,-3*I, -2 + I,....:[
1 - I, -2 + I, 1 + 4*I,....:[
-1, -5 + I, -2 + I,....:[-2 + 4*I, 2 - I, 8 - 4*I,
sage: Q, R = A.QR()
sage: Q.is_unitary()Truesage: U, S, V = A.SVD()

1, -2 + 3*I],
0,
2 + I],
1 + I, -5 - 4*I],
1 - 8*I, 3 - 2*I]])(continues on next page)759

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: U.is_unitary(algorithm= naive )Truesage: U.is_unitary(algorithm= orthonormal )Truesage: V.is_unitary(algorithm= naive )True>>> from sage.all import *>>> # needs sage.symbolic>>> A = matrix(CDF, [[Integer(1) - I,
-Integer(3)*I, -Integer(2) + I, ␣˓→Integer(1), -Integer(2) + Integer(3)*I],...
[
Integer(1) - I, -Integer(2) + I, Integer(1) +␣˓→Integer(4)*I,
Integer(0),Integer(2) + I],...
[-Integer(1), -Integer(5) + I, -Integer(2) + I, ␣
˓→ Integer(1) + I, -Integer(5) - Integer(4)*I],...
[-Integer(2) + Integer(4)*I, Integer(2) - I, Integer(8)␣
˓→- Integer(4)*I,
Integer(1) - Integer(8)*I, Integer(3) - Integer(2)*I]])>>> Q, R = A.QR()>>> Q.is_unitary()
True>>> U, S, V = A.SVD()>>> U.is_unitary(algorithm= naive )True>>> U.is_unitary(algorithm= orthonormal )True>>> V.is_unitary(algorithm= naive )True

If we make the tolerance too strict we can get misleading results.
sage: A = matrix(RDF, 10, 10, [1/(i+j+1) for i in range(10) for j in␣˓→range(10)])sage: Q, R = A.QR()
sage: Q.is_unitary(algorithm= naive , tol=1e-16)
False
sage: Q.is_unitary(algorithm= orthonormal , tol=1e-17)
False>>> from sage.all import *>>> A = matrix(RDF, Integer(10), Integer(10), [Integer(1)/(i+j+Integer(1))␣
˓→for i in range(Integer(10)) for j in range(Integer(10))])>>> Q, R = A.QR()>>> Q.is_unitary(algorithm= naive , tol=RealNumber( 1e-16 ))False>>> Q.is_unitary(algorithm= orthonormal , tol=RealNumber( 1e-17 ))False

Rectangular matrices are not unitary/orthogonal, even if their columns form an orthonormal set.
sage: A = matrix(CDF, [[1,0], [0,0], [0,1]])
sage: A.is_unitary()
False>>> from sage.all import *>>> A = matrix(CDF, [[Integer(1),Integer(0)], [Integer(0),Integer(0)],␣
(continues on next page)

760

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[Integer(0),Integer(1)]])>>> A.is_unitary()
False
˓→

The smallest cases:
sage: P = matrix(CDF, 0, 0)
sage: P.is_unitary(algorithm= naive )Truesage: P = matrix(CDF, 1, 1, [1])sage: P.is_unitary(algorithm= orthonormal )Truesage: P = matrix(CDF, 0, 0,)
sage: P.is_unitary(algorithm= orthonormal )True>>> from sage.all import *>>> P = matrix(CDF, Integer(0), Integer(0))>>> P.is_unitary(algorithm= naive )True>>> P = matrix(CDF, Integer(1), Integer(1), [Integer(1)])>>> P.is_unitary(algorithm= orthonormal )True>>> P = matrix(CDF, Integer(0), Integer(0),)>>> P.is_unitary(algorithm= orthonormal )True

AUTHOR:• Rob Beezer (2011-05-04)
left_eigenvectors(other=None, homogeneous=False)
Compute the ordinary or generalized left eigenvectors of a matrix of double precision real or complex numbers(i.e. RDF or CDF).
INPUT:• other – a square matrix 𝐵 (default: None) in a generalized eigenvalue problem; if None, an ordinary
eigenvalue problem is solved• homogeneous – boolean (default: False); if True, use homogeneous coordinates for the eigenvalues in the output
OUTPUT:
A list of triples, each of the form (e,[v],1), where e is the eigenvalue, and v is an associated left eigenvector such that𝑣𝐴 = 𝑒𝑣.
If the matrix 𝐴 is of size 𝑛, then there are 𝑛 triples.
If a matrix 𝐵 is passed as optional argument, the output is a solution to the generalized eigenvalue problem
such that𝑣𝐴 = 𝑒𝑣𝐵.
761

Matrices and Spaces of Matrices, Release 10.4

If homogeneous is set, each eigenvalue is returned as a tuple (𝛼, 𝛽) of homogeneous coordinates such that𝛽𝑣𝐴 = 𝛼𝑣𝐵.
The format of the output is designed to match the format for exact results. However, since matrices here
have numerical entries, the resulting eigenvalues will also be numerical. No attempt is made to determine
if two eigenvalues are equal, or if eigenvalues might actually be zero. So the algebraic multiplicity of eacheigenvalue is reported as 1. Decisions about equal eigenvalues or zero eigenvalues should be addressed in thecalling routine.
The SciPy routines used for these computations produce eigenvectors normalized to have length 1, but on
different hardware they may vary by a complex sign. So for doctests we have normalized output by forcing
their eigenvectors to have their first non-zero entry equal to one.
ALGORITHM:
Values are computed with the SciPy library using scipy.linalg.eig().
EXAMPLES:
sage: m = matrix(RDF, [[-5, 3, 2, 8],[10, 2, 4, -2],[-1, -10, -10, -17],[-2,␣˓→7, 6, 13]])sage: m[ -5.03.0
2.0
8.0][ 10.0
2.0
4.0 -2.0][ -1.0 -10.0 -10.0 -17.0][ -2.0
7.0
6.0 13.0]
sage: spectrum = m.left_eigenvectors()
sage: for i in range(len(spectrum)):....:
spectrum[i][1][0] = matrix(RDF, spectrum[i][1]).echelon_form()[0]sage: spectrum[0] # tol 1e-13(2.0, [(1.0, 1.0, 1.0, 1.0)], 1)
sage: spectrum[1] # tol 1e-13(1.0, [(1.0, 0.8, 0.8, 0.6)], 1)
sage: spectrum[2] # tol 1e-13(-2.0, [(1.0, 0.4, 0.6, 0.2)], 1)
sage: spectrum[3] # tol 1e-13(-1.0, [(1.0, 1.0, 2.0, 2.0)], 1)>>> from sage.all import *>>> m = matrix(RDF, [[-Integer(5), Integer(3), Integer(2), Integer(8)],˓→[Integer(10), Integer(2), Integer(4), -Integer(2)],[-Integer(1), ˓→Integer(10), -Integer(10), -Integer(17)],[-Integer(2), Integer(7),␣
˓→Integer(6), Integer(13)]])>>> m[ -5.03.0
2.0
8.0][ 10.0
2.0
4.0 -2.0][ -1.0 -10.0 -10.0 -17.0][ -2.0
7.0
6.0 13.0]>>> spectrum = m.left_eigenvectors()>>> for i in range(len(spectrum)):...
spectrum[i][Integer(1)][Integer(0)] = matrix(RDF,␣
˓→spectrum[i][Integer(1)]).echelon_form()[Integer(0)]>>> spectrum[Integer(0)] # tol 1e-13(2.0, [(1.0, 1.0, 1.0, 1.0)], 1)>>> spectrum[Integer(1)] # tol 1e-13(1.0, [(1.0, 0.8, 0.8, 0.6)], 1)>>> spectrum[Integer(2)] # tol 1e-13(-2.0, [(1.0, 0.4, 0.6, 0.2)], 1)(continues on next page)

762

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> spectrum[Integer(3)] # tol 1e-13(-1.0, [(1.0, 1.0, 2.0, 2.0)], 1)

A generalized eigenvalue problem:
sage: A = matrix(CDF, [[1+I, -2], [3, 4]])sage: B = matrix(CDF, [[0, 7-I], [2, -3]])
sage: E = A.eigenvectors_left(B)sage: all((v * A - e * v * B).norm() < 1e-14 for e, [v], _ in E)
True>>> from sage.all import *>>> A = matrix(CDF, [[Integer(1)+I, -Integer(2)], [Integer(3), Integer(4)]])>>> B = matrix(CDF, [[Integer(0), Integer(7)-I], [Integer(2), -Integer(3)]])>>> E = A.eigenvectors_left(B)>>> all((v * A - e * v * B).norm() < RealNumber( 1e-14 ) for e, [v], _ in E)
True

In a generalized eigenvalue problem with a singular matrix 𝐵, we can check the eigenvector property using
homogeneous coordinates, even though the quotient 𝛼/𝛽 is not always defined:
sage: A = matrix.identity(CDF, 2)
sage: B = matrix(CDF, [[2, 1+I], [4, 2+2*I]])sage: E = A.eigenvectors_left(B, homogeneous=True)
sage: all((beta * v * A - alpha * v * B).norm() < 1e-14....:
for (alpha, beta), [v], _ in E)
True>>> from sage.all import *>>> A = matrix.identity(CDF, Integer(2))>>> B = matrix(CDF, [[Integer(2), Integer(1)+I], [Integer(4),␣
˓→Integer(2)+Integer(2)*I]])>>> E = A.eigenvectors_left(B, homogeneous=True)>>> all((beta * v * A - alpha * v * B).norm() < RealNumber( 1e-14 )...
for (alpha, beta), [v], _ in E)
True

See also:
eigenvalues(), eigenvectors_right(), Matrix.eigenmatrix_left().
log_determinant()
Compute the log of the absolute value of the determinant using LU decomposition.
Note: This is useful if the usual determinant overflows.
EXAMPLES:
sage: m = matrix(RDF,2,2,range(4)); m[0.0 1.0][2.0 3.0]
sage: RDF(log(abs(m.determinant())))
0.6931471805599453
sage: m.log_determinant()
0.6931471805599453(continues on next page)763

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: m = matrix(RDF,0,0,[]); m[]
sage: m.log_determinant()
0.0
sage: m = matrix(CDF,2,2,range(4)); m[0.0 1.0][2.0 3.0]
sage: RDF(log(abs(m.determinant())))
0.6931471805599453
sage: m.log_determinant()
0.6931471805599453
sage: m = matrix(CDF,0,0,[]); m[]
sage: m.log_determinant()
0.0>>> from sage.all import *>>> m = matrix(RDF,Integer(2),Integer(2),range(Integer(4))); m[0.0 1.0][2.0 3.0]>>> RDF(log(abs(m.determinant())))
0.6931471805599453>>> m.log_determinant()
0.6931471805599453>>> m = matrix(RDF,Integer(0),Integer(0),[]); m[]>>> m.log_determinant()
0.0>>> m = matrix(CDF,Integer(2),Integer(2),range(Integer(4))); m[0.0 1.0][2.0 3.0]>>> RDF(log(abs(m.determinant())))
0.6931471805599453>>> m.log_determinant()
0.6931471805599453>>> m = matrix(CDF,Integer(0),Integer(0),[]); m[]>>> m.log_determinant()
0.0

norm(p=2)
Return the norm of the matrix.
INPUT:• p – (default: 2); controls which norm is computed, allowable values are ‘frob’ (for the Frobenius norm),
integers -2, -1, 1, 2, positive and negative infinity. See output discussion for specifics.
OUTPUT:
Returned value is a double precision floating point value in RDF. Row and column sums described below
are√ sums of the absolute values of the entries, where the absolute value of the complex number 𝑎 + 𝑏𝑖 is
𝑎2 + 𝑏2 . Singular values are the “diagonal” entries of the “S” matrix in the singular value decomposition.

764

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

• p =frob : the Frobenius norm, which for a matrix 𝐴 = (𝑎𝑖𝑗 ) computes
⎛
⎞1/2
∑︁
2
⎝
|𝑎𝑖,𝑗 | ⎠𝑖,𝑗

• p = Infinity or p = oo: the maximum row sum.
• p = -Infinity or p = -oo: the minimum column sum.
• p = 1: the maximum column sum.
• p = -1: the minimum column sum.
• p = 2: the induced 2-norm, equal to the maximum singular value.
• p = -2: the minimum singular value.
ALGORITHM:
Computation is performed by the norm() function of the SciPy/NumPy library.
EXAMPLES:First over the reals.
sage: A = matrix(RDF, 3, range(-3, 6)); A[-3.0 -2.0 -1.0][ 0.0 1.0 2.0]
[ 3.0 4.0 5.0]
sage: A.norm()
7.99575670...
sage: A.norm(p= frob )8.30662386...
sage: A.norm(p=Infinity)
12.0
sage: A.norm(p=-Infinity)
3.0
sage: A.norm(p=1)
8.0
sage: A.norm(p=-1)
6.0
sage: A.norm(p=2)
7.99575670...
sage: A.norm(p=-2) < 10^-15
True>>> from sage.all import *>>> A = matrix(RDF, Integer(3), range(-Integer(3), Integer(6))); A[-3.0 -2.0 -1.0][ 0.0 1.0 2.0]
[ 3.0 4.0 5.0]>>> A.norm()
7.99575670...
>>> A.norm(p= frob )8.30662386...
>>> A.norm(p=Infinity)
12.0>>> A.norm(p=-Infinity)
3.0(continues on next page)765

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> A.norm(p=Integer(1))
8.0>>> A.norm(p=-Integer(1))
6.0>>> A.norm(p=Integer(2))
7.99575670...
>>> A.norm(p=-Integer(2)) < Integer(10)**-Integer(15)True

And over the complex numbers.
sage: # needs sage.symbolic
sage: B = matrix(CDF, 2, [[1+I, 2+3*I],[3+4*I,3*I]]); B[1.0 + 1.0*I 2.0 + 3.0*I][3.0 + 4.0*I
3.0*I]
sage: B.norm()
6.66189877...
sage: B.norm(p= frob )7.0
sage: B.norm(p=Infinity)
8.0
sage: B.norm(p=-Infinity)
5.01976483...
sage: B.norm(p=1)
6.60555127...
sage: B.norm(p=-1)
6.41421356...
sage: B.norm(p=2)
6.66189877...
sage: B.norm(p=-2)
2.14921023...
>>> from sage.all import *>>> # needs sage.symbolic>>> B = matrix(CDF, Integer(2), [[Integer(1)+I, Integer(2)+Integer(3)*I],
˓→[Integer(3)+Integer(4)*I,Integer(3)*I]]); B[1.0 + 1.0*I 2.0 + 3.0*I][3.0 + 4.0*I
3.0*I]>>> B.norm()
6.66189877...
>>> B.norm(p= frob )7.0>>> B.norm(p=Infinity)
8.0>>> B.norm(p=-Infinity)
5.01976483...
>>> B.norm(p=Integer(1))
6.60555127...
>>> B.norm(p=-Integer(1))
6.41421356...
>>> B.norm(p=Integer(2))
6.66189877...
>>> B.norm(p=-Integer(2))
2.14921023...

Since it is invariant under unitary multiplication, the Frobenius norm is equal to the square root of the sumof squares of the singular values.
766

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

sage: A = matrix(RDF, 5, range(1,26))
sage: f = A.norm(p= frob )sage: U, S, V = A.SVD()
sage: s = sqrt(sum([S[i,i]^2 for i in range(5)]))sage: abs(f-s) < 1.0e-12
True>>> from sage.all import *>>> A = matrix(RDF, Integer(5), range(Integer(1),Integer(26)))>>> f = A.norm(p= frob )>>> U, S, V = A.SVD()>>> s = sqrt(sum([S[i,i]**Integer(2) for i in range(Integer(5))]))>>> abs(f-s) < RealNumber( 1.0e-12 )True

Return values are in 𝑅𝐷𝐹 .
sage: A = matrix(CDF, 2, range(4))
sage: A.norm() in RDF
True>>> from sage.all import *>>> A = matrix(CDF, Integer(2), range(Integer(4)))>>> A.norm() in RDF
True

Improper values of p are caught.
sage: A.norm(p= bogus )Traceback (most recent call last):...
ValueError: matrix norm p must be +/- infinity, frob or an integer, not␣
˓→bogussage: A.norm(p=632)
Traceback (most recent call last):...
ValueError: matrix norm integer values of p must be -2, -1, 1 or 2, not 632>>> from sage.all import *>>> A.norm(p= bogus )Traceback (most recent call last):...
ValueError: matrix norm p must be +/- infinity, frob or an integer, not␣
˓→bogus>>> A.norm(p=Integer(632))
Traceback (most recent call last):...
ValueError: matrix norm integer values of p must be -2, -1, 1 or 2, not 632

right_eigenvectors(other=None, homogeneous=False)
Compute the ordinary or generalized right eigenvectors of a matrix of double precision real or complex numbers (i.e. RDF or CDF).
INPUT:• other – a square matrix 𝐵 (default: None) in a generalized eigenvalue problem; if None, an ordinary
eigenvalue problem is solved
767Matrices and Spaces of Matrices, Release 10.4

• homogeneous – boolean (default: False); if True, use homogeneous coordinates for the eigenvalues in the output
OUTPUT:
A list of triples, each of the form (e,[v],1), where e is the eigenvalue, and v is an associated righteigenvector such that
𝐴𝑣 = 𝑒𝑣.
If the matrix 𝐴 is of size 𝑛, then there are 𝑛 triples.
If a matrix 𝐵 is passed as optional argument, the output is a solution to the generalized eigenvalue problem
such that
𝐴𝑣 = 𝑒𝐵𝑣.
If homogeneous is set, each eigenvalue is returned as a tuple (𝛼, 𝛽) of homogeneous coordinates such that
𝛽𝐴𝑣 = 𝛼𝐵𝑣.
The format of the output is designed to match the format for exact results. However, since matrices here
have numerical entries, the resulting eigenvalues will also be numerical. No attempt is made to determine
if two eigenvalues are equal, or if eigenvalues might actually be zero. So the algebraic multiplicity of eacheigenvalue is reported as 1. Decisions about equal eigenvalues or zero eigenvalues should be addressed in thecalling routine.
The SciPy routines used for these computations produce eigenvectors normalized to have length 1, but on
different hardware they may vary by a complex sign. So for doctests we have normalized output by forcing
their eigenvectors to have their first non-zero entry equal to one.
ALGORITHM:
Values are computed with the SciPy library using scipy.linalg.eig().
EXAMPLES:
sage: m = matrix(RDF, [[-9, -14, 19, -74],[-1, 2, 4, -11],[-4, -12, 6, -32],
˓→[0, -2, -1, 1]])
sage: m[ -9.0 -14.0 19.0 -74.0][ -1.0
2.0
4.0 -11.0][ -4.0 -12.0
6.0 -32.0][ 0.0 -2.0 -1.0
1.0]
sage: spectrum = m.right_eigenvectors()
sage: for i in range(len(spectrum)):....:
spectrum[i][1][0] = matrix(RDF, spectrum[i][1]).echelon_form()[0]sage: spectrum[0] # tol 1e-13(2.0, [(1.0, -2.0, 3.0, 1.0)], 1)
sage: spectrum[1] # tol 1e-13(1.0, [(1.0, -0.666666666666633, 1.333333333333286, 0.33333333333331555)], 1)
sage: spectrum[2] # tol 1e-13(-2.0, [(1.0, -0.2, 1.0, 0.2)], 1)
sage: spectrum[3] # tol 1e-12(-1.0, [(1.0, -0.5, 2.0, 0.5)], 1)>>> from sage.all import *>>> m = matrix(RDF, [[-Integer(9), -Integer(14), Integer(19), -Integer(74)],[˓→Integer(1), Integer(2), Integer(4), -Integer(11)],[-Integer(4), (continues on next page)

768

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Integer(12), Integer(6), -Integer(32)],[Integer(0), -Integer(2), ˓→Integer(1), Integer(1)]])>>> m[ -9.0 -14.0 19.0 -74.0][ -1.0
2.0
4.0 -11.0][ -4.0 -12.0
6.0 -32.0][ 0.0 -2.0 -1.0
1.0]>>> spectrum = m.right_eigenvectors()>>> for i in range(len(spectrum)):...
spectrum[i][Integer(1)][Integer(0)] = matrix(RDF,␣
˓→spectrum[i][Integer(1)]).echelon_form()[Integer(0)]>>> spectrum[Integer(0)] # tol 1e-13(2.0, [(1.0, -2.0, 3.0, 1.0)], 1)>>> spectrum[Integer(1)] # tol 1e-13(1.0, [(1.0, -0.666666666666633, 1.333333333333286, 0.33333333333331555)], 1)>>> spectrum[Integer(2)] # tol 1e-13(-2.0, [(1.0, -0.2, 1.0, 0.2)], 1)>>> spectrum[Integer(3)] # tol 1e-12(-1.0, [(1.0, -0.5, 2.0, 0.5)], 1)˓→A generalized eigenvalue problem:
sage: A = matrix(CDF, [[1+I, -2], [3, 4]])sage: B = matrix(CDF, [[0, 7-I], [2, -3]])
sage: E = A.eigenvectors_right(B)sage: all((A * v - e * B * v).norm() < 1e-14 for e, [v], _ in E)
True>>> from sage.all import *>>> A = matrix(CDF, [[Integer(1)+I, -Integer(2)], [Integer(3), Integer(4)]])>>> B = matrix(CDF, [[Integer(0), Integer(7)-I], [Integer(2), -Integer(3)]])>>> E = A.eigenvectors_right(B)>>> all((A * v - e * B * v).norm() < RealNumber( 1e-14 ) for e, [v], _ in E)
True

In a generalized eigenvalue problem with a singular matrix 𝐵, we can check the eigenvector property using
homogeneous coordinates, even though the quotient 𝛼/𝛽 is not always defined:
sage: A = matrix.identity(RDF, 2)
sage: B = matrix(RDF, [[3, 5], [6, 10]])sage: E = A.eigenvectors_right(B, homogeneous=True)
sage: all((beta * A * v - alpha * B * v).norm() < 1e-14....:
for (alpha, beta), [v], _ in E)
True>>> from sage.all import *>>> A = matrix.identity(RDF, Integer(2))>>> B = matrix(RDF, [[Integer(3), Integer(5)], [Integer(6), Integer(10)]])>>> E = A.eigenvectors_right(B, homogeneous=True)>>> all((beta * A * v - alpha * B * v).norm() < RealNumber( 1e-14 )...
for (alpha, beta), [v], _ in E)
True

See also:
eigenvalues(), eigenvectors_left(), Matrix.eigenmatrix_right().

769

Matrices and Spaces of Matrices, Release 10.4

round(ndigits=0)
Return a copy of the matrix where all entries have been rounded to a given precision in decimal digits (default
0 digits).
INPUT:• ndigits – The precision in number of decimal digits
OUTPUT:
A modified copy of the matrix
EXAMPLES:
sage: M = matrix(CDF, [[10.234r + 34.2343jr, 34e10r]])
sage: M
[10.234 + 34.2343*I
340000000000.0]
sage: M.round(2)[10.23 + 34.23*I 340000000000.0]
sage: M.round()[ 10.0 + 34.0*I 340000000000.0]>>> from sage.all import *>>> M = matrix(CDF, [[10.234 + 34.2343J, 34e10]])>>> M[10.234 + 34.2343*I
340000000000.0]>>> M.round(Integer(2))[10.23 + 34.23*I 340000000000.0]>>> M.round()[ 10.0 + 34.0*I 340000000000.0]

schur(base_ring=None)
Return the Schur decomposition of the matrix.
INPUT:• base_ring – optional, defaults to the base ring of self. Use this to request the base ring of the
returned matrices, which will affect the format of the results.
OUTPUT:
A pair of immutable matrices. The first is a unitary matrix 𝑄. The second, 𝑇 , is upper-triangular whenreturned over the complex numbers, while it is almost upper-triangular over the reals. In the latter case, there
can be some 2 × 2 blocks on the diagonal which represent a pair of conjugate complex eigenvalues of self.
If self is the matrix 𝐴, then𝐴 = 𝑄𝑇 (𝑄)𝑡where the latter matrix is the conjugate-transpose of Q, which is also the inverse of Q, since Q is unitary.
Note that in the case of a normal matrix (Hermitian, symmetric, and others), the upper-triangular matrix is adiagonal matrix with eigenvalues of self on the diagonal, and the unitary matrix has columns that form an
orthonormal basis composed of eigenvectors of self. This is known as “orthonormal diagonalization”.
Warning: The Schur decomposition is not unique, as there may be numerous choices for the vectorsof the orthonormal basis, and consequently different possibilities for the upper-triangular matrix. However, the diagonal of the upper-triangular matrix will always contain the eigenvalues of the matrix (in the

770

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

complex version), or 2 × 2 block matrices in the real version representing pairs of conjugate complex
eigenvalues.
In particular, results may vary across systems and processors.
EXAMPLES:First over the complexes. The similar matrix is always upper-triangular in this case.
sage: # needs sage.symbolic
sage: A = matrix(CDF, 4, 4, range(16)) + matrix(CDF, 4, 4,....:[x^3*I for x in range(0, 16)])
sage: Q, T = A.schur()sage: (Q*Q.conjugate().transpose()).zero_at(1e-12) # tol 1e-12[ 0.999999999999999
0.0
0.0
0.0]
[
0.0 0.9999999999999996
0.0
0.0]
[
0.0
0.0 0.9999999999999992
0.0]
[
0.0
0.0
0.0 0.9999999999999999]
sage: all(T.zero_at(1.0e-12)[i,j] == 0 for i in range(4) for j in range(i))
Truesage: (Q*T*Q.conjugate().transpose() - A).zero_at(1.0e-11)[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
sage: eigenvalues = [T[i,i] for i in range(4)]; eigenvalues[30.733... + 4648.541...*I, -0.184... - 159.057...*I, -0.523... + 11.158...*I,
˓→ -0.025... - 0.642...*I]
sage: A.eigenvalues()[30.733... + 4648.541...*I, -0.184... - 159.057...*I, -0.523... + 11.158...*I,
˓→ -0.025... - 0.642...*I]
sage: abs(A.norm()-T.norm()) < 1e-10
True>>> from sage.all import *>>> # needs sage.symbolic>>> A = matrix(CDF, Integer(4), Integer(4), range(Integer(16))) + matrix(CDF,␣
˓→Integer(4), Integer(4),...
[x**Integer(3)*I for x in␣˓→range(Integer(0), Integer(16))])>>> Q, T = A.schur()>>> (Q*Q.conjugate().transpose()).zero_at(RealNumber( 1e-12 )) # tol 1e-12[ 0.999999999999999
0.0
0.0
0.0]
[
0.0 0.9999999999999996
0.0
0.0]
[
0.0
0.0 0.9999999999999992
0.0]
[
0.0
0.0
0.0 0.9999999999999999]>>> all(T.zero_at(RealNumber( 1.0e-12 ))[i,j] == Integer(0) for i in␣
˓→range(Integer(4)) for j in range(i))
True>>> (Q*T*Q.conjugate().transpose() - A).zero_at(RealNumber( 1.0e-11 ))[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]>>> eigenvalues = [T[i,i] for i in range(Integer(4))]; eigenvalues[30.733... + 4648.541...*I, -0.184... - 159.057...*I, -0.523... + 11.158...*I,
˓→ -0.025... - 0.642...*I](continues on next page)771

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> A.eigenvalues()[30.733... + 4648.541...*I, -0.184... - 159.057...*I, -0.523... + 11.158...*I,
˓→ -0.025... - 0.642...*I]>>> abs(A.norm()-T.norm()) < RealNumber( 1e-10 )True

We begin with a real matrix but ask for a decomposition over the complexes. The result will yield anupper-triangular matrix over the complex numbers for T.
sage: A = matrix(RDF, 4, 4, [x^3 for x in range(16)])
sage: Q, T = A.schur(base_ring=CDF)
sage: (Q*Q.conjugate().transpose()).zero_at(1e-12) # tol 1e-12[0.9999999999999987
0.0
0.0
0.0]
[
0.0 0.9999999999999999
0.0
0.0]
[
0.0
0.0 1.0000000000000013
0.0]
[
0.0
0.0
0.0 1.0000000000000007]
sage: T.parent()
Full MatrixSpace of 4 by 4 dense matrices over Complex Double Field
sage: all(T.zero_at(1.0e-12)[i,j] == 0 for i in range(4) for j in range(i))
Truesage: (Q*T*Q.conjugate().transpose() - A).zero_at(1.0e-11)[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]>>> from sage.all import *>>> A = matrix(RDF, Integer(4), Integer(4), [x**Integer(3) for x in␣˓→range(Integer(16))])>>> Q, T = A.schur(base_ring=CDF)>>> (Q*Q.conjugate().transpose()).zero_at(RealNumber( 1e-12 )) # tol 1e-12[0.9999999999999987
0.0
0.0
0.0]
[
0.0 0.9999999999999999
0.0
0.0]
[
0.0
0.0 1.0000000000000013
0.0]
[
0.0
0.0
0.0 1.0000000000000007]>>> T.parent()
Full MatrixSpace of 4 by 4 dense matrices over Complex Double Field>>> all(T.zero_at(RealNumber( 1.0e-12 ))[i,j] == Integer(0) for i in␣
˓→range(Integer(4)) for j in range(i))
True>>> (Q*T*Q.conjugate().transpose() - A).zero_at(RealNumber( 1.0e-11 ))[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]

Now totally over the reals. But with complex eigenvalues, the similar matrix may not be upper-triangular.
But “at worst” there may be some 2 × 2 blocks on the diagonal which represent a pair of conjugate complex
eigenvalues. These blocks will then just interrupt the zeros below the main diagonal. This example has a pairof these of the blocks.
sage: A = matrix(RDF, 4, 4, [[1, 0, -3, -1],....:
[4, -16, -7, 0],....:[1, 21, 1, -2],....:
[26, -1, -2, 1]])
sage: Q, T = A.schur()(continues on next page)772

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: (Q*Q.conjugate().transpose()) # tol 1e-12[0.9999999999999994
0.0
0.0
0.0]
[
0.0 1.0000000000000013
0.0
0.0]
[
0.0
0.0 1.0000000000000004
0.0]
[
0.0
0.0
0.0 1.0000000000000016]
sage: all(T.zero_at(1.0e-12)[i,j] == 0 for i in range(4) for j in range(i))
False
sage: all(T.zero_at(1.0e-12)[i,j] == 0 for i in range(4) for j in range(i-1))
True
sage: (Q*T*Q.conjugate().transpose() - A).zero_at(1.0e-11)[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
sage: sorted(T[0:2,0:2].eigenvalues() + T[2:4,2:4].eigenvalues())[-5.710... - 8.382...*I, -5.710... + 8.382...*I, -0.789... - 2.336...*I, -0.
˓→789... + 2.336...*I]
sage: sorted(A.eigenvalues())[-5.710... - 8.382...*I, -5.710... + 8.382...*I, -0.789... - 2.336...*I, -0.
˓→789... + 2.336...*I]
sage: abs(A.norm()-T.norm()) < 1e-12
True>>> from sage.all import *>>> A = matrix(RDF, Integer(4), Integer(4), [[Integer(1), Integer(0), ˓→Integer(3), -Integer(1)],...
[Integer(4), -Integer(16), -Integer(7),␣
˓→Integer(0)],...
[Integer(1), Integer(21), Integer(1), -Integer(2)],...
[Integer(26), -Integer(1), -Integer(2),␣
˓→Integer(1)]])>>> Q, T = A.schur()>>> (Q*Q.conjugate().transpose()) # tol 1e-12[0.9999999999999994
0.0
0.0
0.0]
[
0.0 1.0000000000000013
0.0
0.0]
[
0.0
0.0 1.0000000000000004
0.0]
[
0.0
0.0
0.0 1.0000000000000016]>>> all(T.zero_at(RealNumber( 1.0e-12 ))[i,j] == Integer(0) for i in␣
˓→range(Integer(4)) for j in range(i))
False>>> all(T.zero_at(RealNumber( 1.0e-12 ))[i,j] == Integer(0) for i in␣
˓→range(Integer(4)) for j in range(i-Integer(1)))
True>>> (Q*T*Q.conjugate().transpose() - A).zero_at(RealNumber( 1.0e-11 ))[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]>>> sorted(T[Integer(0):Integer(2),Integer(0):Integer(2)].eigenvalues() +␣˓→T[Integer(2):Integer(4),Integer(2):Integer(4)].eigenvalues())[-5.710... - 8.382...*I, -5.710... + 8.382...*I, -0.789... - 2.336...*I, -0.
˓→789... + 2.336...*I]>>> sorted(A.eigenvalues())[-5.710... - 8.382...*I, -5.710... + 8.382...*I, -0.789... - 2.336...*I, -0.
˓→789... + 2.336...*I]>>> abs(A.norm()-T.norm()) < RealNumber( 1e-12 )
True

773

Matrices and Spaces of Matrices, Release 10.4

Starting with complex numbers and requesting a result over the reals will never happen.
sage: # needs sage.symbolic
sage: A = matrix(CDF, 2, 2, [[2+I, -1+3*I], [5-4*I, 2-7*I]])sage: A.schur(base_ring=RDF)
Traceback (most recent call last):...
TypeError: unable to convert input matrix over CDF to a matrix over RDF>>> from sage.all import *>>> # needs sage.symbolic>>> A = matrix(CDF, Integer(2), Integer(2), [[Integer(2)+I, ˓→Integer(1)+Integer(3)*I], [Integer(5)-Integer(4)*I, Integer(2)˓→Integer(7)*I]])>>> A.schur(base_ring=RDF)
Traceback (most recent call last):...
TypeError: unable to convert input matrix over CDF to a matrix over RDF

If theory predicts your matrix is real, but it contains some very small imaginary parts, you can specify thecutoff for “small” imaginary parts, then request the output as real matrices, and let the routine do the rest.
sage: A = matrix(RDF, 2, 2, [1, 1, -1, 0]) + matrix(CDF, 2, 2, [1.0e-14*I]*4)
sage: B = A.zero_at(1.0e-12)
sage: B.parent()
Full MatrixSpace of 2 by 2 dense matrices over Complex Double Field
sage: Q, T = B.schur(RDF)
sage: Q.parent()
Full MatrixSpace of 2 by 2 dense matrices over Real Double Field
sage: T.parent()
Full MatrixSpace of 2 by 2 dense matrices over Real Double Field
sage: Q.round(6)[ 0.707107 0.707107][-0.707107 0.707107]
sage: T.round(6)[ 0.5 1.5][-0.5 0.5]
sage: (Q*T*Q.conjugate().transpose() - B).zero_at(1.0e-11)[0.0 0.0][0.0 0.0]>>> from sage.all import *>>> A = matrix(RDF, Integer(2), Integer(2), [Integer(1), Integer(1), ˓→Integer(1), Integer(0)]) + matrix(CDF, Integer(2), Integer(2), [RealNumber(
˓→ 1.0e-14 )*I]*Integer(4))>>> B = A.zero_at(RealNumber( 1.0e-12 ))>>> B.parent()
Full MatrixSpace of 2 by 2 dense matrices over Complex Double Field>>> Q, T = B.schur(RDF)>>> Q.parent()
Full MatrixSpace of 2 by 2 dense matrices over Real Double Field>>> T.parent()
Full MatrixSpace of 2 by 2 dense matrices over Real Double Field>>> Q.round(Integer(6))[ 0.707107 0.707107][-0.707107 0.707107]>>> T.round(Integer(6))(continues on next page)

774

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 0.5 1.5][-0.5 0.5]>>> (Q*T*Q.conjugate().transpose() - B).zero_at(RealNumber( 1.0e-11 ))[0.0 0.0][0.0 0.0]

A Hermitian matrix has real eigenvalues, so the similar matrix will be upper-triangular. Furthermore, aHermitian matrix is diagonalizable with respect to an orthonormal basis, composed of eigenvectors of thematrix. Here that basis is the set of columns of the unitary matrix.
sage: # needs sage.symbolic
sage: A = matrix(CDF, [[52,-9*I - 8,
6*I - 187, -188*I + 2],....:[
9*I - 8,12,
-58*I + 59,
30*I + 42],....:[-6*I - 187, 58*I + 59,
2677, 2264*I + 65],....:
[ 188*I + 2, -30*I + 42, -2264*I + 65,
2080]])
sage: Q, T = A.schur()sage: T = T.zero_at(1.0e-12).change_ring(RDF)
sage: T.round(6)[4680.13301
0.0
0.0
0.0]
[
0.0 102.715967
0.0
0.0]
[
0.0
0.0 35.039344
0.0]
[
0.0
0.0
0.0
3.11168]
sage: (Q*Q.conjugate().transpose()).zero_at(1e-12) # tol 1e-12[1.0000000000000004
0.0
0.0
0.0]
[
0.0 0.9999999999999989
0.0
0.0]
[
0.0
0.0 1.0000000000000002
0.0]
[
0.0
0.0
0.0 0.9999999999999992]
sage: (Q*T*Q.conjugate().transpose() - A).zero_at(1.0e-11)[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]>>> from sage.all import *>>> # needs sage.symbolic>>> A = matrix(CDF, [[Integer(52),-Integer(9)*I - Integer(8),␣˓→Integer(6)*I - Integer(187),-Integer(188)*I + Integer(2)],...
[Integer(9)*I - Integer(8),Integer(12),
˓→Integer(58)*I + Integer(59),Integer(30)*I + Integer(42)],...
[-Integer(6)*I - Integer(187), Integer(58)*I +␣˓→Integer(59),Integer(2677), Integer(2264)*I + Integer(65)],...
[ Integer(188)*I + Integer(2), -Integer(30)*I +␣˓→Integer(42), -Integer(2264)*I + Integer(65),Integer(2080)]])>>> Q, T = A.schur()>>> T = T.zero_at(RealNumber( 1.0e-12 )).change_ring(RDF)>>> T.round(Integer(6))[4680.13301
0.0
0.0
0.0]
[
0.0 102.715967
0.0
0.0]
[
0.0
0.0 35.039344
0.0]
[
0.0
0.0
0.0
3.11168]>>> (Q*Q.conjugate().transpose()).zero_at(RealNumber( 1e-12 )) # tol 1e-12[1.0000000000000004
0.0
0.0
0.0]
[
0.0 0.9999999999999989
0.0
0.0]
[
0.0
0.0 1.0000000000000002
0.0]
[
0.0
0.0
0.0 0.9999999999999992]>>> (Q*T*Q.conjugate().transpose() - A).zero_at(RealNumber( 1.0e-11 ))(continues on next page)775

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]

Similarly, a real symmetric matrix has only real eigenvalues, and there is an orthonormal basis composed of
eigenvectors of the matrix.
sage: A = matrix(RDF, [[ 1, -2, 5, -3],....:[-2, 9, 1, 5],....:[ 5, 1, 3 , 7],....:[-3, 5, 7, -8]])sage: Q, T = A.schur()sage: Q.round(4)[-0.3027 -0.751
0.576 -0.1121][ 0.139 -0.3892 -0.2648 0.8713][ 0.4361
0.359 0.7599 0.3217][ -0.836 0.3945 0.1438 0.3533]
sage: T = T.zero_at(10^-12)
sage: all(abs(e) < 10^-4....:for e in (T - diagonal_matrix(RDF, [-13.5698, -0.8508, 7.7664, 11.
˓→6542])).list())
True
sage: (Q*Q.transpose()) # tol 1e-12[0.9999999999999998
0.0
0.0
0.0]
[
0.0
1.0
0.0
0.0]
[
0.0
0.0 0.9999999999999998
0.0]
[
0.0
0.0
0.0 0.9999999999999996]
sage: (Q*T*Q.transpose() - A).zero_at(1.0e-11)[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]>>> from sage.all import *>>> A = matrix(RDF, [[ Integer(1), -Integer(2), Integer(5), -Integer(3)],...
[-Integer(2), Integer(9), Integer(1), Integer(5)],...
[ Integer(5), Integer(1), Integer(3) , Integer(7)],...
[-Integer(3), Integer(5), Integer(7), -Integer(8)]])>>> Q, T = A.schur()>>> Q.round(Integer(4))[-0.3027 -0.751
0.576 -0.1121][ 0.139 -0.3892 -0.2648 0.8713][ 0.4361
0.359 0.7599 0.3217][ -0.836 0.3945 0.1438 0.3533]>>> T = T.zero_at(Integer(10)**-Integer(12))>>> all(abs(e) < Integer(10)**-Integer(4)...
for e in (T - diagonal_matrix(RDF, [-RealNumber( 13.5698 ), ˓→RealNumber( 0.8508 ), RealNumber( 7.7664 ), RealNumber( 11.6542 )])).list())
True>>> (Q*Q.transpose()) # tol 1e-12[0.9999999999999998
0.0
0.0
0.0]
[
0.0
1.0
0.0
0.0]
[
0.0
0.0 0.9999999999999998
0.0]
[
0.0
0.0
0.0 0.9999999999999996]>>> (Q*T*Q.transpose() - A).zero_at(RealNumber( 1.0e-11 ))(continues on next page)

776

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]
[0.0 0.0 0.0 0.0]

The results are cached, both as a real factorization and also as a complex factorization. This means the returned
matrices are immutable.
sage: A = matrix(RDF, 2, 2, [[0, -1], [1, 0]])sage: Qr, Tr = A.schur(base_ring=RDF)
sage: Qc, Tc = A.schur(base_ring=CDF)
sage: all(M.is_immutable() for M in [Qr, Tr, Qc, Tc])
True
sage: Tr.round(6) != Tc.round(6)True>>> from sage.all import *>>> A = matrix(RDF, Integer(2), Integer(2), [[Integer(0), -Integer(1)],␣
˓→[Integer(1), Integer(0)]])>>> Qr, Tr = A.schur(base_ring=RDF)>>> Qc, Tc = A.schur(base_ring=CDF)>>> all(M.is_immutable() for M in [Qr, Tr, Qc, Tc])
True>>> Tr.round(Integer(6)) != Tc.round(Integer(6))
True

AUTHOR:• Rob Beezer (2011-03-31)
singular_values(eps=None)
Return a sorted list of the singular values of the matrix.
INPUT:• eps – (default: None); the largest number which will be considered to be zero. May also be set to thestring ‘auto’. See the discussion below.
OUTPUT:
A sorted list of the singular values of the matrix, which are the diagonal entries of the “S” matrix in the SVD
decomposition. As such, the values are real and are returned as elements of RDF. The list is sorted withlarger values first, and since theory predicts these values are always positive, for a rank-deficient matrix thelist should end in zeros (but in practice may not). The length of the list is the minimum of the row count andcolumn count for the matrix.
The number of non-zero singular values will be the rank of the matrix. However, as a numerical matrix, it
is impossible to control the difference between zero entries and very small non-zero entries. As an informed
consumer it is up to you to use the output responsibly. We will do our best, and give you the tools to workwith the output, but we cannot give you a guarantee.
With eps set to None you will get the raw singular values and can manage them as you see fit. You may
also set eps to any positive floating point value you wish. If you set eps to ‘auto’ this routine will computea reasonable cutoff value, based on the size of the matrix, the largest singular value and the smallest nonzero
value representable by the 53-bit precision values used. See the discussion at page 268 of [Wat2010].
See the examples for a way to use the “verbose” facility to easily watch the zero cutoffs in action.
ALGORITHM:
777

Matrices and Spaces of Matrices, Release 10.4

The singular values come from the SVD decomposition computed by SciPy/NumPy using scipy.
linalg.svd().
EXAMPLES:
Singular values close to zero have trailing digits that may vary on different hardware. For exact matrices, thenumber of non-zero singular values will equal the rank of the matrix. So for some of the doctests we roundthe small singular values that ideally would be zero, to control the variability across hardware.
This matrix has a determinant of one. A chain of two or three theorems implies the product of the singularvalues must also be one.
sage: A = matrix(QQ, [[ 1, 0, 0, 0, 0, 1, 3],....:[-2, 1, 1, -2, 0, -4, 0],....:[ 1, 0, 1, -4, -6, -3, 7],....:[-2, 2, 1, 1, 7, 1, -1],....:[-1, 0, -1, 5, 8, 4, -6],....:
[ 4, -2, -2, 1, -3, 0, 8],....:[-2, 1, 0, 2, 7, 3, -4]])
sage: A.determinant()
1sage: B = A.change_ring(RDF)
sage: sv = B.singular_values(); sv # tol 1e-12[20.523980658874265, 8.486837028536643, 5.86168134845073, 2.4429165899286978,␣
˓→0.5831970144724045, 0.26933287286576313, 0.0025524488076110402]
sage: prod(sv) # tol 1e-120.9999999999999525>>> from sage.all import *>>> A = matrix(QQ, [[ Integer(1), Integer(0), Integer(0), Integer(0), ␣
˓→Integer(0),Integer(1), Integer(3)],...
[-Integer(2), Integer(1), Integer(1), -Integer(2), ␣
˓→Integer(0), -Integer(4),Integer(0)],...
[ Integer(1), Integer(0), Integer(1), -Integer(4), ˓→Integer(6), -Integer(3),Integer(7)],...
[-Integer(2), Integer(2), Integer(1), Integer(1), ␣
˓→Integer(7),Integer(1), -Integer(1)],...
[-Integer(1), Integer(0), -Integer(1), Integer(5), ␣˓→Integer(8),Integer(4), -Integer(6)],...
[ Integer(4), -Integer(2), -Integer(2), Integer(1), ˓→Integer(3),Integer(0), Integer(8)],...
[-Integer(2), Integer(1), Integer(0), Integer(2), ␣
˓→Integer(7),Integer(3), -Integer(4)]])>>> A.determinant()
1>>> B = A.change_ring(RDF)>>> sv = B.singular_values(); sv # tol 1e-12[20.523980658874265, 8.486837028536643, 5.86168134845073, 2.4429165899286978,␣
˓→0.5831970144724045, 0.26933287286576313, 0.0025524488076110402]>>> prod(sv) # tol 1e-120.9999999999999525

An exact matrix that is obviously not of full rank, and then a computation of the singular values after conversion to an approximate matrix.
sage: A = matrix(QQ, [[1/3, 2/3, 11/3],....:[2/3, 1/3, 7/3],....:[2/3, 5/3, 27/3]])(continues on next page)

778

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: A.rank()
2sage: B = A.change_ring(CDF)
sage: sv = B.singular_values()
sage: sv[0:2][10.1973039..., 0.487045871...]
sage: sv[2] < 1e-14
True>>> from sage.all import *>>> A = matrix(QQ, [[Integer(1)/Integer(3), Integer(2)/Integer(3),␣
˓→Integer(11)/Integer(3)],...
[Integer(2)/Integer(3), Integer(1)/Integer(3), ␣
˓→Integer(7)/Integer(3)],...
[Integer(2)/Integer(3), Integer(5)/Integer(3),␣
˓→Integer(27)/Integer(3)]])>>> A.rank()
2>>> B = A.change_ring(CDF)>>> sv = B.singular_values()>>> sv[Integer(0):Integer(2)][10.1973039..., 0.487045871...]>>> sv[Integer(2)] < RealNumber( 1e-14 )True

A matrix of rank 3 over the complex numbers.
sage: A = matrix(CDF, [[46*I - 28, -47*I - 50, 21*I + 51, -62*I - 782, 13*I +␣
˓→22],....:[35*I - 20, -32*I - 46, 18*I + 43, -57*I - 670, 7*I +␣
˓→3],
....:
[22*I - 13, -23*I - 23, 9*I + 24, -26*I - 347, 7*I +␣
˓→13],....:[-44*I + 23, 41*I + 57, -19*I - 54, 60*I + 757, -11*I ˓→ 9],....:[30*I - 18, -30*I - 34, 14*I + 34, -42*I - 522, 8*I +␣
˓→12]])
sage: sv = A.singular_values()
sage: sv[0:3] # tol 1e-14[1440.7336659952966, 18.404403413369227, 6.839707797136151]
sage: (sv[3] < 10^-13) or sv[3]Truesage: (sv[4] < 10^-14) or sv[4]True>>> from sage.all import *>>> A = matrix(CDF, [[Integer(46)*I - Integer(28), -Integer(47)*I -␣˓→Integer(50), Integer(21)*I + Integer(51), -Integer(62)*I - Integer(782),␣
˓→Integer(13)*I + Integer(22)],...
[Integer(35)*I - Integer(20), -Integer(32)*I -␣˓→Integer(46), Integer(18)*I + Integer(43), -Integer(57)*I - Integer(670),␣
˓→Integer(7)*I + Integer(3)],...
[Integer(22)*I - Integer(13), -Integer(23)*I -␣˓→Integer(23), Integer(9)*I + Integer(24), -Integer(26)*I - Integer(347),␣
˓→Integer(7)*I + Integer(13)],...
[-Integer(44)*I + Integer(23), Integer(41)*I +␣
(continues on next page)779

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Integer(57), -Integer(19)*I - Integer(54), Integer(60)*I + Integer(757), ˓→Integer(11)*I - Integer(9)],...
[Integer(30)*I - Integer(18), -Integer(30)*I -␣˓→Integer(34), Integer(14)*I + Integer(34), -Integer(42)*I - Integer(522),␣
˓→Integer(8)*I + Integer(12)]])>>> sv = A.singular_values()>>> sv[Integer(0):Integer(3)] # tol 1e-14[1440.7336659952966, 18.404403413369227, 6.839707797136151]>>> (sv[Integer(3)] < Integer(10)**-Integer(13)) or sv[Integer(3)]True>>> (sv[Integer(4)] < Integer(10)**-Integer(14)) or sv[Integer(4)]True˓→A full-rank matrix that is ill-conditioned. We use this to illustrate ways of using the various possibilities
for eps, including one that is ill-advised. Notice that the automatically computed cutoff gets this (difficult)example slightly wrong. This illustrates the impossibility of any automated process always getting this right.
Use with caution and judgement.
sage: entries = [1/(i+j+1) for i in range(12) for j in range(12)]sage: B = matrix(QQ, 12, 12, entries)
sage: B.rank()
12sage: A = B.change_ring(RDF)
sage: A.condition() > 1.59e16 or A.condition()Truesage: A.singular_values(eps=None) # abs tol 7e-16[1.7953720595619975, 0.38027524595503703, 0.04473854875218107, 0.
˓→0037223122378911614, 0.0002330890890217751, 1.116335748323284e-05, 4.
˓→082376110397296e-07, 1.1228610675717613e-08, 2.2519645713496478e-10, 3.
˓→1113486853814003e-12, 2.6500422260778388e-14, 9.87312834948426e-17]
sage: A.singular_values(eps= auto ) # abs tol 7e-16[1.7953720595619975, 0.38027524595503703, 0.04473854875218107, 0.
˓→0037223122378911614, 0.0002330890890217751, 1.116335748323284e-05, 4.
˓→082376110397296e-07, 1.1228610675717613e-08, 2.2519645713496478e-10, 3.
˓→1113486853814003e-12, 2.6500422260778388e-14, 0.0]
sage: A.singular_values(eps=1e-4) # abs tol 7e-16[1.7953720595619975, 0.38027524595503703, 0.04473854875218107, 0.
˓→0037223122378911614, 0.0002330890890217751, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.
˓→0]>>> from sage.all import *>>> entries = [Integer(1)/(i+j+Integer(1)) for i in range(Integer(12)) for j␣
˓→in range(Integer(12))]>>> B = matrix(QQ, Integer(12), Integer(12), entries)>>> B.rank()
12>>> A = B.change_ring(RDF)>>> A.condition() > RealNumber( 1.59e16 ) or A.condition()
True>>> A.singular_values(eps=None) # abs tol 7e-16[1.7953720595619975, 0.38027524595503703, 0.04473854875218107, 0.
˓→0037223122378911614, 0.0002330890890217751, 1.116335748323284e-05, 4.
˓→082376110397296e-07, 1.1228610675717613e-08, 2.2519645713496478e-10, 3.
˓→1113486853814003e-12, 2.6500422260778388e-14, 9.87312834948426e-17](continues on next page)

780

Chapter 21. Dense matrices using a NumPy backend

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> A.singular_values(eps= auto ) # abs tol 7e-16[1.7953720595619975, 0.38027524595503703, 0.04473854875218107, 0.
˓→0037223122378911614, 0.0002330890890217751, 1.116335748323284e-05, 4.
˓→082376110397296e-07, 1.1228610675717613e-08, 2.2519645713496478e-10, 3.
˓→1113486853814003e-12, 2.6500422260778388e-14, 0.0]>>> A.singular_values(eps=RealNumber( 1e-4 )) # abs tol 7e-16[1.7953720595619975, 0.38027524595503703, 0.04473854875218107, 0.
˓→0037223122378911614, 0.0002330890890217751, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.
˓→0]With Sage’s “verbose” facility, you can compactly see the cutoff at work. In any application of this routine,or those that build upon it, it would be a good idea to conduct this exercise on samples. We also test here that
all the values are returned in 𝑅𝐷𝐹 since singular values are always real.
sage: A = matrix(CDF, 4, range(16))
sage: from sage.misc.verbose import set_verbose
sage: set_verbose(1)sage: sv = A.singular_values(eps= auto ); sv
verbose 1 (<module>) singular values,
smallest-non-zero:cutoff:largest-zero,2.2766...:6.2421...e-14:...
[35.13996365902..., 2.27661020871472..., 0.0, 0.0]
sage: set_verbose(0)sage: all(s in RDF for s in sv)
True>>> from sage.all import *>>> A = matrix(CDF, Integer(4), range(Integer(16)))>>> from sage.misc.verbose import set_verbose>>> set_verbose(Integer(1))>>> sv = A.singular_values(eps= auto ); sv
verbose 1 (<module>) singular values,
smallest-non-zero:cutoff:largest-zero,2.2766...:6.2421...e-14:...
[35.13996365902..., 2.27661020871472..., 0.0, 0.0]>>> set_verbose(Integer(0))>>> all(s in RDF for s in sv)
True

AUTHOR:• Rob Beezer - (2011-02-18)
zero_at(eps)Return a copy of the matrix where elements smaller than or equal to eps are replaced with zeroes. For
complex matrices, the real and imaginary parts are considered individually.
This is useful for modifying output from algorithms which have large relative errors when producing zeroelements, e.g. to create reliable doctests.
INPUT:• eps – Cutoff value
OUTPUT:
A modified copy of the matrix.
781

Matrices and Spaces of Matrices, Release 10.4

EXAMPLES:
sage: # needs sage.symbolic
sage: a = matrix(CDF, [[1, 1e-4r, 1+1e-100jr], [1e-8+3j, 0, 1e-58r]])
sage: a[1.0
0.0001 1.0 + 1e-100*I][ 1e-08 + 3.0*I
0.0
1e-58]
sage: a.zero_at(1e-50)[
1.00.00011.0][1e-08 + 3.0*I
0.0
0.0]
sage: a.zero_at(1e-4)
[ 1.0
0.0
1.0]
[3.0*I
0.0
0.0]>>> from sage.all import *>>> # needs sage.symbolic>>> a = matrix(CDF, [[Integer(1), 1e-4, Integer(1)+1e-100J], [RealNumber( 1e-8˓→ )+ComplexNumber(0,3 ), Integer(0), 1e-58]])
>>> a
[
1.0
0.0001 1.0 + 1e-100*I][ 1e-08 + 3.0*I
0.0
1e-58]>>> a.zero_at(RealNumber( 1e-50 ))[1.0
0.00011.0][1e-08 + 3.0*I
0.0
0.0]>>> a.zero_at(RealNumber( 1e-4 ))
[ 1.0
0.0
1.0]
[3.0*I
0.0
0.0]

782

Chapter 21. Dense matrices using a NumPy backend

CHAPTERTWENTYTWODENSE MATRICES OVER THE REAL DOUBLE FIELD USING NUMPYEXAMPLES:
sage: b = Mat(RDF,2,3).basis()
sage: b[0,0][1.0 0.0 0.0]
[0.0 0.0 0.0]>>> from sage.all import *>>> b = Mat(RDF,Integer(2),Integer(3)).basis()>>> b[Integer(0),Integer(0)][1.0 0.0 0.0]
[0.0 0.0 0.0]

We deal with the case of zero rows or zero columns:
sage: m = MatrixSpace(RDF,0,3)
sage: m.zero_matrix()[]>>> from sage.all import *>>> m = MatrixSpace(RDF,Integer(0),Integer(3))>>> m.zero_matrix()[]

AUTHORS:• Jason Grout (2008-09): switch to NumPy backend, factored out the Matrix_double_dense class• Josh Kantor• William Stein: many bug fixes and touch ups.
class sage.matrix.matrix_real_double_dense.Matrix_real_double_dense
Bases: Matrix_double_denseClass that implements matrices over the real double field. These are supposed to be fast matrix operations using C
doubles. Most operations are implemented using numpy which will call the underlying BLAS on the system.
EXAMPLES:
sage: m = Matrix(RDF, [[1,2],[3,4]])
sage: m**2
[ 7.0 10.0][15.0 22.0]
sage: n = m^(-1); n# rel tol 1e-15#␣(continues on next page)783

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)needs scipy[-1.9999999999999996 0.9999999999999998][ 1.4999999999999998 -0.4999999999999999]
˓→>>> from sage.all import *>>> m = Matrix(RDF, [[Integer(1),Integer(2)],[Integer(3),Integer(4)]])>>> m**Integer(2)[ 7.0 10.0][15.0 22.0]>>> n = m**(-Integer(1)); n# rel tol 1e-15
˓→# needs scipy[-1.9999999999999996 0.9999999999999998][ 1.4999999999999998 -0.4999999999999999]

␣

To compute eigenvalues, use the method left_eigenvectors() or right_eigenvectors().
sage: p,e = m.right_eigenvectors()
˓→needs scipy>>> from sage.all import *>>> p,e = m.right_eigenvectors()
˓→needs scipy#␣#␣The result is a pair (p,e), where p is a diagonal matrix of eigenvalues and e is a matrix whose columns are theeigenvectors.
To solve a linear system 𝐴𝑥 = 𝑏 where A = [[1,2],[3,4]] and 𝑏 = [5, 6]:
sage: b = vector(RDF,[5,6])
sage: m.solve_right(b) # rel tol 1e-15
˓→needs scipy(-3.9999999999999987, 4.499999999999999)>>> from sage.all import *>>> b = vector(RDF,[Integer(5),Integer(6)])>>> m.solve_right(b) # rel tol 1e-15
˓→needs scipy(-3.9999999999999987, 4.499999999999999)#␣#␣

See the methods QR(), LU(), and SVD() for QR, LU, and singular value decomposition.

784

Chapter 22. Dense matrices over the Real Double Field using NumPy

CHAPTERTWENTYTHREE

DENSE MATRICES OVER GF(2) USING THE M4RI LIBRARYAUTHOR: Martin Albrecht <malb@informatik.uni-bremen.de>
EXAMPLES:
sage: a = matrix(GF(2),3,range(9),sparse=False); a[0 1 0][1 0 1][0 1 0]sage: a.rank()
2sage: type(a)<class sage.matrix.matrix_mod2_dense.Matrix_mod2_dense >sage: a[0,0] = 1
sage: a.rank()
3sage: parent(a)Full MatrixSpace of 3 by 3 dense matrices over Finite Field of size 2
sage: a^2
[0 1 1][1 0 0][1 0 1]
sage: a+a[0 0 0][0 0 0][0 0 0]sage: b = a.new_matrix(2,3,range(6)); b[0 1 0][1 0 1]
sage: a*b
Traceback (most recent call last):...
TypeError: unsupported operand parent(s) for *: Full MatrixSpace of 3 by 3 dense␣˓→matrices over Finite Field of size 2
and Full MatrixSpace of 2 by 3 dense␣˓→matrices over Finite Field of size 2
sage: b*a
[1 0 1][1 0 0]sage: TestSuite(a).run()sage: TestSuite(b).run()(continues on next page)785

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: a.echelonize(); a[1 0 0][0 1 0][0 0 1]
sage: b.echelonize(); b[1 0 1][0 1 0]>>> from sage.all import *>>> a = matrix(GF(Integer(2)),Integer(3),range(Integer(9)),sparse=False); a[0 1 0][1 0 1][0 1 0]>>> a.rank()
2>>> type(a)<class sage.matrix.matrix_mod2_dense.Matrix_mod2_dense >>>> a[Integer(0),Integer(0)] = Integer(1)>>> a.rank()
3>>> parent(a)Full MatrixSpace of 3 by 3 dense matrices over Finite Field of size 2>>> a**Integer(2)[0 1 1][1 0 0][1 0 1]>>> a+a[0 0 0][0 0 0][0 0 0]>>> b = a.new_matrix(Integer(2),Integer(3),range(Integer(6))); b[0 1 0][1 0 1]>>> a*b
Traceback (most recent call last):...
TypeError: unsupported operand parent(s) for *: Full MatrixSpace of 3 by 3 dense␣˓→matrices over Finite Field of size 2
and Full MatrixSpace of 2 by 3 dense␣˓→matrices over Finite Field of size 2>>> b*a[1 0 1][1 0 0]>>> TestSuite(a).run()>>> TestSuite(b).run()>>> a.echelonize(); a[1 0 0][0 1 0][0 0 1]>>> b.echelonize(); b[1 0 1][0 1 0]786

Chapter 23. Dense matrices over GF(2) using the M4RI libraryMatrices and Spaces of Matrices, Release 10.4

Todo:
• make LinBox frontend and use it– charpoly ?
– minpoly ?
• make Matrix_modn_frontend and use it (?)
class sage.matrix.matrix_mod2_dense.Matrix_mod2_dense
Bases: Matrix_dense
Dense matrix over GF(2).
augment(right, subdivide=False)
Augments self with right.
EXAMPLES:
sage: MS = MatrixSpace(GF(2),3,3)
sage: A = MS([0, 1, 0, 1, 1, 0, 1, 1, 1]); A[0 1 0][1 1 0][1 1 1]
sage: B = A.augment(MS(1)); B[0 1 0 1 0 0]
[1 1 0 0 1 0]
[1 1 1 0 0 1]
sage: B.echelonize(); B[1 0 0 1 1 0]
[0 1 0 1 0 0]
[0 0 1 0 1 1]
sage: C = B.matrix_from_columns([3,4,5]); C[1 1 0][1 0 0][0 1 1]
sage: C == ~A
True
sage: C*A == MS(1)True>>> from sage.all import *>>> MS = MatrixSpace(GF(Integer(2)),Integer(3),Integer(3))>>> A = MS([Integer(0), Integer(1), Integer(0), Integer(1), Integer(1),␣
˓→Integer(0), Integer(1), Integer(1), Integer(1)]); A[0 1 0][1 1 0][1 1 1]>>> B = A.augment(MS(Integer(1))); B[0 1 0 1 0 0]
[1 1 0 0 1 0]
[1 1 1 0 0 1]>>> B.echelonize(); B[1 0 0 1 1 0]
[0 1 0 1 0 0]
[0 0 1 0 1 1]>>> C = B.matrix_from_columns([Integer(3),Integer(4),Integer(5)]); C(continues on next page)787

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[1 1 0][1 0 0][0 1 1]>>> C == ~A
True>>> C*A == MS(Integer(1))
True

A vector may be augmented to a matrix.
sage: A = matrix(GF(2), 3, 4, range(12))
sage: v = vector(GF(2), 3, range(3))
sage: A.augment(v)[0 1 0 1 0]
[0 1 0 1 1]
[0 1 0 1 0]>>> from sage.all import *>>> A = matrix(GF(Integer(2)), Integer(3), Integer(4), range(Integer(12)))>>> v = vector(GF(Integer(2)), Integer(3), range(Integer(3)))>>> A.augment(v)[0 1 0 1 0]
[0 1 0 1 1]
[0 1 0 1 0]

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(GF(2), 3, 5, range(15))
sage: B = matrix(GF(2), 3, 3, range(9))
sage: A.augment(B, subdivide=True)[0 1 0 1 0|0 1 0]
[1 0 1 0 1|1 0 1]
[0 1 0 1 0|0 1 0]>>> from sage.all import *>>> A = matrix(GF(Integer(2)), Integer(3), Integer(5), range(Integer(15)))>>> B = matrix(GF(Integer(2)), Integer(3), Integer(3), range(Integer(9)))>>> A.augment(B, subdivide=True)[0 1 0 1 0|0 1 0]
[1 0 1 0 1|1 0 1]
[0 1 0 1 0|0 1 0]

columns(copy=True)
Return list of the columns of self.
INPUT:• copy – (default: True) if True, return a copy so you can modify it safely
EXAMPLES:
An example with a small 3x3 matrix:
sage: M2 = Matrix(GF(2), [[1, 0, 0], [0, 1, 0], [0, 1, 1]])
sage: M2.columns()[(1, 0, 0), (0, 1, 1), (0, 0, 1)]788

Chapter 23. Dense matrices over GF(2) using the M4RI libraryMatrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> M2 = Matrix(GF(Integer(2)), [[Integer(1), Integer(0), Integer(0)],␣
˓→[Integer(0), Integer(1), Integer(0)], [Integer(0), Integer(1), Integer(1)]])>>> M2.columns()[(1, 0, 0), (0, 1, 1), (0, 0, 1)]

density(approx=False)
Return the density of this matrix.
By density we understand the ratio of the number of nonzero positions and the self.nrows() * self.ncols(), i.e.
the number of possible nonzero positions.
INPUT:• approx – return floating point approximation (default: False)
EXAMPLES:
sage: A = random_matrix(GF(2), 1000, 1000)
sage: d = A.density()
sage: float(d) == A.density(approx=True)
True
sage: len(A.nonzero_positions())/1000^2 == dTruesage: total = 1.0
sage: density_sum = A.density()
sage: while abs(density_sum/total - 0.5) > 0.001:....:
A = random_matrix(GF(2), 1000, 1000)....:
total += 1....:
density_sum += A.density()>>> from sage.all import *>>> A = random_matrix(GF(Integer(2)), Integer(1000), Integer(1000))>>> d = A.density()>>> float(d) == A.density(approx=True)
True>>> len(A.nonzero_positions())/Integer(1000)**Integer(2) == dTrue>>> total = RealNumber( 1.0 )>>> density_sum = A.density()>>> while abs(density_sum/total - RealNumber( 0.5 )) > RealNumber( 0.001 ):...
A = random_matrix(GF(Integer(2)), Integer(1000), Integer(1000))...
total += Integer(1)...
density_sum += A.density()

determinant()
Return the determinant of this matrix over GF(2).
EXAMPLES:
sage: matrix(GF(2),2,[1,1,0,1]).determinant()
1sage: matrix(GF(2),2,[1,1,1,1]).determinant()
0789

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> matrix(GF(Integer(2)),Integer(2),[Integer(1),Integer(1),Integer(0),˓→Integer(1)]).determinant()
1>>> matrix(GF(Integer(2)),Integer(2),[Integer(1),Integer(1),Integer(1),˓→Integer(1)]).determinant()0echelonize(algorithm='heuristic', cutoff=0, reduced=True, **kwds)
Puts self in (reduced) row echelon form.
INPUT:• self – a mutable matrix• algorithm– ‘heuristic’ – uses M4RI and PLUQ (default)– ‘m4ri’ – uses M4RI
– ‘pluq’ – uses PLUQ factorization– ‘classical’ – uses classical Gaussian elimination• k – the parameter ‘k’ of the M4RI algorithm. It MUST be between 1 and 16 (inclusive). If it is not
specified it will be calculated as 3/4 * log_2( min(nrows, ncols) ) as suggested in the M4RI paper.
• reduced – return reduced row echelon form (default: True)
EXAMPLES:
sage: A = random_matrix(GF(2), 10, 10)
sage: B = A.__copy__(); B.echelonize() # fastest
sage: C = A.__copy__(); C.echelonize(k=2) # force ksage: E = A.__copy__(); E.echelonize(algorithm= classical ) # force Gaussian␣˓→elimination
sage: B == C == E
True>>> from sage.all import *>>> A = random_matrix(GF(Integer(2)), Integer(10), Integer(10))>>> B = A.__copy__(); B.echelonize() # fastest>>> C = A.__copy__(); C.echelonize(k=Integer(2)) # force k>>> E = A.__copy__(); E.echelonize(algorithm= classical ) # force Gaussian␣˓→elimination>>> B == C == E
True

ALGORITHM:
Uses M4RI library
REFERENCES:• [Bar2006]
randomize(density=1, nonzero=False)
Randomize density proportion of the entries of this matrix, leaving the rest unchanged.
INPUT:• density – float; proportion (roughly) to be considered for changes
790

Chapter 23. Dense matrices over GF(2) using the M4RI libraryMatrices and Spaces of Matrices, Release 10.4

• nonzero – Bool (default: False); whether the new entries are forced to be non-zero
OUTPUT:• None, the matrix is modified in-space
EXAMPLES:
sage: A = matrix(GF(2), 5, 5, 0)
sage: A.randomize(0.5)
sage: A.density() < 0.5
True
sage: expected = 0.5
sage: A = matrix(GF(2), 5, 5, 0)
sage: A.randomize()
sage: density_sum = float(A.density())
sage: total = 1
sage: while abs(density_sum/total - expected) > 0.001:....:
A = matrix(GF(2), 5, 5, 0)....:
A.randomize()....:
density_sum += float(A.density())....:
total += 1>>> from sage.all import *>>> A = matrix(GF(Integer(2)), Integer(5), Integer(5), Integer(0))>>> A.randomize(RealNumber( 0.5 ))>>> A.density() < RealNumber( 0.5 )True>>> expected = RealNumber( 0.5 )>>> A = matrix(GF(Integer(2)), Integer(5), Integer(5), Integer(0))>>> A.randomize()>>> density_sum = float(A.density())>>> total = Integer(1)>>> while abs(density_sum/total - expected) > RealNumber( 0.001 ):...
A = matrix(GF(Integer(2)), Integer(5), Integer(5), Integer(0))...
A.randomize()...
density_sum += float(A.density())...
total += Integer(1)rank(algorithm='ple')
Return the rank of this matrix.
On average ‘ple’ should be faster than ‘m4ri’ and hence it is the default choice. However, for small - i.e. quite
few thousand rows & columns - and sparse matrices ‘m4ri’ might be a better choice.
INPUT:• algorithm – either “ple” or “m4ri”
EXAMPLES:
sage: while random_matrix(GF(2), 1000, 1000).rank() != 999:
....:
pass
sage: A = matrix(GF(2),10, 0)
sage: A.rank()
0791

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> while random_matrix(GF(Integer(2)), Integer(1000), Integer(1000)).rank() !
˓→= Integer(999):...
pass>>> A = matrix(GF(Integer(2)),Integer(10), Integer(0))>>> A.rank()0row(i, from_list=False)
Return the i’th row of this matrix as a vector.
This row is a dense vector if and only if the matrix is a dense matrix.
INPUT:• i – integer• from_list – bool (default: False); if True, returns the i’th element of self.rows() (seerows()), which may be faster, but requires building a list of all rows the first time it is called after anentry of the matrix is changed.
EXAMPLES:
sage: l = [GF(2).random_element() for _ in range(100)]
sage: A = matrix(GF(2), 10, 10 , l)sage: list(A.row(0)) == l[:10]Truesage: list(A.row(-1)) == l[-10:]
True
sage: list(A.row(2, from_list=True)) == l[20:30]
True
sage: A = Matrix(GF(2),1,0)
sage: A.row(0)()>>> from sage.all import *>>> l = [GF(Integer(2)).random_element() for _ in range(Integer(100))]>>> A = matrix(GF(Integer(2)), Integer(10), Integer(10) , l)>>> list(A.row(Integer(0))) == l[:Integer(10)]True>>> list(A.row(-Integer(1))) == l[-Integer(10):]True>>> list(A.row(Integer(2), from_list=True)) == l[Integer(20):Integer(30)]
True>>> A = Matrix(GF(Integer(2)),Integer(1),Integer(0))>>> A.row(Integer(0))()

str(rep_mapping=None, zero=None, plus_one=None, minus_one=None, unicode=False, shape=None,
character_art=False, left_border=None, right_border=None, top_border=None, bottom_border=None)
Return a nice string representation of the matrix.
INPUT:

792

Chapter 23. Dense matrices over GF(2) using the M4RI libraryMatrices and Spaces of Matrices, Release 10.4

• rep_mapping – a dictionary or callable used to override the usual representation of elements. For a
dictionary, keys should be elements of the base ring and values the desired string representation.
• zero – string (default: None); if not None use the value of zero as the representation of the zeroelement.
• plus_one – string (default: None); if not None use the value of plus_one as the representation of
the one element.
• minus_one – Ignored. Only for compatibility with generic matrices.
• unicode – boolean (default: False). Whether to use Unicode symbols instead of ASCII symbols forbrackets and subdivision lines.
• shape – one of "square" or "round" (default: None). Switches between round and square brackets. The default depends on the setting of the unicode keyword argument. For Unicode symbols, thedefault is round brackets in accordance with the TeX rendering, while the ASCII rendering defaults tosquare brackets.
• character_art – boolean (default: False); if True, the result will be of type AsciiArt orUnicodeArt which support line breaking of wide matrices that exceed the window width• left_border, right_border – sequence (default: None); if not None, call str() on the elements and use the results as labels for the rows of the matrix. The labels appear outside of the parentheses.
• top_border, bottom_border – sequence (default: None); if not None, call str() on the elements and use the results as labels for the columns of the matrix. The labels appear outside of theparentheses.
EXAMPLES:
sage: B = matrix(GF(2), 3, 3, [0, 1, 0, 0, 1, 1, 0, 0, 0])
sage: B # indirect doctest[0 1 0][0 1 1][0 0 0]sage: block_matrix([[B, 1], [0, B]])
[0 1 0|1 0 0]
[0 1 1|0 1 0]
[0 0 0|0 0 1][-----+-----][0 0 0|0 1 0]
[0 0 0|0 1 1]
[0 0 0|0 0 0]
sage: B.str(zero= . )[. 1 .]\n[. 1 1]\n[. . .]sage: M = matrix.identity(GF(2), 3)
sage: M.subdivide(None, 2)
sage: print(M.str(unicode=True, shape= square ))⎡1 0│0⎤⎢0 1│0⎥⎣0 0│1⎦
sage: print(unicode_art(M)) # indirect doctest⎛1 0│0⎞⎜0 1│0⎟⎝0 0│1⎠793

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> B = matrix(GF(Integer(2)), Integer(3), Integer(3), [Integer(0),␣
˓→Integer(1), Integer(0), Integer(0), Integer(1), Integer(1), Integer(0),␣
˓→Integer(0), Integer(0)])>>> B # indirect doctest[0 1 0][0 1 1][0 0 0]>>> block_matrix([[B, Integer(1)], [Integer(0), B]])
[0 1 0|1 0 0]
[0 1 1|0 1 0]
[0 0 0|0 0 1][-----+-----][0 0 0|0 1 0]
[0 0 0|0 1 1]
[0 0 0|0 0 0]>>> B.str(zero= . )[. 1 .]\n[. 1 1]\n[. . .]>>> M = matrix.identity(GF(Integer(2)), Integer(3))>>> M.subdivide(None, Integer(2))>>> print(M.str(unicode=True, shape= square ))⎡1 0│0⎤⎢0 1│0⎥⎣0 0│1⎦>>> print(unicode_art(M)) # indirect doctest⎛1 0│0⎞⎜0 1│0⎟⎝0 0│1⎠submatrix(row=0, col=0, nrows=-1, ncols=-1)
Return submatrix from the index row, col (inclusive) with dimension nrows x ncols.
INPUT:• row – index of start row• col – index of start column• nrows – number of rows of submatrix• ncols – number of columns of submatrix
EXAMPLES:
sage: A = random_matrix(GF(2),200,200)
sage: A[0:2,0:2] == A.submatrix(0,0,2,2)
True
sage: A[0:100,0:100] == A.submatrix(0,0,100,100)
True
sage: A == A.submatrix(0,0,200,200)
True
sage: A[1:3,1:3] == A.submatrix(1,1,2,2)
True
sage: A[1:100,1:100] == A.submatrix(1,1,99,99)
True
sage: A[1:200,1:200] == A.submatrix(1,1,199,199)
True

794

Chapter 23. Dense matrices over GF(2) using the M4RI libraryMatrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = random_matrix(GF(Integer(2)),Integer(200),Integer(200))>>> A[Integer(0):Integer(2),Integer(0):Integer(2)] == A.submatrix(Integer(0),˓→Integer(0),Integer(2),Integer(2))
True>>> A[Integer(0):Integer(100),Integer(0):Integer(100)] == A.
˓→submatrix(Integer(0),Integer(0),Integer(100),Integer(100))
True>>> A == A.submatrix(Integer(0),Integer(0),Integer(200),Integer(200))
True>>> A[Integer(1):Integer(3),Integer(1):Integer(3)] == A.submatrix(Integer(1),˓→Integer(1),Integer(2),Integer(2))
True>>> A[Integer(1):Integer(100),Integer(1):Integer(100)] == A.
˓→submatrix(Integer(1),Integer(1),Integer(99),Integer(99))
True>>> A[Integer(1):Integer(200),Integer(1):Integer(200)] == A.
˓→submatrix(Integer(1),Integer(1),Integer(199),Integer(199))
True

TESTS for handling of default arguments (Issue #18761):
sage: A.submatrix(17,15) == A.submatrix(17,15,183,185)
True
sage: A.submatrix(row=100,col=37,nrows=1,ncols=3) == A.submatrix(100,37,1,3)
True>>> from sage.all import *>>> A.submatrix(Integer(17),Integer(15)) == A.submatrix(Integer(17),
˓→Integer(15),Integer(183),Integer(185))
True>>> A.submatrix(row=Integer(100),col=Integer(37),nrows=Integer(1),˓→ncols=Integer(3)) == A.submatrix(Integer(100),Integer(37),Integer(1),˓→Integer(3))
Truetranspose()
Returns transpose of self and leaves self untouched.
EXAMPLES:
sage: A = Matrix(GF(2),3,5,[1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0])
sage: A
[1 0 1 0 0]
[0 1 1 0 0]
[1 1 0 1 0]
sage: B = A.transpose(); B[1 0 1][0 1 1][1 1 0][0 0 1][0 0 0]sage: B.transpose() == A
True

795

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = Matrix(GF(Integer(2)),Integer(3),Integer(5),[Integer(1), Integer(0),␣
˓→Integer(1), Integer(0), Integer(0), Integer(0), Integer(1), Integer(1),␣
˓→Integer(0), Integer(0), Integer(1), Integer(1), Integer(0), Integer(1),␣
˓→Integer(0)])>>> A[1 0 1 0 0]
[0 1 1 0 0]
[1 1 0 1 0]>>> B = A.transpose(); B[1 0 1][0 1 1][1 1 0][0 0 1][0 0 0]>>> B.transpose() == ATrue

.T is a convenient shortcut for the transpose:
sage: A.T
[1 0 1][0 1 1][1 1 0][0 0 1][0 0 0]>>> from sage.all import *>>> A.T[1 0 1][0 1 1][1 1 0][0 0 1][0 0 0]sage.matrix.matrix_mod2_dense.from_png(filename)Returns a dense matrix over GF(2) from a 1-bit PNG image read from filename. No attempt is made to verify
that the filename string actually points to a PNG image.
INPUT:• filename – a string
EXAMPLES:
sage: from sage.matrix.matrix_mod2_dense import from_png, to_png
sage: A = random_matrix(GF(2),10,10)
sage: fn = tmp_filename()
sage: to_png(A, fn)
sage: B = from_png(fn)sage: A == B
True>>> from sage.all import *>>> from sage.matrix.matrix_mod2_dense import from_png, to_png>>> A = random_matrix(GF(Integer(2)),Integer(10),Integer(10))>>> fn = tmp_filename()(continues on next page)

796

Chapter 23. Dense matrices over GF(2) using the M4RI libraryMatrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> to_png(A, fn)>>> B = from_png(fn)>>> A == B
Truesage.matrix.matrix_mod2_dense.parity(a)Return the parity of the number of bits in a.
EXAMPLES:
sage: from sage.matrix.matrix_mod2_dense import parity
sage: parity(1)1sage: parity(3)0sage: parity(0x10000101011)
1>>> from sage.all import *>>> from sage.matrix.matrix_mod2_dense import parity>>> parity(Integer(1))
1>>> parity(Integer(3))
0>>> parity(Integer(0x10000101011))
1

sage.matrix.matrix_mod2_dense.ple(A, algorithm='standard', param=0)
Return PLE factorization of A.
INPUT:• A – matrix• algorithm– ‘standard’ asymptotically fast (default)– ‘russian’ M4RI inspired– ‘naive’ naive cubic• param – either k for ‘mmpf’ is chosen or matrix multiplication cutoff for ‘standard’ (default: 0)
EXAMPLES:
sage: from sage.matrix.matrix_mod2_dense import ple
sage: A = matrix(GF(2), 4, 4, [0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0])
sage: A[0 1 0 1][0 1 1 1][0 0 0 1][0 1 1 0]
sage: LU, P, Q = ple(A)sage: LU
[1 0 0 1][1 1 0 0](continues on next page)797

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 0 1 0][1 1 1 0]
sage: P[0, 1, 2, 3]
sage: Q[1, 2, 3, 3]
sage: A = random_matrix(GF(2),1000,1000)
sage: ple(A) == ple(A, russian ) == ple(A, naive )True>>> from sage.all import *>>> from sage.matrix.matrix_mod2_dense import ple>>> A = matrix(GF(Integer(2)), Integer(4), Integer(4), [Integer(0), Integer(1),␣
˓→Integer(0), Integer(1), Integer(0), Integer(1), Integer(1), Integer(1),␣
˓→Integer(0), Integer(0), Integer(0), Integer(1), Integer(0), Integer(1),␣
˓→Integer(1), Integer(0)])>>> A[0 1 0 1][0 1 1 1][0 0 0 1][0 1 1 0]>>> LU, P, Q = ple(A)>>> LU[1 0 0 1][1 1 0 0][0 0 1 0][1 1 1 0]>>> P[0, 1, 2, 3]>>> Q[1, 2, 3, 3]>>> A = random_matrix(GF(Integer(2)),Integer(1000),Integer(1000))>>> ple(A) == ple(A, russian ) == ple(A, naive )Truesage.matrix.matrix_mod2_dense.pluq(A, algorithm='standard', param=0)
Return PLUQ factorization of A.
INPUT:• A – matrix• algorithm– ‘standard’ asymptotically fast (default)– ‘mmpf’ M4RI inspired– ‘naive’ naive cubic• param – either k for ‘mmpf’ is chosen or matrix multiplication cutoff for ‘standard’ (default: 0)798

Chapter 23. Dense matrices over GF(2) using the M4RI libraryMatrices and Spaces of Matrices, Release 10.4

EXAMPLES:
sage: from sage.matrix.matrix_mod2_dense import pluq
sage: A = matrix(GF(2), 4, 4, [0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0])
sage: A[0 1 0 1][0 1 1 1][0 0 0 1][0 1 1 0]
sage: LU, P, Q = pluq(A)sage: LU
[1 0 1 0][1 1 0 0][0 0 1 0][1 1 1 0]
sage: P[0, 1, 2, 3]
sage: Q[1, 2, 3, 3]>>> from sage.all import *>>> from sage.matrix.matrix_mod2_dense import pluq>>> A = matrix(GF(Integer(2)), Integer(4), Integer(4), [Integer(0), Integer(1),␣
˓→Integer(0), Integer(1), Integer(0), Integer(1), Integer(1), Integer(1),␣
˓→Integer(0), Integer(0), Integer(0), Integer(1), Integer(0), Integer(1),␣
˓→Integer(1), Integer(0)])>>> A[0 1 0 1][0 1 1 1][0 0 0 1][0 1 1 0]>>> LU, P, Q = pluq(A)>>> LU[1 0 1 0][1 1 0 0][0 0 1 0][1 1 1 0]>>> P[0, 1, 2, 3]>>> Q[1, 2, 3, 3]

sage.matrix.matrix_mod2_dense.to_png(A, filename)
Saves the matrix A to filename as a 1-bit PNG image.
INPUT:• A – a matrix over GF(2)• filename – a string for a file in a writable position
EXAMPLES:
sage: from sage.matrix.matrix_mod2_dense import from_png, to_png
sage: A = random_matrix(GF(2),10,10)(continues on next page)799

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: fn = tmp_filename()
sage: to_png(A, fn)
sage: B = from_png(fn)sage: A == B
True>>> from sage.all import *>>> from sage.matrix.matrix_mod2_dense import from_png, to_png>>> A = random_matrix(GF(Integer(2)),Integer(10),Integer(10))>>> fn = tmp_filename()>>> to_png(A, fn)>>> B = from_png(fn)>>> A == B
Truesage.matrix.matrix_mod2_dense.unpickle_matrix_mod2_dense_v2(r, c, data, size,
immutable=False)
Deserialize a matrix encoded in the string s.
INPUT:• r – number of rows of matrix• c – number of columns of matrix• s – a string• size – length of the string s• immutable – (default: False) whether the matrix is immutable or not
EXAMPLES:
sage: A = random_matrix(GF(2),100,101)
sage: _, (r,c,s,s2,i) = A.__reduce__()sage: from sage.matrix.matrix_mod2_dense import unpickle_matrix_mod2_dense_v2
sage: unpickle_matrix_mod2_dense_v2(r,c,s,s2,i) == A
True
sage: loads(dumps(A)) == A
True>>> from sage.all import *>>> A = random_matrix(GF(Integer(2)),Integer(100),Integer(101))>>> _, (r,c,s,s2,i) = A.__reduce__()>>> from sage.matrix.matrix_mod2_dense import unpickle_matrix_mod2_dense_v2>>> unpickle_matrix_mod2_dense_v2(r,c,s,s2,i) == A
True>>> loads(dumps(A)) == A
True

800

Chapter 23. Dense matrices over GF(2) using the M4RI libraryCHAPTERTWENTYFOURDENSE MATRICES OVER F2𝐸 FOR 2 ≤ 𝐸 ≤ 16 USING THE M4RIE
LIBRARY

The M4RIE library offers two matrix representations:
1) mzed_t
m x n matrices over F2𝑒 are internally represented roughly as m x (en) matrices over F2 . Several elements
are packed into words such that each element is filled with zeroes until the next power of two. Thus, forexample, elements of F23 are represented as [0xxx|0xxx|0xxx|0xxx|...]. This representation iswrapped as Matrix_gf2e_dense in Sage.
Multiplication and elimination both use “Newton-John” tables. These tables are simply all possible multiples of a given row in a matrix such that a scale+add operation is reduced to a table lookup + add. On top
of Newton-John multiplication M4RIE implements asymptotically fast Strassen-Winograd multiplication.
Elimination uses simple Gaussian elimination which requires 𝑂(𝑛3 ) additions but only 𝑂(𝑛2 * 2𝑒 ) multiplications.
2) mzd_slice_t
m x n matrices over F2𝑒 are internally represented as slices of m x n matrices over F2 . This representation
allows for very fast matrix times matrix products using Karatsuba’s polynomial multiplication for polynomials
over matrices. However, it is not feature complete yet and hence not wrapped in Sage for now.
See http://m4ri.sagemath.org for more details on the M4RIE library.
EXAMPLES:
sage: K.<a> = GF(2^8)
sage: A = random_matrix(K, 3,4)
sage: E = A.echelon_form()
sage: A.row_space() == E.row_space()
True
sage: all(r[r.nonzero_positions()[0]] == 1 for r in E.rows() if r)
True>>> from sage.all import *>>> K = GF(Integer(2)**Integer(8), names=( a ,)); (a,) = K._first_ngens(1)>>> A = random_matrix(K, Integer(3),Integer(4))>>> E = A.echelon_form()>>> A.row_space() == E.row_space()
True>>> all(r[r.nonzero_positions()[Integer(0)]] == Integer(1) for r in E.rows() if r)
True

AUTHOR:• Martin Albrecht <martinralbrecht@googlemail.com>
801

Matrices and Spaces of Matrices, Release 10.4

Todo: Wrap mzd_slice_t.
REFERENCES:• [BB2009]class sage.matrix.matrix_gf2e_dense.M4RIE_finite_field
Bases: object
A thin wrapper around the M4RIE finite field class such that we can put it in a hash table. This class is not meant
for public consumption.
class sage.matrix.matrix_gf2e_dense.Matrix_gf2e_dense
Bases: Matrix_dense
Create new matrix over 𝐺𝐹 (2𝑒 ) for 2 ≤ 𝑒 ≤ 16.
INPUT:• parent – a matrix space over GF(2^e)• entries – see matrix()• copy – ignored (for backwards compatibility)• coerce – if False, assume without checking that the entries lie in the base ring
EXAMPLES:
sage: K.<a> = GF(2^4)
sage: l = [K.random_element() for _ in range(3*4)]
sage: A = Matrix(K, 3, 4, l)sage: l == A.list()True
sage: l[0] == A[0,0]Truesage: A = Matrix(K, 3, 3, a); A[a 0 0][0 a 0][0 0 a]>>> from sage.all import *>>> K = GF(Integer(2)**Integer(4), names=( a ,)); (a,) = K._first_ngens(1)>>> l = [K.random_element() for _ in range(Integer(3)*Integer(4))]>>> A = Matrix(K, Integer(3), Integer(4), l)>>> l == A.list()
True>>> l[Integer(0)] == A[Integer(0),Integer(0)]True>>> A = Matrix(K, Integer(3), Integer(3), a); A[a 0 0][0 a 0][0 0 a]802

Chapter 24. Dense matrices over F2𝑒 for 2 ≤ 𝑒 ≤ 16 using the M4RIE libraryMatrices and Spaces of Matrices, Release 10.4

augment(right)
Augments self with right.
INPUT:• right – a matrix
EXAMPLES:
sage: K.<a> = GF(2^4)
sage: MS = MatrixSpace(K,3,3)
sage: A = random_matrix(K,3,3)
sage: B = A.augment(MS(1))
sage: B.echelonize()
sage: C = B.matrix_from_columns([3,4,5])
sage: A.rank() < 3 or C == ~A
True
sage: A.rank() < 3 or C*A == MS(1)True>>> from sage.all import *>>> K = GF(Integer(2)**Integer(4), names=( a ,)); (a,) = K._first_ngens(1)>>> MS = MatrixSpace(K,Integer(3),Integer(3))>>> A = random_matrix(K,Integer(3),Integer(3))>>> B = A.augment(MS(Integer(1)))>>> B.echelonize()>>> C = B.matrix_from_columns([Integer(3),Integer(4),Integer(5)])>>> A.rank() < Integer(3) or C == ~A
True>>> A.rank() < Integer(3) or C*A == MS(Integer(1))
Truecling(*C)
Pack the matrices over F2 into this matrix over F2𝑒 .
∑︀Elements in F2𝑒 can be represented as 𝑐𝑖 𝑎𝑖 where 𝑎 is a root the minimal polynomial. If this matrix is 𝐴
then this function writes 𝑐𝑖 𝑎𝑖 to the entry 𝐴[𝑥, 𝑦] where 𝑐𝑖 is the entry 𝐶𝑖 [𝑥, 𝑦].
INPUT:• C – a list of matrices over GF(2)EXAMPLES:
sage: K.<a> = GF(2^2)
sage: A = matrix(K, 5, 5)
sage: A0 = random_matrix(GF(2), 5, 5)
sage: A1 = random_matrix(GF(2), 5, 5)
sage: A.cling(A0, A1)
sage: all(A.list()[i] == A0.list()[i] + a*A1.list()[i] for i in range(25))
True>>> from sage.all import *>>> K = GF(Integer(2)**Integer(2), names=( a ,)); (a,) = K._first_ngens(1)>>> A = matrix(K, Integer(5), Integer(5))>>> A0 = random_matrix(GF(Integer(2)), Integer(5), Integer(5))>>> A1 = random_matrix(GF(Integer(2)), Integer(5), Integer(5))>>> A.cling(A0, A1)>>> all(A.list()[i] == A0.list()[i] + a*A1.list()[i] for i in␣(continues on next page)803

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

range(Integer(25)))
True˓→Slicing and clinging are inverse operations:sage: B0, B1 = A.slice()
sage: B0 == A0 and B1 == A1
True>>> from sage.all import *>>> B0, B1 = A.slice()>>> B0 == A0 and B1 == A1
Trueechelonize(algorithm='heuristic', reduced=True, **kwds)
Compute the row echelon form of self in place.
INPUT:• algorithm – one of the following - heuristic – let M4RIE decide (default) - newton_john– use newton_john table based algorithm - ple – use PLE decomposition - naive – use naive cubic
Gaussian elimination (M4RIE implementation) - builtin – use naive cubic Gaussian elimination (Sageimplementation)• reduced – if True return reduced echelon form. No guarantee is given that the matrix is not reduced
if False (default: True)
EXAMPLES:
sage: K.<a> = GF(2^4)
sage: m,n = 3, 5
sage: A = random_matrix(K, 3, 5)
sage: R = A.row_space()sage: A.echelonize()
sage: all(r[r.nonzero_positions()[0]] == 1 for r in A.rows() if r)
True
sage: A.row_space() == R
True
sage: K.<a> = GF(2^3)
sage: m,n = 3, 5
sage: MS = MatrixSpace(K,m,n)
sage: A = random_matrix(K, 3, 5)
sage: B = copy(A).echelon_form( newton_john )sage: C = copy(A).echelon_form( naive )sage: D = copy(A).echelon_form( builtin )sage: B == C == D
True
sage: all(r[r.nonzero_positions()[0]] == 1 for r in B.rows() if r)
True>>> from sage.all import *>>> K = GF(Integer(2)**Integer(4), names=( a ,)); (a,) = K._first_ngens(1)>>> m,n = Integer(3), Integer(5)>>> A = random_matrix(K, Integer(3), Integer(5))>>> R = A.row_space()>>> A.echelonize()(continues on next page)

804

Chapter 24. Dense matrices over F2𝑒 for 2 ≤ 𝑒 ≤ 16 using the M4RIE libraryMatrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> all(r[r.nonzero_positions()[Integer(0)]] == Integer(1) for r in A.rows()␣
˓→if r)True>>> A.row_space() == R
True>>> K = GF(Integer(2)**Integer(3), names=( a ,)); (a,) = K._first_ngens(1)>>> m,n = Integer(3), Integer(5)>>> MS = MatrixSpace(K,m,n)>>> A = random_matrix(K, Integer(3), Integer(5))>>> B = copy(A).echelon_form( newton_john )>>> C = copy(A).echelon_form( naive )>>> D = copy(A).echelon_form( builtin )>>> B == C == D
True>>> all(r[r.nonzero_positions()[Integer(0)]] == Integer(1) for r in B.rows()␣
˓→if r)Truerandomize(density=1, nonzero=False, *args, **kwds)
Randomize density proportion of the entries of this matrix, leaving the rest unchanged.
INPUT:• density – float; proportion (roughly) to be considered for changes• nonzero – Bool (default: False); whether the new entries are forced to be non-zero
OUTPUT:• None, the matrix is modified in-place
EXAMPLES:
sage: K.<a> = GF(2^4)
sage: total_count = 0
sage: from collections import defaultdict
sage: dic = defaultdict(Integer)
sage: def add_samples():....:
global dic, total_count....:for _ in range(100):....:
A = Matrix(K,3,3)....:
A.randomize()....:
for a in A.list():....:dic[a] += 1....:
total_count += 1.0
sage: add_samples()sage: while not all(abs(dic[a]/total_count - 1/16) < 0.01 for a in dic):....:
add_samples()sage: def add_sample(density):....:
global density_sum, total_count....:total_count += 1.0....:
density_sum += random_matrix(K, 1000, 1000, density=density).
˓→density()
sage: density_sum = 0.0
sage: total_count = 0.0(continues on next page)805

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: add_sample(0.1)
sage: while abs(density_sum/total_count - 0.1) > 0.001:....:
add_sample(0.1)
sage: density_sum = 0.0
sage: total_count = 0.0
sage: add_sample(1.0)
sage: while abs(density_sum/total_count - 1.0) > 0.001:....:
add_sample(1.0)
sage: density_sum = 0.0
sage: total_count = 0.0
sage: add_sample(0.5)
sage: while abs(density_sum/total_count - 0.5) > 0.001:....:
add_sample(0.5)>>> from sage.all import *>>> K = GF(Integer(2)**Integer(4), names=( a ,)); (a,) = K._first_ngens(1)>>> total_count = Integer(0)>>> from collections import defaultdict>>> dic = defaultdict(Integer)>>> def add_samples():...
global dic, total_count...
for _ in range(Integer(100)):...
A = Matrix(K,Integer(3),Integer(3))...
A.randomize()...
for a in A.list():...
dic[a] += Integer(1)...
total_count += RealNumber( 1.0 )>>> add_samples()>>> while not all(abs(dic[a]/total_count - Integer(1)/Integer(16)) <␣
˓→RealNumber( 0.01 ) for a in dic):...
add_samples()>>> def add_sample(density):...
global density_sum, total_count...
total_count += RealNumber( 1.0 )...
density_sum += random_matrix(K, Integer(1000), Integer(1000),␣
˓→density=density).density()>>> density_sum = RealNumber( 0.0 )>>> total_count = RealNumber( 0.0 )>>> add_sample(RealNumber( 0.1 ))>>> while abs(density_sum/total_count - RealNumber( 0.1 )) > RealNumber( 0.001
˓→ ):
...
add_sample(RealNumber( 0.1 ))>>> density_sum = RealNumber( 0.0 )>>> total_count = RealNumber( 0.0 )>>> add_sample(RealNumber( 1.0 ))>>> while abs(density_sum/total_count - RealNumber( 1.0 )) > RealNumber( 0.001
˓→ ):
...
add_sample(RealNumber( 1.0 ))>>> density_sum = RealNumber( 0.0 )>>> total_count = RealNumber( 0.0 )(continues on next page)

806

Chapter 24. Dense matrices over F2𝑒 for 2 ≤ 𝑒 ≤ 16 using the M4RIE libraryMatrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> add_sample(RealNumber( 0.5 ))>>> while abs(density_sum/total_count - RealNumber( 0.5 )) > RealNumber( 0.001
˓→ ):
...
add_sample(RealNumber( 0.5 ))Note, that the matrix is updated and not zero-ed out before being randomized:
sage: def add_sample(density, nonzero):....:
global density_sum, total_count....:total_count += 1.0....:
A = matrix(K, 1000, 1000)....:
A.randomize(nonzero=nonzero, density=density)....:
A.randomize(nonzero=nonzero, density=density)....:
density_sum += A.density()
sage: density_sum = 0.0
sage: total_count = 0.0
sage: add_sample(0.1, True)
sage: while abs(density_sum/total_count - (1 - 0.9^2)) > 0.001:....:
add_sample(0.1, True)
sage: density_sum = 0.0
sage: total_count = 0.0
sage: add_sample(0.1, False)
sage: while abs(density_sum/total_count - (1 - 0.9^2)*15/16) > 0.001:....:
add_sample(0.1, False)
sage: density_sum = 0.0
sage: total_count = 0.0
sage: add_sample(0.05, True)
sage: while abs(density_sum/total_count - (1 - 0.95^2)) > 0.001:....:
add_sample(0.05, True)
sage: density_sum = 0.0
sage: total_count = 0.0
sage: add_sample(0.5, True)
sage: while abs(density_sum/total_count - (1 - 0.5^2)) > 0.001:....:
add_sample(0.5, True)>>> from sage.all import *>>> def add_sample(density, nonzero):...
global density_sum, total_count...
total_count += RealNumber( 1.0 )...
A = matrix(K, Integer(1000), Integer(1000))...
A.randomize(nonzero=nonzero, density=density)...
A.randomize(nonzero=nonzero, density=density)...
density_sum += A.density()>>> density_sum = RealNumber( 0.0 )>>> total_count = RealNumber( 0.0 )>>> add_sample(RealNumber( 0.1 ), True)>>> while abs(density_sum/total_count - (Integer(1) - RealNumber( 0.9
˓→ )**Integer(2))) > RealNumber( 0.001 ):...
add_sample(RealNumber( 0.1 ), True)>>> density_sum = RealNumber( 0.0 )(continues on next page)807

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> total_count = RealNumber( 0.0 )>>> add_sample(RealNumber( 0.1 ), False)>>> while abs(density_sum/total_count - (Integer(1) - RealNumber( 0.9
˓→ )**Integer(2))*Integer(15)/Integer(16)) > RealNumber( 0.001 ):...
add_sample(RealNumber( 0.1 ), False)>>> density_sum = RealNumber( 0.0 )>>> total_count = RealNumber( 0.0 )>>> add_sample(RealNumber( 0.05 ), True)>>> while abs(density_sum/total_count - (Integer(1) - RealNumber( 0.95
˓→ )**Integer(2))) > RealNumber( 0.001 ):...
add_sample(RealNumber( 0.05 ), True)>>> density_sum = RealNumber( 0.0 )>>> total_count = RealNumber( 0.0 )>>> add_sample(RealNumber( 0.5 ), True)>>> while abs(density_sum/total_count - (Integer(1) - RealNumber( 0.5
˓→ )**Integer(2))) > RealNumber( 0.001 ):...
add_sample(RealNumber( 0.5 ), True)rank()
Return the rank of this matrix (cached).
EXAMPLES:
sage: K.<a> = GF(2^4)
sage: A = random_matrix(K, 10, 10, algorithm="unimodular")sage: A.rank()
10sage: A = matrix(K, 10, 0)
sage: A.rank()
0>>> from sage.all import *>>> K = GF(Integer(2)**Integer(4), names=( a ,)); (a,) = K._first_ngens(1)>>> A = random_matrix(K, Integer(10), Integer(10), algorithm="unimodular")>>> A.rank()
10>>> A = matrix(K, Integer(10), Integer(0))>>> A.rank()
0slice()
Unpack this matrix into matrices over F2 .
∑︀
Elements in F2𝑒 can be represented as 𝑐𝑖 𝑎𝑖 where 𝑎 is a root the minimal polynomial. This function returns
a tuple of matrices 𝐶 whose entry 𝐶𝑖 [𝑥, 𝑦] is the coefficient of 𝑐𝑖 in 𝐴[𝑥, 𝑦] if this matrix is 𝐴.
EXAMPLES:
sage: K.<a> = GF(2^2)
sage: A = random_matrix(K, 5, 5)
sage: A0, A1 = A.slice()
sage: all(A.list()[i] == A0.list()[i] + a*A1.list()[i] for i in range(25))
True
sage: K.<a> = GF(2^3)(continues on next page)

808

Chapter 24. Dense matrices over F2𝑒 for 2 ≤ 𝑒 ≤ 16 using the M4RIE libraryMatrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: A = random_matrix(K, 5, 5)
sage: A0, A1, A2 = A.slice()
sage: all(A.list()[i] == A0.list()[i] + a*A1.list()[i] + a^2*A2.list()[i] for␣
˓→i in range(25))
True>>> from sage.all import *>>> K = GF(Integer(2)**Integer(2), names=( a ,)); (a,) = K._first_ngens(1)>>> A = random_matrix(K, Integer(5), Integer(5))>>> A0, A1 = A.slice()>>> all(A.list()[i] == A0.list()[i] + a*A1.list()[i] for i in␣
˓→range(Integer(25)))
True>>> K = GF(Integer(2)**Integer(3), names=( a ,)); (a,) = K._first_ngens(1)>>> A = random_matrix(K, Integer(5), Integer(5))>>> A0, A1, A2 = A.slice()>>> all(A.list()[i] == A0.list()[i] + a*A1.list()[i] + a**Integer(2)*A2.
˓→list()[i] for i in range(Integer(25)))
True

Slicing and clinging are inverse operations:sage: B = matrix(K, 5, 5)
sage: B.cling(A0, A1, A2)
sage: B == A
True>>> from sage.all import *>>> B = matrix(K, Integer(5), Integer(5))>>> B.cling(A0, A1, A2)>>> B == A
True

submatrix(row=0, col=0, nrows=-1, ncols=-1)
Return submatrix from the index row,col (inclusive) with dimension nrows x ncols.
INPUT:• row – index of start row• col – index of start column• nrows – number of rows of submatrix• ncols – number of columns of submatrix
EXAMPLES:
sage: K.<a> = GF(2^10)sage: A = random_matrix(K,200,200)
sage: A[0:2,0:2] == A.submatrix(0,0,2,2)
True
sage: A[0:100,0:100] == A.submatrix(0,0,100,100)
True
sage: A == A.submatrix(0,0,200,200)
True(continues on next page)809

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: A[1:3,1:3] == A.submatrix(1,1,2,2)
True
sage: A[1:100,1:100] == A.submatrix(1,1,99,99)
True
sage: A[1:200,1:200] == A.submatrix(1,1,199,199)
True>>> from sage.all import *>>> K = GF(Integer(2)**Integer(10), names=( a ,)); (a,) = K._first_ngens(1)>>> A = random_matrix(K,Integer(200),Integer(200))>>> A[Integer(0):Integer(2),Integer(0):Integer(2)] == A.submatrix(Integer(0),˓→Integer(0),Integer(2),Integer(2))
True>>> A[Integer(0):Integer(100),Integer(0):Integer(100)] == A.
˓→submatrix(Integer(0),Integer(0),Integer(100),Integer(100))
True>>> A == A.submatrix(Integer(0),Integer(0),Integer(200),Integer(200))
True>>> A[Integer(1):Integer(3),Integer(1):Integer(3)] == A.submatrix(Integer(1),˓→Integer(1),Integer(2),Integer(2))
True>>> A[Integer(1):Integer(100),Integer(1):Integer(100)] == A.
˓→submatrix(Integer(1),Integer(1),Integer(99),Integer(99))
True>>> A[Integer(1):Integer(200),Integer(1):Integer(200)] == A.
˓→submatrix(Integer(1),Integer(1),Integer(199),Integer(199))
True

TESTS for handling of default arguments (Issue #18761):
sage: A.submatrix(17,15) == A.submatrix(17,15,183,185)
True
sage: A.submatrix(row=100,col=37,nrows=1,ncols=3) == A.submatrix(100,37,1,3)
True>>> from sage.all import *>>> A.submatrix(Integer(17),Integer(15)) == A.submatrix(Integer(17),
˓→Integer(15),Integer(183),Integer(185))
True>>> A.submatrix(row=Integer(100),col=Integer(37),nrows=Integer(1),˓→ncols=Integer(3)) == A.submatrix(Integer(100),Integer(37),Integer(1),˓→Integer(3))
Truesage.matrix.matrix_gf2e_dense.unpickle_matrix_gf2e_dense_v0(a, base_ring, nrows, ncols)
EXAMPLES:
sage: K.<a> = GF(2^2)
sage: A = random_matrix(K,10,10)
sage: f, s= A.__reduce__()sage: from sage.matrix.matrix_gf2e_dense import unpickle_matrix_gf2e_dense_v0
sage: f == unpickle_matrix_gf2e_dense_v0
True
sage: f(*s) == A
True

810

Chapter 24. Dense matrices over F2𝑒 for 2 ≤ 𝑒 ≤ 16 using the M4RIE libraryMatrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> K = GF(Integer(2)**Integer(2), names=( a ,)); (a,) = K._first_ngens(1)>>> A = random_matrix(K,Integer(10),Integer(10))>>> f, s= A.__reduce__()>>> from sage.matrix.matrix_gf2e_dense import unpickle_matrix_gf2e_dense_v0>>> f == unpickle_matrix_gf2e_dense_v0
True>>> f(*s) == ATrue

We can still unpickle pickles from before Issue #19240:
sage: old_pickle = b x\x9c\x85RKo\xd3@\x10\xae\xdd$$\xdb&\xe5U\x1e-\x8f\xc2\xc9\
˓→x12RD#$\xce\xa0\xb4\x80\x07\xa2\xca\xc2\x07\x0e\xd5\xe2:\x1b\xdb\x8acg\x1c\xa7J\
˓→x85*!\xa4\x90\xe6\x07p\xe0\xc4\x01q\xe5\xc4\x19\xf5\xd0?\xc1\x81\xdf\x80\xb8q\
˓→x0b\xb3\x8eMS\xa1\x82V;;\xb3\xdf\xce\xf7\xcd\x8e\xe6\xb5j\xf7,GT;V\x1cy\x83\xf4\
˓→xe0\x9d\xb0Y\x13\xbc)\x82\x9e \xfd\xa0\xeb\xd9m_\xf0\xbf1\xbe{\x97\xa1\xa2\x9d\
˓→xc6\xf0\x0f\x82,\x7f\x9d\xa1\xaa\x81\n\xb9m\x9c\xd7\xf4\xf1d2\x81-h\xc0#(\x03\
˓→x83\x15\xdas\xc9*\xc3\x13x\x0cu0\xd28\x97\x9e*(0\x9f\xfa\x1b\xd0\xd2\x7fH\x82\
˓→xb5\xf4\xa2@TO\xe19\x01I\xac\x136\x991\x9f\xa4\xf9&\xcd\x07i\xbe\xcb\xd4ib\t\
˓→xba\xa4\xf6\x02zIT\xd1\x8f2(u\x15\xfd\x9d<\xee@\x05V\xd3\x94E*\xb0\x0e\x0fH\xad\˓→xa8\xbf\x97\xa0\r\x03\xfd\xf0\xb8\x1aU\xff\x92\x90\xe8?\xa5\xd6\x814_\xa5\xf9(\
˓→xcd\xafc\xe99\xe2\xd9\xa0\x06\xd4\xf5\xcf\xf2\xf2!\xbc\xd4\xdf\x90#\xc0\x8f\r\
˓→xccM\x1b\xdd\x8b\xa3\xbe\x1d\xf7#QmYv\x1cF{\xcc\x11\x81\x88<\x9b\xa71\xcf:\xce0\
˓→xaf\x9d\x96\xe3\x87a\xbb\xdf\xe5\x8e\x1f\xeeX>\xc3\x82\xb9\xb0\xe9\x05^,6=\xe17\
˓→xf1\xcc\xd0\xc0"u\xb0d\xe6wDl\xdd\x1fa)e\x8a\xbc\xc0\xe9U\xbd \x16\x8e\x88X\
˓→xc7j\x0b\x9e\x05\xc8L\xe5\x1e%.\x98\x8a5\xc4\xc5\xd9\xf7\xdd\xd0\xdf\x0b\xc2\
˓→x8eg\xf93.wZ\xb5\xc1\x94B\xf8\xa2#\x82\x98a\xf9\xffY\x12\xe3v\x18L\xff\x14Fl\
˓→xeb\x0ff\x10\xc4\xb0\xa2\xb9y\xcd-\xba%\xcd\xa5\x8ajT\xd1\x92\xa9\x0c\x86x\xb6a\
˓→xe6h\xf8\x02<g\xaa\xaf\xf6\xdd%\x89\xae\x13z\xfe \xc6\x0b\xfb1^4p\x99\x1e6\xc6\
˓→xd4\xebK\xdbx\xf9\xc4\x8f[Iw\xf8\x89\xef\xcbQf\xcfh\xe3\x95\x8c\xebj&\xb9\xe2.\
˓→x8f\x0c\\ui\x89\xf1x\xf4\xd6\xc0kf\xc1\xf1v\xad(\xc4\xeb\x89~\xfa\xf0\x06\xa8\
˓→xa4\x7f\x93\xf4\xd7\x0c\xbcE#\xad\x92\xfc\xed\xeao\xefX\\\x03
sage: loads(old_pickle)[
0a][a + 1
1]>>> from sage.all import *>>> old_pickle = b x\x9c\x85RKo\xd3@\x10\xae\xdd$$\xdb&\xe5U\x1e-\x8f\xc2\xc9\
˓→x12RD#$\xce\xa0\xb4\x80\x07\xa2\xca\xc2\x07\x0e\xd5\xe2:\x1b\xdb\x8acg\x1c\xa7J\
˓→x85*!\xa4\x90\xe6\x07p\xe0\xc4\x01q\xe5\xc4\x19\xf5\xd0?\xc1\x81\xdf\x80\xb8q\
˓→x0b\xb3\x8eMS\xa1\x82V;;\xb3\xdf\xce\xf7\xcd\x8e\xe6\xb5j\xf7,GT;V\x1cy\x83\xf4\
˓→xe0\x9d\xb0Y\x13\xbc)\x82\x9e \xfd\xa0\xeb\xd9m_\xf0\xbf1\xbe{\x97\xa1\xa2\x9d\
˓→xc6\xf0\x0f\x82,\x7f\x9d\xa1\xaa\x81\n\xb9m\x9c\xd7\xf4\xf1d2\x81-h\xc0#(\x03\
˓→x83\x15\xdas\xc9*\xc3\x13x\x0cu0\xd28\x97\x9e*(0\x9f\xfa\x1b\xd0\xd2\x7fH\x82\
˓→xb5\xf4\xa2@TO\xe19\x01I\xac\x136\x991\x9f\xa4\xf9&\xcd\x07i\xbe\xcb\xd4ib\t\
˓→xba\xa4\xf6\x02zIT\xd1\x8f2(u\x15\xfd\x9d<\xee@\x05V\xd3\x94E*\xb0\x0e\x0fH\xad\˓→xa8\xbf\x97\xa0\r\x03\xfd\xf0\xb8\x1aU\xff\x92\x90\xe8?\xa5\xd6\x814_\xa5\xf9(\
˓→xcd\xafc\xe99\xe2\xd9\xa0\x06\xd4\xf5\xcf\xf2\xf2!\xbc\xd4\xdf\x90#\xc0\x8f\r\
˓→xccM\x1b\xdd\x8b\xa3\xbe\x1d\xf7#QmYv\x1cF{\xcc\x11\x81\x88<\x9b\xa71\xcf:\xce0\
˓→xaf\x9d\x96\xe3\x87a\xbb\xdf\xe5\x8e\x1f\xeeX>\xc3\x82\xb9\xb0\xe9\x05^,6=\xe17\
˓→xf1\xcc\xd0\xc0"u\xb0d\xe6wDl\xdd\x1fa)e\x8a\xbc\xc0\xe9U\xbd \x16\x8e\x88X\
˓→xc7j\x0b\x9e\x05\xc8L\xe5\x1e%.\x98\x8a5\xc4\xc5\xd9\xf7\xdd\xd0\xdf\x0b\xc2\
˓→x8eg\xf93.wZ\xb5\xc1\x94B\xf8\xa2#\x82\x98a\xf9\xffY\x12\xe3v\x18L\xff\x14Fl\
˓→xeb\x0ff\x10\xc4\xb0\xa2\xb9y\xcd-\xba%\xcd\xa5\x8ajT\xd1\x92\xa9\x0c\x86x\xb6a\
˓→xe6h\xf8\x02<g\xaa\xaf\xf6\xdd%\x89\xae\x13z\xfe \xc6\x0b\xfb1^4p\x99\x1e6\xc6\
˓→xd4\xebK\xdbx\xf9\xc4\x8f[Iw\xf8\x89\xef\xcbQf\xcfh\xe3\x95\x8c\xebj&\xb9\xe2.\(continues on next page)811

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)x8f\x0c\\ui\x89\xf1x\xf4\xd6\xc0kf\xc1\xf1v\xad(\xc4\xeb\x89~\xfa\xf0\x06\xa8\
˓→xa4\x7f\x93\xf4\xd7\x0c\xbcE#\xad\x92\xfc\xed\xeao\xefX\\\x03>>> loads(old_pickle)[
0a][a + 11]
˓→812

Chapter 24. Dense matrices over F2𝑒 for 2 ≤ 𝑒 ≤ 16 using the M4RIE libraryCHAPTERTWENTYFIVEDENSE MATRICES OVER Z/𝑁 Z FOR 𝑁 < 94906266 USING LINBOX’S
MODULAR<DOUBLE>

AUTHORS:• Burcin Erocal• Martin Albrecht
class sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_double
Bases: Matrix_modn_dense_template
Dense matrices over Z/𝑛Z for 𝑛 < 94906266 using LinBox’s Modular<double>
These are matrices with integer entries mod n represented as floating-point numbers in a 64-bit word for use with
LinBox routines. This allows for n up to 94906266. By default, the analogous Matrix_modn_dense_float
class is used for smaller moduli, specifically for n up to 28 .
Routines here are for the most basic access, see the matrix_modn_dense_template.pxi file forhigher-level routines.
class sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_template
Bases: Matrix_dense
Create a new matrix.
INPUT:• parent – a matrix space• entries – see matrix()• copy – ignored (for backwards compatibility)• coerce – perform modular reduction first?
EXAMPLES:
sage: A = random_matrix(GF(3),1000,1000)
sage: type(A)<class sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_float >sage: A = random_matrix(Integers(10),1000,1000)
sage: type(A)<class sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_float >sage: A = random_matrix(Integers(2^16),1000,1000)
sage: type(A)<class sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_double >813

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = random_matrix(GF(Integer(3)),Integer(1000),Integer(1000))>>> type(A)<class sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_float >>>> A = random_matrix(Integers(Integer(10)),Integer(1000),Integer(1000))>>> type(A)<class sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_float >>>> A = random_matrix(Integers(Integer(2)**Integer(16)),Integer(1000),
˓→Integer(1000))>>> type(A)<class sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_double >charpoly(var='x', algorithm='linbox')
Return the characteristic polynomial of self.
INPUT:• var – a variable name• algorithm – ‘generic’, ‘linbox’ or ‘all’ (default: linbox)
EXAMPLES:
sage: A = random_matrix(GF(19), 10, 10)
sage: B = copy(A)sage: char_p = A.characteristic_polynomial()
sage: char_p(A) == 0
True
sage: B == A
# A is not modified
True
sage: min_p = A.minimal_polynomial(proof=True)
sage: min_p.divides(char_p)
True>>> from sage.all import *>>> A = random_matrix(GF(Integer(19)), Integer(10), Integer(10))>>> B = copy(A)>>> char_p = A.characteristic_polynomial()>>> char_p(A) == Integer(0)True>>> B == A
# A is not modified
True>>> min_p = A.minimal_polynomial(proof=True)>>> min_p.divides(char_p)
True
sage: A = random_matrix(GF(2916337), 7, 7)
˓→needs sage.rings.finite_rings
sage: B = copy(A)sage: char_p = A.characteristic_polynomial()
sage: char_p(A) == 0
True
sage: B == A
# A is not modified
True

#␣

sage: min_p = A.minimal_polynomial(proof=True)(continues on next page)

814

Chapter 25. Dense matrices over Z/𝑛Z for 𝑛 < 94906266 using LinBox’s Modular<double>

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: min_p.divides(char_p)
True
sage: A = Mat(Integers(6),3,3)(range(9))
sage: A.charpoly()x^3>>> from sage.all import *>>> A = random_matrix(GF(Integer(2916337)), Integer(7), Integer(7))˓→# needs sage.rings.finite_rings>>> B = copy(A)>>> char_p = A.characteristic_polynomial()>>> char_p(A) == Integer(0)True>>> B == A
# A is not modified
True␣>>> min_p = A.minimal_polynomial(proof=True)>>> min_p.divides(char_p)
True>>> A = Mat(Integers(Integer(6)),Integer(3),Integer(3))(range(Integer(9)))>>> A.charpoly()x^3

ALGORITHM: Uses LinBox if self.base_ring() is a field, otherwise use Hessenberg form algorithm.
determinant()
Return the determinant of this matrix.
EXAMPLES:
sage: s = set()sage: while s != set(GF(7)):....:
A = random_matrix(GF(7), 10, 10)....:s.add(A.determinant())>>> from sage.all import *>>> s = set()>>> while s != set(GF(Integer(7))):...
A = random_matrix(GF(Integer(7)), Integer(10), Integer(10))...
s.add(A.determinant())
sage: A = random_matrix(GF(7), 100, 100)
sage: A.determinant() == A.transpose().determinant()
True
sage: B = random_matrix(GF(7), 100, 100)
sage: (A*B).determinant() == A.determinant() * B.determinant()
True>>> from sage.all import *>>> A = random_matrix(GF(Integer(7)), Integer(100), Integer(100))>>> A.determinant() == A.transpose().determinant()
True(continues on next page)815

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> B = random_matrix(GF(Integer(7)), Integer(100), Integer(100))>>> (A*B).determinant() == A.determinant() * B.determinant()
True
sage: # needs sage.rings.finite_rings
sage: A = random_matrix(GF(16007), 10, 10)
sage: A.determinant().parent() is GF(16007)
True>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> A = random_matrix(GF(Integer(16007)), Integer(10), Integer(10))>>> A.determinant().parent() is GF(Integer(16007))
True
sage: # needs sage.rings.finite_rings
sage: A = random_matrix(GF(16007), 100, 100)
sage: A.determinant().parent() is GF(16007)
True
sage: A.determinant() == A.transpose().determinant()
True
sage: B = random_matrix(GF(16007), 100, 100)
sage: (A*B).determinant() == A.determinant() * B.determinant()
True>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> A = random_matrix(GF(Integer(16007)), Integer(100), Integer(100))>>> A.determinant().parent() is GF(Integer(16007))
True>>> A.determinant() == A.transpose().determinant()
True>>> B = random_matrix(GF(Integer(16007)), Integer(100), Integer(100))>>> (A*B).determinant() == A.determinant() * B.determinant()
True

Parallel computation:
sage: # needs sage.rings.finite_rings
sage: A = random_matrix(GF(65521),200)
sage: B = copy(A)sage: Parallelism().set( linbox , nproc=2)
sage: d = A.determinant()
sage: Parallelism().set( linbox , nproc=1) # switch off parallelization
sage: e = B.determinant()
sage: d==e
True>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> A = random_matrix(GF(Integer(65521)),Integer(200))>>> B = copy(A)>>> Parallelism().set( linbox , nproc=Integer(2))>>> d = A.determinant()(continues on next page)

816

Chapter 25. Dense matrices over Z/𝑛Z for 𝑛 < 94906266 using LinBox’s Modular<double>

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> Parallelism().set( linbox , nproc=Integer(1)) # switch off parallelization>>> e = B.determinant()>>> d==eTrueechelonize(algorithm='linbox_noefd', **kwds)
Put self in reduced row echelon form.
INPUT:• self – a mutable matrix• algorithm– linbox – uses the LinBox library (wrapping fflas-ffpack)– linbox_noefd – uses the FFPACK directly, less memory and faster (default)– gauss – uses a custom slower 𝑂(𝑛3 ) Gauss elimination implemented in Sage.
– all – compute using both algorithms and verify that the results are the same.
• **kwds – these are all ignored
OUTPUT:• self is put in reduced row echelon form.
• the rank of self is computed and cached• the pivot columns of self are computed and cached.
• the fact that self is now in echelon form is recorded and cached so future calls to echelonize return
immediately.
EXAMPLES:
sage: A = random_matrix(GF(7), 10, 20)
sage: E = A.echelon_form()
sage: A.row_space() == E.row_space()
True
sage: all(r[r.nonzero_positions()[0]] == 1 for r in E.rows() if r)
True>>> from sage.all import *>>> A = random_matrix(GF(Integer(7)), Integer(10), Integer(20))>>> E = A.echelon_form()>>> A.row_space() == E.row_space()
True>>> all(r[r.nonzero_positions()[Integer(0)]] == Integer(1) for r in E.rows()␣
˓→if r)True
sage: A = random_matrix(GF(13), 10, 10)
sage: while A.rank() != 10:....:
A = random_matrix(GF(13), 10, 10)
sage: MS = parent(A)sage: B = A.augment(MS(1))
sage: B.echelonize()
sage: A.rank()(continues on next page)817

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)10
sage: C = B.submatrix(0,10,10,10)
sage: ~A == C
True>>> from sage.all import *>>> A = random_matrix(GF(Integer(13)), Integer(10), Integer(10))>>> while A.rank() != Integer(10):...
A = random_matrix(GF(Integer(13)), Integer(10), Integer(10))>>> MS = parent(A)>>> B = A.augment(MS(Integer(1)))>>> B.echelonize()>>> A.rank()
10>>> C = B.submatrix(Integer(0),Integer(10),Integer(10),Integer(10))>>> ~A == C
True
sage: A = random_matrix(Integers(10), 10, 20)
sage: A.echelon_form()
Traceback (most recent call last):...
NotImplementedError: Echelon form not implemented over˓→modulo 10 .

Ring of integers␣

>>> from sage.all import *>>> A = random_matrix(Integers(Integer(10)), Integer(10), Integer(20))>>> A.echelon_form()
Traceback (most recent call last):...
NotImplementedError: Echelon form not implemented over Ring of integers␣
˓→modulo 10 .
sage: # needs sage.rings.finite_rings
sage: A = random_matrix(GF(16007), 10, 20)
sage: E = A.echelon_form()
sage: A.row_space() == E.row_space()
True
sage: all(r[r.nonzero_positions()[0]] == 1 for r in E.rows() if r)
True>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> A = random_matrix(GF(Integer(16007)), Integer(10), Integer(20))>>> E = A.echelon_form()>>> A.row_space() == E.row_space()
True>>> all(r[r.nonzero_positions()[Integer(0)]] == Integer(1) for r in E.rows()␣
˓→if r)True
sage: A = random_matrix(Integers(10000), 10, 20)
sage: A.echelon_form()
Traceback (most recent call last):(continues on next page)

818

Chapter 25. Dense matrices over Z/𝑛Z for 𝑛 < 94906266 using LinBox’s Modular<double>

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
NotImplementedError: Echelon form not implemented over˓→modulo 10000 .

Ring of integers␣

>>> from sage.all import *>>> A = random_matrix(Integers(Integer(10000)), Integer(10), Integer(20))>>> A.echelon_form()
Traceback (most recent call last):...
NotImplementedError: Echelon form not implemented over Ring of integers␣
˓→modulo 10000 .

Parallel computation:
sage: # needs sage.rings.finite_rings
sage: A = random_matrix(GF(65521),100,200)
sage: Parallelism().set( linbox , nproc=2)
sage: E = A.echelon_form()
sage: Parallelism().set( linbox , nproc=1) # switch off parallelization
sage: F = A.echelon_form()
sage: E==F
True>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> A = random_matrix(GF(Integer(65521)),Integer(100),Integer(200))>>> Parallelism().set( linbox , nproc=Integer(2))>>> E = A.echelon_form()>>> Parallelism().set( linbox , nproc=Integer(1)) # switch off parallelization>>> F = A.echelon_form()>>> E==F
Truehessenbergize()
Transforms self in place to its Hessenberg form.
EXAMPLES:
sage: A = random_matrix(GF(17), 10, 10, density=0.1)
sage: B = copy(A)sage: A.hessenbergize()
sage: all(A[i,j] == 0 for j in range(10) for i in range(j+2, 10))True
sage: A.charpoly() == B.charpoly()
True>>> from sage.all import *>>> A = random_matrix(GF(Integer(17)), Integer(10), Integer(10),␣
˓→density=RealNumber( 0.1 ))>>> B = copy(A)>>> A.hessenbergize()>>> all(A[i,j] == Integer(0) for j in range(Integer(10)) for i in␣
˓→range(j+Integer(2), Integer(10)))
True>>> A.charpoly() == B.charpoly()
True

819

Matrices and Spaces of Matrices, Release 10.4

lift()
Return the lift of this matrix to the integers.
EXAMPLES:
sage: A = matrix(GF(7),2,3,[1..6])
sage: A.lift()[1 2 3][4 5 6]sage: A.lift().parent()
Full MatrixSpace of 2 by 3 dense matrices over Integer Ringsage: # needs sage.rings.finite_rings
sage: A = matrix(GF(16007),2,3,[1..6])
sage: A.lift()[1 2 3][4 5 6]sage: A.lift().parent()
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring>>> from sage.all import *>>> A = matrix(GF(Integer(7)),Integer(2),Integer(3),(ellipsis_
˓→range(Integer(1),Ellipsis,Integer(6))))>>> A.lift()[1 2 3][4 5 6]>>> A.lift().parent()
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring>>> # needs sage.rings.finite_rings>>> A = matrix(GF(Integer(16007)),Integer(2),Integer(3),(ellipsis_
˓→range(Integer(1),Ellipsis,Integer(6))))>>> A.lift()[1 2 3][4 5 6]>>> A.lift().parent()
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring

Subdivisions are preserved when lifting:sage: A.subdivide([], [1,1]); A[1||2 3][4||5 6]sage: A.lift()[1||2 3][4||5 6]>>> from sage.all import *>>> A.subdivide([], [Integer(1),Integer(1)]); A[1||2 3][4||5 6]>>> A.lift()[1||2 3][4||5 6]matrix_from_columns(columns)
Return the matrix constructed from self using columns with indices in the columns list.

820

Chapter 25. Dense matrices over Z/𝑛Z for 𝑛 < 94906266 using LinBox’s Modular<double>

Matrices and Spaces of Matrices, Release 10.4

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

matrix_from_rows(rows)
Return the matrix constructed from self using rows with indices in the rows list.
EXAMPLES:
sage: M = MatrixSpace(Integers(8),3,3)
sage: A = M(range(9)); A[0 1 2][3 4 5][6 7 0]sage: A.matrix_from_rows([2,1])[6 7 0][3 4 5]>>> from sage.all import *>>> M = MatrixSpace(Integers(Integer(8)),Integer(3),Integer(3))>>> A = M(range(Integer(9))); A[0 1 2][3 4 5][6 7 0]>>> A.matrix_from_rows([Integer(2),Integer(1)])[6 7 0][3 4 5]matrix_from_rows_and_columns(rows, columns)
Return the matrix constructed from self from the given rows and columns.
EXAMPLES:
sage: M = MatrixSpace(Integers(8),3,3)
sage: A = M(range(9)); A[0 1 2][3 4 5][6 7 0](continues on next page)821

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

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))>>> 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]

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]

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]AUTHORS:• Jaap Spies (2006-02-18)• Didier Deshommes: some Pyrex speedups implemented
minpoly(var='x', algorithm='linbox', proof=None)
Returns the minimal polynomial of`` self``.
INPUT:• var – a variable name822

Chapter 25. Dense matrices over Z/𝑛Z for 𝑛 < 94906266 using LinBox’s Modular<double>

Matrices and Spaces of Matrices, Release 10.4

• algorithm – generic or linbox (default: linbox)• proof – (default: True); whether to provably return the true minimal polynomial; if False, weonly guarantee to return a divisor of the minimal polynomial. There are also certainly cases where thecomputed results is frequently not exactly equal to the minimal polynomial (but is instead merely a divisorof it).

Warning:
If proof=True, minpoly is insanely slow compared to proof=False.
This matters since proof=True is the default, unless you first type proof.
linear_algebra(False).
EXAMPLES:
sage: A = random_matrix(GF(17), 10, 10)
sage: B = copy(A)sage: min_p = A.minimal_polynomial(proof=True)
sage: min_p(A) == 0
True
sage: B == A
True
sage: char_p = A.characteristic_polynomial()
sage: min_p.divides(char_p)
True>>> from sage.all import *>>> A = random_matrix(GF(Integer(17)), Integer(10), Integer(10))>>> B = copy(A)>>> min_p = A.minimal_polynomial(proof=True)>>> min_p(A) == Integer(0)True>>> B == A
True>>> char_p = A.characteristic_polynomial()>>> min_p.divides(char_p)
True
sage: A = random_matrix(GF(1214471), 10, 10)
˓→needs sage.rings.finite_rings
sage: B = copy(A)sage: min_p = A.minimal_polynomial(proof=True)
sage: min_p(A) == 0
True
sage: B == A
True

#␣

sage: char_p = A.characteristic_polynomial()
sage: min_p.divides(char_p)
True>>> from sage.all import *>>> A = random_matrix(GF(Integer(1214471)), Integer(10), Integer(10))˓→# needs sage.rings.finite_rings␣(continues on next page)823

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> B = copy(A)>>> min_p = A.minimal_polynomial(proof=True)>>> min_p(A) == Integer(0)True>>> B == A
True>>> char_p = A.characteristic_polynomial()>>> min_p.divides(char_p)
True

EXAMPLES:
sage: R.<x>=GF(3)[]sage: A = matrix(GF(3),2,[0,0,1,2])
sage: A.minpoly()x^2 + xsage: A.minpoly(proof=False) in [x, x+1, x^2+x]
True>>> from sage.all import *>>> R = GF(Integer(3))[ x ]; (x,) = R._first_ngens(1)>>> A = matrix(GF(Integer(3)),Integer(2),[Integer(0),Integer(0),Integer(1),˓→Integer(2)])>>> A.minpoly()x^2 + x>>> A.minpoly(proof=False) in [x, x+Integer(1), x**Integer(2)+x]
True

randomize(density=1, nonzero=False)
Randomize density proportion of the entries of this matrix, leaving the rest unchanged.
INPUT:• density – Integer; proportion (roughly) to be considered
for changes• nonzero – Bool (default: False); whether the new
entries are forced to be non-zero
OUTPUT:• None, the matrix is modified in-space
EXAMPLES:
sage: A = matrix(GF(5), 5, 5, 0)
sage: total_count = 0
sage: from collections import defaultdict
sage: dic = defaultdict(Integer)
sage: def add_samples(density):....:
global dic, total_count....:for _ in range(100):....:
A = Matrix(GF(5), 5, 5, 0)....:
A.randomize(density)....:
for a in A.list():(continues on next page)

824

Chapter 25. Dense matrices over Z/𝑛Z for 𝑛 < 94906266 using LinBox’s Modular<double>

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

....:
....:

dic[a] += 1
total_count += 1.0

sage: add_samples(1.0)
sage: while not all(abs(dic[a]/total_count - 1/5) < 0.01 for a in dic):....:
add_samples(1.0)
sage: def add_sample(density):....:
global density_sum, total_count....:total_count += 1.0....:
density_sum += random_matrix(GF(5), 1000, 1000, density=density).
˓→density()
sage: density_sum = 0.0
sage: total_count = 0.0
sage: add_sample(0.5)
sage: expected_density = 1.0 - (999/1000)^500
sage: expected_density
0.3936...
sage: while abs(density_sum/total_count - expected_density) > 0.001:....:
add_sample(0.5)>>> from sage.all import *>>> A = matrix(GF(Integer(5)), Integer(5), Integer(5), Integer(0))>>> total_count = Integer(0)>>> from collections import defaultdict>>> dic = defaultdict(Integer)>>> def add_samples(density):...
global dic, total_count...
for _ in range(Integer(100)):...
A = Matrix(GF(Integer(5)), Integer(5), Integer(5), Integer(0))...
A.randomize(density)...
for a in A.list():...
dic[a] += Integer(1)...
total_count += RealNumber( 1.0 )>>> add_samples(RealNumber( 1.0 ))>>> while not all(abs(dic[a]/total_count - Integer(1)/Integer(5)) <␣
˓→RealNumber( 0.01 ) for a in dic):...
add_samples(RealNumber( 1.0 ))>>> def add_sample(density):...
global density_sum, total_count...
total_count += RealNumber( 1.0 )...
density_sum += random_matrix(GF(Integer(5)), Integer(1000),␣
˓→Integer(1000), density=density).density()>>> density_sum = RealNumber( 0.0 )>>> total_count = RealNumber( 0.0 )>>> add_sample(RealNumber( 0.5 ))>>> expected_density = RealNumber( 1.0 ) - (Integer(999)/
˓→Integer(1000))**Integer(500)>>> expected_density
0.3936...
>>> while abs(density_sum/total_count - expected_density) > RealNumber( 0.001
˓→ ):
...
add_sample(RealNumber( 0.5 ))825

Matrices and Spaces of Matrices, Release 10.4

The matrix is updated instead of overwritten:
sage: def add_sample(density):....:
global density_sum, total_count....:total_count += 1.0....:
A = random_matrix(GF(5), 1000, 1000, density=density)....:
A.randomize(density=density, nonzero=True)....:
density_sum += A.density()
sage: density_sum = 0.0
sage: total_count = 0.0
sage: add_sample(0.5)
sage: expected_density = 1.0 - (999/1000)^1000
sage: expected_density
0.6323...
sage: while abs(density_sum/total_count - expected_density) > 0.001:....:
add_sample(0.5)
sage: density_sum = 0.0
sage: total_count = 0.0
sage: add_sample(0.1)
sage: expected_density = 1.0 - (999/1000)^200
sage: expected_density
0.1813...
sage: while abs(density_sum/total_count - expected_density) > 0.001:....:
add_sample(0.1)>>> from sage.all import *>>> def add_sample(density):...
global density_sum, total_count...
total_count += RealNumber( 1.0 )...
A = random_matrix(GF(Integer(5)), Integer(1000), Integer(1000),␣
˓→density=density)...
A.randomize(density=density, nonzero=True)...
density_sum += A.density()>>> density_sum = RealNumber( 0.0 )>>> total_count = RealNumber( 0.0 )>>> add_sample(RealNumber( 0.5 ))>>> expected_density = RealNumber( 1.0 ) - (Integer(999)/
˓→Integer(1000))**Integer(1000)>>> expected_density
0.6323...
>>> while abs(density_sum/total_count - expected_density) > RealNumber( 0.001
˓→ ):
...
add_sample(RealNumber( 0.5 ))>>> density_sum = RealNumber( 0.0 )>>> total_count = RealNumber( 0.0 )>>> add_sample(RealNumber( 0.1 ))>>> expected_density = RealNumber( 1.0 ) - (Integer(999)/
˓→Integer(1000))**Integer(200)>>> expected_density
0.1813...
>>> while abs(density_sum/total_count - expected_density) > RealNumber( 0.001
˓→ ):
...
add_sample(RealNumber( 0.1 ))rank()
826

Chapter 25. Dense matrices over Z/𝑛Z for 𝑛 < 94906266 using LinBox’s Modular<double>

Matrices and Spaces of Matrices, Release 10.4

Return the rank of this matrix.
EXAMPLES:
sage: A = random_matrix(GF(3), 100, 100)
sage: B = copy(A)sage: _ = A.rank()
sage: B == A
True
sage: A = random_matrix(GF(3), 100, 100, density=0.01)
sage: A.transpose().rank() == A.rank()
True
sage: A = matrix(GF(3), 100, 100)
sage: A.rank()
0>>> from sage.all import *>>> A = random_matrix(GF(Integer(3)), Integer(100), Integer(100))>>> B = copy(A)>>> _ = A.rank()>>> B == A
True>>> A = random_matrix(GF(Integer(3)), Integer(100), Integer(100),␣
˓→density=RealNumber( 0.01 ))>>> A.transpose().rank() == A.rank()
True>>> A = matrix(GF(Integer(3)), Integer(100), Integer(100))>>> A.rank()
0Rank is not implemented over the integers modulo a composite yet.:sage: M = matrix(Integers(4), 2, [2,2,2,2])
sage: M.rank()
Traceback (most recent call last):...
NotImplementedError: Echelon form not implemented over˓→modulo 4 .

Ring of integers␣

>>> from sage.all import *>>> M = matrix(Integers(Integer(4)), Integer(2), [Integer(2),Integer(2),˓→Integer(2),Integer(2)])>>> M.rank()
Traceback (most recent call last):...
NotImplementedError: Echelon form not implemented over Ring of integers␣
˓→modulo 4 .
sage: # needs sage.rings.finite_rings
sage: A = random_matrix(GF(16007), 100, 100)
sage: B = copy(A)sage: A.rank()(continues on next page)827

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)100
sage: B == A
True
sage: MS = A.parent()
sage: MS(1) == ~A*A
True>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> A = random_matrix(GF(Integer(16007)), Integer(100), Integer(100))>>> B = copy(A)>>> A.rank()
100>>> B == A
True>>> MS = A.parent()>>> MS(Integer(1)) == ~A*A
Trueright_kernel_matrix(algorithm='linbox', basis='echelon')
Returns a matrix whose rows form a basis for the right kernel of self.
If the base ring is the ring of integers modulo a composite, the keyword arguments are ignored and thecomputation is delegated to Matrix_dense.right_kernel_matrix().
INPUT:• algorithm – (default: linbox ) a parameter that is passed on to self.echelon_form, if
computation of an echelon form is required; see that routine for allowable values• basis – (default: echelon ) a keyword that describes the format of the basis returned, allowablevalues are:–echelon : the basis matrix is in echelon form–

pivot : the basis matrix is such that the submatrix obtainedby taking the columns that in self contain no pivots, is the identity matrix–

computed : no work is done to transform the basis; inthe current implementation the result is the negative of that returned by pivot

OUTPUT:
A matrix X whose rows are a basis for the right kernel of self. This means that self * X.transpose()
is a zero matrix.
The result is not cached, but the routine benefits when self is known to be in echelon form already.
EXAMPLES:
sage: M = matrix(GF(5),6,6,range(36))
sage: M.right_kernel_matrix(basis= computed )[4 2 4 0 0 0]
[3 3 0 4 0 0]
[2 4 0 0 4 0]
[1 0 0 0 0 4]
sage: M.right_kernel_matrix(basis= pivot )[1 3 1 0 0 0]
[2 2 0 1 0 0](continues on next page)

828

Chapter 25. Dense matrices over Z/𝑛Z for 𝑛 < 94906266 using LinBox’s Modular<double>

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[3 1 0 0 1 0]
[4 0 0 0 0 1]
sage: M.right_kernel_matrix()[1 0 0 0 0 4]
[0 1 0 0 1 3]
[0 0 1 0 2 2]
[0 0 0 1 3 1]
sage: M * M.right_kernel_matrix().transpose()[0 0 0 0][0 0 0 0][0 0 0 0][0 0 0 0][0 0 0 0][0 0 0 0]>>> from sage.all import *>>> M = matrix(GF(Integer(5)),Integer(6),Integer(6),range(Integer(36)))>>> M.right_kernel_matrix(basis= computed )[4 2 4 0 0 0]
[3 3 0 4 0 0]
[2 4 0 0 4 0]
[1 0 0 0 0 4]>>> M.right_kernel_matrix(basis= pivot )[1 3 1 0 0 0]
[2 2 0 1 0 0]
[3 1 0 0 1 0]
[4 0 0 0 0 1]>>> M.right_kernel_matrix()[1 0 0 0 0 4]
[0 1 0 0 1 3]
[0 0 1 0 2 2]
[0 0 0 1 3 1]>>> M * M.right_kernel_matrix().transpose()[0 0 0 0][0 0 0 0][0 0 0 0][0 0 0 0][0 0 0 0][0 0 0 0]

submatrix(row=0, col=0, nrows=-1, ncols=-1)
Return the matrix constructed from self using the specified range of rows and columns.
INPUT:• row, col – index of the starting row and column. Indices start at zero
• nrows, ncols – (optional) number of rows and columns to take. If not provided, take all rows below
and all columns to the right of the starting entry
See also:Thefunctionsmatrix_from_rows(),
matrix_from_columns(),andmatrix_from_rows_and_columns() allow one to select arbitrary subsets of rows and/or columns.
EXAMPLES:
Take the 3 × 3 submatrix starting from entry (1, 1) in a 4 × 4 matrix:829

Matrices and Spaces of Matrices, Release 10.4

sage: m = matrix(GF(17),4, [1..16])
sage: m.submatrix(1, 1)[ 6 7 8][10 11 12][14 15 16]>>> from sage.all import *>>> m = matrix(GF(Integer(17)),Integer(4), (ellipsis_range(Integer(1),˓→Ellipsis,Integer(16))))>>> m.submatrix(Integer(1), Integer(1))[ 6 7 8][10 11 12][14 15 16]Same thing, except take only two rows:
sage: m.submatrix(1, 1, 2)[ 6 7 8][10 11 12]>>> from sage.all import *>>> m.submatrix(Integer(1), Integer(1), Integer(2))[ 6 7 8][10 11 12]

And now take only one column:
sage: m.submatrix(1, 1, 2, 1)
[ 6]
[10]
>>> from sage.all import *>>> m.submatrix(Integer(1), Integer(1), Integer(2), Integer(1))
[ 6]
[10]

You can take zero rows or columns if you want:sage: m.submatrix(0, 0, 0)[]
sage: parent(m.submatrix(0, 0, 0))
Full MatrixSpace of 0 by 4 dense matrices over Finite Field of size 17>>> from sage.all import *>>> m.submatrix(Integer(0), Integer(0), Integer(0))[]>>> parent(m.submatrix(Integer(0), Integer(0), Integer(0)))
Full MatrixSpace of 0 by 4 dense matrices over Finite Field of size 17transpose()
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.

830

Chapter 25. Dense matrices over Z/𝑛Z for 𝑛 < 94906266 using LinBox’s Modular<double>

Matrices and Spaces of Matrices, Release 10.4

sage: M = MatrixSpace(GF(41),sage: A = M([1,2,3,4])
sage: B = A.transpose()sage: B
[1 3]
[2 4]
sage: A
[1 2]
[3 4]

2)

>>> from sage.all import *>>> M = MatrixSpace(GF(Integer(41)), Integer(2))>>> A = M([Integer(1),Integer(2),Integer(3),Integer(4)])>>> B = A.transpose()
>>> B
[1 3]
[2 4]
>>> A
[1 2]
[3 4]

.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]
sage: A.subdivide(None, 1); A
[1|2]
[3|4]
sage: A.transpose()
[1 3]
[---]
[2 4]
>>> from sage.all import *>>> A.subdivide(None, Integer(1)); A
[1|2]
[3|4]
>>> A.transpose()
[1 3]
[---]
[2 4]

831

Matrices and Spaces of Matrices, Release 10.4

832

Chapter 25. Dense matrices over Z/𝑛Z for 𝑛 < 94906266 using LinBox’s Modular<double>

CHAPTERTWENTYSIXDENSE MATRICES OVER Z/𝑁 Z FOR 𝑁 < 28 USING LINBOX’S
MODULAR<FLOAT>AUTHORS: - Burcin Erocal - Martin Albrecht
class sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_float
Bases: Matrix_modn_dense_template
Dense matrices over Z/𝑛Z for 𝑛 < 28 using LinBox’s Modular<float>
These are matrices with integer entries mod n represented as floating-point numbers in a 32-bit word for use with
LinBox routines. This could allow for n up to 211 , but for performance reasons this is limited to n up to 28 , andfor larger moduli the Matrix_modn_dense_double class is used.
Routines here are for the most basic access, see the matrix_modn_dense_template.pxi file forhigher-level routines.
class sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_template
Bases: Matrix_dense
Create a new matrix.
INPUT:• parent – a matrix space• entries – see matrix()• copy – ignored (for backwards compatibility)• coerce – perform modular reduction first?
EXAMPLES:
sage: A = random_matrix(GF(3),1000,1000)
sage: type(A)<class sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_float >sage: A = random_matrix(Integers(10),1000,1000)
sage: type(A)<class sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_float >sage: A = random_matrix(Integers(2^16),1000,1000)
sage: type(A)<class sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_double >>>> from sage.all import *>>> A = random_matrix(GF(Integer(3)),Integer(1000),Integer(1000))>>> type(A)<class sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_float >(continues on next page)833

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> A = random_matrix(Integers(Integer(10)),Integer(1000),Integer(1000))>>> type(A)<class sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_float >>>> A = random_matrix(Integers(Integer(2)**Integer(16)),Integer(1000),
˓→Integer(1000))>>> type(A)<class sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_double >charpoly(var='x', algorithm='linbox')
Return the characteristic polynomial of self.
INPUT:• var – a variable name• algorithm – ‘generic’, ‘linbox’ or ‘all’ (default: linbox)
EXAMPLES:
sage: A = random_matrix(GF(19), 10, 10)
sage: B = copy(A)sage: char_p = A.characteristic_polynomial()
sage: char_p(A) == 0
True
sage: B == A
# A is not modified
True
sage: min_p = A.minimal_polynomial(proof=True)
sage: min_p.divides(char_p)
True>>> from sage.all import *>>> A = random_matrix(GF(Integer(19)), Integer(10), Integer(10))>>> B = copy(A)>>> char_p = A.characteristic_polynomial()>>> char_p(A) == Integer(0)True>>> B == A
# A is not modified
True>>> min_p = A.minimal_polynomial(proof=True)>>> min_p.divides(char_p)
True
sage: A = random_matrix(GF(2916337), 7, 7)
˓→needs sage.rings.finite_rings
sage: B = copy(A)sage: char_p = A.characteristic_polynomial()
sage: char_p(A) == 0
True
sage: B == A
# A is not modified
True

#␣

sage: min_p = A.minimal_polynomial(proof=True)
sage: min_p.divides(char_p)
True(continues on next page)

834

Chapter 26. Dense matrices over Z/𝑛Z for 𝑛 < 28 using LinBox’s Modular<float>

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: A = Mat(Integers(6),3,3)(range(9))
sage: A.charpoly()x^3>>> from sage.all import *>>> A = random_matrix(GF(Integer(2916337)), Integer(7), Integer(7))˓→# needs sage.rings.finite_rings>>> B = copy(A)>>> char_p = A.characteristic_polynomial()>>> char_p(A) == Integer(0)True>>> B == A
# A is not modified
True␣>>> min_p = A.minimal_polynomial(proof=True)>>> min_p.divides(char_p)
True>>> A = Mat(Integers(Integer(6)),Integer(3),Integer(3))(range(Integer(9)))>>> A.charpoly()x^3

ALGORITHM: Uses LinBox if self.base_ring() is a field, otherwise use Hessenberg form algorithm.
determinant()
Return the determinant of this matrix.
EXAMPLES:
sage: s = set()sage: while s != set(GF(7)):....:
A = random_matrix(GF(7), 10, 10)....:s.add(A.determinant())>>> from sage.all import *>>> s = set()>>> while s != set(GF(Integer(7))):...
A = random_matrix(GF(Integer(7)), Integer(10), Integer(10))...
s.add(A.determinant())
sage: A = random_matrix(GF(7), 100, 100)
sage: A.determinant() == A.transpose().determinant()
True
sage: B = random_matrix(GF(7), 100, 100)
sage: (A*B).determinant() == A.determinant() * B.determinant()
True>>> from sage.all import *>>> A = random_matrix(GF(Integer(7)), Integer(100), Integer(100))>>> A.determinant() == A.transpose().determinant()
True>>> B = random_matrix(GF(Integer(7)), Integer(100), Integer(100))>>> (A*B).determinant() == A.determinant() * B.determinant()
True

835

Matrices and Spaces of Matrices, Release 10.4

sage: # needs sage.rings.finite_rings
sage: A = random_matrix(GF(16007), 10, 10)
sage: A.determinant().parent() is GF(16007)
True>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> A = random_matrix(GF(Integer(16007)), Integer(10), Integer(10))>>> A.determinant().parent() is GF(Integer(16007))
True
sage: # needs sage.rings.finite_rings
sage: A = random_matrix(GF(16007), 100, 100)
sage: A.determinant().parent() is GF(16007)
True
sage: A.determinant() == A.transpose().determinant()
True
sage: B = random_matrix(GF(16007), 100, 100)
sage: (A*B).determinant() == A.determinant() * B.determinant()
True>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> A = random_matrix(GF(Integer(16007)), Integer(100), Integer(100))>>> A.determinant().parent() is GF(Integer(16007))
True>>> A.determinant() == A.transpose().determinant()
True>>> B = random_matrix(GF(Integer(16007)), Integer(100), Integer(100))>>> (A*B).determinant() == A.determinant() * B.determinant()
True

Parallel computation:
sage: # needs sage.rings.finite_rings
sage: A = random_matrix(GF(65521),200)
sage: B = copy(A)sage: Parallelism().set( linbox , nproc=2)
sage: d = A.determinant()
sage: Parallelism().set( linbox , nproc=1) # switch off parallelization
sage: e = B.determinant()
sage: d==e
True>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> A = random_matrix(GF(Integer(65521)),Integer(200))>>> B = copy(A)>>> Parallelism().set( linbox , nproc=Integer(2))>>> d = A.determinant()>>> Parallelism().set( linbox , nproc=Integer(1)) # switch off parallelization>>> e = B.determinant()>>> d==eTrueechelonize(algorithm='linbox_noefd', **kwds)

836

Chapter 26. Dense matrices over Z/𝑛Z for 𝑛 < 28 using LinBox’s Modular<float>

Matrices and Spaces of Matrices, Release 10.4

Put self in reduced row echelon form.
INPUT:• self – a mutable matrix• algorithm– linbox – uses the LinBox library (wrapping fflas-ffpack)– linbox_noefd – uses the FFPACK directly, less memory and faster (default)– gauss – uses a custom slower 𝑂(𝑛3 ) Gauss elimination implemented in Sage.
– all – compute using both algorithms and verify that the results are the same.
• **kwds – these are all ignored
OUTPUT:• self is put in reduced row echelon form.
• the rank of self is computed and cached• the pivot columns of self are computed and cached.
• the fact that self is now in echelon form is recorded and cached so future calls to echelonize return
immediately.
EXAMPLES:
sage: A = random_matrix(GF(7), 10, 20)
sage: E = A.echelon_form()
sage: A.row_space() == E.row_space()
True
sage: all(r[r.nonzero_positions()[0]] == 1 for r in E.rows() if r)
True>>> from sage.all import *>>> A = random_matrix(GF(Integer(7)), Integer(10), Integer(20))>>> E = A.echelon_form()>>> A.row_space() == E.row_space()
True>>> all(r[r.nonzero_positions()[Integer(0)]] == Integer(1) for r in E.rows()␣
˓→if r)True
sage: A = random_matrix(GF(13), 10, 10)
sage: while A.rank() != 10:....:
A = random_matrix(GF(13), 10, 10)
sage: MS = parent(A)sage: B = A.augment(MS(1))
sage: B.echelonize()
sage: A.rank()
10sage: C = B.submatrix(0,10,10,10)
sage: ~A == C
True>>> from sage.all import *>>> A = random_matrix(GF(Integer(13)), Integer(10), Integer(10))>>> while A.rank() != Integer(10):(continues on next page)837

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
A = random_matrix(GF(Integer(13)), Integer(10), Integer(10))>>> MS = parent(A)>>> B = A.augment(MS(Integer(1)))>>> B.echelonize()>>> A.rank()
10>>> C = B.submatrix(Integer(0),Integer(10),Integer(10),Integer(10))>>> ~A == C
True
sage: A = random_matrix(Integers(10), 10, 20)
sage: A.echelon_form()
Traceback (most recent call last):...
NotImplementedError: Echelon form not implemented over˓→modulo 10 .

Ring of integers␣

>>> from sage.all import *>>> A = random_matrix(Integers(Integer(10)), Integer(10), Integer(20))>>> A.echelon_form()
Traceback (most recent call last):...
NotImplementedError: Echelon form not implemented over Ring of integers␣
˓→modulo 10 .
sage: # needs sage.rings.finite_rings
sage: A = random_matrix(GF(16007), 10, 20)
sage: E = A.echelon_form()
sage: A.row_space() == E.row_space()
True
sage: all(r[r.nonzero_positions()[0]] == 1 for r in E.rows() if r)
True>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> A = random_matrix(GF(Integer(16007)), Integer(10), Integer(20))>>> E = A.echelon_form()>>> A.row_space() == E.row_space()
True>>> all(r[r.nonzero_positions()[Integer(0)]] == Integer(1) for r in E.rows()␣
˓→if r)True
sage: A = random_matrix(Integers(10000), 10, 20)
sage: A.echelon_form()
Traceback (most recent call last):...
NotImplementedError: Echelon form not implemented over˓→modulo 10000 .

Ring of integers␣

>>> from sage.all import *>>> A = random_matrix(Integers(Integer(10000)), Integer(10), Integer(20))>>> A.echelon_form()
Traceback (most recent call last):(continues on next page)

838

Chapter 26. Dense matrices over Z/𝑛Z for 𝑛 < 28 using LinBox’s Modular<float>

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
NotImplementedError: Echelon form not implemented over˓→modulo 10000 .

Ring of integers␣

Parallel computation:
sage: # needs sage.rings.finite_rings
sage: A = random_matrix(GF(65521),100,200)
sage: Parallelism().set( linbox , nproc=2)
sage: E = A.echelon_form()
sage: Parallelism().set( linbox , nproc=1) # switch off parallelization
sage: F = A.echelon_form()
sage: E==F
True>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> A = random_matrix(GF(Integer(65521)),Integer(100),Integer(200))>>> Parallelism().set( linbox , nproc=Integer(2))>>> E = A.echelon_form()>>> Parallelism().set( linbox , nproc=Integer(1)) # switch off parallelization>>> F = A.echelon_form()>>> E==F
Truehessenbergize()
Transforms self in place to its Hessenberg form.
EXAMPLES:
sage: A = random_matrix(GF(17), 10, 10, density=0.1)
sage: B = copy(A)sage: A.hessenbergize()
sage: all(A[i,j] == 0 for j in range(10) for i in range(j+2, 10))True
sage: A.charpoly() == B.charpoly()
True>>> from sage.all import *>>> A = random_matrix(GF(Integer(17)), Integer(10), Integer(10),␣
˓→density=RealNumber( 0.1 ))>>> B = copy(A)>>> A.hessenbergize()>>> all(A[i,j] == Integer(0) for j in range(Integer(10)) for i in␣
˓→range(j+Integer(2), Integer(10)))
True>>> A.charpoly() == B.charpoly()Truelift()
Return the lift of this matrix to the integers.
EXAMPLES:
sage: A = matrix(GF(7),2,3,[1..6])
sage: A.lift()(continues on next page)839

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[1 2 3][4 5 6]sage: A.lift().parent()
Full MatrixSpace of 2 by 3 dense matrices over Integer Ringsage: # needs sage.rings.finite_rings
sage: A = matrix(GF(16007),2,3,[1..6])
sage: A.lift()[1 2 3][4 5 6]sage: A.lift().parent()
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring>>> from sage.all import *>>> A = matrix(GF(Integer(7)),Integer(2),Integer(3),(ellipsis_
˓→range(Integer(1),Ellipsis,Integer(6))))>>> A.lift()[1 2 3][4 5 6]>>> A.lift().parent()
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring>>> # needs sage.rings.finite_rings>>> A = matrix(GF(Integer(16007)),Integer(2),Integer(3),(ellipsis_
˓→range(Integer(1),Ellipsis,Integer(6))))>>> A.lift()[1 2 3][4 5 6]>>> A.lift().parent()
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring

Subdivisions are preserved when lifting:sage: A.subdivide([], [1,1]); A[1||2 3][4||5 6]sage: A.lift()[1||2 3][4||5 6]>>> from sage.all import *>>> A.subdivide([], [Integer(1),Integer(1)]); A[1||2 3][4||5 6]>>> A.lift()[1||2 3][4||5 6]matrix_from_columns(columns)
Return the matrix constructed from self using columns with indices in the columns list.
EXAMPLES:
sage: M = MatrixSpace(Integers(8),3,3)
sage: A = M(range(9)); A[0 1 2](continues on next page)

840

Chapter 26. Dense matrices over Z/𝑛Z for 𝑛 < 28 using LinBox’s Modular<float>

Matrices and Spaces of Matrices, Release 10.4

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

matrix_from_rows(rows)
Return the matrix constructed from self using rows with indices in the rows list.
EXAMPLES:
sage: M = MatrixSpace(Integers(8),3,3)
sage: A = M(range(9)); A[0 1 2][3 4 5][6 7 0]sage: A.matrix_from_rows([2,1])[6 7 0][3 4 5]>>> from sage.all import *>>> M = MatrixSpace(Integers(Integer(8)),Integer(3),Integer(3))>>> A = M(range(Integer(9))); A[0 1 2][3 4 5][6 7 0]>>> A.matrix_from_rows([Integer(2),Integer(1)])[6 7 0][3 4 5]matrix_from_rows_and_columns(rows, columns)
Return the matrix constructed from self from the given rows and columns.
EXAMPLES:
sage: M = MatrixSpace(Integers(8),3,3)
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])(continues on next page)841

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[4 5]
[7 0]
>>> from sage.all import *>>> M = MatrixSpace(Integers(Integer(8)),Integer(3),Integer(3))>>> 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]

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]

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]AUTHORS:• Jaap Spies (2006-02-18)• Didier Deshommes: some Pyrex speedups implemented
minpoly(var='x', algorithm='linbox', proof=None)
Returns the minimal polynomial of`` self``.
INPUT:• var – a variable name• algorithm – generic or linbox (default: linbox)

842

Chapter 26. Dense matrices over Z/𝑛Z for 𝑛 < 28 using LinBox’s Modular<float>

Matrices and Spaces of Matrices, Release 10.4

• proof – (default: True); whether to provably return the true minimal polynomial; if False, weonly guarantee to return a divisor of the minimal polynomial. There are also certainly cases where thecomputed results is frequently not exactly equal to the minimal polynomial (but is instead merely a divisorof it).

Warning:
If proof=True, minpoly is insanely slow compared to proof=False.
This matters since proof=True is the default, unless you first type proof.
linear_algebra(False).
EXAMPLES:
sage: A = random_matrix(GF(17), 10, 10)
sage: B = copy(A)sage: min_p = A.minimal_polynomial(proof=True)
sage: min_p(A) == 0
True
sage: B == A
True
sage: char_p = A.characteristic_polynomial()
sage: min_p.divides(char_p)
True>>> from sage.all import *>>> A = random_matrix(GF(Integer(17)), Integer(10), Integer(10))>>> B = copy(A)>>> min_p = A.minimal_polynomial(proof=True)>>> min_p(A) == Integer(0)True>>> B == A
True>>> char_p = A.characteristic_polynomial()>>> min_p.divides(char_p)
True
sage: A = random_matrix(GF(1214471), 10, 10)
˓→needs sage.rings.finite_rings
sage: B = copy(A)sage: min_p = A.minimal_polynomial(proof=True)
sage: min_p(A) == 0
True
sage: B == A
True

#␣

sage: char_p = A.characteristic_polynomial()
sage: min_p.divides(char_p)
True>>> from sage.all import *>>> A = random_matrix(GF(Integer(1214471)), Integer(10), Integer(10))˓→# needs sage.rings.finite_rings>>> B = copy(A)>>> min_p = A.minimal_polynomial(proof=True)␣(continues on next page)843

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> min_p(A) == Integer(0)True>>> B == A
True>>> char_p = A.characteristic_polynomial()>>> min_p.divides(char_p)
True

EXAMPLES:
sage: R.<x>=GF(3)[]sage: A = matrix(GF(3),2,[0,0,1,2])
sage: A.minpoly()x^2 + xsage: A.minpoly(proof=False) in [x, x+1, x^2+x]
True>>> from sage.all import *>>> R = GF(Integer(3))[ x ]; (x,) = R._first_ngens(1)>>> A = matrix(GF(Integer(3)),Integer(2),[Integer(0),Integer(0),Integer(1),˓→Integer(2)])>>> A.minpoly()x^2 + x>>> A.minpoly(proof=False) in [x, x+Integer(1), x**Integer(2)+x]
True

randomize(density=1, nonzero=False)
Randomize density proportion of the entries of this matrix, leaving the rest unchanged.
INPUT:• density – Integer; proportion (roughly) to be considered
for changes• nonzero – Bool (default: False); whether the new
entries are forced to be non-zero
OUTPUT:• None, the matrix is modified in-space
EXAMPLES:
sage: A = matrix(GF(5), 5, 5, 0)
sage: total_count = 0
sage: from collections import defaultdict
sage: dic = defaultdict(Integer)
sage: def add_samples(density):....:
global dic, total_count....:for _ in range(100):....:
A = Matrix(GF(5), 5, 5, 0)....:
A.randomize(density)....:
for a in A.list():....:dic[a] += 1....:
total_count += 1.0(continues on next page)

844

Chapter 26. Dense matrices over Z/𝑛Z for 𝑛 < 28 using LinBox’s Modular<float>

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: add_samples(1.0)
sage: while not all(abs(dic[a]/total_count - 1/5) < 0.01 for a in dic):....:
add_samples(1.0)
sage: def add_sample(density):....:
global density_sum, total_count....:total_count += 1.0....:
density_sum += random_matrix(GF(5), 1000, 1000, density=density).
˓→density()
sage: density_sum = 0.0
sage: total_count = 0.0
sage: add_sample(0.5)
sage: expected_density = 1.0 - (999/1000)^500
sage: expected_density
0.3936...
sage: while abs(density_sum/total_count - expected_density) > 0.001:....:
add_sample(0.5)>>> from sage.all import *>>> A = matrix(GF(Integer(5)), Integer(5), Integer(5), Integer(0))>>> total_count = Integer(0)>>> from collections import defaultdict>>> dic = defaultdict(Integer)>>> def add_samples(density):...
global dic, total_count...
for _ in range(Integer(100)):...
A = Matrix(GF(Integer(5)), Integer(5), Integer(5), Integer(0))...
A.randomize(density)...
for a in A.list():...
dic[a] += Integer(1)...
total_count += RealNumber( 1.0 )>>> add_samples(RealNumber( 1.0 ))>>> while not all(abs(dic[a]/total_count - Integer(1)/Integer(5)) <␣
˓→RealNumber( 0.01 ) for a in dic):...
add_samples(RealNumber( 1.0 ))>>> def add_sample(density):...
global density_sum, total_count...
total_count += RealNumber( 1.0 )...
density_sum += random_matrix(GF(Integer(5)), Integer(1000),␣
˓→Integer(1000), density=density).density()>>> density_sum = RealNumber( 0.0 )>>> total_count = RealNumber( 0.0 )>>> add_sample(RealNumber( 0.5 ))>>> expected_density = RealNumber( 1.0 ) - (Integer(999)/
˓→Integer(1000))**Integer(500)>>> expected_density
0.3936...
>>> while abs(density_sum/total_count - expected_density) > RealNumber( 0.001
˓→ ):
...
add_sample(RealNumber( 0.5 ))The matrix is updated instead of overwritten:
845

Matrices and Spaces of Matrices, Release 10.4

sage: def add_sample(density):....:
global density_sum, total_count....:total_count += 1.0....:
A = random_matrix(GF(5), 1000, 1000, density=density)....:
A.randomize(density=density, nonzero=True)....:
density_sum += A.density()
sage: density_sum = 0.0
sage: total_count = 0.0
sage: add_sample(0.5)
sage: expected_density = 1.0 - (999/1000)^1000
sage: expected_density
0.6323...
sage: while abs(density_sum/total_count - expected_density) > 0.001:....:
add_sample(0.5)
sage: density_sum = 0.0
sage: total_count = 0.0
sage: add_sample(0.1)
sage: expected_density = 1.0 - (999/1000)^200
sage: expected_density
0.1813...
sage: while abs(density_sum/total_count - expected_density) > 0.001:....:
add_sample(0.1)>>> from sage.all import *>>> def add_sample(density):...
global density_sum, total_count...
total_count += RealNumber( 1.0 )...
A = random_matrix(GF(Integer(5)), Integer(1000), Integer(1000),␣
˓→density=density)...
A.randomize(density=density, nonzero=True)...
density_sum += A.density()>>> density_sum = RealNumber( 0.0 )>>> total_count = RealNumber( 0.0 )>>> add_sample(RealNumber( 0.5 ))>>> expected_density = RealNumber( 1.0 ) - (Integer(999)/
˓→Integer(1000))**Integer(1000)>>> expected_density
0.6323...
>>> while abs(density_sum/total_count - expected_density) > RealNumber( 0.001
˓→ ):
...
add_sample(RealNumber( 0.5 ))>>> density_sum = RealNumber( 0.0 )>>> total_count = RealNumber( 0.0 )>>> add_sample(RealNumber( 0.1 ))>>> expected_density = RealNumber( 1.0 ) - (Integer(999)/
˓→Integer(1000))**Integer(200)>>> expected_density
0.1813...
>>> while abs(density_sum/total_count - expected_density) > RealNumber( 0.001
˓→ ):
...
add_sample(RealNumber( 0.1 ))rank()

846

Chapter 26. Dense matrices over Z/𝑛Z for 𝑛 < 28 using LinBox’s Modular<float>

Matrices and Spaces of Matrices, Release 10.4

Return the rank of this matrix.
EXAMPLES:
sage: A = random_matrix(GF(3), 100, 100)
sage: B = copy(A)sage: _ = A.rank()
sage: B == A
True
sage: A = random_matrix(GF(3), 100, 100, density=0.01)
sage: A.transpose().rank() == A.rank()
True
sage: A = matrix(GF(3), 100, 100)
sage: A.rank()
0>>> from sage.all import *>>> A = random_matrix(GF(Integer(3)), Integer(100), Integer(100))>>> B = copy(A)>>> _ = A.rank()>>> B == A
True>>> A = random_matrix(GF(Integer(3)), Integer(100), Integer(100),␣
˓→density=RealNumber( 0.01 ))>>> A.transpose().rank() == A.rank()
True>>> A = matrix(GF(Integer(3)), Integer(100), Integer(100))>>> A.rank()
0Rank is not implemented over the integers modulo a composite yet.:sage: M = matrix(Integers(4), 2, [2,2,2,2])
sage: M.rank()
Traceback (most recent call last):...
NotImplementedError: Echelon form not implemented over˓→modulo 4 .

Ring of integers␣

>>> from sage.all import *>>> M = matrix(Integers(Integer(4)), Integer(2), [Integer(2),Integer(2),˓→Integer(2),Integer(2)])>>> M.rank()
Traceback (most recent call last):...
NotImplementedError: Echelon form not implemented over Ring of integers␣
˓→modulo 4 .
sage: # needs sage.rings.finite_rings
sage: A = random_matrix(GF(16007), 100, 100)
sage: B = copy(A)sage: A.rank()
100(continues on next page)847

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: B == A
True
sage: MS = A.parent()
sage: MS(1) == ~A*A
True>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> A = random_matrix(GF(Integer(16007)), Integer(100), Integer(100))>>> B = copy(A)>>> A.rank()
100>>> B == A
True>>> MS = A.parent()>>> MS(Integer(1)) == ~A*A
Trueright_kernel_matrix(algorithm='linbox', basis='echelon')
Returns a matrix whose rows form a basis for the right kernel of self.
If the base ring is the ring of integers modulo a composite, the keyword arguments are ignored and thecomputation is delegated to Matrix_dense.right_kernel_matrix().
INPUT:• algorithm – (default: linbox ) a parameter that is passed on to self.echelon_form, if
computation of an echelon form is required; see that routine for allowable values• basis – (default: echelon ) a keyword that describes the format of the basis returned, allowablevalues are:–echelon : the basis matrix is in echelon form–

pivot : the basis matrix is such that the submatrix obtainedby taking the columns that in self contain no pivots, is the identity matrix–

computed : no work is done to transform the basis; inthe current implementation the result is the negative of that returned by pivot

OUTPUT:
A matrix X whose rows are a basis for the right kernel of self. This means that self * X.transpose()
is a zero matrix.
The result is not cached, but the routine benefits when self is known to be in echelon form already.
EXAMPLES:
sage: M = matrix(GF(5),6,6,range(36))
sage: M.right_kernel_matrix(basis= computed )[4 2 4 0 0 0]
[3 3 0 4 0 0]
[2 4 0 0 4 0]
[1 0 0 0 0 4]
sage: M.right_kernel_matrix(basis= pivot )[1 3 1 0 0 0]
[2 2 0 1 0 0]
[3 1 0 0 1 0]
(continues on next page)

848

Chapter 26. Dense matrices over Z/𝑛Z for 𝑛 < 28 using LinBox’s Modular<float>

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[4 0 0 0 0 1]
sage: M.right_kernel_matrix()[1 0 0 0 0 4]
[0 1 0 0 1 3]
[0 0 1 0 2 2]
[0 0 0 1 3 1]
sage: M * M.right_kernel_matrix().transpose()[0 0 0 0][0 0 0 0][0 0 0 0][0 0 0 0][0 0 0 0][0 0 0 0]>>> from sage.all import *>>> M = matrix(GF(Integer(5)),Integer(6),Integer(6),range(Integer(36)))>>> M.right_kernel_matrix(basis= computed )[4 2 4 0 0 0]
[3 3 0 4 0 0]
[2 4 0 0 4 0]
[1 0 0 0 0 4]>>> M.right_kernel_matrix(basis= pivot )[1 3 1 0 0 0]
[2 2 0 1 0 0]
[3 1 0 0 1 0]
[4 0 0 0 0 1]>>> M.right_kernel_matrix()[1 0 0 0 0 4]
[0 1 0 0 1 3]
[0 0 1 0 2 2]
[0 0 0 1 3 1]>>> M * M.right_kernel_matrix().transpose()[0 0 0 0][0 0 0 0][0 0 0 0][0 0 0 0][0 0 0 0][0 0 0 0]

submatrix(row=0, col=0, nrows=-1, ncols=-1)
Return the matrix constructed from self using the specified range of rows and columns.
INPUT:• row, col – index of the starting row and column. Indices start at zero
• nrows, ncols – (optional) number of rows and columns to take. If not provided, take all rows below
and all columns to the right of the starting entry
See also:Thefunctionsmatrix_from_rows(),
matrix_from_columns(),andmatrix_from_rows_and_columns() allow one to select arbitrary subsets of rows and/or columns.
EXAMPLES:
Take the 3 × 3 submatrix starting from entry (1, 1) in a 4 × 4 matrix:849

Matrices and Spaces of Matrices, Release 10.4

sage: m = matrix(GF(17),4, [1..16])
sage: m.submatrix(1, 1)[ 6 7 8][10 11 12][14 15 16]>>> from sage.all import *>>> m = matrix(GF(Integer(17)),Integer(4), (ellipsis_range(Integer(1),˓→Ellipsis,Integer(16))))>>> m.submatrix(Integer(1), Integer(1))[ 6 7 8][10 11 12][14 15 16]Same thing, except take only two rows:
sage: m.submatrix(1, 1, 2)[ 6 7 8][10 11 12]>>> from sage.all import *>>> m.submatrix(Integer(1), Integer(1), Integer(2))[ 6 7 8][10 11 12]

And now take only one column:
sage: m.submatrix(1, 1, 2, 1)
[ 6]
[10]
>>> from sage.all import *>>> m.submatrix(Integer(1), Integer(1), Integer(2), Integer(1))
[ 6]
[10]

You can take zero rows or columns if you want:sage: m.submatrix(0, 0, 0)[]
sage: parent(m.submatrix(0, 0, 0))
Full MatrixSpace of 0 by 4 dense matrices over Finite Field of size 17>>> from sage.all import *>>> m.submatrix(Integer(0), Integer(0), Integer(0))[]>>> parent(m.submatrix(Integer(0), Integer(0), Integer(0)))
Full MatrixSpace of 0 by 4 dense matrices over Finite Field of size 17transpose()
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.

850

Chapter 26. Dense matrices over Z/𝑛Z for 𝑛 < 28 using LinBox’s Modular<float>

Matrices and Spaces of Matrices, Release 10.4

sage: M = MatrixSpace(GF(41),sage: A = M([1,2,3,4])
sage: B = A.transpose()sage: B
[1 3]
[2 4]
sage: A
[1 2]
[3 4]

2)

>>> from sage.all import *>>> M = MatrixSpace(GF(Integer(41)), Integer(2))>>> A = M([Integer(1),Integer(2),Integer(3),Integer(4)])>>> B = A.transpose()
>>> B
[1 3]
[2 4]
>>> A
[1 2]
[3 4]

.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]
sage: A.subdivide(None, 1); A
[1|2]
[3|4]
sage: A.transpose()
[1 3]
[---]
[2 4]
>>> from sage.all import *>>> A.subdivide(None, Integer(1)); A
[1|2]
[3|4]
>>> A.transpose()
[1 3]
[---]
[2 4]

851

Matrices and Spaces of Matrices, Release 10.4

852

Chapter 26. Dense matrices over Z/𝑛Z for 𝑛 < 28 using LinBox’s Modular<float>

CHAPTERTWENTYSEVENSPARSE MATRICES OVER Z/𝑁 Z FOR 𝑁 SMALL

This is a compiled implementation of sparse matrices over Z/𝑛Z for 𝑛 small.
Todo: move vectors into a Cython vector class - add _add_ and _mul_ methods.
EXAMPLES:
sage: a = matrix(Integers(37),3,3,range(9),sparse=True); a[0 1 2][3 4 5][6 7 8]sage: type(a)<class sage.matrix.matrix_modn_sparse.Matrix_modn_sparse >sage: parent(a)Full MatrixSpace of 3 by 3 sparse matrices over Ring of integers modulo 37
sage: a^2
[15 18 21][ 5 17 29][32 16 0]
sage: a+a
[ 0 2 4][ 6 8 10][12 14 16]
sage: b = a.new_matrix(2,3,range(6)); b[0 1 2][3 4 5]sage: a*b
Traceback (most recent call last):...
TypeError: unsupported operand parent(s) for *: Full MatrixSpace of 3 by 3 sparse␣
˓→matrices over Ring of integers modulo 37
and Full MatrixSpace of 2 by 3 sparse␣
˓→matrices over Ring of integers modulo 37
sage: b*a
[15 18 21][ 5 17 29]>>> from sage.all import *>>> a = matrix(Integers(Integer(37)),Integer(3),Integer(3),range(Integer(9)),˓→sparse=True); a[0 1 2][3 4 5][6 7 8]>>> type(a)(continues on next page)853

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)<class sage.matrix.matrix_modn_sparse.Matrix_modn_sparse >>>> parent(a)Full MatrixSpace of 3 by 3 sparse matrices over Ring of integers modulo 37>>> a**Integer(2)[15 18 21][ 5 17 29][32 16 0]>>> a+a[ 0 2 4][ 6 8 10][12 14 16]>>> b = a.new_matrix(Integer(2),Integer(3),range(Integer(6))); b[0 1 2][3 4 5]>>> a*b
Traceback (most recent call last):...
TypeError: unsupported operand parent(s) for *: Full MatrixSpace of 3 by 3 sparse␣
˓→matrices over Ring of integers modulo 37
and Full MatrixSpace of 2 by 3 sparse␣
˓→matrices over Ring of integers modulo 37>>> b*a[15 18 21][ 5 17 29]
sage: TestSuite(a).run()sage: TestSuite(b).run()>>> from sage.all import *>>> TestSuite(a).run()>>> TestSuite(b).run()sage: a.echelonize(); a[ 1 0 36]
[ 0 1 2][ 0 0 0]sage: b.echelonize(); b[ 1 0 36]
[ 0 1 2]sage: a.pivots()(0, 1)
sage: b.pivots()(0, 1)
sage: a.rank()
2sage: b.rank()
2sage: a[2,2] = 5
sage: a.rank()
3>>> from sage.all import *>>> a.echelonize(); a[ 1 0 36]
[ 0 1 2][ 0 0 0](continues on next page)

854

Chapter 27. Sparse matrices over Z/𝑛Z for 𝑛 small

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> b.echelonize(); b[ 1 0 36]
[ 0 1 2]>>> a.pivots()(0, 1)>>> b.pivots()(0, 1)>>> a.rank()
2>>> b.rank()2>>> a[Integer(2),Integer(2)] = Integer(5)>>> a.rank()
3

class sage.matrix.matrix_modn_sparse.Matrix_modn_sparse
Bases: Matrix_sparse
Create a sparse matrix over the integers modulo n.
INPUT:• parent – a matrix space over the integers modulo n• entries – see matrix()• copy – ignored (for backwards compatibility)• coerce – if False, assume without checking that the entries lie in the base ringdensity()
Return the density of self, i.e., the ratio of the number of nonzero entries of self to the total size of self.
EXAMPLES:
sage: A = matrix(QQ,3,3,[0,1,2,3,0,0,6,7,8],sparse=True)
sage: A.density()
2/3>>> from sage.all import *>>> A = matrix(QQ,Integer(3),Integer(3),[Integer(0),Integer(1),Integer(2),˓→Integer(3),Integer(0),Integer(0),Integer(6),Integer(7),Integer(8)],˓→sparse=True)>>> A.density()
2/3

Notice that the density parameter does not ensure the density of a matrix; it is only an upper bound.
sage: A = random_matrix(GF(127), 200, 200, density=0.3, sparse=True)
sage: density_sum = float(A.density())
sage: total = 1
sage: expected_density = 1.0 - (199/200)^60
sage: expected_density
0.2597...
sage: while abs(density_sum/total - expected_density) > 0.001:....:
A = random_matrix(GF(127), 200, 200, density=0.3, sparse=True)....:
density_sum += float(A.density())....:
total += 1855

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> A = random_matrix(GF(Integer(127)), Integer(200), Integer(200),␣
˓→density=RealNumber( 0.3 ), sparse=True)>>> density_sum = float(A.density())>>> total = Integer(1)>>> expected_density = RealNumber( 1.0 ) - (Integer(199)/
˓→Integer(200))**Integer(60)>>> expected_density
0.2597...
>>> while abs(density_sum/total - expected_density) > RealNumber( 0.001 ):...
A = random_matrix(GF(Integer(127)), Integer(200), Integer(200),␣
˓→density=RealNumber( 0.3 ), sparse=True)...
density_sum += float(A.density())...
total += Integer(1)determinant(algorithm=None)
Return the determinant of this matrix.
INPUT:• algorithm – either "linbox" (default) or "generic".
EXAMPLES:
sage: A = matrix(GF(3), 4, range(16), sparse=True)
sage: B = identity_matrix(GF(3), 4, sparse=True)
sage: (A + B).det()2
sage: (A + B).det(algorithm="linbox")
2
sage: (A + B).det(algorithm="generic")2
sage: (A + B).det(algorithm="hey")
Traceback (most recent call last):...
ValueError: no algorithm hey
sage: matrix(GF(11), 1, 2, sparse=True).det()Traceback (most recent call last):...
ValueError: self must be a square matrix>>> from sage.all import *>>> A = matrix(GF(Integer(3)), Integer(4), range(Integer(16)), sparse=True)>>> B = identity_matrix(GF(Integer(3)), Integer(4), sparse=True)>>> (A + B).det()2>>> (A + B).det(algorithm="linbox")2>>> (A + B).det(algorithm="generic")2>>> (A + B).det(algorithm="hey")
Traceback (most recent call last):...
ValueError: no algorithm hey>>> matrix(GF(Integer(11)), Integer(1), Integer(2), sparse=True).det()Traceback (most recent call last):(continues on next page)

856

Chapter 27. Sparse matrices over Z/𝑛Z for 𝑛 small

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
ValueError: self must be a square matrix

matrix_from_columns(cols)
Return the matrix constructed from self using columns with indices in the columns list.
EXAMPLES:
sage: M = MatrixSpace(GF(127),3,3,sparse=True)
sage: A = M(range(9)); A[0 1 2][3 4 5][6 7 8]sage: A.matrix_from_columns([2,1])
[2 1]
[5 4]
[8 7]
>>> from sage.all import *>>> M = MatrixSpace(GF(Integer(127)),Integer(3),Integer(3),sparse=True)>>> A = M(range(Integer(9))); A[0 1 2][3 4 5][6 7 8]>>> A.matrix_from_columns([Integer(2),Integer(1)])
[2 1]
[5 4]
[8 7]

matrix_from_rows(rows)
Return the matrix constructed from self using rows with indices in the rows list.
INPUT:• rows – list or tuple of row indices
EXAMPLES:
sage: M = MatrixSpace(GF(127),3,3,sparse=True)
sage: A = M(range(9)); A[0 1 2][3 4 5][6 7 8]sage: A.matrix_from_rows([2,1])[6 7 8][3 4 5]>>> from sage.all import *>>> M = MatrixSpace(GF(Integer(127)),Integer(3),Integer(3),sparse=True)>>> A = M(range(Integer(9))); A[0 1 2][3 4 5][6 7 8]>>> A.matrix_from_rows([Integer(2),Integer(1)])[6 7 8][3 4 5]857

Matrices and Spaces of Matrices, Release 10.4

prank(algorithm=None)
Return the rank of this matrix.
INPUT:• algorithm – either "linbox" (only available for matrices over prime fields) or "generic"
EXAMPLES:
sage: A = matrix(GF(127), 2, 2, sparse=True)
sage: A[0,0] = 34
sage: A[0,1] = 102
sage: A[1,0] = 55
sage: A[1,1] = 74
sage: A.rank()
2sage: A._clear_cache()sage: A.rank(algorithm="generic")2
sage: A._clear_cache()sage: A.rank(algorithm="hey")
Traceback (most recent call last):...
ValueError: no algorithm hey>>> from sage.all import *>>> A = matrix(GF(Integer(127)), Integer(2), Integer(2), sparse=True)>>> A[Integer(0),Integer(0)] = Integer(34)>>> A[Integer(0),Integer(1)] = Integer(102)>>> A[Integer(1),Integer(0)] = Integer(55)>>> A[Integer(1),Integer(1)] = Integer(74)>>> A.rank()
2>>> A._clear_cache()>>> A.rank(algorithm="generic")2>>> A._clear_cache()>>> A.rank(algorithm="hey")
Traceback (most recent call last):...
ValueError: no algorithm hey

REFERENCES:• Jean-Guillaume Dumas and Gilles Villars. ‘Computing the Rank of Large Sparse Matrices over Finite
Fields’. Proc. CASC’2002, The Fifth International Workshop on Computer Algebra in Scientific Computing, Big Yalta, Crimea, Ukraine, 22-27 sept. 2002, Springer-Verlag, http://perso.ens-lyon.fr/gilles.
villard/BIBLIOGRAPHIE/POSTSCRIPT/rankjgd.ps
Note: For very sparse matrices Gaussian elimination is faster because it barely has anything to do. If the fillin needs to be considered, ‘Symbolic Reordering’ is usually much faster.
swap_rows(r1, r2)

858

Chapter 27. Sparse matrices over Z/𝑛Z for 𝑛 small

Matrices and Spaces of Matrices, Release 10.4transpose()
Return the transpose of self.
EXAMPLES:
sage: A = matrix(GF(127),3,3,[0,1,0,2,0,0,3,0,0],sparse=True)
sage: A[0 1 0][2 0 0][3 0 0]sage: A.transpose()[0 2 3][1 0 0][0 0 0]>>> from sage.all import *>>> A = matrix(GF(Integer(127)),Integer(3),Integer(3),[Integer(0),Integer(1),˓→Integer(0),Integer(2),Integer(0),Integer(0),Integer(3),Integer(0),˓→Integer(0)],sparse=True)>>> A[0 1 0][2 0 0][3 0 0]>>> A.transpose()[0 2 3][1 0 0][0 0 0].T is a convenient shortcut for the transpose:
sage: A.T
[0 2 3][1 0 0][0 0 0]>>> from sage.all import *>>> A.T[0 2 3][1 0 0][0 0 0]859

Matrices and Spaces of Matrices, Release 10.4

860

Chapter 27. Sparse matrices over Z/𝑛Z for 𝑛 small

CHAPTERTWENTYEIGHTSYMBOLIC DENSE MATRICESEXAMPLES:
sage: matrix(SR, 2, 2, range(4))
[0 1]
[2 3]
sage: matrix(SR, 2, 2, var( t ))
[t 0]
[0 t]
>>> from sage.all import *>>> matrix(SR, Integer(2), Integer(2), range(Integer(4)))
[0 1]
[2 3]
>>> matrix(SR, Integer(2), Integer(2), var( t ))
[t 0]
[0 t]

Arithmetic:sage: -matrix(SR, 2, range(4))[ 0 -1][-2 -3]sage: m = matrix(SR, 2, [1..4]); sqrt(2)*m[ sqrt(2) 2*sqrt(2)][3*sqrt(2) 4*sqrt(2)]sage: m = matrix(SR, 4, [1..4^2])sage: m * m[ 90 100 110 120][202 228 254 280]
[314 356 398 440]
[426 484 542 600]
sage: m = matrix(SR, 3, [1, 2, 3]); m
[1]
[2]
[3]
sage: m.transpose() * m[14]>>> from sage.all import *>>> -matrix(SR, Integer(2), range(Integer(4)))[ 0 -1][-2 -3](continues on next page)861

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> m = matrix(SR, Integer(2), (ellipsis_range(Integer(1),Ellipsis,Integer(4))));␣
˓→sqrt(Integer(2))*m[ sqrt(2) 2*sqrt(2)][3*sqrt(2) 4*sqrt(2)]>>> m = matrix(SR, Integer(4), (ellipsis_range(Integer(1),Ellipsis,
˓→Integer(4)**Integer(2))))>>> m * m
[ 90 100 110 120][202 228 254 280]
[314 356 398 440]
[426 484 542 600]>>> m = matrix(SR, Integer(3), [Integer(1), Integer(2), Integer(3)]); m
[1]
[2]
[3]
>>> m.transpose() * m[14]Computing inverses:
sage: M = matrix(SR, 2, var( a,b,c,d ))sage: ~M
[1/a - b*c/(a^2*(b*c/a - d))b/(a*(b*c/a - d))][c/(a*(b*c/a - d))-1/(b*c/a - d)]sage: (~M*M).simplify_rational()
[1 0]
[0 1]
sage: M = matrix(SR, 3, 3, range(9)) - var( t )sage: (~M * M).simplify_rational()[1 0 0][0 1 0][0 0 1]
sage: matrix(SR, 1, 1, 1).inverse()[1]
sage: matrix(SR, 0, 0).inverse()[]
sage: matrix(SR, 3, 0).inverse()
Traceback (most recent call last):...
ArithmeticError: self must be a square matrix>>> from sage.all import *>>> M = matrix(SR, Integer(2), var( a,b,c,d ))>>> ~M[1/a - b*c/(a^2*(b*c/a - d))b/(a*(b*c/a - d))][c/(a*(b*c/a - d))-1/(b*c/a - d)]>>> (~M*M).simplify_rational()
[1 0]
[0 1]
>>> M = matrix(SR, Integer(3), Integer(3), range(Integer(9))) - var( t )>>> (~M * M).simplify_rational()[1 0 0][0 1 0][0 0 1](continues on next page)862

Chapter 28. Symbolic dense matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> matrix(SR, Integer(1), Integer(1), Integer(1)).inverse()[1]>>> matrix(SR, Integer(0), Integer(0)).inverse()[]>>> matrix(SR, Integer(3), Integer(0)).inverse()
Traceback (most recent call last):...
ArithmeticError: self must be a square matrix

Transposition:
sage: m = matrix(SR, 2, [sqrt(2), -1, pi, e^2])sage: m.transpose()[sqrt(2)
pi]
[
-1
e^2]
>>> from sage.all import *>>> m = matrix(SR, Integer(2), [sqrt(Integer(2)), -Integer(1), pi, e**Integer(2)])>>> m.transpose()[sqrt(2)
pi]
[
-1
e^2]

.T is a convenient shortcut for the transpose:
sage: m.T
[sqrt(2)
[
-1

pi]
e^2]

>>> from sage.all import *>>> m.T[sqrt(2)
pi]
[
-1
e^2]

Test pickling:sage: m = matrix(SR, 2, [sqrt(2), 3, pi, e]); m[sqrt(2)3][pie]sage: TestSuite(m).run()>>> from sage.all import *>>> m = matrix(SR, Integer(2), [sqrt(Integer(2)), Integer(3), pi, e]); m[sqrt(2)3][pie]>>> TestSuite(m).run()

Comparison:
sage: m = matrix(SR, 2, [sqrt(2), 3, pi, e])sage: m == mTrue
sage: m != 3
True
sage: m = matrix(SR,2,[1..4]); n = m^2(continues on next page)863

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: (exp(m+n) - exp(m)*exp(n)).simplify_rational() == 0
True

# indirect test>>> from sage.all import *>>> m = matrix(SR, Integer(2), [sqrt(Integer(2)), Integer(3), pi, e])>>> m == m
True>>> m != Integer(3)True>>> m = matrix(SR,Integer(2),(ellipsis_range(Integer(1),Ellipsis,Integer(4)))); n =␣
˓→m**Integer(2)>>> (exp(m+n) - exp(m)*exp(n)).simplify_rational() == Integer(0)# indirect test
True

Determinant:sage: M = matrix(SR, 2, 2, [x,2,3,4])
sage: M.determinant()
4*x - 6sage: M = matrix(SR, 3,3,range(9))
sage: M.det()0
sage: t = var( t )sage: M = matrix(SR, 2, 2, [cos(t), sin(t), -sin(t), cos(t)])
sage: M.det()cos(t)^2 + sin(t)^2
sage: M = matrix([[sqrt(x),0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]])
sage: det(M)sqrt(x)>>> from sage.all import *>>> M = matrix(SR, Integer(2), Integer(2), [x,Integer(2),Integer(3),Integer(4)])>>> M.determinant()
4*x - 6>>> M = matrix(SR, Integer(3),Integer(3),range(Integer(9)))>>> M.det()0>>> t = var( t )>>> M = matrix(SR, Integer(2), Integer(2), [cos(t), sin(t), -sin(t), cos(t)])>>> M.det()cos(t)^2 + sin(t)^2>>> M = matrix([[sqrt(x),Integer(0),Integer(0),Integer(0)], [Integer(0),Integer(1),˓→Integer(0),Integer(0)], [Integer(0),Integer(0),Integer(1),Integer(0)], [Integer(0),˓→Integer(0),Integer(0),Integer(1)]])>>> det(M)sqrt(x)

Permanents:
sage: M = matrix(SR, 2, 2, [x,2,3,4])
sage: M.permanent()
4*x + 6>>> from sage.all import *>>> M = matrix(SR, Integer(2), Integer(2), [x,Integer(2),Integer(3),Integer(4)])(continues on next page)

864

Chapter 28. Symbolic dense matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> M.permanent()
4*x + 6Rank:
sage: M = matrix(SR, 5, 5, range(25))
sage: M.rank()
2sage: M = matrix(SR, 5, 5, range(25)) - var( t )sage: M.rank()
5.. warning:::meth: rank may return the wrong answer if it cannot determine that amatrix element that is equivalent to zero is indeed so.
>>> from sage.all import *>>> M = matrix(SR, Integer(5), Integer(5), range(Integer(25)))>>> M.rank()
2>>> M = matrix(SR, Integer(5), Integer(5), range(Integer(25))) - var( t )>>> M.rank()
5.. warning:::meth: rank may return the wrong answer if it cannot determine that amatrix element that is equivalent to zero is indeed so.

Copying symbolic matrices:sage: m = matrix(SR, 2, [sqrt(2), 3, pi, e])sage: n = copy(m)sage: n[0,0] = sin(1)sage: m[sqrt(2)3][pie]sage: n[sin(1)3][pie]>>> from sage.all import *>>> m = matrix(SR, Integer(2), [sqrt(Integer(2)), Integer(3), pi, e])>>> n = copy(m)>>> n[Integer(0),Integer(0)] = sin(Integer(1))>>> m[sqrt(2)
3]
[
pi
e]
>>> n
[sin(1)3][pie]Conversion to Maxima:865

Matrices and Spaces of Matrices, Release 10.4

sage: m = matrix(SR, 2, [sqrt(2), 3, pi, e])sage: m._maxima_()matrix([sqrt(2),3],[%pi,%e])>>> from sage.all import *>>> m = matrix(SR, Integer(2), [sqrt(Integer(2)), Integer(3), pi, e])>>> m._maxima_()matrix([sqrt(2),3],[%pi,%e])class sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense
Bases: Matrix_generic_dense
arguments()
Return a tuple of the arguments that self can take.
EXAMPLES:
sage: var( x,y,z )(x, y, z)sage: M = MatrixSpace(SR,2,2)
sage: M(x).arguments()(x,)
sage: M(x+sin(x)).arguments()(x,)>>> from sage.all import *>>> var( x,y,z )(x, y, z)>>> M = MatrixSpace(SR,Integer(2),Integer(2))>>> M(x).arguments()(x,)>>> M(x+sin(x)).arguments()(x,)

canonicalize_radical()Choose a canonical branch of each entry
canonicalize_radical() componentwise.

of

self

by

calling

Expression.

EXAMPLES:
sage: var( x , y )(x, y)
sage: l1 = [sqrt(2)*sqrt(3)*sqrt(6) , log(x*y)]
sage: l2 = [sin(x/(x^2 + x)) , 1]
sage: m = matrix([l1, l2])
sage: m[sqrt(6)*sqrt(3)*sqrt(2)log(x*y)][sin(x/(x^2 + x))
1]
sage: m.canonicalize_radical()[
6 log(x) + log(y)][ sin(1/(x + 1))
1]>>> from sage.all import *>>> var( x , y )(x, y)>>> l1 = [sqrt(Integer(2))*sqrt(Integer(3))*sqrt(Integer(6)) , log(x*y)](continues on next page)

866

Chapter 28. Symbolic dense matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> l2 = [sin(x/(x**Integer(2) + x)) , Integer(1)]>>> m = matrix([l1, l2])>>> m[sqrt(6)*sqrt(3)*sqrt(2)log(x*y)][sin(x/(x^2 + x))
1]>>> m.canonicalize_radical()[
6 log(x) + log(y)][ sin(1/(x + 1))
1]

charpoly(var='x', algorithm=None)
Compute the characteristic polynomial of self, using maxima.
Note: The characteristic polynomial is defined as det(𝑥𝐼 − 𝐴).
INPUT:• var – (default: ‘x’) name of variable of charpoly
EXAMPLES:
sage: M = matrix(SR, 2, 2, var( a,b,c,d ))sage: M.charpoly( t )t^2 + (-a - d)*t - b*c + a*d
sage: matrix(SR, 5, [1..5^2]).charpoly()x^5 - 65*x^4 - 250*x^3>>> from sage.all import *>>> M = matrix(SR, Integer(2), Integer(2), var( a,b,c,d ))>>> M.charpoly( t )t^2 + (-a - d)*t - b*c + a*d>>> matrix(SR, Integer(5), (ellipsis_range(Integer(1),Ellipsis,
˓→Integer(5)**Integer(2)))).charpoly()x^5 - 65*x^4 - 250*x^3echelonize(**kwds)
Echelonize using the classical algorithm.
eigenvalues(extend=True)
Compute the eigenvalues by solving the characteristic polynomial in maxima.
The argument extend is ignored but kept for compatibility with other matrix classes.
EXAMPLES:
sage: a=matrix(SR,[[1,2],[3,4]])
sage: a.eigenvalues()[-1/2*sqrt(33) + 5/2, 1/2*sqrt(33) + 5/2]>>> from sage.all import *>>> a=matrix(SR,[[Integer(1),Integer(2)],[Integer(3),Integer(4)]])>>> a.eigenvalues()[-1/2*sqrt(33) + 5/2, 1/2*sqrt(33) + 5/2]

eigenvectors_left(other=None)
Compute the left eigenvectors of a matrix.

867

Matrices and Spaces of Matrices, Release 10.4

INPUT:• other – a square matrix 𝐵 (default: None) in a generalized eigenvalue problem; if None, an ordinary
eigenvalue problem is solved (currently supported only if the base ring of self is RDF or CDF)
OUTPUT:For each distinct eigenvalue, returns a list of the form (e,V,n) where e is the eigenvalue, V is a list of eigenvectors forming a basis for the corresponding left eigenspace, and n is the algebraic multiplicity of the eigenvalue.
EXAMPLES:
sage: A = matrix(SR,3,3,range(9)); A[0 1 2][3 4 5][6 7 8]sage: es = A.eigenvectors_left(); es[(-3*sqrt(6) + 6, [(1, -1/5*sqrt(6) + 4/5, -2/5*sqrt(6) + 3/5)], 1),(3*sqrt(6) + 6, [(1, 1/5*sqrt(6) + 4/5, 2/5*sqrt(6) + 3/5)], 1),(0, [(1, -2, 1)], 1)]
sage: eval, [evec], mult = es[0]sage: delta = eval*evec - evec*A
sage: abs(abs(delta)) < 1e-10
3/5*sqrt(((2*sqrt(6) - 3)*(sqrt(6) - 2) + 7*sqrt(6) - 18)^2 + ((sqrt(6) -␣˓→2)*(sqrt(6) - 4) + 6*sqrt(6) - 14)^2) < (1.00000000000000e-10)
sage: abs(abs(delta)).n() < 1e-10
True>>> from sage.all import *>>> A = matrix(SR,Integer(3),Integer(3),range(Integer(9))); A[0 1 2][3 4 5][6 7 8]>>> es = A.eigenvectors_left(); es[(-3*sqrt(6) + 6, [(1, -1/5*sqrt(6) + 4/5, -2/5*sqrt(6) + 3/5)], 1),(3*sqrt(6) + 6, [(1, 1/5*sqrt(6) + 4/5, 2/5*sqrt(6) + 3/5)], 1),(0, [(1, -2, 1)], 1)]>>> eval, [evec], mult = es[Integer(0)]>>> delta = eval*evec - evec*A>>> abs(abs(delta)) < RealNumber( 1e-10 )3/5*sqrt(((2*sqrt(6) - 3)*(sqrt(6) - 2) + 7*sqrt(6) - 18)^2 + ((sqrt(6) -␣˓→2)*(sqrt(6) - 4) + 6*sqrt(6) - 14)^2) < (1.00000000000000e-10)>>> abs(abs(delta)).n() < RealNumber( 1e-10 )Truesage: A = matrix(SR, 2, 2, var( a,b,c,d ))sage: A.eigenvectors_left()[(1/2*a + 1/2*d - 1/2*sqrt(a^2 + 4*b*c - 2*a*d + d^2), [(1, -1/2*(a - d +␣˓→sqrt(a^2 + 4*b*c - 2*a*d + d^2))/c)], 1), (1/2*a + 1/2*d + 1/2*sqrt(a^2 +␣
˓→4*b*c - 2*a*d + d^2), [(1, -1/2*(a - d - sqrt(a^2 + 4*b*c - 2*a*d + d^2))/˓→c)], 1)]
sage: es = A.eigenvectors_left(); es[(1/2*a + 1/2*d - 1/2*sqrt(a^2 + 4*b*c - 2*a*d + d^2), [(1, -1/2*(a - d +␣˓→sqrt(a^2 + 4*b*c - 2*a*d + d^2))/c)], 1), (1/2*a + 1/2*d + 1/2*sqrt(a^2 +␣
˓→4*b*c - 2*a*d + d^2), [(1, -1/2*(a - d - sqrt(a^2 + 4*b*c - 2*a*d + d^2))/˓→c)], 1)]
sage: eval, [evec], mult = es[0]sage: delta = eval*evec - evec*A(continues on next page)

868

Chapter 28. Symbolic dense matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: delta.apply_map(lambda x: x.full_simplify())(0, 0)>>> from sage.all import *>>> A = matrix(SR, Integer(2), Integer(2), var( a,b,c,d ))>>> A.eigenvectors_left()[(1/2*a + 1/2*d - 1/2*sqrt(a^2 + 4*b*c - 2*a*d + d^2), [(1, -1/2*(a - d +␣˓→sqrt(a^2 + 4*b*c - 2*a*d + d^2))/c)], 1), (1/2*a + 1/2*d + 1/2*sqrt(a^2 +␣
˓→4*b*c - 2*a*d + d^2), [(1, -1/2*(a - d - sqrt(a^2 + 4*b*c - 2*a*d + d^2))/˓→c)], 1)]>>> es = A.eigenvectors_left(); es[(1/2*a + 1/2*d - 1/2*sqrt(a^2 + 4*b*c - 2*a*d + d^2), [(1, -1/2*(a - d +␣˓→sqrt(a^2 + 4*b*c - 2*a*d + d^2))/c)], 1), (1/2*a + 1/2*d + 1/2*sqrt(a^2 +␣
˓→4*b*c - 2*a*d + d^2), [(1, -1/2*(a - d - sqrt(a^2 + 4*b*c - 2*a*d + d^2))/˓→c)], 1)]>>> eval, [evec], mult = es[Integer(0)]>>> delta = eval*evec - evec*A>>> delta.apply_map(lambda x: x.full_simplify())(0, 0)

This routine calls Maxima and can struggle with even small matrices with a few variables, such as a 3 × 3
matrix with three variables. However, if the entries are integers or rationals it can produce exact values ina reasonable time. These examples create 0-1 matrices from the adjacency matrices of graphs and illustrate
how the format and type of the results differ when the base ring changes. First for matrices over the rational
numbers, then the same matrix but viewed as a symbolic matrix.
sage: G=graphs.CycleGraph(5)sage: am = G.adjacency_matrix()
sage: spectrum = am.eigenvectors_left()
sage: qqbar_evalue = spectrum[2][0]sage: type(qqbar_evalue)<class sage.rings.qqbar.AlgebraicNumber >sage: qqbar_evalue
0.618033988749895?
sage: am = G.adjacency_matrix().change_ring(SR)sage: spectrum = am.eigenvectors_left()
sage: symbolic_evalue = spectrum[2][0]sage: type(symbolic_evalue)<class sage.symbolic.expression.Expression >sage: symbolic_evalue
1/2*sqrt(5) - 1/2
sage: bool(qqbar_evalue == symbolic_evalue)
True>>> from sage.all import *>>> G=graphs.CycleGraph(Integer(5))>>> am = G.adjacency_matrix()>>> spectrum = am.eigenvectors_left()>>> qqbar_evalue = spectrum[Integer(2)][Integer(0)]>>> type(qqbar_evalue)<class sage.rings.qqbar.AlgebraicNumber >>>> qqbar_evalue
0.618033988749895?
(continues on next page)869

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> am = G.adjacency_matrix().change_ring(SR)>>> spectrum = am.eigenvectors_left()>>> symbolic_evalue = spectrum[Integer(2)][Integer(0)]>>> type(symbolic_evalue)<class sage.symbolic.expression.Expression >>>> symbolic_evalue
1/2*sqrt(5) - 1/2>>> bool(qqbar_evalue == symbolic_evalue)
True

A slightly larger matrix with a “nice” spectrum.
sage: G = graphs.CycleGraph(6)sage: am = G.adjacency_matrix().change_ring(SR)sage: am.eigenvectors_left()[(-1, [(1, 0, -1, 1, 0, -1), (0, 1, -1, 0, 1, -1)], 2), (1, [(1, 0, -1, -1, 0,
˓→ 1), (0, 1, 1, 0, -1, -1)], 2), (-2, [(1, -1, 1, -1, 1, -1)], 1), (2, [(1,␣˓→1, 1, 1, 1, 1)], 1)]>>> from sage.all import *>>> G = graphs.CycleGraph(Integer(6))>>> am = G.adjacency_matrix().change_ring(SR)>>> am.eigenvectors_left()[(-1, [(1, 0, -1, 1, 0, -1), (0, 1, -1, 0, 1, -1)], 2), (1, [(1, 0, -1, -1, 0,
˓→ 1), (0, 1, 1, 0, -1, -1)], 2), (-2, [(1, -1, 1, -1, 1, -1)], 1), (2, [(1,␣˓→1, 1, 1, 1, 1)], 1)]eigenvectors_right(other=None)
Compute the right eigenvectors of a matrix.
INPUT:• other – a square matrix 𝐵 (default: None) in a generalized eigenvalue problem; if None, an ordinary
eigenvalue problem is solved (currently supported only if the base ring of self is RDF or CDF)
OUTPUT:For each distinct eigenvalue, returns a list of the form (e,V,n) where e is the eigenvalue, V is a list of eigenvectors forming a basis for the corresponding right eigenspace, and n is the algebraic multiplicity of theeigenvalue.
EXAMPLES:
sage: A = matrix(SR,2,2,range(4)); A
[0 1]
[2 3]
sage: right = A.eigenvectors_right(); right[(-1/2*sqrt(17) + 3/2, [(1, -1/2*sqrt(17) + 3/2)], 1), (1/2*sqrt(17) + 3/2,␣˓→[(1, 1/2*sqrt(17) + 3/2)], 1)]>>> from sage.all import *>>> A = matrix(SR,Integer(2),Integer(2),range(Integer(4))); A
[0 1]
[2 3]
>>> right = A.eigenvectors_right(); right(continues on next page)

870

Chapter 28. Symbolic dense matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[(-1/2*sqrt(17) + 3/2, [(1, -1/2*sqrt(17) + 3/2)], 1), (1/2*sqrt(17) + 3/2,␣˓→[(1, 1/2*sqrt(17) + 3/2)], 1)]

The right eigenvectors are nothing but the left eigenvectors of the transpose matrix:
sage: left = A.transpose().eigenvectors_left(); left[(-1/2*sqrt(17) + 3/2, [(1, -1/2*sqrt(17) + 3/2)], 1), (1/2*sqrt(17) + 3/2,␣˓→[(1, 1/2*sqrt(17) + 3/2)], 1)]
sage: right[0][1] == left[0][1]True>>> from sage.all import *>>> left = A.transpose().eigenvectors_left(); left[(-1/2*sqrt(17) + 3/2, [(1, -1/2*sqrt(17) + 3/2)], 1), (1/2*sqrt(17) + 3/2,␣˓→[(1, 1/2*sqrt(17) + 3/2)], 1)]>>> right[Integer(0)][Integer(1)] == left[Integer(0)][Integer(1)]
True

exp()
Return the matrix exponential of this matrix 𝑋, which is the matrix
𝑒𝑋 =

∞
∑︁
𝑋𝑘
𝑘=0

𝑘!

.

This function depends on maxima’s matrix exponentiation function, which does not deal well with floating
point numbers. If the matrix has floating point numbers, they will be rounded automatically to rational numbers during the computation.
EXAMPLES:
sage: m = matrix(SR,2, [0,x,x,0]); m
[0 x]
[x 0]
sage: m.exp()[1/2*(e^(2*x) + 1)*e^(-x) 1/2*(e^(2*x) - 1)*e^(-x)][1/2*(e^(2*x) - 1)*e^(-x) 1/2*(e^(2*x) + 1)*e^(-x)]
sage: exp(m)[1/2*(e^(2*x) + 1)*e^(-x) 1/2*(e^(2*x) - 1)*e^(-x)][1/2*(e^(2*x) - 1)*e^(-x) 1/2*(e^(2*x) + 1)*e^(-x)]>>> from sage.all import *>>> m = matrix(SR,Integer(2), [Integer(0),x,x,Integer(0)]); m
[0 x]
[x 0]
>>> m.exp()[1/2*(e^(2*x) + 1)*e^(-x) 1/2*(e^(2*x) - 1)*e^(-x)][1/2*(e^(2*x) - 1)*e^(-x) 1/2*(e^(2*x) + 1)*e^(-x)]>>> exp(m)[1/2*(e^(2*x) + 1)*e^(-x) 1/2*(e^(2*x) - 1)*e^(-x)][1/2*(e^(2*x) - 1)*e^(-x) 1/2*(e^(2*x) + 1)*e^(-x)]

Exponentiation works on 0x0 and 1x1 matrices, but the 1x1 example requires a patched version of maxima(Issue #32898) for now:871

Matrices and Spaces of Matrices, Release 10.4

sage: m = matrix(SR,0,[]); m[]
sage: m.exp()[]
sage: m = matrix(SR,1,[2]); m[2]
sage: m.exp() # not tested, requires patched maxima[e^2]>>> from sage.all import *>>> m = matrix(SR,Integer(0),[]); m[]>>> m.exp()[]>>> m = matrix(SR,Integer(1),[Integer(2)]); m[2]>>> m.exp() # not tested, requires patched maxima[e^2]Commuting matrices 𝑚, 𝑛 have the property that 𝑒𝑚+𝑛 = 𝑒𝑚 𝑒𝑛 (but non-commuting matrices need not):sage: m = matrix(SR,2,[1..4]); n = m^2
sage: m*n
[ 37 54][ 81 118]
sage: n*m
[ 37 54][ 81 118]
sage: a = exp(m+n) - exp(m)*exp(n)sage: a.simplify_rational() == 0
True>>> from sage.all import *>>> m = matrix(SR,Integer(2),(ellipsis_range(Integer(1),Ellipsis,
˓→Integer(4)))); n = m**Integer(2)>>> m*n[ 37 54][ 81 118]>>> n*m[ 37 54][ 81 118]>>> a = exp(m+n) - exp(m)*exp(n)>>> a.simplify_rational() == Integer(0)True

The input matrix must be square:
sage: m = matrix(SR,2,3,[1..6]); exp(m)Traceback (most recent call last):...
ValueError: exp only defined on square matrices>>> from sage.all import *>>> m = matrix(SR,Integer(2),Integer(3),(ellipsis_range(Integer(1),Ellipsis,(continues on next page)872

Chapter 28. Symbolic dense matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Integer(6)))); exp(m)Traceback (most recent call last):...
ValueError: exp only defined on square matrices˓→In this example we take the symbolic answer and make it numerical at the end:
sage: exp(matrix(SR, [[1.2, 5.6], [3,4]])).change_ring(RDF)[ 346.5574872980695 661.7345909344504][354.50067371488416 677.4247827652946]# rel tol 1e-15>>> from sage.all import *>>> exp(matrix(SR, [[RealNumber( 1.2 ), RealNumber( 5.6 )], [Integer(3),˓→Integer(4)]])).change_ring(RDF)# rel tol 1e-15[ 346.5574872980695 661.7345909344504][354.50067371488416 677.4247827652946]

Another example involving the reversed identity matrix, which we clumsily create:
sage: m = identity_matrix(SR,4); m = matrix(list(reversed(m.rows()))) * x
sage: exp(m)[1/2*(e^(2*x) + 1)*e^(-x)
0
0 1/
˓→2*(e^(2*x) - 1)*e^(-x)][
0 1/2*(e^(2*x) + 1)*e^(-x) 1/2*(e^(2*x) - 1)*e^(-x) ␣˓→
0][
0 1/2*(e^(2*x) - 1)*e^(-x) 1/2*(e^(2*x) + 1)*e^(-x) ␣˓→
0][1/2*(e^(2*x) - 1)*e^(-x)
0
0 1/
˓→2*(e^(2*x) + 1)*e^(-x)]>>> from sage.all import *>>> m = identity_matrix(SR,Integer(4)); m = matrix(list(reversed(m.rows())))␣
˓→* x>>> exp(m)[1/2*(e^(2*x) + 1)*e^(-x)
0
0 1/
˓→2*(e^(2*x) - 1)*e^(-x)][
0 1/2*(e^(2*x) + 1)*e^(-x) 1/2*(e^(2*x) - 1)*e^(-x) ␣˓→
0][
0 1/2*(e^(2*x) - 1)*e^(-x) 1/2*(e^(2*x) + 1)*e^(-x) ␣˓→
0][1/2*(e^(2*x) - 1)*e^(-x)
0
0 1/
˓→2*(e^(2*x) + 1)*e^(-x)]

expand()Operate point-wise on each element.
EXAMPLES:
sage: M = matrix(2, 2, range(4)) - var( x )sage: M*M[x^2 + 2-2*x + 3][-4*x + 6 (x - 3)^2 + 2]
sage: (M*M).expand()[x^2 + 2-2*x + 3][-4*x + 6 x^2 - 6*x + 11]873

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> M = matrix(Integer(2), Integer(2), range(Integer(4))) - var( x )>>> M*M[x^2 + 2-2*x + 3][-4*x + 6 (x - 3)^2 + 2]>>> (M*M).expand()[x^2 + 2-2*x + 3][-4*x + 6 x^2 - 6*x + 11]

factor()Operate point-wise on each element.
EXAMPLES:
sage: M = matrix(SR, 2, 2, x^2 - 2*x + 1); M[x^2 - 2*x + 1
0][
0 x^2 - 2*x + 1]
sage: M.factor()[(x - 1)^2
0][
0 (x - 1)^2]>>> from sage.all import *>>> M = matrix(SR, Integer(2), Integer(2), x**Integer(2) - Integer(2)*x +␣˓→Integer(1)); M[x^2 - 2*x + 1
0][
0 x^2 - 2*x + 1]>>> M.factor()[(x - 1)^2
0][
0 (x - 1)^2]

fcp(var='x')
Return the factorization of the characteristic polynomial of self.
INPUT:• var – (default: ‘x’) name of variable of charpoly
EXAMPLES:
sage: a = matrix(SR,[[1,2],[3,4]])
sage: a.fcp()x^2 - 5*x - 2
sage: [i for i in a.fcp()][(x^2 - 5*x - 2, 1)]
sage: a = matrix(SR,[[1,0],[0,2]])
sage: a.fcp()(x - 2) * (x - 1)sage: [i for i in a.fcp()][(x - 2, 1), (x - 1, 1)]
sage: a = matrix(SR, 5, [1..5^2])sage: a.fcp()(x^2 - 65*x - 250) * x^3
sage: list(a.fcp())[(x^2 - 65*x - 250, 1), (x, 3)]>>> from sage.all import *>>> a = matrix(SR,[[Integer(1),Integer(2)],[Integer(3),Integer(4)]])(continues on next page)874

Chapter 28. Symbolic dense matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> a.fcp()x^2 - 5*x - 2>>> [i for i in a.fcp()][(x^2 - 5*x - 2, 1)]>>> a = matrix(SR,[[Integer(1),Integer(0)],[Integer(0),Integer(2)]])>>> a.fcp()(x - 2) * (x - 1)>>> [i for i in a.fcp()][(x - 2, 1), (x - 1, 1)]>>> a = matrix(SR, Integer(5), (ellipsis_range(Integer(1),Ellipsis,
˓→Integer(5)**Integer(2))))>>> a.fcp()(x^2 - 65*x - 250) * x^3>>> list(a.fcp())[(x^2 - 65*x - 250, 1), (x, 3)]function(*args)
Return a matrix over a callable symbolic expression ring.
EXAMPLES:
sage: x, y = var( x,y )sage: v = matrix([[x,y],[x*sin(y), 0]])sage: w = v.function([x,y]); w[(x, y) |--> x(x, y) |--> y][(x, y) |--> x*sin(y)(x, y) |--> 0]
sage: w.parent()
Full MatrixSpace of 2 by 2 dense matrices over Callable function ring with␣
˓→arguments (x, y)>>> from sage.all import *>>> x, y = var( x,y )>>> v = matrix([[x,y],[x*sin(y), Integer(0)]])>>> w = v.function([x,y]); w[(x, y) |--> x(x, y) |--> y][(x, y) |--> x*sin(y)(x, y) |--> 0]>>> w.parent()
Full MatrixSpace of 2 by 2 dense matrices over Callable function ring with␣
˓→arguments (x, y)jordan_form(subdivide=True, transformation=False)
Return a Jordan normal form of self.
INPUT:• self – a square matrix• subdivide – boolean (default: True)• transformation – boolean (default: False)
OUTPUT:
If transformation is False, only a Jordan normal form (unique up to the ordering of the Jordan blocks)
is returned. Otherwise, a pair (J, P) is returned, where J is a Jordan normal form and P is an invertible
matrix such that self equals P * J * P^(-1).
If subdivide is True, the Jordan blocks in the returned matrix J are indicated by a subdivision in thesense of subdivide().
875

Matrices and Spaces of Matrices, Release 10.4

EXAMPLES:
We start with some examples of diagonalisable matrices:sage: a,b,c,d = var( a,b,c,d )sage: matrix([a]).jordan_form()[a]sage: matrix([[a, 0], [1, d]]).jordan_form(subdivide=True)
[d|0]
[-+-]
[0|a]
sage: matrix([[a, 0], [1, d]]).jordan_form(subdivide=False)
[d 0]
[0 a]
sage: matrix([[a, x, x], [0, b, x], [0, 0, c]]).jordan_form()[c|0|0][-+-+-][0|b|0][-+-+-][0|0|a]>>> from sage.all import *>>> a,b,c,d = var( a,b,c,d )>>> matrix([a]).jordan_form()[a]>>> matrix([[a, Integer(0)], [Integer(1), d]]).jordan_form(subdivide=True)
[d|0]
[-+-]
[0|a]
>>> matrix([[a, Integer(0)], [Integer(1), d]]).jordan_form(subdivide=False)
[d 0]
[0 a]
>>> matrix([[a, x, x], [Integer(0), b, x], [Integer(0), Integer(0), c]]).
˓→jordan_form()[c|0|0][-+-+-][0|b|0][-+-+-][0|0|a]In the following examples, we compute Jordan forms of some non-diagonalisable matrices:sage: matrix([[a, a], [0, a]]).jordan_form()
[a 1]
[0 a]
sage: matrix([[a, 0, b], [0, c, 0], [0, 0, a]]).jordan_form()[c|0 0][-+---][0|a 1][0|0 a]>>> from sage.all import *>>> matrix([[a, a], [Integer(0), a]]).jordan_form()
[a 1]
[0 a]
>>> matrix([[a, Integer(0), b], [Integer(0), c, Integer(0)], [Integer(0),␣
˓→Integer(0), a]]).jordan_form()[c|0 0](continues on next page)876

Chapter 28. Symbolic dense matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[-+---][0|a 1][0|0 a]The following examples illustrate the transformation flag. Note that symbolic expressions may need tobe simplified to make consistency checks succeed:
sage: A = matrix([[x - a*c, a^2], [-c^2, x + a*c]])sage: J, P = A.jordan_form(transformation=True)
sage: J, P(
[x 1] [-a*c1][0 x], [-c^20])sage: A1 = P * J * ~P; A1[-a*c + x (a*c - x)*a/c + a*x/c][-c^2
a*c + x]sage: A1.simplify_rational() == A
True
sage: B = matrix([[a, b, c], [0, a, d], [0, 0, a]])sage: J, T = B.jordan_form(transformation=True)
sage: J, T(
[a 1 0] [b*dc0][0 a 1] [ 0d0][0 0 a], [ 001])sage: (B * T).simplify_rational() == T * J
True>>> from sage.all import *>>> A = matrix([[x - a*c, a**Integer(2)], [-c**Integer(2), x + a*c]])>>> J, P = A.jordan_form(transformation=True)>>> J, P([x 1] [-a*c1][0 x], [-c^20])>>> A1 = P * J * ~P; A1[-a*c + x (a*c - x)*a/c + a*x/c][-c^2
a*c + x]>>> A1.simplify_rational() == A
True>>> B = matrix([[a, b, c], [Integer(0), a, d], [Integer(0), Integer(0), a]])>>> J, T = B.jordan_form(transformation=True)>>> J, T([a 1 0] [b*dc0][0 a 1] [ 0d0][0 0 a], [ 001])>>> (B * T).simplify_rational() == T * J
True

Finally, some examples involving square roots:877

Matrices and Spaces of Matrices, Release 10.4

sage: matrix([[a, -b], [b, a]]).jordan_form()[a - I*b|0][-------+-------][
0|a + I*b]
sage: matrix([[a, b], [c, d]]).jordan_form(subdivide=False)[1/2*a + 1/2*d - 1/2*sqrt(a^2 + 4*b*c - 2*a*d + d^2)
˓→0][
0 1/2*a + 1/2*d + 1/
˓→2*sqrt(a^2 + 4*b*c - 2*a*d + d^2)]>>> from sage.all import *>>> matrix([[a, -b], [b, a]]).jordan_form()[a - I*b|0][-------+-------][
0|a + I*b]>>> matrix([[a, b], [c, d]]).jordan_form(subdivide=False)[1/2*a + 1/2*d - 1/2*sqrt(a^2 + 4*b*c - 2*a*d + d^2)
˓→0][
0 1/2*a + 1/2*d + 1/
˓→2*sqrt(a^2 + 4*b*c - 2*a*d + d^2)]␣␣minpoly(var='x')
Return the minimal polynomial of self.
EXAMPLES:
sage: M = Matrix.identity(SR, 2)
sage: M.minpoly()x - 1
sage: t = var( t )sage: m = matrix(2, [1, 2, 4, t])sage: m.minimal_polynomial()x^2 + (-t - 1)*x + t - 8>>> from sage.all import *>>> M = Matrix.identity(SR, Integer(2))>>> M.minpoly()x - 1>>> t = var( t )>>> m = matrix(Integer(2), [Integer(1), Integer(2), Integer(4), t])>>> m.minimal_polynomial()x^2 + (-t - 1)*x + t - 8

number_of_arguments()
Return the number of arguments that self can take.
EXAMPLES:
sage: var( a,b,c,x,y )(a, b, c, x, y)
sage: m = matrix([[a, (x+y)/(x+y)], [x^2, y^2+2]]); m[a1][x^2 y^2 + 2]
sage: m.number_of_arguments()
3878

Chapter 28. Symbolic dense matrices

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> var( a,b,c,x,y )(a, b, c, x, y)>>> m = matrix([[a, (x+y)/(x+y)], [x**Integer(2), y**Integer(2)+Integer(2)]]);
˓→ m
[
a
1]
[
x^2 y^2 + 2]>>> m.number_of_arguments()
3

simplify()
Simplify self.
EXAMPLES:
sage: var( x,y,z )(x, y, z)sage: m = matrix([[z, (x+y)/(x+y)], [x^2, y^2+2]]); m[z
1][x^2 y^2 + 2]
sage: m.simplify()[z
1][x^2 y^2 + 2]>>> from sage.all import *>>> var( x,y,z )(x, y, z)>>> m = matrix([[z, (x+y)/(x+y)], [x**Integer(2), y**Integer(2)+Integer(2)]]);
˓→ m
[
z
1]
[
x^2 y^2 + 2]>>> m.simplify()[z
1][x^2 y^2 + 2]

simplify_full()
Simplify a symbolic matrix by calling Expression.simplify_full() componentwise.
INPUT:• self – the matrix whose entries we should simplify.
OUTPUT:
A copy of self with all of its entries simplified.
EXAMPLES:
Symbolic matrices will have their entries simplified:sage: a,n,k = SR.var( a,n,k )sage: f1 = sin(x)^2 + cos(x)^2
sage: f2 = sin(x/(x^2 + x))
sage: f3 = binomial(n,k)*factorial(k)*factorial(n-k)
sage: f4 = x*sin(2)/(x^a)
sage: A = matrix(SR, [[f1,f2],[f3,f4]])
sage: A.simplify_full()[1sin(1/(x + 1))][
factorial(n) x^(-a + 1)*sin(2)]879Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> a,n,k = SR.var( a,n,k )>>> f1 = sin(x)**Integer(2) + cos(x)**Integer(2)>>> f2 = sin(x/(x**Integer(2) + x))>>> f3 = binomial(n,k)*factorial(k)*factorial(n-k)>>> f4 = x*sin(Integer(2))/(x**a)>>> A = matrix(SR, [[f1,f2],[f3,f4]])>>> A.simplify_full()[1sin(1/(x + 1))][
factorial(n) x^(-a + 1)*sin(2)]simplify_rational()
EXAMPLES:
sage: M = matrix(SR, 3, 3, range(9)) - var( t )sage: (~M*M)[0,0]t*(3*(2/t + (6/t + 7)/((t - 3/t - 4)*t))*(2/t + (6/t + 5)/((t - 3/t- 4)*t))/(t - (6/t + 7)*(6/t + 5)/(t - 3/t - 4) - 12/t - 8) + 1/t +3/((t - 3/t - 4)*t^2)) - 6*(2/t + (6/t + 5)/((t - 3/t - 4)*t))/(t (6/t + 7)*(6/t + 5)/(t - 3/t - 4) - 12/t - 8) - 3*(6/t + 7)*(2/t +(6/t + 5)/((t - 3/t - 4)*t))/((t - (6/t + 7)*(6/t + 5)/(t - 3/t 4) - 12/t - 8)*(t - 3/t - 4)) - 3/((t - 3/t - 4)*t)
sage: expand((~M*M)[0,0])1
sage: (~M * M).simplify_rational()[1 0 0][0 1 0][0 0 1]>>> from sage.all import *>>> M = matrix(SR, Integer(3), Integer(3), range(Integer(9))) - var( t )>>> (~M*M)[Integer(0),Integer(0)]t*(3*(2/t + (6/t + 7)/((t - 3/t - 4)*t))*(2/t + (6/t + 5)/((t - 3/t- 4)*t))/(t - (6/t + 7)*(6/t + 5)/(t - 3/t - 4) - 12/t - 8) + 1/t +3/((t - 3/t - 4)*t^2)) - 6*(2/t + (6/t + 5)/((t - 3/t - 4)*t))/(t (6/t + 7)*(6/t + 5)/(t - 3/t - 4) - 12/t - 8) - 3*(6/t + 7)*(2/t +(6/t + 5)/((t - 3/t - 4)*t))/((t - (6/t + 7)*(6/t + 5)/(t - 3/t 4) - 12/t - 8)*(t - 3/t - 4)) - 3/((t - 3/t - 4)*t)>>> expand((~M*M)[Integer(0),Integer(0)])
1>>> (~M * M).simplify_rational()[1 0 0][0 1 0][0 0 1]

simplify_trig()
EXAMPLES:
sage: theta = var( theta )sage: M = matrix(SR, 2, 2, [cos(theta), sin(theta), -sin(theta), cos(theta)])sage: ~M
[1/cos(theta) - sin(theta)^2/((sin(theta)^2/cos(theta) +␣˓→cos(theta))*cos(theta)^2)-sin(theta)/((sin(theta)^2/
˓→cos(theta) + cos(theta))*cos(theta))][sin(theta)/((sin(theta)^2/cos(theta) +␣˓→cos(theta))*cos(theta))
1/(continues on next page)

880

Chapter 28. Symbolic dense matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)(sin(theta)^2/cos(theta) + cos(theta))]sage: (~M).simplify_trig()[ cos(theta) -sin(theta)][ sin(theta) cos(theta)]˓→>>> from sage.all import *>>> theta = var( theta )>>> M = matrix(SR, Integer(2), Integer(2), [cos(theta), sin(theta), ˓→sin(theta), cos(theta)])>>> ~M[1/cos(theta) - sin(theta)^2/((sin(theta)^2/cos(theta) +␣˓→cos(theta))*cos(theta)^2)-sin(theta)/((sin(theta)^2/
˓→cos(theta) + cos(theta))*cos(theta))][sin(theta)/((sin(theta)^2/cos(theta) +␣˓→cos(theta))*cos(theta))
1/
˓→(sin(theta)^2/cos(theta) + cos(theta))]>>> (~M).simplify_trig()[ cos(theta) -sin(theta)][ sin(theta) cos(theta)]

variables()Return the variables of self.
EXAMPLES:
sage: var( a,b,c,x,y )(a, b, c, x, y)
sage: m = matrix([[x, x+2], [x^2, x^2+2]]); m[xx + 2][x^2 x^2 + 2]
sage: m.variables()(x,)
sage: m = matrix([[a, b+c], [x^2, y^2+2]]); m[ab + c][x^2 y^2 + 2]
sage: m.variables()(a, b, c, x, y)>>> from sage.all import *>>> var( a,b,c,x,y )(a, b, c, x, y)>>> m = matrix([[x, x+Integer(2)], [x**Integer(2),␣
˓→x**Integer(2)+Integer(2)]]); m[xx + 2][x^2 x^2 + 2]>>> m.variables()(x,)>>> m = matrix([[a, b+c], [x**Integer(2), y**Integer(2)+Integer(2)]]); m[ab + c][x^2 y^2 + 2]>>> m.variables()(a, b, c, x, y)

881

Matrices and Spaces of Matrices, Release 10.4

882

Chapter 28. Symbolic dense matrices

CHAPTERTWENTYNINESYMBOLIC SPARSE MATRICESEXAMPLES:
sage: matrix(SR, 2, 2, range(4), sparse=True)
[0 1]
[2 3]
sage: matrix(SR, 2, 2, var( t ), sparse=True)
[t 0]
[0 t]
>>> from sage.all import *>>> matrix(SR, Integer(2), Integer(2), range(Integer(4)), sparse=True)
[0 1]
[2 3]
>>> matrix(SR, Integer(2), Integer(2), var( t ), sparse=True)
[t 0]
[0 t]

Arithmetic:sage: -matrix(SR, 2, range(4), sparse=True)[ 0 -1][-2 -3]sage: m = matrix(SR, 2, [1..4], sparse=True); sqrt(2)*m[ sqrt(2) 2*sqrt(2)][3*sqrt(2) 4*sqrt(2)]sage: m = matrix(SR, 4, [1..4^2], sparse=True)
sage: m * m[ 90 100 110 120][202 228 254 280]
[314 356 398 440]
[426 484 542 600]
sage: m = matrix(SR, 3, [1, 2, 3], sparse=True); m
[1]
[2]
[3]
sage: m.transpose() * m[14]>>> from sage.all import *>>> -matrix(SR, Integer(2), range(Integer(4)), sparse=True)[ 0 -1][-2 -3](continues on next page)883

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> m = matrix(SR, Integer(2), (ellipsis_range(Integer(1),Ellipsis,Integer(4))),␣
˓→sparse=True); sqrt(Integer(2))*m[ sqrt(2) 2*sqrt(2)][3*sqrt(2) 4*sqrt(2)]>>> m = matrix(SR, Integer(4), (ellipsis_range(Integer(1),Ellipsis,
˓→Integer(4)**Integer(2))), sparse=True)>>> m * m
[ 90 100 110 120][202 228 254 280]
[314 356 398 440]
[426 484 542 600]>>> m = matrix(SR, Integer(3), [Integer(1), Integer(2), Integer(3)], sparse=True); m
[1]
[2]
[3]
>>> m.transpose() * m[14]Computing inverses:
sage: M = matrix(SR, 2, var( a,b,c,d ), sparse=True)
sage: ~M
[1/a - b*c/(a^2*(b*c/a - d))b/(a*(b*c/a - d))][c/(a*(b*c/a - d))-1/(b*c/a - d)]sage: (~M*M).simplify_rational()
[1 0]
[0 1]
sage: M = matrix(SR, 3, 3, range(9), sparse=True) - var( t )sage: (~M * M).simplify_rational()[1 0 0][0 1 0][0 0 1]
sage: matrix(SR, 1, 1, 1, sparse=True).inverse()[1]
sage: matrix(SR, 0, 0, sparse=True).inverse()[]
sage: matrix(SR, 3, 0, sparse=True).inverse()
Traceback (most recent call last):...
ArithmeticError: self must be a square matrix>>> from sage.all import *>>> M = matrix(SR, Integer(2), var( a,b,c,d ), sparse=True)>>> ~M[1/a - b*c/(a^2*(b*c/a - d))b/(a*(b*c/a - d))][c/(a*(b*c/a - d))-1/(b*c/a - d)]>>> (~M*M).simplify_rational()
[1 0]
[0 1]
>>> M = matrix(SR, Integer(3), Integer(3), range(Integer(9)), sparse=True) - var( t )>>> (~M * M).simplify_rational()[1 0 0][0 1 0][0 0 1](continues on next page)884

Chapter 29. Symbolic sparse matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> matrix(SR, Integer(1), Integer(1), Integer(1), sparse=True).inverse()[1]>>> matrix(SR, Integer(0), Integer(0), sparse=True).inverse()[]>>> matrix(SR, Integer(3), Integer(0), sparse=True).inverse()
Traceback (most recent call last):...
ArithmeticError: self must be a square matrix

Transposition:
sage: m = matrix(SR, 2, [sqrt(2), -1, pi, e^2], sparse=True)
sage: m.transpose()[sqrt(2)
pi]
[
-1
e^2]
>>> from sage.all import *>>> m = matrix(SR, Integer(2), [sqrt(Integer(2)), -Integer(1), pi, e**Integer(2)],␣
˓→sparse=True)>>> m.transpose()[sqrt(2)
pi]
[
-1
e^2]

.T is a convenient shortcut for the transpose:
sage: m.T
[sqrt(2)
[
-1

pi]
e^2]

>>> from sage.all import *>>> m.T[sqrt(2)
pi]
[
-1
e^2]

Test pickling:sage: m = matrix(SR, 2, [sqrt(2), 3, pi, e], sparse=True); m[sqrt(2)3][pie]sage: TestSuite(m).run()>>> from sage.all import *>>> m = matrix(SR, Integer(2), [sqrt(Integer(2)), Integer(3), pi, e], sparse=True); m[sqrt(2)3][pie]>>> TestSuite(m).run()

Comparison:
sage: m = matrix(SR, 2, [sqrt(2), 3, pi, e], sparse=True)
sage: m == mTrue
sage: m != 3
True(continues on next page)885

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: m = matrix(SR,2,[1..4], sparse=True); n = m^2
sage: (exp(m+n) - exp(m)*exp(n)).simplify_rational() == 0
True

# indirect test>>> from sage.all import *>>> m = matrix(SR, Integer(2), [sqrt(Integer(2)), Integer(3), pi, e], sparse=True)>>> m == m
True>>> m != Integer(3)True>>> m = matrix(SR,Integer(2),(ellipsis_range(Integer(1),Ellipsis,Integer(4))),␣
˓→sparse=True); n = m**Integer(2)>>> (exp(m+n) - exp(m)*exp(n)).simplify_rational() == Integer(0)# indirect test
True

Determinant:sage: M = matrix(SR, 2, 2, [x,2,3,4], sparse=True)
sage: M.determinant()
4*x - 6sage: M = matrix(SR, 3,3,range(9), sparse=True)
sage: M.det()0
sage: t = var( t )sage: M = matrix(SR, 2, 2, [cos(t), sin(t), -sin(t), cos(t)], sparse=True)
sage: M.det()cos(t)^2 + sin(t)^2
sage: M = matrix([[sqrt(x),0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]], sparse=True)
sage: det(M)sqrt(x)>>> from sage.all import *>>> M = matrix(SR, Integer(2), Integer(2), [x,Integer(2),Integer(3),Integer(4)],␣
˓→sparse=True)>>> M.determinant()
4*x - 6>>> M = matrix(SR, Integer(3),Integer(3),range(Integer(9)), sparse=True)>>> M.det()0>>> t = var( t )>>> M = matrix(SR, Integer(2), Integer(2), [cos(t), sin(t), -sin(t), cos(t)],␣
˓→sparse=True)>>> M.det()cos(t)^2 + sin(t)^2>>> M = matrix([[sqrt(x),Integer(0),Integer(0),Integer(0)], [Integer(0),Integer(1),˓→Integer(0),Integer(0)], [Integer(0),Integer(0),Integer(1),Integer(0)], [Integer(0),˓→Integer(0),Integer(0),Integer(1)]], sparse=True)>>> det(M)sqrt(x)

Permanents:
sage: M = matrix(SR, 2, 2, [x,2,3,4], sparse=True)
sage: M.permanent()
4*x + 6886

Chapter 29. Symbolic sparse matrices

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> M = matrix(SR, Integer(2), Integer(2), [x,Integer(2),Integer(3),Integer(4)],␣
˓→sparse=True)>>> M.permanent()
4*x + 6Rank:
sage: M = matrix(SR, 5, 5, range(25), sparse=True)
sage: M.rank()
2sage: M = matrix(SR, 5, 5, range(25), sparse=True) - var( t )sage: M.rank()
5.. warning:::meth: rank may return the wrong answer if it cannot determine that amatrix element that is equivalent to zero is indeed so.
>>> from sage.all import *>>> M = matrix(SR, Integer(5), Integer(5), range(Integer(25)), sparse=True)>>> M.rank()
2>>> M = matrix(SR, Integer(5), Integer(5), range(Integer(25)), sparse=True) - var( t )>>> M.rank()
5.. warning:::meth: rank may return the wrong answer if it cannot determine that amatrix element that is equivalent to zero is indeed so.

Copying symbolic matrices:sage: m = matrix(SR, 2, [sqrt(2), 3, pi, e], sparse=True)
sage: n = copy(m)sage: n[0,0] = sin(1)sage: m[sqrt(2)3][pie]sage: n[sin(1)3][pie]>>> from sage.all import *>>> m = matrix(SR, Integer(2), [sqrt(Integer(2)), Integer(3), pi, e], sparse=True)>>> n = copy(m)>>> n[Integer(0),Integer(0)] = sin(Integer(1))>>> m[sqrt(2)
3]
[
pi
e]
>>> n
[sin(1)3][pie]Conversion to Maxima:
887

Matrices and Spaces of Matrices, Release 10.4

sage: m = matrix(SR, 2, [sqrt(2), 3, pi, e], sparse=True)
sage: m._maxima_()matrix([sqrt(2),3],[%pi,%e])>>> from sage.all import *>>> m = matrix(SR, Integer(2), [sqrt(Integer(2)), Integer(3), pi, e], sparse=True)>>> m._maxima_()matrix([sqrt(2),3],[%pi,%e])class sage.matrix.matrix_symbolic_sparse.Matrix_symbolic_sparse
Bases: Matrix_generic_sparse
arguments()
Return a tuple of the arguments that self can take.
EXAMPLES:
sage: var( x,y,z )(x, y, z)sage: M = MatrixSpace(SR,2,2, sparse=True)
sage: M(x).arguments()(x,)
sage: M(x+sin(x)).arguments()(x,)>>> from sage.all import *>>> var( x,y,z )(x, y, z)>>> M = MatrixSpace(SR,Integer(2),Integer(2), sparse=True)>>> M(x).arguments()(x,)>>> M(x+sin(x)).arguments()(x,)

canonicalize_radical()Choose a canonical branch of each entry
canonicalize_radical() componentwise.

of

self

by

calling

Expression.

EXAMPLES:
sage: var( x , y )(x, y)
sage: l1 = [sqrt(2)*sqrt(3)*sqrt(6) , log(x*y)]
sage: l2 = [sin(x/(x^2 + x)) , 1]
sage: m = matrix([l1, l2], sparse=True)
sage: m[sqrt(6)*sqrt(3)*sqrt(2)log(x*y)][sin(x/(x^2 + x))
1]
sage: m.canonicalize_radical()[
6 log(x) + log(y)][ sin(1/(x + 1))
1]>>> from sage.all import *>>> var( x , y )(x, y)>>> l1 = [sqrt(Integer(2))*sqrt(Integer(3))*sqrt(Integer(6)) , log(x*y)](continues on next page)

888

Chapter 29. Symbolic sparse matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> l2 = [sin(x/(x**Integer(2) + x)) , Integer(1)]>>> m = matrix([l1, l2], sparse=True)>>> m[sqrt(6)*sqrt(3)*sqrt(2)log(x*y)][sin(x/(x^2 + x))
1]>>> m.canonicalize_radical()[
6 log(x) + log(y)][ sin(1/(x + 1))
1]

charpoly(var='x', algorithm=None)
Compute the characteristic polynomial of self, using maxima.
Note: The characteristic polynomial is defined as det(𝑥𝐼 − 𝐴).
INPUT:• var – (default: ‘x’) name of variable of charpoly
EXAMPLES:
sage: M = matrix(SR, 2, 2, var( a,b,c,d ), sparse=True)
sage: M.charpoly( t )t^2 + (-a - d)*t - b*c + a*d
sage: matrix(SR, 5, [1..5^2], sparse=True).charpoly()x^5 - 65*x^4 - 250*x^3>>> from sage.all import *>>> M = matrix(SR, Integer(2), Integer(2), var( a,b,c,d ), sparse=True)>>> M.charpoly( t )t^2 + (-a - d)*t - b*c + a*d>>> matrix(SR, Integer(5), (ellipsis_range(Integer(1),Ellipsis,
˓→Integer(5)**Integer(2))), sparse=True).charpoly()x^5 - 65*x^4 - 250*x^3echelonize(**kwds)
Echelonize using the classical algorithm.
eigenvalues(extend=True)
Compute the eigenvalues by solving the characteristic polynomial in maxima.
The argument extend is ignored but kept for compatibility with other matrix classes.
EXAMPLES:
sage: a=matrix(SR,[[1,2],[3,4]], sparse=True)
sage: a.eigenvalues()[-1/2*sqrt(33) + 5/2, 1/2*sqrt(33) + 5/2]>>> from sage.all import *>>> a=matrix(SR,[[Integer(1),Integer(2)],[Integer(3),Integer(4)]],␣
˓→sparse=True)>>> a.eigenvalues()[-1/2*sqrt(33) + 5/2, 1/2*sqrt(33) + 5/2]

889

Matrices and Spaces of Matrices, Release 10.4

eigenvectors_left(other=None)
Compute the left eigenvectors of a matrix.
INPUT:• other – a square matrix 𝐵 (default: None) in a generalized eigenvalue problem; if None, an ordinary
eigenvalue problem is solved (currently supported only if the base ring of self is RDF or CDF)
OUTPUT:For each distinct eigenvalue, returns a list of the form (e,V,n) where e is the eigenvalue, V is a list of eigenvectors forming a basis for the corresponding left eigenspace, and n is the algebraic multiplicity of the eigenvalue.
EXAMPLES:
sage: A = matrix(SR,3,3,range(9), sparse=True); A[0 1 2][3 4 5][6 7 8]sage: es = A.eigenvectors_left(); es[(-3*sqrt(6) + 6, [(1, -1/5*sqrt(6) + 4/5, -2/5*sqrt(6) + 3/5)], 1),(3*sqrt(6) + 6, [(1, 1/5*sqrt(6) + 4/5, 2/5*sqrt(6) + 3/5)], 1),(0, [(1, -2, 1)], 1)]
sage: eval, [evec], mult = es[0]sage: delta = eval*evec - evec*A
sage: abs(abs(delta)) < 1e-10
3/5*sqrt(((2*sqrt(6) - 3)*(sqrt(6) - 2) + 7*sqrt(6) - 18)^2 + ((sqrt(6) -␣˓→2)*(sqrt(6) - 4) + 6*sqrt(6) - 14)^2) < (1.00000000000000e-10)
sage: abs(abs(delta)).n() < 1e-10
True>>> from sage.all import *>>> A = matrix(SR,Integer(3),Integer(3),range(Integer(9)), sparse=True); A[0 1 2][3 4 5][6 7 8]>>> es = A.eigenvectors_left(); es[(-3*sqrt(6) + 6, [(1, -1/5*sqrt(6) + 4/5, -2/5*sqrt(6) + 3/5)], 1),(3*sqrt(6) + 6, [(1, 1/5*sqrt(6) + 4/5, 2/5*sqrt(6) + 3/5)], 1),(0, [(1, -2, 1)], 1)]>>> eval, [evec], mult = es[Integer(0)]>>> delta = eval*evec - evec*A>>> abs(abs(delta)) < RealNumber( 1e-10 )3/5*sqrt(((2*sqrt(6) - 3)*(sqrt(6) - 2) + 7*sqrt(6) - 18)^2 + ((sqrt(6) -␣˓→2)*(sqrt(6) - 4) + 6*sqrt(6) - 14)^2) < (1.00000000000000e-10)>>> abs(abs(delta)).n() < RealNumber( 1e-10 )Truesage: A = matrix(SR, 2, 2, var( a,b,c,d ), sparse=True)
sage: A.eigenvectors_left()[(1/2*a + 1/2*d - 1/2*sqrt(a^2 + 4*b*c - 2*a*d + d^2), [(1, -1/2*(a - d +␣˓→sqrt(a^2 + 4*b*c - 2*a*d + d^2))/c)], 1), (1/2*a + 1/2*d + 1/2*sqrt(a^2 +␣
˓→4*b*c - 2*a*d + d^2), [(1, -1/2*(a - d - sqrt(a^2 + 4*b*c - 2*a*d + d^2))/˓→c)], 1)]
sage: es = A.eigenvectors_left(); es[(1/2*a + 1/2*d - 1/2*sqrt(a^2 + 4*b*c - 2*a*d + d^2), [(1, -1/2*(a - d +␣˓→sqrt(a^2 + 4*b*c - 2*a*d + d^2))/c)], 1), (1/2*a + 1/2*d + 1/2*sqrt(a^2 +␣
˓→4*b*c - 2*a*d + d^2), [(1, -1/2*(a - d - sqrt(a^2 + 4*b*c - 2*a*d + d^2))/˓→c)], 1)](continues on next page)

890

Chapter 29. Symbolic sparse matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: eval, [evec], mult = es[0]sage: delta = eval*evec - evec*A
sage: delta.apply_map(lambda x: x.full_simplify())(0, 0)>>> from sage.all import *>>> A = matrix(SR, Integer(2), Integer(2), var( a,b,c,d ), sparse=True)>>> A.eigenvectors_left()[(1/2*a + 1/2*d - 1/2*sqrt(a^2 + 4*b*c - 2*a*d + d^2), [(1, -1/2*(a - d +␣˓→sqrt(a^2 + 4*b*c - 2*a*d + d^2))/c)], 1), (1/2*a + 1/2*d + 1/2*sqrt(a^2 +␣
˓→4*b*c - 2*a*d + d^2), [(1, -1/2*(a - d - sqrt(a^2 + 4*b*c - 2*a*d + d^2))/˓→c)], 1)]>>> es = A.eigenvectors_left(); es[(1/2*a + 1/2*d - 1/2*sqrt(a^2 + 4*b*c - 2*a*d + d^2), [(1, -1/2*(a - d +␣˓→sqrt(a^2 + 4*b*c - 2*a*d + d^2))/c)], 1), (1/2*a + 1/2*d + 1/2*sqrt(a^2 +␣
˓→4*b*c - 2*a*d + d^2), [(1, -1/2*(a - d - sqrt(a^2 + 4*b*c - 2*a*d + d^2))/˓→c)], 1)]>>> eval, [evec], mult = es[Integer(0)]>>> delta = eval*evec - evec*A>>> delta.apply_map(lambda x: x.full_simplify())(0, 0)

This routine calls Maxima and can struggle with even small matrices with a few variables, such as a 3 × 3
matrix with three variables. However, if the entries are integers or rationals it can produce exact values ina reasonable time. These examples create 0-1 matrices from the adjacency matrices of graphs and illustrate
how the format and type of the results differ when the base ring changes. First for matrices over the rational
numbers, then the same matrix but viewed as a symbolic matrix.
sage: G=graphs.CycleGraph(5)sage: am = G.adjacency_matrix(sparse=True)
sage: spectrum = am.eigenvectors_left()
sage: qqbar_evalue = spectrum[2][0]sage: type(qqbar_evalue)<class sage.rings.qqbar.AlgebraicNumber >sage: qqbar_evalue
0.618033988749895?
sage: am = G.adjacency_matrix(sparse=True).change_ring(SR)sage: spectrum = am.eigenvectors_left()
sage: symbolic_evalue = spectrum[2][0]sage: type(symbolic_evalue)<class sage.symbolic.expression.Expression >sage: symbolic_evalue
1/2*sqrt(5) - 1/2
sage: bool(qqbar_evalue == symbolic_evalue)
True>>> from sage.all import *>>> G=graphs.CycleGraph(Integer(5))>>> am = G.adjacency_matrix(sparse=True)>>> spectrum = am.eigenvectors_left()>>> qqbar_evalue = spectrum[Integer(2)][Integer(0)]>>> type(qqbar_evalue)<class sage.rings.qqbar.AlgebraicNumber >>>> qqbar_evalue(continues on next page)891

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

0.618033988749895?
>>> am = G.adjacency_matrix(sparse=True).change_ring(SR)>>> spectrum = am.eigenvectors_left()>>> symbolic_evalue = spectrum[Integer(2)][Integer(0)]>>> type(symbolic_evalue)<class sage.symbolic.expression.Expression >>>> symbolic_evalue
1/2*sqrt(5) - 1/2>>> bool(qqbar_evalue == symbolic_evalue)
True

A slightly larger matrix with a “nice” spectrum.
sage: G = graphs.CycleGraph(6)sage: am = G.adjacency_matrix(sparse=True).change_ring(SR)sage: am.eigenvectors_left()[(-1, [(1, 0, -1, 1, 0, -1), (0, 1, -1, 0, 1, -1)], 2), (1, [(1, 0, -1, -1, 0,
˓→ 1), (0, 1, 1, 0, -1, -1)], 2), (-2, [(1, -1, 1, -1, 1, -1)], 1), (2, [(1,␣˓→1, 1, 1, 1, 1)], 1)]>>> from sage.all import *>>> G = graphs.CycleGraph(Integer(6))>>> am = G.adjacency_matrix(sparse=True).change_ring(SR)>>> am.eigenvectors_left()[(-1, [(1, 0, -1, 1, 0, -1), (0, 1, -1, 0, 1, -1)], 2), (1, [(1, 0, -1, -1, 0,
˓→ 1), (0, 1, 1, 0, -1, -1)], 2), (-2, [(1, -1, 1, -1, 1, -1)], 1), (2, [(1,␣˓→1, 1, 1, 1, 1)], 1)]eigenvectors_right(other=None)
Compute the right eigenvectors of a matrix.
INPUT:• other – a square matrix 𝐵 (default: None) in a generalized eigenvalue problem; if None, an ordinary
eigenvalue problem is solved (currently supported only if the base ring of self is RDF or CDF)
OUTPUT:For each distinct eigenvalue, returns a list of the form (e,V,n) where e is the eigenvalue, V is a list of eigenvectors forming a basis for the corresponding right eigenspace, and n is the algebraic multiplicity of theeigenvalue.
EXAMPLES:
sage: A = matrix(SR,2,2,range(4), sparse=True); A
[0 1]
[2 3]
sage: right = A.eigenvectors_right(); right[(-1/2*sqrt(17) + 3/2, [(1, -1/2*sqrt(17) + 3/2)], 1), (1/2*sqrt(17) + 3/2,␣˓→[(1, 1/2*sqrt(17) + 3/2)], 1)]>>> from sage.all import *>>> A = matrix(SR,Integer(2),Integer(2),range(Integer(4)), sparse=True); A
[0 1]
[2 3]
(continues on next page)892

Chapter 29. Symbolic sparse matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> right = A.eigenvectors_right(); right[(-1/2*sqrt(17) + 3/2, [(1, -1/2*sqrt(17) + 3/2)], 1), (1/2*sqrt(17) + 3/2,␣˓→[(1, 1/2*sqrt(17) + 3/2)], 1)]

The right eigenvectors are nothing but the left eigenvectors of the transpose matrix:
sage: left = A.transpose().eigenvectors_left(); left[(-1/2*sqrt(17) + 3/2, [(1, -1/2*sqrt(17) + 3/2)], 1), (1/2*sqrt(17) + 3/2,␣˓→[(1, 1/2*sqrt(17) + 3/2)], 1)]
sage: right[0][1] == left[0][1]True>>> from sage.all import *>>> left = A.transpose().eigenvectors_left(); left[(-1/2*sqrt(17) + 3/2, [(1, -1/2*sqrt(17) + 3/2)], 1), (1/2*sqrt(17) + 3/2,␣˓→[(1, 1/2*sqrt(17) + 3/2)], 1)]>>> right[Integer(0)][Integer(1)] == left[Integer(0)][Integer(1)]
True

exp()
Return the matrix exponential of this matrix 𝑋, which is the matrix
𝑒𝑋 =

∞
∑︁
𝑋𝑘
𝑘=0

𝑘!

.

This function depends on maxima’s matrix exponentiation function, which does not deal well with floating
point numbers. If the matrix has floating point numbers, they will be rounded automatically to rational numbers during the computation.
EXAMPLES:
sage: m = matrix(SR,2, [0,x,x,0], sparse=True); m
[0 x]
[x 0]
sage: m.exp()[1/2*(e^(2*x) + 1)*e^(-x) 1/2*(e^(2*x) - 1)*e^(-x)][1/2*(e^(2*x) - 1)*e^(-x) 1/2*(e^(2*x) + 1)*e^(-x)]
sage: exp(m)[1/2*(e^(2*x) + 1)*e^(-x) 1/2*(e^(2*x) - 1)*e^(-x)][1/2*(e^(2*x) - 1)*e^(-x) 1/2*(e^(2*x) + 1)*e^(-x)]>>> from sage.all import *>>> m = matrix(SR,Integer(2), [Integer(0),x,x,Integer(0)], sparse=True); m
[0 x]
[x 0]
>>> m.exp()[1/2*(e^(2*x) + 1)*e^(-x) 1/2*(e^(2*x) - 1)*e^(-x)][1/2*(e^(2*x) - 1)*e^(-x) 1/2*(e^(2*x) + 1)*e^(-x)]>>> exp(m)[1/2*(e^(2*x) + 1)*e^(-x) 1/2*(e^(2*x) - 1)*e^(-x)][1/2*(e^(2*x) - 1)*e^(-x) 1/2*(e^(2*x) + 1)*e^(-x)]

Exponentiation works on 0x0 and 1x1 matrices, but the 1x1 example requires a patched version of maxima(Issue #32898) for now:893

Matrices and Spaces of Matrices, Release 10.4

sage: m = matrix(SR,0,[], sparse=True); m[]sage: m.exp()[]
sage: m = matrix(SR,1,[2], sparse=True); m[2]
sage: m.exp() # not tested, requires patched maxima[e^2]>>> from sage.all import *>>> m = matrix(SR,Integer(0),[], sparse=True); m[]>>> m.exp()[]>>> m = matrix(SR,Integer(1),[Integer(2)], sparse=True); m[2]>>> m.exp() # not tested, requires patched maxima[e^2]Commuting matrices 𝑚, 𝑛 have the property that 𝑒𝑚+𝑛 = 𝑒𝑚 𝑒𝑛 (but non-commuting matrices need not):sage: m = matrix(SR,2,[1..4], sparse=True); n = m^2
sage: m*n
[ 37 54][ 81 118]
sage: n*m
[ 37 54][ 81 118]
sage: a = exp(m+n) - exp(m)*exp(n)sage: a.simplify_rational() == 0
True>>> from sage.all import *>>> m = matrix(SR,Integer(2),(ellipsis_range(Integer(1),Ellipsis,Integer(4))),
˓→ sparse=True); n = m**Integer(2)>>> m*n[ 37 54][ 81 118]>>> n*m[ 37 54][ 81 118]>>> a = exp(m+n) - exp(m)*exp(n)>>> a.simplify_rational() == Integer(0)True

The input matrix must be square:
sage: m = matrix(SR,2,3,[1..6], sparse=True); exp(m)Traceback (most recent call last):...
ValueError: exp only defined on square matrices>>> from sage.all import *>>> m = matrix(SR,Integer(2),Integer(3),(ellipsis_range(Integer(1),Ellipsis,(continues on next page)894

Chapter 29. Symbolic sparse matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Integer(6))), sparse=True); exp(m)Traceback (most recent call last):...
ValueError: exp only defined on square matrices˓→In this example we take the symbolic answer and make it numerical at the end:
sage: exp(matrix(SR, [[1.2, 5.6], [3,4]], sparse=True)).change_ring(RDF)˓→rel tol 1e-15[ 346.5574872980695 661.7345909344504][354.50067371488416 677.4247827652946]#␣>>> from sage.all import *>>> exp(matrix(SR, [[RealNumber( 1.2 ), RealNumber( 5.6 )], [Integer(3),˓→Integer(4)]], sparse=True)).change_ring(RDF)# rel tol 1e-15[ 346.5574872980695 661.7345909344504][354.50067371488416 677.4247827652946]

Another example involving the reversed identity matrix, which we clumsily create:
sage: m = identity_matrix(SR,4, sparse=True)
sage: m = matrix(list(reversed(m.rows())), sparse=True) * x
sage: exp(m)[1/2*(e^(2*x) + 1)*e^(-x)
0
0 1/
˓→2*(e^(2*x) - 1)*e^(-x)][
0 1/2*(e^(2*x) + 1)*e^(-x) 1/2*(e^(2*x) - 1)*e^(-x) ␣˓→
0][
0 1/2*(e^(2*x) - 1)*e^(-x) 1/2*(e^(2*x) + 1)*e^(-x) ␣˓→
0][1/2*(e^(2*x) - 1)*e^(-x)
0
0 1/
˓→2*(e^(2*x) + 1)*e^(-x)]>>> from sage.all import *>>> m = identity_matrix(SR,Integer(4), sparse=True)>>> m = matrix(list(reversed(m.rows())), sparse=True) * x>>> exp(m)[1/2*(e^(2*x) + 1)*e^(-x)
0
0 1/
˓→2*(e^(2*x) - 1)*e^(-x)][
0 1/2*(e^(2*x) + 1)*e^(-x) 1/2*(e^(2*x) - 1)*e^(-x) ␣˓→
0][
0 1/2*(e^(2*x) - 1)*e^(-x) 1/2*(e^(2*x) + 1)*e^(-x) ␣˓→
0][1/2*(e^(2*x) - 1)*e^(-x)
0
0 1/
˓→2*(e^(2*x) + 1)*e^(-x)]

expand()Operate point-wise on each element.
EXAMPLES:
sage: M = matrix(2, 2, range(4)) - var( x )sage: M*M[x^2 + 2-2*x + 3][-4*x + 6 (x - 3)^2 + 2]
sage: (M*M).expand()(continues on next page)895

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[[x^2 + 2-2*x + 3]-4*x + 6 x^2 - 6*x + 11]>>> from sage.all import *>>> M = matrix(Integer(2), Integer(2), range(Integer(4))) - var( x )>>> M*M[x^2 + 2-2*x + 3][-4*x + 6 (x - 3)^2 + 2]>>> (M*M).expand()[x^2 + 2-2*x + 3][-4*x + 6 x^2 - 6*x + 11]

factor()Operate point-wise on each element.
EXAMPLES:
sage: M = matrix(SR, 2, 2, x^2 - 2*x + 1, sparse=True); M[x^2 - 2*x + 1
0][
0 x^2 - 2*x + 1]
sage: M.factor()[(x - 1)^2
0][
0 (x - 1)^2]>>> from sage.all import *>>> M = matrix(SR, Integer(2), Integer(2), x**Integer(2) - Integer(2)*x +␣˓→Integer(1), sparse=True); M[x^2 - 2*x + 1
0][
0 x^2 - 2*x + 1]>>> M.factor()[(x - 1)^2
0][
0 (x - 1)^2]

fcp(var='x')
Return the factorization of the characteristic polynomial of self.
INPUT:• var – (default: ‘x’) name of variable of charpoly
EXAMPLES:
sage: a = matrix(SR,[[1,2],[3,4]], sparse=True)
sage: a.fcp()x^2 - 5*x - 2
sage: [i for i in a.fcp()][(x^2 - 5*x - 2, 1)]
sage: a = matrix(SR,[[1,0],[0,2]], sparse=True)
sage: a.fcp()(x - 2) * (x - 1)sage: [i for i in a.fcp()][(x - 2, 1), (x - 1, 1)]
sage: a = matrix(SR, 5, [1..5^2], sparse=True)
sage: a.fcp()(x^2 - 65*x - 250) * x^3
sage: list(a.fcp())[(x^2 - 65*x - 250, 1), (x, 3)]896

Chapter 29. Symbolic sparse matrices

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> a = matrix(SR,[[Integer(1),Integer(2)],[Integer(3),Integer(4)]],␣
˓→sparse=True)>>> a.fcp()x^2 - 5*x - 2>>> [i for i in a.fcp()][(x^2 - 5*x - 2, 1)]>>> a = matrix(SR,[[Integer(1),Integer(0)],[Integer(0),Integer(2)]],␣
˓→sparse=True)>>> a.fcp()(x - 2) * (x - 1)>>> [i for i in a.fcp()][(x - 2, 1), (x - 1, 1)]>>> a = matrix(SR, Integer(5), (ellipsis_range(Integer(1),Ellipsis,
˓→Integer(5)**Integer(2))), sparse=True)>>> a.fcp()(x^2 - 65*x - 250) * x^3>>> list(a.fcp())[(x^2 - 65*x - 250, 1), (x, 3)]function(*args)
Return a matrix over a callable symbolic expression ring.
EXAMPLES:
sage: x, y = var( x,y )sage: v = matrix([[x,y],[x*sin(y), 0]], sparse=True)
sage: w = v.function([x,y]); w[(x, y) |--> x(x, y) |--> y][(x, y) |--> x*sin(y)(x, y) |--> 0]
sage: w.parent()
Full MatrixSpace of 2 by 2 sparse matrices over Callable function ring with␣
˓→arguments (x, y)>>> from sage.all import *>>> x, y = var( x,y )>>> v = matrix([[x,y],[x*sin(y), Integer(0)]], sparse=True)>>> w = v.function([x,y]); w[(x, y) |--> x(x, y) |--> y][(x, y) |--> x*sin(y)(x, y) |--> 0]>>> w.parent()
Full MatrixSpace of 2 by 2 sparse matrices over Callable function ring with␣
˓→arguments (x, y)jordan_form(subdivide=True, transformation=False)
Return a Jordan normal form of self.
INPUT:• self – a square matrix• subdivide – boolean (default: True)• transformation – boolean (default: False)
OUTPUT:
If transformation is False, only a Jordan normal form (unique up to the ordering of the Jordan blocks)
is returned. Otherwise, a pair (J, P) is returned, where J is a Jordan normal form and P is an invertible
matrix such that self equals P * J * P^(-1).
897Matrices and Spaces of Matrices, Release 10.4

If subdivide is True, the Jordan blocks in the returned matrix J are indicated by a subdivision in thesense of subdivide().
EXAMPLES:
We start with some examples of diagonalisable matrices:sage: a,b,c,d = var( a,b,c,d )sage: matrix([a], sparse=True).jordan_form()[a]sage: matrix([[a, 0], [1, d]], sparse=True).jordan_form(subdivide=True)
[d|0]
[-+-]
[0|a]
sage: matrix([[a, 0], [1, d]], sparse=True).jordan_form(subdivide=False)
[d 0]
[0 a]
sage: matrix([[a, x, x], [0, b, x], [0, 0, c]], sparse=True).jordan_form()[c|0|0][-+-+-][0|b|0][-+-+-][0|0|a]>>> from sage.all import *>>> a,b,c,d = var( a,b,c,d )>>> matrix([a], sparse=True).jordan_form()[a]>>> matrix([[a, Integer(0)], [Integer(1), d]], sparse=True).jordan_
˓→form(subdivide=True)
[d|0]
[-+-]
[0|a]
>>> matrix([[a, Integer(0)], [Integer(1), d]], sparse=True).jordan_
˓→form(subdivide=False)
[d 0]
[0 a]
>>> matrix([[a, x, x], [Integer(0), b, x], [Integer(0), Integer(0), c]],␣
˓→sparse=True).jordan_form()[c|0|0][-+-+-][0|b|0][-+-+-][0|0|a]In the following examples, we compute Jordan forms of some non-diagonalisable matrices:sage: matrix([[a, a], [0, a]], sparse=True).jordan_form()
[a 1]
[0 a]
sage: matrix([[a, 0, b], [0, c, 0], [0, 0, a]], sparse=True).jordan_form()[c|0 0][-+---][0|a 1][0|0 a]>>> from sage.all import *>>> matrix([[a, a], [Integer(0), a]], sparse=True).jordan_form()(continues on next page)

898

Chapter 29. Symbolic sparse matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[a 1]
[0 a]
>>> matrix([[a, Integer(0), b], [Integer(0), c, Integer(0)], [Integer(0),␣
˓→Integer(0), a]], sparse=True).jordan_form()[c|0 0][-+---][0|a 1][0|0 a]The following examples illustrate the transformation flag. Note that symbolic expressions may need tobe simplified to make consistency checks succeed:
sage: A = matrix([[x - a*c, a^2], [-c^2, x + a*c]], sparse=True)
sage: J, P = A.jordan_form(transformation=True)
sage: J, P(
[x 1] [-a*c1][0 x], [-c^20])sage: A1 = P * J * ~P; A1[-a*c + x (a*c - x)*a/c + a*x/c][-c^2
a*c + x]sage: A1.simplify_rational() == A
True
sage: B = matrix([[a, b, c], [0, a, d], [0, 0, a]], sparse=True)
sage: J, T = B.jordan_form(transformation=True)
sage: J, T(
[a 1 0] [b*dc0][0 a 1] [ 0d0][0 0 a], [ 001])sage: (B * T).simplify_rational() == T * J
True>>> from sage.all import *>>> A = matrix([[x - a*c, a**Integer(2)], [-c**Integer(2), x + a*c]],␣
˓→sparse=True)>>> J, P = A.jordan_form(transformation=True)>>> J, P([x 1] [-a*c1][0 x], [-c^20])>>> A1 = P * J * ~P; A1[-a*c + x (a*c - x)*a/c + a*x/c][-c^2
a*c + x]>>> A1.simplify_rational() == A
True>>> B = matrix([[a, b, c], [Integer(0), a, d], [Integer(0), Integer(0), a]],␣
˓→sparse=True)>>> J, T = B.jordan_form(transformation=True)>>> J, T((continues on next page)899

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[a 1 0] [b*dc0][0 a 1] [ 0d0][0 0 a], [ 001])>>> (B * T).simplify_rational() == T * J
True

Finally, some examples involving square roots:
sage: matrix([[a, -b], [b, a]], sparse=True).jordan_form()[a - I*b|0][-------+-------][
0|a + I*b]
sage: matrix([[a, b], [c, d]], sparse=True).jordan_form(subdivide=False)[1/2*a + 1/2*d - 1/2*sqrt(a^2 + 4*b*c - 2*a*d + d^2)
˓→0][
0 1/2*a + 1/2*d + 1/
˓→2*sqrt(a^2 + 4*b*c - 2*a*d + d^2)]>>> from sage.all import *>>> matrix([[a, -b], [b, a]], sparse=True).jordan_form()[a - I*b|0][-------+-------][
0|a + I*b]>>> matrix([[a, b], [c, d]], sparse=True).jordan_form(subdivide=False)[1/2*a + 1/2*d - 1/2*sqrt(a^2 + 4*b*c - 2*a*d + d^2)
˓→0][
0 1/2*a + 1/2*d + 1/
˓→2*sqrt(a^2 + 4*b*c - 2*a*d + d^2)]␣␣minpoly(var='x')
Return the minimal polynomial of self.
EXAMPLES:
sage: M = Matrix.identity(SR, 2, sparse=True)
sage: M.minpoly()x - 1
sage: t = var( t )sage: m = matrix(2, [1, 2, 4, t], sparse=True)
sage: m.minimal_polynomial()x^2 + (-t - 1)*x + t - 8>>> from sage.all import *>>> M = Matrix.identity(SR, Integer(2), sparse=True)>>> M.minpoly()x - 1>>> t = var( t )>>> m = matrix(Integer(2), [Integer(1), Integer(2), Integer(4), t],␣˓→sparse=True)>>> m.minimal_polynomial()x^2 + (-t - 1)*x + t - 8

number_of_arguments()

900

Chapter 29. Symbolic sparse matrices

Matrices and Spaces of Matrices, Release 10.4

Return the number of arguments that self can take.
EXAMPLES:
sage: var( a,b,c,x,y )(a, b, c, x, y)
sage: m = matrix([[a, (x+y)/(x+y)], [x^2, y^2+2]], sparse=True); m[a1][x^2 y^2 + 2]
sage: m.number_of_arguments()
3>>> from sage.all import *>>> var( a,b,c,x,y )(a, b, c, x, y)>>> m = matrix([[a, (x+y)/(x+y)], [x**Integer(2), y**Integer(2)+Integer(2)]],␣
˓→sparse=True); m[a1][x^2 y^2 + 2]>>> m.number_of_arguments()
3

simplify()
Simplify self.
EXAMPLES:
sage: var( x,y,z )(x, y, z)sage: m = matrix([[z, (x+y)/(x+y)], [x^2, y^2+2]], sparse=True); m[z
1][x^2 y^2 + 2]
sage: m.simplify()[z
1][x^2 y^2 + 2]>>> from sage.all import *>>> var( x,y,z )(x, y, z)>>> m = matrix([[z, (x+y)/(x+y)], [x**Integer(2), y**Integer(2)+Integer(2)]],␣
˓→sparse=True); m[z
1][x^2 y^2 + 2]>>> m.simplify()[z
1][x^2 y^2 + 2]

simplify_full()
Simplify a symbolic matrix by calling Expression.simplify_full() componentwise.
INPUT:• self – the matrix whose entries we should simplify.
OUTPUT:
A copy of self with all of its entries simplified.
EXAMPLES:
901

Matrices and Spaces of Matrices, Release 10.4

Symbolic matrices will have their entries simplified:sage: a,n,k = SR.var( a,n,k )sage: f1 = sin(x)^2 + cos(x)^2
sage: f2 = sin(x/(x^2 + x))
sage: f3 = binomial(n,k)*factorial(k)*factorial(n-k)
sage: f4 = x*sin(2)/(x^a)
sage: A = matrix(SR, [[f1,f2],[f3,f4]], sparse=True)
sage: A.simplify_full()[1sin(1/(x + 1))][
factorial(n) x^(-a + 1)*sin(2)]>>> from sage.all import *>>> a,n,k = SR.var( a,n,k )>>> f1 = sin(x)**Integer(2) + cos(x)**Integer(2)>>> f2 = sin(x/(x**Integer(2) + x))>>> f3 = binomial(n,k)*factorial(k)*factorial(n-k)>>> f4 = x*sin(Integer(2))/(x**a)>>> A = matrix(SR, [[f1,f2],[f3,f4]], sparse=True)>>> A.simplify_full()[1sin(1/(x + 1))][
factorial(n) x^(-a + 1)*sin(2)]simplify_rational()
EXAMPLES:
sage: M = matrix(SR, 3, 3, range(9), sparse=True) - var( t )sage: (~M*M)[0,0]t*(3*(2/t + (6/t + 7)/((t - 3/t - 4)*t))*(2/t + (6/t + 5)/((t - 3/t- 4)*t))/(t - (6/t + 7)*(6/t + 5)/(t - 3/t - 4) - 12/t - 8) + 1/t +3/((t - 3/t - 4)*t^2)) - 6*(2/t + (6/t + 5)/((t - 3/t - 4)*t))/(t (6/t + 7)*(6/t + 5)/(t - 3/t - 4) - 12/t - 8) - 3*(6/t + 7)*(2/t +(6/t + 5)/((t - 3/t - 4)*t))/((t - (6/t + 7)*(6/t + 5)/(t - 3/t 4) - 12/t - 8)*(t - 3/t - 4)) - 3/((t - 3/t - 4)*t)
sage: expand((~M*M)[0,0])1
sage: (~M * M).simplify_rational()[1 0 0][0 1 0][0 0 1]>>> from sage.all import *>>> M = matrix(SR, Integer(3), Integer(3), range(Integer(9)), sparse=True) -␣˓→var( t )>>> (~M*M)[Integer(0),Integer(0)]t*(3*(2/t + (6/t + 7)/((t - 3/t - 4)*t))*(2/t + (6/t + 5)/((t - 3/t- 4)*t))/(t - (6/t + 7)*(6/t + 5)/(t - 3/t - 4) - 12/t - 8) + 1/t +3/((t - 3/t - 4)*t^2)) - 6*(2/t + (6/t + 5)/((t - 3/t - 4)*t))/(t (6/t + 7)*(6/t + 5)/(t - 3/t - 4) - 12/t - 8) - 3*(6/t + 7)*(2/t +(6/t + 5)/((t - 3/t - 4)*t))/((t - (6/t + 7)*(6/t + 5)/(t - 3/t 4) - 12/t - 8)*(t - 3/t - 4)) - 3/((t - 3/t - 4)*t)>>> expand((~M*M)[Integer(0),Integer(0)])
1>>> (~M * M).simplify_rational()[1 0 0][0 1 0][0 0 1]

902

Chapter 29. Symbolic sparse matrices

Matrices and Spaces of Matrices, Release 10.4

simplify_trig()
EXAMPLES:
sage: theta = var( theta )sage: M = matrix(SR, 2, 2, [cos(theta), sin(theta), -sin(theta), cos(theta)],␣
˓→sparse=True)
sage: ~M
[1/cos(theta) - sin(theta)^2/((sin(theta)^2/cos(theta) +␣˓→cos(theta))*cos(theta)^2)-sin(theta)/((sin(theta)^2/
˓→cos(theta) + cos(theta))*cos(theta))][sin(theta)/((sin(theta)^2/cos(theta) +␣˓→cos(theta))*cos(theta))
1/
˓→(sin(theta)^2/cos(theta) + cos(theta))]sage: (~M).simplify_trig()[ cos(theta) -sin(theta)][ sin(theta) cos(theta)]>>> from sage.all import *>>> theta = var( theta )>>> M = matrix(SR, Integer(2), Integer(2), [cos(theta), sin(theta), ˓→sin(theta), cos(theta)], sparse=True)>>> ~M[1/cos(theta) - sin(theta)^2/((sin(theta)^2/cos(theta) +␣˓→cos(theta))*cos(theta)^2)-sin(theta)/((sin(theta)^2/
˓→cos(theta) + cos(theta))*cos(theta))][sin(theta)/((sin(theta)^2/cos(theta) +␣˓→cos(theta))*cos(theta))
1/
˓→(sin(theta)^2/cos(theta) + cos(theta))]>>> (~M).simplify_trig()[ cos(theta) -sin(theta)][ sin(theta) cos(theta)]

variables()Return the variables of self.
EXAMPLES:
sage: var( a,b,c,x,y )(a, b, c, x, y)
sage: m = matrix([[x, x+2], [x^2, x^2+2]], sparse=True); m[xx + 2][x^2 x^2 + 2]
sage: m.variables()(x,)
sage: m = matrix([[a, b+c], [x^2, y^2+2]], sparse=True); m[ab + c][x^2 y^2 + 2]
sage: m.variables()(a, b, c, x, y)>>> from sage.all import *>>> var( a,b,c,x,y )(a, b, c, x, y)>>> m = matrix([[x, x+Integer(2)], [x**Integer(2), x**Integer(2)+Integer(2)]],
˓→ sparse=True); m[xx + 2][x^2 x^2 + 2]
(continues on next page)903

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> m.variables()(x,)>>> m = matrix([[a, b+c], [x**Integer(2), y**Integer(2)+Integer(2)]],␣
˓→sparse=True); m[ab + c][x^2 y^2 + 2]>>> m.variables()(a, b, c, x, y)

904

Chapter 29. Symbolic sparse matrices

CHAPTERTHIRTYDENSE MATRICES OVER THE COMPLEX DOUBLE FIELD USINGNUMPYEXAMPLES:
sage: b = Mat(CDF,2,3).basis()
sage: b[0,0][1.0 0.0 0.0]
[0.0 0.0 0.0]>>> from sage.all import *>>> b = Mat(CDF,Integer(2),Integer(3)).basis()>>> b[Integer(0),Integer(0)][1.0 0.0 0.0]
[0.0 0.0 0.0]

We deal with the case of zero rows or zero columns:
sage: m = MatrixSpace(CDF,0,3)
sage: m.zero_matrix()[]>>> from sage.all import *>>> m = MatrixSpace(CDF,Integer(0),Integer(3))>>> m.zero_matrix()[]

AUTHORS:• Jason Grout (2008-09): switch to NumPy backend• Josh Kantor• William Stein: many bug fixes and touch ups.
class sage.matrix.matrix_complex_double_dense.Matrix_complex_double_dense
Bases: Matrix_double_denseClass that implements matrices over the real double field. These are supposed to be fast matrix operations using C
doubles. Most operations are implemented using numpy which will call the underlying BLAS on the system.
EXAMPLES:
sage: # needs sage.symbolic
sage: m = Matrix(CDF, [[1,2*I],[3+I,4]])
sage: m**2
(continues on next page)905

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[-1.0 + 6.0*I
10.0*I][15.0 + 5.0*I 14.0 + 6.0*I]
sage: n= m^(-1); n # abs tol 1e-15[ 0.3333333333333333 + 0.3333333333333333*I 0.16666666666666669 - 0.
˓→16666666666666666*I][-0.16666666666666666 - 0.3333333333333333*I 0.08333333333333331 + 0.
˓→08333333333333333*I]>>> from sage.all import *>>> # needs sage.symbolic>>> m = Matrix(CDF, [[Integer(1),Integer(2)*I],[Integer(3)+I,Integer(4)]])>>> m**Integer(2)[-1.0 + 6.0*I
10.0*I][15.0 + 5.0*I 14.0 + 6.0*I]>>> n= m**(-Integer(1)); n # abs tol 1e-15[ 0.3333333333333333 + 0.3333333333333333*I 0.16666666666666669 - 0.
˓→16666666666666666*I][-0.16666666666666666 - 0.3333333333333333*I 0.08333333333333331 + 0.
˓→08333333333333333*I]

To compute eigenvalues, use the methods left_eigenvectors() or right_eigenvectors():
sage: p,e = m.right_eigenvectors()
˓→needs sage.symbolic>>> from sage.all import *>>> p,e = m.right_eigenvectors()
˓→needs sage.symbolic#␣#␣The result is a pair (p,e), where p is a diagonal matrix of eigenvalues and e is a matrix whose columns are theeigenvectors.
To solve a linear system 𝐴𝑥 = 𝑏 where A = [[1,2*I],[3+I,4]] and b = [5,6]:
sage: b = vector(CDF,[5,6])
˓→needs sage.symbolic
sage: m.solve_right(b) # abs tol 1e-14
˓→needs sage.symbolic(2.6666666666666665 + 0.6666666666666669*I, -0.3333333333333333 - 1.
˓→1666666666666667*I)>>> from sage.all import *>>> b = vector(CDF,[Integer(5),Integer(6)])˓→# needs sage.symbolic>>> m.solve_right(b) # abs tol 1e-14
˓→needs sage.symbolic(2.6666666666666665 + 0.6666666666666669*I, -0.3333333333333333 - 1.
˓→1666666666666667*I)

#␣
#␣

␣
#␣

See the methods QR(), LU(), and SVD() for QR, LU, and singular value decomposition.

906

Chapter 30. Dense matrices over the Complex Double Field using NumPy

CHAPTERTHIRTYONE

ARBITRARY PRECISION COMPLEX BALL MATRICESAUTHORS:• Clemens Heuberger (2014-10-25): Initial version.
This is an incomplete interface to the acb_mat module of FLINT; it may be useful to refer to its documentation for moredetails.
class sage.matrix.matrix_complex_ball_dense.Matrix_complex_ball_dense
Bases: Matrix_dense
Matrix over a complex ball field. Implemented using the acb_mat type of the FLINT library.
EXAMPLES:
sage: MatrixSpace(CBF, 3)(2)[2.000000000000000
00][
0 2.000000000000000
0][0
0 2.000000000000000]
sage: matrix(CBF, 1, 3, [1, 2, -3])
[ 1.000000000000000 2.000000000000000 -3.000000000000000]>>> from sage.all import *>>> MatrixSpace(CBF, Integer(3))(Integer(2))[2.000000000000000
00][
0 2.000000000000000
0][0
0 2.000000000000000]>>> matrix(CBF, Integer(1), Integer(3), [Integer(1), Integer(2), -Integer(3)])[ 1.000000000000000 2.000000000000000 -3.000000000000000]

charpoly(var='x', algorithm=None)
Compute the characteristic polynomial of this matrix.
EXAMPLES:
sage: from sage.matrix.benchmark import hilbert_matrix
sage: mat = hilbert_matrix(5).change_ring(ComplexBallField(10))
sage: mat.charpoly()x^5 + ([-1.8 +/- 0.0258])*x^4 + ([0.3 +/- 0.05...)*x^3 +([+/- 0.0...])*x^2 + ([+/- 0.0...])*x + [+/- 0.0...]>>> from sage.all import *>>> from sage.matrix.benchmark import hilbert_matrix>>> mat = hilbert_matrix(Integer(5)).change_
˓→ring(ComplexBallField(Integer(10)))(continues on next page)907

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> mat.charpoly()x^5 + ([-1.8 +/- 0.0258])*x^4 + ([0.3 +/- 0.05...)*x^3 +([+/- 0.0...])*x^2 + ([+/- 0.0...])*x + [+/- 0.0...]contains(other)
Test if the set of complex matrices represented by self is contained in that represented by other.
EXAMPLES:
sage: b = CBF(0, RBF(0, rad=.1r)); b[+/- 0.101]*I
sage: matrix(CBF, [0, b]).contains(matrix(CBF, [0, 0]))True
sage: matrix(CBF, [0, b]).contains(matrix(CBF, [b, 0]))False
sage: matrix(CBF, [b, b]).contains(matrix(CBF, [b, 0]))True>>> from sage.all import *>>> b = CBF(Integer(0), RBF(Integer(0), rad=.1)); b[+/- 0.101]*I>>> matrix(CBF, [Integer(0), b]).contains(matrix(CBF, [Integer(0),␣
˓→Integer(0)]))True>>> matrix(CBF, [Integer(0), b]).contains(matrix(CBF, [b, Integer(0)]))False>>> matrix(CBF, [b, b]).contains(matrix(CBF, [b, Integer(0)]))True

determinant()
Compute the determinant of this matrix.
EXAMPLES:
sage: matrix(CBF, [[1/2, 1/3], [1, 1]]).determinant()[0.1666666666666667 +/- ...e-17]
sage: matrix(CBF, [[1/2, 1/3], [1, 1]]).det()[0.1666666666666667 +/- ...e-17]
sage: matrix(CBF, [[1/2, 1/3]]).determinant()
Traceback (most recent call last):...
ValueError: self must be a square matrix>>> from sage.all import *>>> matrix(CBF, [[Integer(1)/Integer(2), Integer(1)/Integer(3)], [Integer(1),␣
˓→Integer(1)]]).determinant()[0.1666666666666667 +/- ...e-17]>>> matrix(CBF, [[Integer(1)/Integer(2), Integer(1)/Integer(3)], [Integer(1),␣
˓→Integer(1)]]).det()[0.1666666666666667 +/- ...e-17]>>> matrix(CBF, [[Integer(1)/Integer(2), Integer(1)/Integer(3)]]).
˓→determinant()
Traceback (most recent call last):...
ValueError: self must be a square matrix

908

Chapter 31. Arbitrary precision complex ball matrices

Matrices and Spaces of Matrices, Release 10.4

eigenvalues(other=None, extend=None)(Experimental.) Compute rigorous enclosures of the eigenvalues of this matrix.
INPUT:• self – an 𝑛 × 𝑛 matrix• other – unsupported (generalized eigenvalue problem), should be None
• extend – ignored
OUTPUT:
A Sequence of complex balls of length equal to the size of the matrix.
Each element represents one eigenvalue with the correct multiplicities in case of overlap. The output intervals
are either disjoint or identical, and identical intervals are guaranteed to be grouped consecutively. Eachcomplete run of 𝑘 identical balls thus represents a cluster of exactly 𝑘 eigenvalues which could not be separated
from each other at the current precision, but which could be isolated from the other eigenvalues.
There is currently no guarantee that the algorithm converges as the working precision is increased.
See the FLINT documentation for more information.
EXAMPLES:
sage: from sage.matrix.benchmark import hilbert_matrix
sage: mat = hilbert_matrix(5).change_ring(CBF)
sage: mat.eigenvalues()
doctest:...: FutureWarning: This class/method/function is marked as␣
˓→experimental.
...
[[1.567050691098...] + [+/- ...]*I, [0.208534218611...] + [+/- ...]*I,[3.287928...e-6...] + [+/- ...]*I, [0.000305898040...] + [+/- ...]*I,[0.011407491623...] + [+/- ...]*I]
sage: mat = Permutation([2, 1, 4, 5, 3]).to_matrix().dense_matrix().change_
˓→ring(CBF)
sage: mat.eigenvalues()
Traceback (most recent call last):...
ValueError: unable to certify the eigenvalues
sage: precond = matrix(ZZ, [[-1, -2, 2, 2, -2], [2, -2, -2, -2, 2],....:[-2, 2, -1, 2, 1], [2, 1, -1, 0, 2], [-2, 0, 1, -1, 1]])
sage: (~precond*mat*precond).eigenvalues()[[-0.5000000000000...] + [-0.8660254037844...]*I, [-1.000000000000...] + [+/-␣
˓→...]*I,[-0.5000000000000...] + [0.8660254037844...]*I,[1.000000000000...] + [+/- ...]*I, [1.000000000000...] + [+/- ...]*I]>>> from sage.all import *>>> from sage.matrix.benchmark import hilbert_matrix>>> mat = hilbert_matrix(Integer(5)).change_ring(CBF)>>> mat.eigenvalues()
doctest:...: FutureWarning: This class/method/function is marked as␣
˓→experimental.
...
[[1.567050691098...] + [+/- ...]*I, [0.208534218611...] + [+/- ...]*I,[3.287928...e-6...] + [+/- ...]*I, [0.000305898040...] + [+/- ...]*I,[0.011407491623...] + [+/- ...]*I](continues on next page)909

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> mat = Permutation([Integer(2), Integer(1), Integer(4), Integer(5),␣
˓→Integer(3)]).to_matrix().dense_matrix().change_ring(CBF)>>> mat.eigenvalues()
Traceback (most recent call last):...
ValueError: unable to certify the eigenvalues>>> precond = matrix(ZZ, [[-Integer(1), -Integer(2), Integer(2), Integer(2), ˓→Integer(2)], [Integer(2), -Integer(2), -Integer(2), -Integer(2),␣
˓→Integer(2)],...
[-Integer(2), Integer(2), -Integer(1), Integer(2), Integer(1)],␣
˓→[Integer(2), Integer(1), -Integer(1), Integer(0), Integer(2)], [-Integer(2),˓→ Integer(0), Integer(1), -Integer(1), Integer(1)]])>>> (~precond*mat*precond).eigenvalues()[[-0.5000000000000...] + [-0.8660254037844...]*I, [-1.000000000000...] + [+/-␣
˓→...]*I,[-0.5000000000000...] + [0.8660254037844...]*I,[1.000000000000...] + [+/- ...]*I, [1.000000000000...] + [+/- ...]*I]

See also:
eigenvectors_right()
eigenvectors_left(other=None, extend=True)(Experimental.) Compute rigorous enclosures of the eigenvalues and left eigenvectors of this matrix.
INPUT:• self – an 𝑛 × 𝑛 matrix• other – unsupported (generalized eigenvalue problem), should be None
• extend – ignored
OUTPUT:
A list of triples of the form (eigenvalue, [eigenvector], 1).
Unlike eigenvalues() and eigenvectors_left_approx(), this method currently fails in thepresence of multiple eigenvalues.
Additionally, there is currently no guarantee that the algorithm converges as the working precision is increased.
See the FLINT documentation for more information.
EXAMPLES:
sage: mat = matrix(CBF, 3, [2, 3, 5, 7, 11, 13, 17, 19, 23])
sage: eigval, eigvec, _ = mat.eigenvectors_left()[0]sage: eigval[1.1052996349...] + [+/- ...]*I
sage: eigvec[0]([0.69817246751...] + [+/- ...]*I, [-0.67419514369...] + [+/- ...]*I, [0.
˓→240865343781...] + [+/- ...]*I)
sage: eigvec[0] * (mat - eigval)([+/- ...] + [+/- ...]*I, [+/- ...] + [+/- ...]*I, [+/- ...] + [+/- ...]*I)>>> from sage.all import *>>> mat = matrix(CBF, Integer(3), [Integer(2), Integer(3), Integer(5),␣
˓→Integer(7), Integer(11), Integer(13), Integer(17), Integer(19),␣
˓→Integer(23)])(continues on next page)

910

Chapter 31. Arbitrary precision complex ball matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> eigval, eigvec, _ = mat.eigenvectors_left()[Integer(0)]>>> eigval[1.1052996349...] + [+/- ...]*I>>> eigvec[Integer(0)]([0.69817246751...] + [+/- ...]*I, [-0.67419514369...] + [+/- ...]*I, [0.
˓→240865343781...] + [+/- ...]*I)>>> eigvec[Integer(0)] * (mat - eigval)([+/- ...] + [+/- ...]*I, [+/- ...] + [+/- ...]*I, [+/- ...] + [+/- ...]*I)

See also:
eigenvectors_right(), eigenvalues(), eigenvectors_left_approx()
eigenvectors_left_approx(other=None, extend=None)(Experimental.) Compute non-rigorous approximations of the left eigenvalues and eigenvectors of this matrix.
INPUT:• self – an 𝑛 × 𝑛 matrix• other – unsupported (generalized eigenvalue problem), should be None
• extend – ignored
OUTPUT:
A list of triples of the form (eigenvalue, [eigenvector], 1). The eigenvalue and the entries ofthe eigenvector are complex balls with zero radius.
No guarantees are made about the accuracy of the output.
See the FLINT documentation for more information.
EXAMPLES:
sage: mat = matrix(CBF, 3, [2, 3, 5, 7, 11, 13, 17, 19, 23])
sage: eigval, eigvec, _ = mat.eigenvectors_left_approx()[0]sage: eigval[1.1052996349... +/- ...]
sage: eigvec[0]([0.69817246751...], [-0.67419514369...], [0.240865343781...])
sage: eigvec[0] * (mat - eigval)([+/- ...], [+/- ...], [+/- ...])>>> from sage.all import *>>> mat = matrix(CBF, Integer(3), [Integer(2), Integer(3), Integer(5),␣
˓→Integer(7), Integer(11), Integer(13), Integer(17), Integer(19),␣
˓→Integer(23)])>>> eigval, eigvec, _ = mat.eigenvectors_left_approx()[Integer(0)]>>> eigval[1.1052996349... +/- ...]>>> eigvec[Integer(0)]([0.69817246751...], [-0.67419514369...], [0.240865343781...])>>> eigvec[Integer(0)] * (mat - eigval)([+/- ...], [+/- ...], [+/- ...])

See also:
eigenvectors_left()911Matrices and Spaces of Matrices, Release 10.4

eigenvectors_right(other=None, extend=None)(Experimental.) Compute rigorous enclosures of the eigenvalues and eigenvectors of this matrix.
INPUT:• self – an 𝑛 × 𝑛 matrix• other – unsupported (generalized eigenvalue problem), should be None
• extend – ignored
OUTPUT:
A list of triples of the form (eigenvalue, [eigenvector], 1).
Unlike eigenvalues() and eigenvectors_right_approx(), this method currently fails in thepresence of multiple eigenvalues.
Additionally, there is currently no guarantee that the algorithm converges as the working precision is increased.
See the FLINT documentation for more information.
EXAMPLES:
sage: from sage.matrix.benchmark import hilbert_matrix
sage: mat = hilbert_matrix(3).change_ring(CBF)
sage: eigval, eigvec, _ = mat.eigenvectors_right()[0]doctest:...: FutureWarning: This class/method/function is marked as␣
˓→experimental.
...
sage: eigval[1.40831892712...] + [+/- ...]*I
sage: eigvec[([0.82704492697...] + [+/- ...]*I, [0.45986390436...] + [+/- ...]*I, [0.
˓→32329843524...] + [+/- ...]*I)]
sage: (mat - eigval)*eigvec[0]([+/- ...] + [+/- ...]*I, [+/- ...] + [+/- ...]*I, [+/- ...] + [+/- ...]*I)>>> from sage.all import *>>> from sage.matrix.benchmark import hilbert_matrix>>> mat = hilbert_matrix(Integer(3)).change_ring(CBF)>>> eigval, eigvec, _ = mat.eigenvectors_right()[Integer(0)]doctest:...: FutureWarning: This class/method/function is marked as␣
˓→experimental.
...
>>> eigval[1.40831892712...] + [+/- ...]*I>>> eigvec[([0.82704492697...] + [+/- ...]*I, [0.45986390436...] + [+/- ...]*I, [0.
˓→32329843524...] + [+/- ...]*I)]>>> (mat - eigval)*eigvec[Integer(0)]([+/- ...] + [+/- ...]*I, [+/- ...] + [+/- ...]*I, [+/- ...] + [+/- ...]*I)

See also:
eigenvectors_right_approx(), eigenvalues()
eigenvectors_right_approx(other=None, extend=None)(Experimental.) Compute non-rigorous approximations of the eigenvalues and eigenvectors of this matrix.
INPUT:• self – an 𝑛 × 𝑛 matrix
912

Chapter 31. Arbitrary precision complex ball matrices

Matrices and Spaces of Matrices, Release 10.4

• other – unsupported (generalized eigenvalue problem), should be None
• extend – ignored
OUTPUT:
A list of triples of the form (eigenvalue, [eigenvector], 1). The eigenvalue and the entries ofthe eigenvector are complex balls with zero radius.
No guarantees are made about the accuracy of the output.
See the FLINT documentation for more information.
EXAMPLES:
sage: from sage.matrix.benchmark import hilbert_matrix
sage: mat = hilbert_matrix(3).change_ring(CBF)
sage: eigval, eigvec, _ = mat.eigenvectors_right_approx()[0]doctest:...: FutureWarning: This class/method/function is marked as␣
˓→experimental.
...
sage: eigval[1.40831892712...]sage: eigval.rad()0.00000000
sage: eigvec[([0.8270449269720...], [0.4598639043655...], [0.3232984352444...])]
sage: (mat - eigval)*eigvec[0]([1e-15 +/- ...], [2e-15 +/- ...], [+/- ...])>>> from sage.all import *>>> from sage.matrix.benchmark import hilbert_matrix>>> mat = hilbert_matrix(Integer(3)).change_ring(CBF)>>> eigval, eigvec, _ = mat.eigenvectors_right_approx()[Integer(0)]doctest:...: FutureWarning: This class/method/function is marked as␣
˓→experimental.
...
>>> eigval[1.40831892712...]>>> eigval.rad()0.00000000>>> eigvec[([0.8270449269720...], [0.4598639043655...], [0.3232984352444...])]>>> (mat - eigval)*eigvec[Integer(0)]([1e-15 +/- ...], [2e-15 +/- ...], [+/- ...])

See also:
eigenvectors_right()
exp()
Compute the exponential of this matrix.
EXAMPLES:
sage: matrix(CBF, [[i*pi, 1], [0, i*pi]]).exp()#␣˓→needs sage.symbolic[[-1.00000000000000 +/- ...e-16] + [+/- ...e-16]*I [-1.00000000000000 +/- ...
˓→e-16] + [+/- ...e-16]*I][
0 [-1.00000000000000 +/- ...
(continues on next page)913

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)e-16] + [+/- ...e-16]*I]
sage: matrix(CBF, [[1/2, 1/3]]).exp()
Traceback (most recent call last):...
ValueError: self must be a square matrix˓→>>> from sage.all import *>>> matrix(CBF, [[i*pi, Integer(1)], [Integer(0), i*pi]]).exp()␣˓→# needs sage.symbolic[[-1.00000000000000 +/- ...e-16] + [+/- ...e-16]*I [-1.00000000000000 +/- ...
˓→e-16] + [+/- ...e-16]*I][
0 [-1.00000000000000 +/- ...
˓→e-16] + [+/- ...e-16]*I]>>> matrix(CBF, [[Integer(1)/Integer(2), Integer(1)/Integer(3)]]).exp()
Traceback (most recent call last):...
ValueError: self must be a square matrix

identical(other)
Test if the corresponding entries of two complex ball matrices represent the same balls.
EXAMPLES:
sage: a = matrix(CBF, [[1/3,2],[3,4]])
sage: b = matrix(CBF, [[1/3,2],[3,4]])
sage: a == b
False
sage: a.identical(b)True>>> from sage.all import *>>> a = matrix(CBF, [[Integer(1)/Integer(3),Integer(2)],[Integer(3),˓→Integer(4)]])>>> b = matrix(CBF, [[Integer(1)/Integer(3),Integer(2)],[Integer(3),˓→Integer(4)]])>>> a == b
False>>> a.identical(b)Trueoverlaps(other)
Test if two matrices with complex ball entries represent overlapping sets of complex matrices.
EXAMPLES:
sage: b = CBF(0, RBF(0, rad=0.1r)); b[+/- 0.101]*I
sage: matrix(CBF, [0, b]).overlaps(matrix(CBF, [b, 0]))True
sage: matrix(CBF, [1, 0]).overlaps(matrix(CBF, [b, 0]))False>>> from sage.all import *>>> b = CBF(Integer(0), RBF(Integer(0), rad=0.1)); b[+/- 0.101]*I(continues on next page)

914

Chapter 31. Arbitrary precision complex ball matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> matrix(CBF, [Integer(0), b]).overlaps(matrix(CBF, [b, Integer(0)]))True>>> matrix(CBF, [Integer(1), Integer(0)]).overlaps(matrix(CBF, [b,␣˓→Integer(0)]))
False

trace()
Compute the trace of this matrix.
EXAMPLES:
sage: matrix(CBF, [[1/3, 1/3], [1, 1]]).trace()[1.333333333333333 +/- ...e-16]
sage: matrix(CBF, [[1/2, 1/3]]).trace()
Traceback (most recent call last):...
ValueError: self must be a square matrix>>> from sage.all import *>>> matrix(CBF, [[Integer(1)/Integer(3), Integer(1)/Integer(3)], [Integer(1),␣
˓→Integer(1)]]).trace()[1.333333333333333 +/- ...e-16]>>> matrix(CBF, [[Integer(1)/Integer(2), Integer(1)/Integer(3)]]).trace()
Traceback (most recent call last):...
ValueError: self must be a square matrix

transpose()
Return the transpose of self.
EXAMPLES:
sage: m = matrix(CBF, 2, 3, [1, 2, 3, 4, 5, 6])
sage: m.transpose()[1.000000000000000 4.000000000000000][2.000000000000000 5.000000000000000][3.000000000000000 6.000000000000000]
sage: m.transpose().parent()
Full MatrixSpace of 3 by 2 dense matrices over Complex ball field with 53␣
˓→bits of precision>>> from sage.all import *>>> m = matrix(CBF, Integer(2), Integer(3), [Integer(1), Integer(2),␣
˓→Integer(3), Integer(4), Integer(5), Integer(6)])>>> m.transpose()[1.000000000000000 4.000000000000000][2.000000000000000 5.000000000000000][3.000000000000000 6.000000000000000]>>> m.transpose().parent()
Full MatrixSpace of 3 by 2 dense matrices over Complex ball field with 53␣
˓→bits of precision915

Matrices and Spaces of Matrices, Release 10.4

916

Chapter 31. Arbitrary precision complex ball matrices

CHAPTERTHIRTYTWODENSE MATRICES OVER UNIVARIATE POLYNOMIALS OVER
FIELDS

The implementation inherits from Matrix_generic_dense but some algorithms are optimized for polynomial matrices.
AUTHORS:• Kwankyu Lee (2016-12-15): initial version with code moved from other files.
• Johan Rosenkilde (2017-02-07): added weak_popov_form()• Vincent Neiger (2018-06-13): added basic functions (row/column degrees, leading positions, leading matrix, testing
reduced and canonical forms)• Vincent Neiger (2018-09-29): added functions for computing and for verifying minimal approximant bases• Vincent Neiger (2020-04-01): added functions for computing and for verifying minimal kernel bases• Vincent Neiger (2021-03-11): added matrix-wise basic functions for univariate polynomials (shifts, reverse, truncate, get coefficient of specified degree)• Vincent Neiger (2021-07-29): added popov_form(). Added more options to weak_popov_form() (column-wise,ordered, zero rows).
• Vincent Neiger (2021-08-07):{left/right}_quo_rem(), reduce().

addedinverse_series_trunc(),solve_{left/right}_series_trunc(),• Vincent Neiger (2024-02-13): added basis_completion(), _is_basis_completion(), _basis_completion_via_reversed_approx().
class sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense
Bases: Matrix_generic_dense
Dense matrix over a univariate polynomial ring over a field.
For a field, we consider matrices over the univariate polynomial ring[𝑥].

They are often used to represent bases of some [𝑥]-modules. In this context, there are two possible representations
which are both commonly used in the literature.
• Working column-wise: each column of the matrix is a vector in the basis; then, a [𝑥]-submodule of [𝑥]𝑚of rank 𝑛 is represented by an 𝑚 × 𝑛 matrix, whose columns span the module (via [𝑥]-linear combinations).
This matrix has full rank, and 𝑛 ≤ 𝑚.
• Working row-wise: each row of the matrix is a vector in the basis; then, a [𝑥]-submodule of [𝑥]𝑛 of rank
𝑚 is represented by an 𝑚 × 𝑛 matrix, whose rows span the module (via [𝑥]-linear combinations). Thismatrix has full rank, and 𝑚 ≤ 𝑛.
For the rest of this class description, we assume that one is working row-wise. For a given such module, all its bases
are equivalent under left-multiplication by a unimodular matrix, that is, a square matrix which has determinant in∖ {0}.
917

Matrices and Spaces of Matrices, Release 10.4

There are bases which are called reduced or minimal: their rows have the minimal degree possible among all basesof this module; here the degree of a row is the maximum of the degrees of the entries of the row. An equivalentcondition is that the leading matrix of this basis has full rank (see leading_matrix(), reduced_form(),
is_reduced()). There is a unique minimal basis, called the Popov basis of the module, which satisfies some
additional normalization condition (see popov_form(), is_popov()).
These notions can be extended via a more general degree measure, involving a tuple of integers which is calledshift and acts as column degree shifts in the definition of row degree. Precisely, for given 𝑠1 , . . . , 𝑠𝑛 ∈ Z and arow vector [𝑝1 · · · 𝑝𝑛 ] ∈ [𝑥]1×𝑛 , its shifted row degree is the maximum of deg(𝑝𝑗 ) + 𝑠𝑗 for 1 ≤ 𝑗 ≤ 𝑛 (seerow_degrees()). Then, reduced bases and Popov bases are defined similarly, with respect to this notion ofdegree.
Another important canonical basis is the Hermite basis, which is an upper triangular matrix satisfying a normalization condition similar to that for the Popov basis. In fact, if 𝑑 is the largest degree appearing in the Hermite basis,then the Hermite basis coincide with the shifted Popov basis with the shifts ((𝑛 − 1)𝑑, . . . , 2𝑑, 𝑑, 0).
basis_completion(row_wise=True, algorithm='approximant')
Return a Smith form-preserving nonsingular completion of a basis of this matrix: row-wise completing a row
basis if row_wise is True; column-wise completing a column basis if it is False.
For a more detailed description, consider the row-wise case (the column-wise case is the same up to matrix
transposition). Let 𝐴 be the input matrix, 𝑚 × 𝑛 over univariate polynomials [𝑥], for some field , and let𝑟 be the rank of 𝐴, which is unknown a priori. This computes a matrix 𝐶 of dimensions (𝑛 − 𝑟) × 𝑛 suchthat stacking both matrices one above the other, say [[𝐴], [𝐶]], gives a matrix of maximal rank 𝑛 and withthe same nontrivial Smith factors as 𝐴. In particular, 𝐶 has full row rank, and the rank of the input matrix
may be recovered from the number of rows of 𝐶.
As a consequence, if 𝐵 is a basis of the module generated by the rows of 𝐴 (for example 𝐵 = 𝐴 if 𝐴 has
full row rank), then [[𝐵], [𝐶]] is nonsingular, and its determinant is the product of the nonzero Smith factorsof 𝐴 up to multiplication by a nonzero element of .
In particular, for 𝐴 with full row rank: if the rows 𝐴 can be completed into a basis of [𝑥]𝑛 (or equivalently,
𝐴 has unimodular column bases, or also, if the rows of 𝐴 generate all polynomial vectors in the rational row
space of 𝐴), then 𝐶 provides such a completion. In this case, [[𝐴], [𝐶]] is unimodular: it is invertible over[𝑥], and 𝑑𝑒𝑡([[𝐴], [𝐶]]) is a nonzero element of the base field .
INPUT:• row_wise – (default: True) boolean, if True then compute a row-wise completion, else compute acolumn-wise completion.
• algorithm – (default: "approximant") selects the approach for computing the completion; currently supported: "approximant" and "smith".
OUTPUT: a matrix over the same base ring as the input matrix, which forms a completion as defined above.
ALGORITHM:• approximant: the approximant-based algorithm follows the ideas in [ZL2014] , based on polynomial
reversals combined with the computation of a minimal kernel basis and a minimal approximant basis.
• smith: the Smith form-based algorithm computes the Smith form of this matrix along with corresponding unimodular transformations, from which a completion is readily obtained.
EXAMPLES:
Three polynomials whose GCD is 1 can be completed into a unimodular matrix:
sage: ring.<x> = GF(7)[]sage: mat = matrix([[x*(x-1)*(x-2), (x-2)*(x-3)*(x-4), (x-4)*(x-5)*(x-6)]])sage: mat(continues on next page)

918

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[x^3 + 4*x^2 + 2*xx^3 + 5*x^2 + 5*x + 4
sage: rcomp = mat.basis_completion(); rcomp[
5*x^2 + 4*x + 1
5*x^2 + 2*x[
2*x^3 + 4*x^2 2*x^3 + 6*x^2 + 2*x + 1
sage: basis = mat.stack(rcomp); basis[x^3 + 4*x^2 + 2*xx^3 + 5*x^2 + 5*x + 4[
5*x^2 + 4*x + 1
5*x^2 + 2*x[
2*x^3 + 4*x^2 2*x^3 + 6*x^2 + 2*x + 1
sage: basis.determinant()
6x^3 + 6*x^2 + 4*x + 6]
5*x^2]
2*x^3 + x^2 + 3*x]x^3 + 6*x^2 + 4*x + 6]
5*x^2]
2*x^3 + x^2 + 3*x]>>> from sage.all import *>>> ring = GF(Integer(7))[ x ]; (x,) = ring._first_ngens(1)>>> mat = matrix([[x*(x-Integer(1))*(x-Integer(2)), (x-Integer(2))*(x˓→Integer(3))*(x-Integer(4)), (x-Integer(4))*(x-Integer(5))*(x-Integer(6))]])>>> mat[x^3 + 4*x^2 + 2*xx^3 + 5*x^2 + 5*x + 4
x^3 + 6*x^2 + 4*x + 6]>>> rcomp = mat.basis_completion(); rcomp[
5*x^2 + 4*x + 1
5*x^2 + 2*x
5*x^2][
2*x^3 + 4*x^2 2*x^3 + 6*x^2 + 2*x + 1
2*x^3 + x^2 + 3*x]>>> basis = mat.stack(rcomp); basis[x^3 + 4*x^2 + 2*xx^3 + 5*x^2 + 5*x + 4
x^3 + 6*x^2 + 4*x + 6][
5*x^2 + 4*x + 1
5*x^2 + 2*x
5*x^2][
2*x^3 + 4*x^2 2*x^3 + 6*x^2 + 2*x + 1
2*x^3 + x^2 + 3*x]>>> basis.determinant()
6

The following matrix has rank 2 and trivial Smith form. It can be completed row-wise into a 3×3 unimodular
matrix (column-wise, there is nothing to complete):sage: mat = matrix(ring, 2, 3, \[[x^2 + 5*x + 5,
3*x^2 + x + 3, 4*x^2 + 5*x + 4], \[5*x^2 + 4*x,3*x^2 + 4*x + 5, 5*x^2 + 5*x + 3]])sage: rcomp = mat.basis_completion(); rcomp[ 2*x^2 + 1 4*x^2 + 3*x 2*x^2 + 3*x]
sage: mat.stack(rcomp).determinant()
3
sage: mat.basis_completion(row_wise=False)[]>>> from sage.all import *>>> mat = matrix(ring, Integer(2), Integer(3), \[[x^2 + 5*x + 5,
3*x^2 + x + 3, 4*x^2 + 5*x + 4], \[5*x^2 + 4*x,3*x^2 + 4*x + 5, 5*x^2 + 5*x + 3]])>>> rcomp = mat.basis_completion(); rcomp[ 2*x^2 + 1 4*x^2 + 3*x 2*x^2 + 3*x]>>> mat.stack(rcomp).determinant()
3>>> mat.basis_completion(row_wise=False)[]

The following matrix has rank 1 and its nonzero Smith factor is 𝑥 + 3. A row-wise completion has a single
nonzero row, whereas a column-wise completion has two columns; in both cases, the Smith form is preserved:
sage: mat = matrix(ring, 3, 2, \[[x^3 + x^2 + 5*x + 5,

2*x^3 + 2*x + 4], \(continues on next page)919

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 3*x^3 + 2*x^2 + x + 3,
6*x^3 + 5*x^2 + x + 1], \[2*x^3 + 5*x^2 + 3*x + 4, 4*x^3 + 6*x^2 + 5*x + 6]])sage: mat.smith_form(transformation=False)[x + 3
0]
[
0
0]
[
0
0]
sage: rcomp = mat.basis_completion(); rcomp[x + 12*x]
sage: ccomp = mat.basis_completion(row_wise=False); ccomp[3*x + 1 4*x + 4][
2*x 5*x + 1][
6*xx]
sage: rcomp.stack(mat).smith_form(transformation=False)[
10][0 x + 3]
[
0
0]
[
0
0]
sage: ccomp.augment(mat).smith_form(transformation=False)
[
1
0
0
0]
[
0
1
0
0]
[
0
0 x + 30]>>> from sage.all import *>>> mat = matrix(ring, Integer(3), Integer(2), \[[x^3 + x^2 + 5*x + 5,
2*x^3 + 2*x + 4], \[ 3*x^3 + 2*x^2 + x + 3,
6*x^3 + 5*x^2 + x + 1], \[2*x^3 + 5*x^2 + 3*x + 4, 4*x^3 + 6*x^2 + 5*x + 6]])>>> mat.smith_form(transformation=False)[x + 3
0]
[
0
0]
[
0
0]
>>> rcomp = mat.basis_completion(); rcomp[x + 1
2*x]>>> ccomp = mat.basis_completion(row_wise=False); ccomp[3*x + 1 4*x + 4][
2*x 5*x + 1][
6*xx]>>> rcomp.stack(mat).smith_form(transformation=False)[
10][0 x + 3]
[
0
0]
[
0
0]
>>> ccomp.augment(mat).smith_form(transformation=False)
[
1
0
0
0]
[
0
1
0
0]
[
0
0 x + 30]Here are a few more examples, similar to the above but over fields other than GF(7):sage: ring.<x> = QQ[]
sage: mat = matrix([[x*(x-1)*(x-2), (x-2)*(x-3)*(x-4), (x-4)*(x-5)*(x-6)]])sage: mat[x^3 - 3*x^2 + 2*xx^3 - 9*x^2 + 26*x - 24 x^3 - 15*x^2 + 74*x -␣
˓→120]
sage: rcomp = mat.basis_completion(algorithm="smith"); rcomp[-1/12*x - 1/12
-1/12*x + 5/12
0](continues on next page)

920

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[
1/12
sage: mat.stack(rcomp).determinant()
1

1/12 1/24*x^2 - 13/24*x + 2]

sage: mat = matrix([[x*(x-1), x*(x-2)], \[x*(x-2), x*(x-3)], \[(x-1)*(x-2), (x-1)*(x-3)]])sage: mat.smith_form(transformation=False)
[1 0]
[0 x]
[0 0]
sage: ccomp = mat.basis_completion(row_wise=False, algorithm="smith")
sage: ccomp[1/2*x - 1/2]
[ 1/2*x - 1]
[1/2*x - 3/2]
sage: ccomp.augment(mat).smith_form(transformation=False)
[
1
0
0]
[
0
1
0]
[
0
0 1/2*x]
sage: field.<a> = NumberField(x**2 - 2)sage: ring.<y> = field[]sage: mat = matrix([[3*a*y - 1, (-8*a - 1)*y - 2*a + 1]])
sage: rcomp = mat.basis_completion(algorithm="smith"); rcomp[ 39/119*a - 30/119 -99/119*a + 67/119]
sage: mat.stack(rcomp).determinant()
1>>> from sage.all import *>>> ring = QQ[ x ]; (x,) = ring._first_ngens(1)>>> mat = matrix([[x*(x-Integer(1))*(x-Integer(2)), (x-Integer(2))*(x˓→Integer(3))*(x-Integer(4)), (x-Integer(4))*(x-Integer(5))*(x-Integer(6))]])>>> mat[x^3 - 3*x^2 + 2*xx^3 - 9*x^2 + 26*x - 24 x^3 - 15*x^2 + 74*x -␣
˓→120]>>> rcomp = mat.basis_completion(algorithm="smith"); rcomp[-1/12*x - 1/12
-1/12*x + 5/12
0]
[
1/12
1/12 1/24*x^2 - 13/24*x + 2]>>> mat.stack(rcomp).determinant()
1>>> mat = matrix([[x*(x-Integer(1)), x*(x-Integer(2))], \[x*(x-2), x*(x-3)], \[(x-1)*(x-2), (x-1)*(x-3)]])>>> mat.smith_form(transformation=False)
[1 0]
[0 x]
[0 0]
>>> ccomp = mat.basis_completion(row_wise=False, algorithm="smith")>>> ccomp[1/2*x - 1/2]
[ 1/2*x - 1]
[1/2*x - 3/2]>>> ccomp.augment(mat).smith_form(transformation=False)[
100](continues on next page)921

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[
[

0
0

1
0]
0 1/2*x]>>> field = NumberField(x**Integer(2) - Integer(2), names=( a ,)); (a,) =␣˓→field._first_ngens(1)>>> ring = field[ y ]; (y,) = ring._first_ngens(1)>>> mat = matrix([[Integer(3)*a*y - Integer(1), (-Integer(8)*a -␣˓→Integer(1))*y - Integer(2)*a + Integer(1)]])>>> rcomp = mat.basis_completion(algorithm="smith"); rcomp[ 39/119*a - 30/119 -99/119*a + 67/119]>>> mat.stack(rcomp).determinant()1coefficient_matrix(d, row_wise=True)
Return the constant matrix which is obtained from this matrix by taking the coefficient of its entries with
degree specified by 𝑑.
• if 𝑑 is an integer, this selects the coefficient of 𝑑 for all entries;• if 𝑑 is a list (𝑑1 , . . . , 𝑑𝑚 ) and row_wise is True, this selects the coefficient of degree 𝑑𝑖 for all entriesof the 𝑖`𝑡ℎ𝑟𝑜𝑤𝑓 𝑜𝑟𝑒𝑎𝑐ℎ`𝑖;• if 𝑑 is a list (𝑑1 , . . . , 𝑑𝑛 ) and row_wise is False, this selects the coefficient of degree 𝑑𝑖 for all entriesof the 𝑗`𝑡ℎ𝑐𝑜𝑙𝑢𝑚𝑛𝑓 𝑜𝑟𝑒𝑎𝑐ℎ`𝑗.
INPUT:• d – a list of integers, or an integer,• row_wise – (default: True) boolean, if True (resp. False) then 𝑑 should be a list of length equal
to the row (resp. column) dimension of this matrix.
OUTPUT: a matrix over the base field.
EXAMPLES:
sage: pR.<x> = GF(7)[]sage: M = Matrix([....:[ x^3+5*x^2+5*x+1,
5,
6*x+4,
0],....:[
6*x^2+3*x+1,
1,
2,
0],
....:
[2*x^3+4*x^2+6*x+4, 5*x + 1, 2*x^2+5*x+5, x^2+5*x+6]....:])
sage: M.coefficient_matrix(2)[5 0 0 0][6 0 0 0][4 0 2 1]
sage: M.coefficient_matrix(0) == M.constant_matrix()True>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> M = Matrix([...
[ x**Integer(3)+Integer(5)*x**Integer(2)+Integer(5)*x+Integer(1),˓→Integer(5),Integer(6)*x+Integer(4),Integer(0)],...
[Integer(6)*x**Integer(2)+Integer(3)*x+Integer(1),␣˓→Integer(1),Integer(2),Integer(0)],␣(continues on next page)922

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
␣
˓→[Integer(2)*x**Integer(3)+Integer(4)*x**Integer(2)+Integer(6)*x+Integer(4),␣
˓→Integer(5)*x + Integer(1), Integer(2)*x**Integer(2)+Integer(5)*x+Integer(5),˓→ x**Integer(2)+Integer(5)*x+Integer(6)]...
])>>> M.coefficient_matrix(Integer(2))[5 0 0 0][6 0 0 0][4 0 2 1]>>> M.coefficient_matrix(Integer(0)) == M.constant_matrix()
True

Row-wise and column-wise coefficient extraction are available:
sage: M.coefficient_matrix([3,2,1])[1 0 0 0][6 0 0 0][6 5 5 5]sage: M.coefficient_matrix([2,0,1,3], row_wise=False)[5 5 6 0][6 1 0 0][4 1 5 0]>>> from sage.all import *>>> M.coefficient_matrix([Integer(3),Integer(2),Integer(1)])[1 0 0 0][6 0 0 0][6 5 5 5]>>> M.coefficient_matrix([Integer(2),Integer(0),Integer(1),Integer(3)], row_
˓→wise=False)[5 5 6 0][6 1 0 0][4 1 5 0]

Negative degrees give zero coefficients:
sage: M.coefficient_matrix([-1,0,1,3], row_wise=False)[0 5 6 0][0 1 0 0][0 1 5 0]>>> from sage.all import *>>> M.coefficient_matrix([-Integer(1),Integer(0),Integer(1),Integer(3)], row_
˓→wise=False)[0 5 6 0][0 1 0 0][0 1 5 0]

Length of list of degrees is checked:
sage: M.coefficient_matrix([2,1,1,2])
Traceback (most recent call last):...
ValueError: length of input degree list should be the row(continues on next page)923

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

dimension of the input matrix
sage: M.coefficient_matrix([3,2,1], row_wise=False)
Traceback (most recent call last):...
ValueError: length of input degree list should be the column
dimension of the input matrix>>> from sage.all import *>>> M.coefficient_matrix([Integer(2),Integer(1),Integer(1),Integer(2)])
Traceback (most recent call last):...
ValueError: length of input degree list should be the row
dimension of the input matrix>>> M.coefficient_matrix([Integer(3),Integer(2),Integer(1)], row_wise=False)
Traceback (most recent call last):...
ValueError: length of input degree list should be the column
dimension of the input matrix

column_degrees(shifts=None)
Return the (shifted) column degrees of this matrix.
For a given polynomial matrix 𝑀 = (𝑀𝑖,𝑗 )𝑖,𝑗 with 𝑚 rows and 𝑛 columns, its column degrees is the tuple(𝑑1 , . . . , 𝑑𝑛 ) where 𝑑𝑗 = max𝑖 (deg(𝑀𝑖,𝑗 )) for 1 ≤ 𝑗 ≤ 𝑛. Thus, 𝑑𝑗 = −1 if the 𝑗-th column of 𝑀 is zero,and 𝑑𝑗 ≥ 0 otherwise.
For given shifts 𝑠1 , . . . , 𝑠𝑚 ∈ Z, the shifted column degrees of 𝑀 is (𝑑1 , . . . , 𝑑𝑛 ) where 𝑑𝑗 =max𝑖 (deg(𝑀𝑖,𝑗 ) + 𝑠𝑖 ). Here, if the 𝑗-th column of 𝑀 is zero then 𝑑𝑗 = min(𝑠1 , . . . , 𝑠𝑚 ) − 1; otherwise 𝑑𝑗
is larger than this value.
INPUT:• shifts – (default: None) list of integers; None is interpreted as shifts=[0,...,0].
OUTPUT: a list of integers.
EXAMPLES:
sage: pR.<x> = GF(7)[]sage: M = Matrix(pR, [[3*x+1, 0, 1], [x^3+3, 0, 0]])sage: M.column_degrees()[3, -1, 0]
sage: M.column_degrees(shifts=[0,2])[5, -1, 0]>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> M = Matrix(pR, [[Integer(3)*x+Integer(1), Integer(0), Integer(1)],␣
˓→[x**Integer(3)+Integer(3), Integer(0), Integer(0)]])>>> M.column_degrees()[3, -1, 0]>>> M.column_degrees(shifts=[Integer(0),Integer(2)])[5, -1, 0]

924

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

A zero column in a polynomial matrix can be identified in the (shifted) column degrees as the entries equal
to min(shifts)-1:
sage: M.column_degrees(shifts=[-2,1])[4, -3, -2]>>> from sage.all import *>>> M.column_degrees(shifts=[-Integer(2),Integer(1)])[4, -3, -2]

The column degrees of an empty matrix (0 × 𝑛 or 𝑚 × 0) is not defined:
sage: M = Matrix(pR, 0, 3)
sage: M.column_degrees()
Traceback (most recent call last):...
ValueError: empty matrix does not have column degrees
sage: M = Matrix(pR, 3, 0)
sage: M.column_degrees()
Traceback (most recent call last):...
ValueError: empty matrix does not have column degrees>>> from sage.all import *>>> M = Matrix(pR, Integer(0), Integer(3))>>> M.column_degrees()
Traceback (most recent call last):...
ValueError: empty matrix does not have column degrees>>> M = Matrix(pR, Integer(3), Integer(0))>>> M.column_degrees()
Traceback (most recent call last):...
ValueError: empty matrix does not have column degrees

See also:
The documentation of row_degrees().
constant_matrix()
Return the constant coefficient of this matrix seen as a polynomial with matrix coefficients; this is also thismatrix evaluated at zero.
OUTPUT: a matrix over the base field.
EXAMPLES:
sage: pR.<x> = GF(7)[]sage: M = Matrix([....:[ x^3+5*x^2+5*x+1,
5,
6*x+4,
0],....:[
6*x^2+3*x+1,
1,
2,
0],
....:
[2*x^3+4*x^2+6*x+4, 5*x + 1, 2*x^2+5*x+5, x^2+5*x+6]....:])
sage: M.constant_matrix()[1 5 4 0](continues on next page)925

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[1 1 2 0][4 1 5 6]>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> M = Matrix([...
[ x**Integer(3)+Integer(5)*x**Integer(2)+Integer(5)*x+Integer(1),␣˓→Integer(5),Integer(6)*x+Integer(4),Integer(0)],...
[Integer(6)*x**Integer(2)+Integer(3)*x+Integer(1),␣˓→Integer(1),Integer(2),Integer(0)],...
␣˓→[Integer(2)*x**Integer(3)+Integer(4)*x**Integer(2)+Integer(6)*x+Integer(4),␣
˓→Integer(5)*x + Integer(1), Integer(2)*x**Integer(2)+Integer(5)*x+Integer(5),˓→ x**Integer(2)+Integer(5)*x+Integer(6)]...
])>>> M.constant_matrix()[1 5 4 0][1 1 2 0][4 1 5 6]

degree()Return the degree of this matrix.
For a given polynomial matrix, its degree is the maximum of the degrees of all its entries. If the matrix isnonzero, this is a nonnegative integer; here, the degree of the zero matrix is -1.
OUTPUT: an integer.
EXAMPLES:
sage: pR.<x> = GF(7)[]sage: M = Matrix(pR, [[3*x+1, 0, 1], [x^3+3, 0, 0]])sage: M.degree()3>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> M = Matrix(pR, [[Integer(3)*x+Integer(1), Integer(0), Integer(1)],␣
˓→[x**Integer(3)+Integer(3), Integer(0), Integer(0)]])>>> M.degree()3

The zero matrix has degree -1:
sage: M = Matrix(pR, 2, 3)
sage: M.degree()-1>>> from sage.all import *>>> M = Matrix(pR, Integer(2), Integer(3))>>> M.degree()-1

For an empty matrix, the degree is not defined:

926

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

sage: M = Matrix(pR, 3, 0)
sage: M.degree()Traceback (most recent call last):...
ValueError: empty matrix does not have a degree>>> from sage.all import *>>> M = Matrix(pR, Integer(3), Integer(0))>>> M.degree()Traceback (most recent call last):...
ValueError: empty matrix does not have a degree

degree_matrix(shifts=None, row_wise=True)
Return the matrix of the (shifted) degrees in this matrix.
For a given polynomial matrix 𝑀 = (𝑀𝑖,𝑗 )𝑖,𝑗 , its degree matrix is the matrix (deg(𝑀𝑖,𝑗 ))𝑖,𝑗 formed by the
degrees of its entries. Here, the degree of the zero polynomial is −1.
For given shifts 𝑠1 , . . . , 𝑠𝑚 ∈ Z, the shifted degree matrix of 𝑀 is either (deg(𝑀𝑖,𝑗 ) + 𝑠𝑗 )𝑖,𝑗 if working
row-wise, or (deg(𝑀𝑖,𝑗 ) + 𝑠𝑖 )𝑖,𝑗 if working column-wise. In the former case, 𝑚 has to be the number ofcolumns of 𝑀 ; in the latter case, the number of its rows. Here, if 𝑀𝑖,𝑗 = 0 then the corresponding entry in theshifted degree matrix is min(𝑠1 , . . . , 𝑠𝑚 ) − 1. For more on shifts and working row-wise versus column-wise,
see the class documentation.
INPUT:• shifts – (default: None) list of integers; None is interpreted as shifts=[0,...,0].
• row_wise – (default: True) boolean, if True then shifts apply to the columns of the matrix andotherwise to its rows (see the class description for more details).
OUTPUT: an integer matrix.
EXAMPLES:
sage: pR.<x> = GF(7)[]sage: M = Matrix(pR, [[3*x+1, 0, 1], [x^3+3, 0, 0]])sage: M.degree_matrix()[ 1 -1 0][ 3 -1 -1]
sage: M.degree_matrix(shifts=[0,1,2])[ 1 -1 2][ 3 -1 -1]>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> M = Matrix(pR, [[Integer(3)*x+Integer(1), Integer(0), Integer(1)],␣
˓→[x**Integer(3)+Integer(3), Integer(0), Integer(0)]])>>> M.degree_matrix()[ 1 -1 0][ 3 -1 -1]>>> M.degree_matrix(shifts=[Integer(0),Integer(1),Integer(2)])[ 1 -1 2][ 3 -1 -1]

927

Matrices and Spaces of Matrices, Release 10.4

The zero entries in the polynomial matrix can be identified in the (shifted) degree matrix as the entries equal
to min(shifts)-1:
sage: M.degree_matrix(shifts=[-2,1,2])[-1 -3 2][ 1 -3 -3]>>> from sage.all import *>>> M.degree_matrix(shifts=[-Integer(2),Integer(1),Integer(2)])[-1 -3 2][ 1 -3 -3]

Using row_wise=False, the function supports shifts applied to the rows of the matrix (which, in termsof modules, means that we are working column-wise, see the class documentation):sage: M.degree_matrix(shifts=[-1,2], row_wise=False)[ 0 -2 -1][ 5 -2 -2]>>> from sage.all import *>>> M.degree_matrix(shifts=[-Integer(1),Integer(2)], row_wise=False)[ 0 -2 -1][ 5 -2 -2]

hermite_form(include_zero_rows=True, transformation=False)
Return the Hermite form of this matrix.
See is_hermite() for a definition of Hermite forms. If the input is a matrix 𝐴, then its Hermite form isthe unique matrix 𝐻 in Hermite form such that 𝑈 𝐴 = 𝐻 for some unimodular matrix 𝑈 .
INPUT:• include_zero_rows – boolean (default: True); if False, the zero rows in the output matrix are
deleted.
• transformation – boolean (default: False); if True, return the transformation matrix.
OUTPUT:• the Hermite normal form 𝐻 of this matrix 𝐴 .
• (optional) transformation matrix 𝑈 such that 𝑈 𝐴 = 𝐻 .
EXAMPLES:
sage: M.<x> = GF(7)[]sage: A = matrix(M, 2, 3, [x, 1, 2*x, x, 1+x, 2])
sage: A.hermite_form()
[
x
1
2*x]
[
0
x 5*x + 2]
sage: A.hermite_form(transformation=True)([x12*x] [1 0][0x 5*x + 2], [6 1])sage: A = matrix(M, 2, 3, [x, 1, 2*x, 2*x, 2, 4*x])
sage: A.hermite_form(transformation=True, include_zero_rows=False)([ x
1 2*x], [0 4])
sage: H, U = A.hermite_form(transformation=True,(continues on next page)

928

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)....:
include_zero_rows=True); H, U(
[ x
1 2*x] [0 4][ 000], [5 1])
sage: U * A == H
True
sage: H, U = A.hermite_form(transformation=True,....:
include_zero_rows=False)
sage: U * A[ x
1 2*x]
sage: U * A == H
True>>> from sage.all import *>>> M = GF(Integer(7))[ x ]; (x,) = M._first_ngens(1)>>> A = matrix(M, Integer(2), Integer(3), [x, Integer(1), Integer(2)*x, x,␣
˓→Integer(1)+x, Integer(2)])>>> A.hermite_form()
[
x
1
2*x]
[
0
x 5*x + 2]>>> A.hermite_form(transformation=True)([x12*x] [1 0][0x 5*x + 2], [6 1])>>> A = matrix(M, Integer(2), Integer(3), [x, Integer(1), Integer(2)*x,␣
˓→Integer(2)*x, Integer(2), Integer(4)*x])>>> A.hermite_form(transformation=True, include_zero_rows=False)([ x
1 2*x], [0 4])>>> H, U = A.hermite_form(transformation=True,...
include_zero_rows=True); H, U(
[ x
1 2*x] [0 4][ 000], [5 1])>>> U * A == H
True>>> H, U = A.hermite_form(transformation=True,...
include_zero_rows=False)>>> U * A
[ x
1 2*x]>>> U * A == H
True

See also:
is_hermite() , popov_form() .
inverse_series_trunc(d)Return a matrix polynomial approximation of precision d of the inverse series of this matrix polynomial.
Here matrix polynomial means that self is seen as a univariate polynomial with matrix coefficients, meaningthat this method has the same output as if one: 1) converts this matrix to a univariate polynomial with matrix
coefficients, 2) calls
sage.rings.polynomial.polynomial_element.Polynomial.
inverse_series_trunc()929

Matrices and Spaces of Matrices, Release 10.4

on that univariate polynomial, and 3) converts back to a matrix of polynomials.
Raises a ZeroDivisionError if the constant matrix of self is not invertible (i.e. has zero determinant);raises an ArithmeticError if self is nonsquare; and raises a ValueError if the precision d is not
positive.
INPUT: a positive integer 𝑑 .
OUTPUT: the unique polynomial matrix 𝐵 of degree less than 𝑑 such that 𝐴𝐵 and 𝐵𝐴 are the identity matrix
modulo 𝑥𝑑 , where 𝐴 is self.
ALGORITHM: This uses Newton iteration, performing about log(𝑑) polynomial matrix multiplications insize 𝑚 × 𝑚 and in degree less than 2𝑑, where 𝑚 is the row dimension of self.
EXAMPLES:
sage: pR.<x> = GF(7)[]sage: A = Matrix(pR, 3, 3,....:[[4*x+5,5*x^2 + x + 1, 4*x^2 + 4],....:[6*x^2 + 6*x + 6, 4*x^2 + 5*x,4*x^2 + x + 3],....:[3*x^2 + 2,
4*x + 1,x^2 + 3*x]])
sage: B = A.inverse_series_trunc(4); B[
x^3 + 5*x^2 + x + 4
x^3 + 5*x^2 + 6*x + 4
6*x^2 + 5*x + 3][
4*x^2 + 5*x + 6
6*x^3 + x^2 + x + 6
3*x^3 + 2*x^2 + 2]
[5*x^3 + 5*x^2 + 6*x + 6 4*x^3 + 2*x^2 + 6*x + 4
6*x^3 + x^2 + 6*x + 1]
sage: (B*A).truncate(4) == 1
True
sage: A.inverse_series_trunc(0)Traceback (most recent call last):...
ValueError: the precision must be positive
sage: A[:2,:].inverse_series_trunc(4)Traceback (most recent call last):...
ArithmeticError: the input matrix must be square
sage: A[0,:] = A[0,:] - A[0,:](0) + A[1,:](0) + A[2,:](0)sage: A.inverse_series_trunc(4)Traceback (most recent call last):...
ZeroDivisionError: the constant matrix term self(0) must be invertible>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> A = Matrix(pR, Integer(3), Integer(3),...
[[Integer(4)*x+Integer(5),Integer(5)*x**Integer(2)␣
˓→+ x + Integer(1), Integer(4)*x**Integer(2) + Integer(4)],...
[Integer(6)*x**Integer(2) + Integer(6)*x + Integer(6),␣
˓→Integer(4)*x**Integer(2) + Integer(5)*x,
Integer(4)*x**Integer(2) + x +␣˓→Integer(3)],...
[Integer(3)*x**Integer(2) + Integer(2),Integer(4)*x +␣˓→Integer(1),x**Integer(2) + Integer(3)*x]])>>> B = A.inverse_series_trunc(Integer(4)); B[x^3 + 5*x^2 + x + 4
x^3 + 5*x^2 + 6*x + 4
6*x^2 + 5*x + 3][
4*x^2 + 5*x + 6
6*x^3 + x^2 + x + 6
3*x^3 + 2*x^2 + 2]
[5*x^3 + 5*x^2 + 6*x + 6 4*x^3 + 2*x^2 + 6*x + 4
6*x^3 + x^2 + 6*x + 1]>>> (B*A).truncate(Integer(4)) == Integer(1)(continues on next page)

930

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

True>>> A.inverse_series_trunc(Integer(0))
Traceback (most recent call last):...
ValueError: the precision must be positive>>> A[:Integer(2),:].inverse_series_trunc(Integer(4))
Traceback (most recent call last):...
ArithmeticError: the input matrix must be square>>> A[Integer(0),:] = A[Integer(0),:] - A[Integer(0),:](Integer(0)) +␣˓→A[Integer(1),:](Integer(0)) + A[Integer(2),:](Integer(0))>>> A.inverse_series_trunc(Integer(4))
Traceback (most recent call last):...
ZeroDivisionError: the constant matrix term self(0) must be invertible

See also:
sage.rings.polynomial.polynomial_element.Polynomial.
inverse_series_trunc() .
Todo: in the current state of polynomial matrix multiplication (July 2021), it would be highly beneficial
to use conversions and rely on polynomials with matrix coefficients when the matrix size is “large” and thedegree “small”, see Issue #31472#comment:5.
is_constant()
Return whether this polynomial matrix is constant, that is, all its entries are constant.
OUTPUT: a boolean.
EXAMPLES:
sage: pR.<x> = GF(7)[]sage: M = Matrix([....:[ x^3+5*x^2+5*x+1,
5,
6*x+4,
0],....:[
6*x^2+3*x+1,
1,
2,
0],
....:
[2*x^3+4*x^2+6*x+4, 5*x + 1, 2*x^2+5*x+5, x^2+5*x+6]....:])
sage: M.is_constant()
False
sage: M = Matrix(pR, [[1,5,2], [3,1,5]]); M.is_constant()
True
sage: M = Matrix.zero(pR, 3, 5); M.is_constant()
True>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> M = Matrix([...
[ x**Integer(3)+Integer(5)*x**Integer(2)+Integer(5)*x+Integer(1),˓→Integer(5),Integer(6)*x+Integer(4),Integer(0)],...
[Integer(6)*x**Integer(2)+Integer(3)*x+Integer(1),␣˓→Integer(1),Integer(2),Integer(0)],␣(continues on next page)931

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
␣
˓→[Integer(2)*x**Integer(3)+Integer(4)*x**Integer(2)+Integer(6)*x+Integer(4),␣
˓→Integer(5)*x + Integer(1), Integer(2)*x**Integer(2)+Integer(5)*x+Integer(5),˓→ x**Integer(2)+Integer(5)*x+Integer(6)]...
])>>> M.is_constant()
False>>> M = Matrix(pR, [[Integer(1),Integer(5),Integer(2)], [Integer(3),˓→Integer(1),Integer(5)]]); M.is_constant()
True>>> M = Matrix.zero(pR, Integer(3), Integer(5)); M.is_constant()
True

See also:
sage.rings.polynomial.polynomial_element.Polynomial.is_constant()
is_hermite(row_wise=True, lower_echelon=False, include_zero_vectors=True)
Return a boolean indicating whether this matrix is in Hermite form.
If working row-wise, a polynomial matrix is said to be in Hermite form if it is in row echelon form withall pivot entries monic and such that all entries above a pivot have degree less than this pivot. Being in row
echelon form means that all zero rows are gathered at the bottom of the matrix, and in each nonzero row thepivot (leftmost nonzero entry) is strictly to the right of the pivot of the row just above this row.
Note that, for any integer 𝑑 strictly greater than all degrees appearing in the Hermite form, then the Hermite
form coincides with the shifted Popov form with the shifts ((𝑛 − 1)𝑑, . . . , 2𝑑, 𝑑, 0), where 𝑛 is the column
dimension.
If working column-wise, a polynomial matrix is said to be in Hermite form if it is in column echelon form
with all pivot entries monic and such that all entries to the left of a pivot have degree less than this pivot.
Being in column echelon form means that all zero columns are gathered at the right-hand side of the matrix,
and in each nonzero column the pivot (topmost nonzero entry) is strictly below the pivot of the column justto the left of this row.
Optional arguments provide support of alternative definitions, concerning the choice of upper or lower echelon
forms and concerning whether zero rows (resp. columns) are allowed.
INPUT:• row_wise – (default: True) boolean, True if working row-wise (see the class description).
• lower_echelon – (default: False) boolean, False if working with upper triangular Hermite
forms, True if working with lower triangular Hermite forms.
• include_zero_vectors – (default: True) boolean, False if one does not allow zero rows (resp.
zero columns) in Hermite forms.
OUTPUT: a boolean.
EXAMPLES:
sage: pR.<x> = GF(7)[]sage: M = Matrix(pR, [[x^4+6*x^3+4*x+4, 3*x+6,
3 ],
....:
[0,
x^2+5*x+5, 2 ],
....:
[0,
0,
x+5]])
sage: M.is_hermite()True
sage: M.is_hermite(row_wise=False)(continues on next page)932

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)True
sage: M.is_hermite(row_wise=False, lower_echelon=True)
False
sage: N = Matrix(pR, [[x+5, 0,
0
],
....:
[2,
x^4+6*x^3+4*x+4, 0
],
....:
[3,
3*x^3+6,
x^2+5*x+5]])
sage: N.is_hermite()
False
sage: N.is_hermite(lower_echelon=True)
True
sage: N.is_hermite(row_wise=False)
False
sage: N.is_hermite(row_wise=False, lower_echelon=True)
False>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> M = Matrix(pR,␣˓→[[x**Integer(4)+Integer(6)*x**Integer(3)+Integer(4)*x+Integer(4),␣
˓→Integer(3)*x+Integer(6),Integer(3) ],...
[Integer(0),␣
˓→x**Integer(2)+Integer(5)*x+Integer(5), Integer(2)],...
[Integer(0),Integer(0),␣
˓→x+Integer(5)]])>>> M.is_hermite()
True>>> M.is_hermite(row_wise=False)
True>>> M.is_hermite(row_wise=False, lower_echelon=True)
False>>> N = Matrix(pR, [[x+Integer(5), Integer(0),Integer(0)
␣
˓→ ],
...
[Integer(2), ␣
˓→x**Integer(4)+Integer(6)*x**Integer(3)+Integer(4)*x+Integer(4), Integer(0) ␣
˓→
],
...
[Integer(3),Integer(3)*x**Integer(3)+Integer(6),␣˓→
x**Integer(2)+Integer(5)*x+Integer(5)]])>>> N.is_hermite()
False>>> N.is_hermite(lower_echelon=True)
True>>> N.is_hermite(row_wise=False)
False>>> N.is_hermite(row_wise=False, lower_echelon=True)
False

Rectangular matrices with zero rows are supported. Zero rows (resp. columns) can be forbidden, and otherwise they should be at the bottom (resp. the right-hand side) of the matrix:
sage: N[:,1:].is_hermite(lower_echelon=True)
False
sage: N[[1,2,0],1:].is_hermite(lower_echelon=True)
True(continues on next page)933

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: N[:2,:].is_hermite(row_wise=False, lower_echelon=True)
True
sage: N[:2,:].is_hermite(row_wise=False,....:
lower_echelon=True,....:
include_zero_vectors=False)
False>>> from sage.all import *>>> N[:,Integer(1):].is_hermite(lower_echelon=True)
False>>> N[[Integer(1),Integer(2),Integer(0)],Integer(1):].is_hermite(lower_
˓→echelon=True)
True>>> N[:Integer(2),:].is_hermite(row_wise=False, lower_echelon=True)
True>>> N[:Integer(2),:].is_hermite(row_wise=False,...
lower_echelon=True,...
include_zero_vectors=False)
False

See also:
hermite_form() .
is_minimal_approximant_basis(pmat, order, shifts=None, row_wise=True, normal_form=False)
Return whether this matrix is an approximant basis in shifts-ordered weak Popov form for the polynomial
matrix pmat at order order.
If normal_form is True, then the polynomial matrix must furthermore be in shifts-Popov form. An
error is raised if the input dimensions are not sound. If a single integer is provided for order, then it isinterpreted as a list of repeated integers with this value. (See minimal_approximant_basis() for
definitions and more details.)
INPUT:• pmat – a polynomial matrix.
• order – a list of positive integers, or a positive integer.
• shifts – (default: None) list of integers; None is interpreted as shifts=[0,...,0].
• row_wise – (default: True) boolean, if True then the basis considered row-wise and operates on theleft of pmat; otherwise it is column-wise and operates on the right of pmat.
• normal_form – (default: False) boolean, if True then checks for a basis in shifts-Popov form.
OUTPUT: a boolean.
ALGORITHM:
Verification that the matrix is formed by approximants is done via a truncated matrix product; verificationthat the matrix is square, nonsingular and in shifted weak Popov form is done via is_weak_popov();
verification that the matrix generates the module of approximants is done via the characterization in Theorem
2.1 of [GN2018] .
EXAMPLES:
sage: pR.<x> = GF(97)[]934

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> pR = GF(Integer(97))[ x ]; (x,) = pR._first_ngens(1)We consider the following example from [Arne Storjohann, Notes on computing minimal approximant bases,
2006]:
sage: order = 8; shifts = [1,1,0,0,0]
sage: pmat = Matrix(pR, 5, 1, [....:pR([35, 0, 41, 87, 3, 42, 22, 90]),....:pR([80, 15, 62, 87, 14, 93, 24, 0]),....:pR([42, 57, 90, 87, 22, 80, 71, 53]),....:
pR([37, 72, 74, 6, 5, 75, 23, 47]),....:
pR([36, 10, 74, 1, 29, 44, 87, 74])])sage: appbas = Matrix(pR, [....:[x+47,
57, 58*x+44,
9*x+23,93*x+76],....:[ 15, x+18, 52*x+23,
15*x+58,
93*x+88],
....:
[ 17,
86, x^2+77*x+16, 76*x+29,
90*x+78],
....:
[ 44,
36, 3*x+42,x^2+50*x+26, 85*x+44],
....:
[
2,
22, 54*x+94,
73*x+24,x^2+2*x+25]])
sage: appbas.is_minimal_approximant_basis(
˓→needs sage.libs.pari....:pmat, order, shifts, row_wise=True, normal_form=True)
True

#␣

>>> from sage.all import *>>> order = Integer(8); shifts = [Integer(1),Integer(1),Integer(0),Integer(0),˓→Integer(0)]>>> pmat = Matrix(pR, Integer(5), Integer(1), [...
pR([Integer(35), Integer(0), Integer(41), Integer(87), Integer(3),␣
˓→Integer(42), Integer(22), Integer(90)]),...
pR([Integer(80), Integer(15), Integer(62), Integer(87), Integer(14),␣
˓→Integer(93), Integer(24),Integer(0)]),...
pR([Integer(42), Integer(57), Integer(90), Integer(87), Integer(22),␣
˓→Integer(80), Integer(71), Integer(53)]),...
pR([Integer(37), Integer(72), Integer(74), Integer(6), Integer(5),␣
˓→Integer(75), Integer(23), Integer(47)]),...
pR([Integer(36), Integer(10), Integer(74), Integer(1), Integer(29),␣
˓→Integer(44), Integer(87), Integer(74)])])>>> appbas = Matrix(pR, [...
[x+Integer(47),Integer(57), Integer(58)*x+Integer(44),␣˓→Integer(9)*x+Integer(23),Integer(93)*x+Integer(76)],...
[ Integer(15), x+Integer(18), Integer(52)*x+Integer(23),␣˓→Integer(15)*x+Integer(58),Integer(93)*x+Integer(88)],...
[ Integer(17),Integer(86),␣
˓→x**Integer(2)+Integer(77)*x+Integer(16), Integer(76)*x+Integer(29),␣˓→Integer(90)*x+Integer(78)],...
[ Integer(44),Integer(36), Integer(3)*x+Integer(42),␣
˓→x**Integer(2)+Integer(50)*x+Integer(26), Integer(85)*x+Integer(44)],...
[
Integer(2),Integer(22), Integer(54)*x+Integer(94),␣˓→Integer(73)*x+Integer(24),x**Integer(2)+Integer(2)*x+Integer(25)]])>>> appbas.is_minimal_approximant_basis(#␣˓→needs sage.libs.pari...
pmat, order, shifts, row_wise=True, normal_form=True)
True

The matrix 𝑥8 Id5 is square, nonsingular, in Popov form, and its rows are approximants for pmat at order
8. However, it is not an approximant basis since its rows generate a module strictly contained in the set of935

Matrices and Spaces of Matrices, Release 10.4

approximants for pmat at order 8:
sage: M = x^8 * Matrix.identity(pR, 5)
sage: M.is_minimal_approximant_basis(pmat, 8)
˓→needs sage.libs.pari
False>>> from sage.all import *>>> M = x**Integer(8) * Matrix.identity(pR, Integer(5))>>> M.is_minimal_approximant_basis(pmat, Integer(8))˓→# needs sage.libs.pari
False

#␣

␣

Since pmat is a single column, with nonzero constant coefficient, its column-wise approximant bases at order
8 are all 1 × 1 matrices [𝑐𝑥8 ] for some nonzero field element 𝑐:sage: M = Matrix(pR, [x^8])
sage: M.is_minimal_approximant_basis(....:
pmat, 8, row_wise=False, normal_form=True)
True>>> from sage.all import *>>> M = Matrix(pR, [x**Integer(8)])>>> M.is_minimal_approximant_basis(...
pmat, Integer(8), row_wise=False, normal_form=True)
True

Exceptions are raised if input dimensions are not sound:sage: appbas.is_minimal_approximant_basis(pmat, [8,8], shifts)
Traceback (most recent call last):...
ValueError: order length should be the column dimensionof the input matrix
sage: appbas.is_minimal_approximant_basis(....:
pmat, order, shifts, row_wise=False)
Traceback (most recent call last):...
ValueError: shifts length should be the column dimensionof the input matrix
sage: Matrix(pR, [x^8]).is_minimal_approximant_basis(pmat, 8)
Traceback (most recent call last):...
ValueError: column dimension should be the row dimension of the
input matrix>>> from sage.all import *>>> appbas.is_minimal_approximant_basis(pmat, [Integer(8),Integer(8)], shifts)
Traceback (most recent call last):...
ValueError: order length should be the column dimensionof the input matrix>>> appbas.is_minimal_approximant_basis(...
pmat, order, shifts, row_wise=False)(continues on next page)

936

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Traceback (most recent call last):...
ValueError: shifts length should be the column dimensionof the input matrix>>> Matrix(pR, [x**Integer(8)]).is_minimal_approximant_basis(pmat, Integer(8))
Traceback (most recent call last):...
ValueError: column dimension should be the row dimension of the
input matrix

See also:
minimal_approximant_basis() .
is_minimal_kernel_basis(pmat, shifts=None, row_wise=True, normal_form=False)
Return whether this matrix is a left kernel basis in shifts-ordered weak Popov form for the polynomial
matrix pmat.
If normal_form is True, then the kernel basis must furthermore be in shifts-Popov form. An error israised if the input dimensions are not sound.
INPUT:• pmat – a polynomial matrix.
• shifts – (default: None) list of integers; None is interpreted as shifts=[0,...,0].
• row_wise – (default: True) boolean, if True then the basis is considered row-wise and operates on
the left of pmat; otherwise it is column-wise and operates on the right of pmat.
• normal_form – (default: False) boolean, if True then checks for a basis in shifts-Popov form.
OUTPUT: a boolean.
ALGORITHM:
Verification that the matrix has full rank and is in shifted weak Popov form is done via is_weak_popov();
verification that the matrix is a left kernel basis is done by checking that the rank is correct, that the productis indeed zero, and that the matrix is saturated, i.e. it has unimodular column bases (see Lemma 6.10 of
https://arxiv.org/pdf/1807.01272.pdf for details).
EXAMPLES:
sage: pR.<x> = GF(97)[]
sage: pmat = Matrix(pR, [[1], [x], [x**2]])
sage: kerbas = Matrix(pR, [[x,-1,0], [0,x,-1]])
sage: kerbas.is_minimal_kernel_basis(pmat)
True>>> from sage.all import *>>> pR = GF(Integer(97))[ x ]; (x,) = pR._first_ngens(1)>>> pmat = Matrix(pR, [[Integer(1)], [x], [x**Integer(2)]])>>> kerbas = Matrix(pR, [[x,-Integer(1),Integer(0)], [Integer(0),x,˓→Integer(1)]])>>> kerbas.is_minimal_kernel_basis(pmat)
True

937

Matrices and Spaces of Matrices, Release 10.4

A matrix in Popov form which has the right rank, all rows in the kernel, but does not generate the kernel:
sage: kerbas = Matrix(pR, [[x**2,0,-1], [0,x,-1]])
sage: kerbas.is_minimal_kernel_basis(pmat)
False>>> from sage.all import *>>> kerbas = Matrix(pR, [[x**Integer(2),Integer(0),-Integer(1)], [Integer(0),˓→x,-Integer(1)]])>>> kerbas.is_minimal_kernel_basis(pmat)
False

Shifts and right kernel bases are supported (with row_wise), and one can test whether the kernel basis isnormalized in shifted-Popov form (with normal_form):
sage: kerbas = Matrix(pR, [[-x,-x**2], [1,0], [0,1]])
sage: kerbas.is_minimal_kernel_basis(....:
pmat.transpose(), row_wise=False,....:
normal_form=True, shifts=[0,1,2])
True>>> from sage.all import *>>> kerbas = Matrix(pR, [[-x,-x**Integer(2)], [Integer(1),Integer(0)],␣
˓→[Integer(0),Integer(1)]])>>> kerbas.is_minimal_kernel_basis(...
pmat.transpose(), row_wise=False,...
normal_form=True, shifts=[Integer(0),Integer(1),Integer(2)])
True

is_popov(shifts=None, row_wise=True, up_to_permutation=False, include_zero_vectors=True)
Return a boolean indicating whether this matrix is in (shifted) Popov form.
If working row-wise (resp. column-wise), a polynomial matrix is said to be in Popov form if it has no zerorow above a nonzero row (resp. no zero column to the left of a nonzero column), the leading positions of its
nonzero rows (resp. columns) are strictly increasing, and for each row (resp. column) the pivot entry is monic
and has degree strictly larger than the other entries in its column (resp. row).
Since other conventions concerning the ordering of the rows (resp. columns) are sometimes useful, an optional
argument allows one to test whether the matrix is in Popov form up to row (resp. column) permutation. For
example, there is an alternative definition which replaces “leading positions strictly increasing” by “row (resp.
column) degree nondecreasing, and for rows (resp. columns) of same degree, leading positions increasing”.
INPUT:• shifts – (default: None) list of integers; None is interpreted as shifts=[0,...,0].
• row_wise – (default: True) boolean, True if working row-wise (see the class description).
• up_to_permutation – (option, default: False) boolean, True if testing Popov form up to row
permutation (if working row-wise).
• include_zero_vectors – (default: True) boolean, False if one does not allow zero rows (resp.
zero columns) in Popov forms.
OUTPUT: a boolean.
REFERENCES:
For the square case, without shifts: [Pop1972] and [Kai1980] (Section 6.7.2). For the general case:[BLV2006] .

938

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

EXAMPLES:
sage: pR.<x> = GF(7)[]sage: M = Matrix(pR, [[x^4+6*x^3+4*x+4, 3*x+6,
3 ],
....:
[x^2+6*x+6,
x^2+5*x+5, 2 ],
....:
[3*x,
6*x+5,
x+5]])
sage: M.is_popov()
True
sage: M.is_popov(shifts=[0,1,2])
True
sage: M[:,:2].is_popov()
False
sage: M[:2,:].is_popov(shifts=[0,1,2])
True
sage: M = Matrix(pR, [[x^4+3*x^3+x^2+2*x+6, x^3+5*x^2+5*x+1],....:[6*x+1,x^2+4*x+1
],
....:
[6,
6
]])
sage: M.is_popov(row_wise=False)
False
sage: M.is_popov(shifts=[0,2,3], row_wise=False)
True>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> M = Matrix(pR,␣˓→[[x**Integer(4)+Integer(6)*x**Integer(3)+Integer(4)*x+Integer(4),␣
˓→Integer(3)*x+Integer(6),Integer(3) ],...
[x**Integer(2)+Integer(6)*x+Integer(6),␣˓→x**Integer(2)+Integer(5)*x+Integer(5), Integer(2)],...
[Integer(3)*x,
Integer(6)*x+Integer(5),˓→x+Integer(5)]])>>> M.is_popov()
True␣>>> M.is_popov(shifts=[Integer(0),Integer(1),Integer(2)])
True>>> M[:,:Integer(2)].is_popov()
False>>> M[:Integer(2),:].is_popov(shifts=[Integer(0),Integer(1),Integer(2)])
True>>> M = Matrix(pR,␣˓→[[x**Integer(4)+Integer(3)*x**Integer(3)+x**Integer(2)+Integer(2)*x+Integer(6),˓→ x**Integer(3)+Integer(5)*x**Integer(2)+Integer(5)*x+Integer(1)],...
[Integer(6)*x+Integer(1),␣˓→x**Integer(2)+Integer(4)*x+Integer(1)],...
[Integer(6),Integer(6)]])>>> M.is_popov(row_wise=False)
False>>> M.is_popov(shifts=[Integer(0),Integer(2),Integer(3)], row_wise=False)(continues on next page)939

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)True

One can forbid zero rows (or columns if not working row-wise):sage: N = Matrix(pR, [[x^4+3*x^3+x^2+2*x+6, 6*x+1],....:[5*x^2+5*x+1,
x^2+4*x+1 ],
....:
[0,
0
]])
sage: N.is_popov()
True
sage: N.is_popov(include_zero_vectors=False)
False>>> from sage.all import *>>> N = Matrix(pR,␣˓→[[x**Integer(4)+Integer(3)*x**Integer(3)+x**Integer(2)+Integer(2)*x+Integer(6),˓→ Integer(6)*x+Integer(1)],...
[Integer(5)*x**Integer(2)+Integer(5)*x+Integer(1),␣˓→ x**Integer(2)+Integer(4)*x+Integer(1) ],...
[Integer(0),Integer(0)]])>>> N.is_popov()
True>>> N.is_popov(include_zero_vectors=False)
False

One can verify Popov form up to row permutation (or column permutation if not working row-wise):sage: M.swap_columns(0, 1)
sage: M.is_popov(shifts=[0,2,3], row_wise=False)
False
sage: M.is_popov(shifts=[0,2,3], row_wise=False,....:
up_to_permutation=True)
True
sage: N.swap_rows(0, 2)
sage: N.is_popov()
False
sage: N.is_popov(up_to_permutation=True)
True>>> from sage.all import *>>> M.swap_columns(Integer(0), Integer(1))>>> M.is_popov(shifts=[Integer(0),Integer(2),Integer(3)], row_wise=False)
False>>> M.is_popov(shifts=[Integer(0),Integer(2),Integer(3)], row_wise=False,...
up_to_permutation=True)
True>>> N.swap_rows(Integer(0), Integer(2))(continues on next page)

940

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> N.is_popov()
False>>> N.is_popov(up_to_permutation=True)
True

is_reduced(shifts=None, row_wise=True, include_zero_vectors=True)
Return a boolean indicating whether this matrix is in (shifted) reduced form.
An 𝑚 × 𝑛 univariate polynomial matrix 𝑀 is said to be in shifted row reduced form if it has 𝑘 nonzero
rows with 𝑘 ≤ 𝑛 and its shifted leading matrix has rank 𝑘. Equivalently, when considering all the matrices
obtained by left-multiplying 𝑀 by a unimodular matrix, then the shifted row degrees of 𝑀 – once sorted in
nondecreasing order – is lexicographically minimal.
Similarly, 𝑀 is said to be in shifted column reduced form if it has 𝑘 nonzero columns with 𝑘 ≤ 𝑚 and its
shifted leading matrix has rank 𝑘.
Sometimes, one forbids 𝑀 to have zero rows (resp. columns) in the above definitions; an optional parameterallows one to adopt this more restrictive setting.
INPUT:• shifts – (default: None) list of integers; None is interpreted as shifts=[0,...,0].
• row_wise – (default: True) boolean, True if working row-wise (see the class description).
• include_zero_vectors – (default: True) boolean, False if one does not allow zero rows inrow reduced forms (resp. zero columns in column reduced forms).
OUTPUT: a boolean value.
REFERENCES:[Wol1974] (Section 2.5, without shifts) and [VBB1992] (Section 3).
EXAMPLES:
sage: pR.<x> = GF(7)[]sage: M = Matrix(pR, [[3*x+1, 0, 1], [x^3+3, 0, 0]])sage: M.is_reduced()
False
sage: M.is_reduced(shifts=[0,1,2])
True
sage: M.is_reduced(shifts=[2,0], row_wise=False)
True
sage: M.is_reduced(shifts=[2,0], row_wise=False,....:
include_zero_vectors=False)
False
sage: M = Matrix(pR, [[3*x+1, 0, 1], [x^3+3, 0, 0], [0, 1, 0]])sage: M.is_reduced(shifts=[2,0,0], row_wise=False)
True>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)(continues on next page)941

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> M = Matrix(pR, [[Integer(3)*x+Integer(1), Integer(0), Integer(1)],␣
˓→[x**Integer(3)+Integer(3), Integer(0), Integer(0)]])>>> M.is_reduced()
False>>> M.is_reduced(shifts=[Integer(0),Integer(1),Integer(2)])
True>>> M.is_reduced(shifts=[Integer(2),Integer(0)], row_wise=False)
True>>> M.is_reduced(shifts=[Integer(2),Integer(0)], row_wise=False,...
include_zero_vectors=False)
False>>> M = Matrix(pR, [[Integer(3)*x+Integer(1), Integer(0), Integer(1)],␣
˓→[x**Integer(3)+Integer(3), Integer(0), Integer(0)], [Integer(0), Integer(1),˓→ Integer(0)]])>>> M.is_reduced(shifts=[Integer(2),Integer(0),Integer(0)], row_wise=False)
True

See also:
leading_matrix() , reduced_form() .
is_weak_popov(shifts=None, row_wise=True, ordered=False, include_zero_vectors=True)
Return a boolean indicating whether this matrix is in (shifted) (ordered) weak Popov form.
If working row-wise (resp. column-wise), a polynomial matrix is said to be in weak Popov form if the leading
positions of its nonzero rows (resp. columns) are pairwise distinct. For the ordered weak Popov form, these
positions must be strictly increasing, except for the possibly repeated -1 entries which are at the end. For theshifted variants, see the class description for an introduction to shifts.
INPUT:• shifts – (default: None) list of integers; None is interpreted as shifts=[0,...,0].
• row_wise – (default: True) boolean, True if working row-wise (see the class description).
• ordered – (default: False) boolean, True if checking for an ordered weak Popov form.
• include_zero_vectors – (default: True) boolean, False if one does not allow zero rows (resp.
zero columns) in (ordered) weak Popov forms.
OUTPUT: a boolean.
REFERENCES:[Kai1980] (Section 6.7.2, square case without shifts), [MS2003] (without shifts), [BLV1999] .
EXAMPLES:
sage: pR.<x> = GF(7)[]sage: M = Matrix([ [x^3+3*x^2+6*x+6, 3*x^2+3*x+6, 4*x^2+x+3],
....:
[5,
1,
0
],
....:
[2*x^2+2,
2*x+5,
x^2+4*x+6] ])sage: M.is_weak_popov()
True

942

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> M = Matrix([␣˓→[x**Integer(3)+Integer(3)*x**Integer(2)+Integer(6)*x+Integer(6),␣
˓→Integer(3)*x**Integer(2)+Integer(3)*x+Integer(6),␣
˓→Integer(4)*x**Integer(2)+x+Integer(3)],...
[Integer(5),Integer(1),Integer(0) ␣
˓→
],
...
[Integer(2)*x**Integer(2)+Integer(2),␣˓→Integer(2)*x+Integer(5),x**Integer(2)+Integer(4)*x+Integer(6)] ])>>> M.is_weak_popov()True

One can check whether the leading positions, in addition to being pairwise distinct, are actually in increasingorder:
sage: M.is_weak_popov(ordered=True)
True
sage: N = M.with_swapped_rows(1, 2)
sage: N.is_weak_popov()
True
sage: N.is_weak_popov(ordered=True)
False>>> from sage.all import *>>> M.is_weak_popov(ordered=True)
True>>> N = M.with_swapped_rows(Integer(1), Integer(2))>>> N.is_weak_popov()
True>>> N.is_weak_popov(ordered=True)
False

Shifts and orientation (row-wise or column-wise) are supported:
sage: M.is_weak_popov(shifts=[2,3,1])
False
sage: M.is_weak_popov(shifts=[0,2,0], row_wise=False,....:ordered=True)
True>>> from sage.all import *>>> M.is_weak_popov(shifts=[Integer(2),Integer(3),Integer(1)])
False>>> M.is_weak_popov(shifts=[Integer(0),Integer(2),Integer(0)], row_wise=False,...
ordered=True)
True

Rectangular matrices are supported:
sage: M = Matrix([....:[ x^3+5*x^2+5*x+1,

5,

6*x+4,

0],(continues on next page)943

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)....:[
6*x^2+3*x+1,
1,
2,
0],
....:
[2*x^3+4*x^2+6*x+4, 5*x + 1, 2*x^2+5*x+5, x^2+5*x+6]....:])
sage: M.is_weak_popov(shifts=[0,2,1,3])
True
sage: M.is_weak_popov(shifts=[0,2,1,3], ordered=True)
True>>> from sage.all import *>>> M = Matrix([...
[ x**Integer(3)+Integer(5)*x**Integer(2)+Integer(5)*x+Integer(1),␣˓→Integer(5),Integer(6)*x+Integer(4),Integer(0)],...
[Integer(6)*x**Integer(2)+Integer(3)*x+Integer(1),␣˓→Integer(1),Integer(2),Integer(0)],...
␣˓→[Integer(2)*x**Integer(3)+Integer(4)*x**Integer(2)+Integer(6)*x+Integer(4),␣
˓→Integer(5)*x + Integer(1), Integer(2)*x**Integer(2)+Integer(5)*x+Integer(5),˓→ x**Integer(2)+Integer(5)*x+Integer(6)]...
])>>> M.is_weak_popov(shifts=[Integer(0),Integer(2),Integer(1),Integer(3)])
True>>> M.is_weak_popov(shifts=[Integer(0),Integer(2),Integer(1),Integer(3)],␣
˓→ordered=True)
True

Zero rows (resp. columns) can be forbidden:
sage: M = Matrix([....:[
6*x+4,
0,
5*x+1, 0],....:[2, 5*x + 1,
6*x^2+3*x+1, 0],....:[2*x^2+5*x+5,
1, 2*x^3+4*x^2+6*x+4, 0]....:])
sage: M.is_weak_popov(shifts=[2,1,0], row_wise=False,....:ordered=True)
True
sage: M.is_weak_popov(shifts=[2,1,0], row_wise=False,....:
include_zero_vectors=False)
False>>> from sage.all import *>>> M = Matrix([...
[
Integer(6)*x+Integer(4),Integer(0),␣
˓→Integer(5)*x+Integer(1), Integer(0)],...
[Integer(2), Integer(5)*x + Integer(1),␣˓→Integer(6)*x**Integer(2)+Integer(3)*x+Integer(1), Integer(0)],...
[Integer(2)*x**Integer(2)+Integer(5)*x+Integer(5),Integer(1),␣
˓→Integer(2)*x**Integer(3)+Integer(4)*x**Integer(2)+Integer(6)*x+Integer(4),␣
˓→Integer(0)]...
])>>> M.is_weak_popov(shifts=[Integer(2),Integer(1),Integer(0)], row_wise=False,...
ordered=True)
True(continues on next page)

944

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> M.is_weak_popov(shifts=[Integer(2),Integer(1),Integer(0)], row_wise=False,...
include_zero_vectors=False)
False

See also:
weak_popov_form() .
leading_matrix(shifts=None, row_wise=True)
Return the (shifted) leading matrix of this matrix.
Let 𝑀 be a univariate polynomial matrix in [𝑥]𝑚×𝑛 . Working row-wise and without shifts, its leading
matrix is the matrix in 𝑚×𝑛 formed by the leading coefficients of the entries of 𝑀 which reach the degreeof the corresponding row.
More precisely, if working row-wise, let 𝑠1 , . . . , 𝑠𝑛 ∈ Z be a shift, and let (𝑑1 , . . . , 𝑑𝑚 ) denote the shiftedrow degrees of 𝑀 . Then, the shifted leading matrix of 𝑀 is the matrix in 𝑚×𝑛 whose entry 𝑖, 𝑗 is thecoefficient of degree 𝑑𝑖 − 𝑠𝑗 of the entry 𝑖, 𝑗 of 𝑀 .
If working column-wise, let 𝑠1 , . . . , 𝑠𝑚 ∈ Z be a shift, and let (𝑑1 , . . . , 𝑑𝑛 ) denote the shifted column degrees
of 𝑀 . Then, the shifted leading matrix of 𝑀 is the matrix in 𝑚×𝑛 whose entry 𝑖, 𝑗 is the coefficient ofdegree 𝑑𝑗 − 𝑠𝑖 of the entry 𝑖, 𝑗 of 𝑀 .
INPUT:• shifts – (default: None) list of integers; None is interpreted as shifts=[0,...,0].
• row_wise – (default: True) boolean, True if working row-wise (see the class description).
OUTPUT: a matrix over the base field.
REFERENCES:[Wol1974] (Section 2.5, without shifts) and [VBB1992] (Section 3).
EXAMPLES:
sage: pR.<x> = GF(7)[]sage: M = Matrix(pR, [[3*x+1, 0, 1], [x^3+3, 0, 0]])sage: M.leading_matrix()[3 0 0][1 0 0]sage: M.leading_matrix().base_ring()
Finite Field of size 7
sage: M.leading_matrix(shifts=[0,1,2])[0 0 1][1 0 0]sage: M.leading_matrix(row_wise=False)[0 0 1][1 0 0]sage: M.leading_matrix(shifts=[-2,1], row_wise=False)[0 0 1][1 0 0]sage: M.leading_matrix(shifts=[2,0], row_wise=False)(continues on next page)945

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[3 0 1][1 0 0]>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> M = Matrix(pR, [[Integer(3)*x+Integer(1), Integer(0), Integer(1)],␣
˓→[x**Integer(3)+Integer(3), Integer(0), Integer(0)]])>>> M.leading_matrix()[3 0 0][1 0 0]>>> M.leading_matrix().base_ring()
Finite Field of size 7>>> M.leading_matrix(shifts=[Integer(0),Integer(1),Integer(2)])[0 0 1][1 0 0]>>> M.leading_matrix(row_wise=False)[0 0 1][1 0 0]>>> M.leading_matrix(shifts=[-Integer(2),Integer(1)], row_wise=False)[0 0 1][1 0 0]>>> M.leading_matrix(shifts=[Integer(2),Integer(0)], row_wise=False)[3 0 1][1 0 0]

leading_positions(shifts=None, row_wise=True, return_degree=False)
Return the (shifted) leading positions (also known as the pivot indices), and optionally the (shifted) pivot
degrees of this matrix.
If working row-wise, for a given shift 𝑠1 , . . . , 𝑠𝑛 ∈ Z, taken as (0, . . . , 0) by default, and a row vector ofunivariate polynomials [𝑝1 , . . . , 𝑝𝑛 ], the leading position of this vector is the index 𝑗 of the rightmost nonzero
entry 𝑝𝑗 such that deg(𝑝𝑗 ) + 𝑠𝑗 is equal to the shifted row degree of the vector. Then the pivot degree of thevector is the degree deg(𝑝𝑗 ).
For the zero row, both the leading positions and degree are −1. For a 𝑚 × 𝑛 polynomial matrix, the leading
positions and pivot degrees are the two lists containing the leading positions and the pivot degrees of its rows.
The definition is similar if working column-wise (instead of rightmost nonzero entry, we choose the bottommost nonzero entry).
INPUT:• shifts – (default: None) list of integers; None is interpreted as shifts=[0,...,0].
• row_wise – (default: True) boolean, True if working row-wise (see the class description).
• return_degree – (default: False) boolean, True implies that the pivot degrees are returned.
OUTPUT: a list of integers if return_degree=False; a pair of lists of integers otherwise.
REFERENCES:[Kai1980] (Section 6.7.2, without shifts).
EXAMPLES:
946

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

sage: pR.<x> = GF(7)[]sage: M = Matrix(pR, [[3*x+1, 0, 1], [x^3+3, 0, 0]])sage: M.leading_positions()[0, 0]
sage: M.leading_positions(return_degree=True)([0, 0], [1, 3])
sage: M.leading_positions(shifts=[0,5,2], return_degree=True)([2, 0], [0, 3])
sage: M.leading_positions(row_wise=False, return_degree=True)([1, -1, 0], [3, -1, 0])
sage: M.leading_positions(shifts=[1,2], row_wise=False,....:
return_degree=True)([1, -1, 0], [3, -1, 0])>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> M = Matrix(pR, [[Integer(3)*x+Integer(1), Integer(0), Integer(1)],␣
˓→[x**Integer(3)+Integer(3), Integer(0), Integer(0)]])>>> M.leading_positions()[0, 0]>>> M.leading_positions(return_degree=True)([0, 0], [1, 3])>>> M.leading_positions(shifts=[Integer(0),Integer(5),Integer(2)], return_˓→degree=True)([2, 0], [0, 3])>>> M.leading_positions(row_wise=False, return_degree=True)([1, -1, 0], [3, -1, 0])>>> M.leading_positions(shifts=[Integer(1),Integer(2)], row_wise=False,...
return_degree=True)([1, -1, 0], [3, -1, 0])In case several entries in the row (resp. column) reach the shifted row (resp. column) degree, the leading
position is chosen as the rightmost (resp. bottommost) such entry:
sage: M.leading_positions(shifts=[0,5,1], return_degree=True)([2, 0], [0, 3])
sage: M.leading_positions(shifts=[2,0], row_wise=False,....:
return_degree=True)([1, -1, 0], [3, -1, 0])>>> from sage.all import *>>> M.leading_positions(shifts=[Integer(0),Integer(5),Integer(1)], return_˓→degree=True)([2, 0], [0, 3])>>> M.leading_positions(shifts=[Integer(2),Integer(0)], row_wise=False,...
return_degree=True)([1, -1, 0], [3, -1, 0])947

Matrices and Spaces of Matrices, Release 10.4

The leading positions and pivot degrees of an empty matrix (0 × 𝑛 or 𝑚 × 0) is not defined:
sage: M = Matrix(pR, 0, 3)
sage: M.leading_positions()
Traceback (most recent call last):...
ValueError: empty matrix does not have leading positions
sage: M.leading_positions(row_wise=False)
Traceback (most recent call last):...
ValueError: empty matrix does not have leading positions
sage: M = Matrix(pR, 3, 0)
sage: M.leading_positions(row_wise=False)
Traceback (most recent call last):...
ValueError: empty matrix does not have leading positions>>> from sage.all import *>>> M = Matrix(pR, Integer(0), Integer(3))>>> M.leading_positions()
Traceback (most recent call last):...
ValueError: empty matrix does not have leading positions>>> M.leading_positions(row_wise=False)
Traceback (most recent call last):...
ValueError: empty matrix does not have leading positions>>> M = Matrix(pR, Integer(3), Integer(0))>>> M.leading_positions(row_wise=False)
Traceback (most recent call last):...
ValueError: empty matrix does not have leading positions

left_quo_rem(B)Return, if it exists, the quotient and remainder (𝑄, 𝑅) such that self is 𝐵𝑄 + 𝑅, where 𝑅 has row degrees
less than those of 𝐵 entrywise.
This method directly calls right_quo_rem() on transposed matrices, and transposes the result. See
right_quo_rem() for a complete documentation and more examples.
EXAMPLES:
sage: pR.<x> = GF(7)[]sage: A = Matrix(pR, 3, 2,....:[[
3*x^3 + 3*x,2*x^3 + 4],....:[ 3*x^3 + 6*x + 5, 6*x^3 + 5*x^2 + 1],....:[ 2*x^3 + 2*x + 6,
3*x^2 + 2*x + 2]])sage: B = Matrix(pR, 3, 3,
....:
[[
3,
x + 3,
6],....:[3*x^3 + 3*x + 1, 4*x^2 + 3*x,6*x^3 + x + 4],....:[ 4*x^2 + x + 4, 3*x^2 + 4*x, 3*x^2 + 3*x + 2]])sage: Q, R = A.left_quo_rem(B); Q, R(
[2*x^2 + 4*x + 6 6*x^2 + 4*x + 1] [3
1](continues on next page)

948

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[3*x^2 + 5*x2*x^2 + x + 5] [6 5*x^2 + 2*x + 3][
6*x^2 + 3*x 4*x^2 + 6*x + 1], [2*x + 3
6*x + 3])sage: rdegR = R.row_degrees(); rdegB = B.row_degrees()
sage: A == B*Q+R and all(rdegR[i] < rdegB[i] for i in range(3))
True
sage: A[:2,:].left_quo_rem(B)Traceback (most recent call last):...
ValueError: row dimension of self should be the row dimension of
the input matrix>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> A = Matrix(pR, Integer(3), Integer(2),...
[[Integer(3)*x**Integer(3) + Integer(3)*x,
␣
˓→Integer(2)*x**Integer(3) + Integer(4)],...
[ Integer(3)*x**Integer(3) + Integer(6)*x + Integer(5),␣
˓→Integer(6)*x**Integer(3) + Integer(5)*x**Integer(2) + Integer(1)],...
[ Integer(2)*x**Integer(3) + Integer(2)*x + Integer(6), ␣
˓→Integer(3)*x**Integer(2) + Integer(2)*x + Integer(2)]])>>> B = Matrix(pR, Integer(3), Integer(3),...
[[Integer(3),x + Integer(3),␣˓→ Integer(6)],...
[Integer(3)*x**Integer(3) + Integer(3)*x + Integer(1),␣
˓→Integer(4)*x**Integer(2) + Integer(3)*x,
Integer(6)*x**Integer(3) + x +␣˓→Integer(4)],...
[ Integer(4)*x**Integer(2) + x + Integer(4),␣
˓→Integer(3)*x**Integer(2) + Integer(4)*x, Integer(3)*x**Integer(2) +␣˓→Integer(3)*x + Integer(2)]])>>> Q, R = A.left_quo_rem(B); Q, R(
[2*x^2 + 4*x + 6 6*x^2 + 4*x + 1] [3
1][
3*x^2 + 5*x2*x^2 + x + 5] [6 5*x^2 + 2*x + 3][
6*x^2 + 3*x 4*x^2 + 6*x + 1], [2*x + 3
6*x + 3])>>> rdegR = R.row_degrees(); rdegB = B.row_degrees()>>> A == B*Q+R and all(rdegR[i] < rdegB[i] for i in range(Integer(3)))
True>>> A[:Integer(2),:].left_quo_rem(B)Traceback (most recent call last):...
ValueError: row dimension of self should be the row dimension of
the input matrix

Rectangular or rank-deficient matrices are supported but there may be no quotient and remainder (unless thematrix has full row rank, see right_quo_rem()):
sage: Q, R = A[:2,:].left_quo_rem(B[:2,:]); Q, R([
3*x + 3
2*x + 1][ 3*x^2 + 5*x 2*x^2 + x + 5] [5[00], [4*x^2 + x + 2)

0]
4*x^2 + x]
(continues on next page)949

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: rdegR = R.row_degrees(); rdegB = B[:2,:].row_degrees()
sage: A[:2,:] == B[:2,:]*Q+R
True
sage: all([rdegR[i] < rdegB[i] for i in range(len(rdegR))])
True
sage: A.left_quo_rem(B[:,:2])Traceback (most recent call last):...
ValueError: division of these matrices does not admit a remainder
with the required degree property>>> from sage.all import *>>> Q, R = A[:Integer(2),:].left_quo_rem(B[:Integer(2),:]); Q, R([
3*x + 3
2*x + 1][ 3*x^2 + 5*x 2*x^2 + x + 5] [50][
00], [4*x^2 + x + 2
4*x^2 + x])>>> rdegR = R.row_degrees(); rdegB = B[:Integer(2),:].row_degrees()>>> A[:Integer(2),:] == B[:Integer(2),:]*Q+R
True>>> all([rdegR[i] < rdegB[i] for i in range(len(rdegR))])
True>>> A.left_quo_rem(B[:,:Integer(2)])
Traceback (most recent call last):...
ValueError: division of these matrices does not admit a remainder
with the required degree property

See also:
right_quo_rem() , reduce() .
minimal_approximant_basis(order, shifts=None, row_wise=True, normal_form=False)
Return an approximant basis in shifts-ordered weak Popov form for this polynomial matrix at order order.
Assuming we work row-wise, if 𝐹 is an 𝑚 × 𝑛 polynomial matrix and (𝑑0 , . . . , 𝑑𝑛−1 ) are positive integers,then an approximant basis for 𝐹 at order (𝑑0 , . . . , 𝑑𝑛−1 ) is a polynomial matrix whose rows form a basisof the module of approximants for 𝐹 at order (𝑑0 , . . . , 𝑑𝑛−1 ). The latter approximants are the polynomial
vectors 𝑝 of size 𝑚 such that the column 𝑗 of 𝑝𝐹 has valuation at least 𝑑𝑗 , for all 0 ≤ 𝑗 ≤ 𝑛 − 1.
If normal_form is True, then the output basis 𝑃 is furthermore in shifts-Popov form. By default, 𝑃
is considered row-wise, that is, its rows are left-approximants for self; if row_wise is False then its
columns are right-approximants for self. It is guaranteed that the degree of the output basis is at most the
maximum of the entries of order, independently of shifts.
An error is raised if the input dimensions are not sound: if working row-wise (resp. column-wise), the lengthof order must be the number of columns (resp. rows) of self, while the length of shifts must be thenumber of rows (resp. columns) of self.
If a single integer is provided for order, then it is converted into a list of repeated integers with this value.
INPUT:• order – a list of positive integers, or a positive integer.

950

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

• shifts – (default: None) list of integers; None is interpreted as shifts=[0,...,0].
• row_wise – (default: True) boolean, if True then the output basis is considered row-wise and operates on the left of self; otherwise it is column-wise and operates on the right of self.
• normal_form – (default: False) boolean, if True then the output basis is in shifts-Popov form.
OUTPUT: a polynomial matrix.
ALGORITHM:
The implementation is inspired from the iterative algorithms described in [VBB1992] and [BL1994] ; forobtaining the normal form, it relies directly on Lemmas 3.3 and 4.1 in [JNSV2016] .
EXAMPLES:
sage: pR.<x> = GF(7)[]sage: order = [4, 3]; shifts = [-1, 2, 0]
sage: F = Matrix(pR, [[5*x^3 + 4*x^2 + 4*x + 6, 5*x^2 + 4*x + 1],....:[
2*x^2 + 2*x + 3, 6*x^2 + 6*x + 3],....:[4*x^3+x + 1, 4*x^2 + 2*x + 3]])sage: P = F.minimal_approximant_basis(order, shifts)
sage: P.is_minimal_approximant_basis(F, order, shifts)
True>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> order = [Integer(4), Integer(3)]; shifts = [-Integer(1), Integer(2),␣
˓→Integer(0)]>>> F = Matrix(pR, [[Integer(5)*x**Integer(3) + Integer(4)*x**Integer(2) +␣˓→Integer(4)*x + Integer(6), Integer(5)*x**Integer(2) + Integer(4)*x +␣˓→Integer(1)],...
[Integer(2)*x**Integer(2) + Integer(2)*x +␣˓→Integer(3), Integer(6)*x**Integer(2) + Integer(6)*x + Integer(3)],...
[Integer(4)*x**Integer(3)+x + Integer(1),␣
˓→Integer(4)*x**Integer(2) + Integer(2)*x + Integer(3)]])>>> P = F.minimal_approximant_basis(order, shifts)>>> P.is_minimal_approximant_basis(F, order, shifts)
True

By default, the computed basis is not required to be in normal form (and will not be except in rare special
cases):
sage: P.is_minimal_approximant_basis(F, order, shifts,....:
normal_form=True)
False
sage: P = F.minimal_approximant_basis(order, shifts,....:
normal_form=True)
sage: P.is_minimal_approximant_basis(F, order, shifts,....:
normal_form=True)
True>>> from sage.all import *>>> P.is_minimal_approximant_basis(F, order, shifts,...
normal_form=True)
False>>> P = F.minimal_approximant_basis(order, shifts,(continues on next page)951

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
normal_form=True)>>> P.is_minimal_approximant_basis(F, order, shifts,...
normal_form=True)
True

If shifts are not specified, they are chosen as uniform [0, . . . , 0] by default. Besides, if the orders are all thesame, one can rather give a single integer:
sage: (F.minimal_approximant_basis(3) ==....: F.minimal_approximant_basis([3,3], shifts=None))True>>> from sage.all import *>>> (F.minimal_approximant_basis(Integer(3)) ==... F.minimal_approximant_basis([Integer(3),Integer(3)], shifts=None))True

One can work column-wise by specifying row_wise=False:
sage: P = F.minimal_approximant_basis([5,2,2], [0,1],....:
row_wise=False)
sage: P.is_minimal_approximant_basis(F, [5,2,2], shifts=[0,1],....:
row_wise=False)
True
sage: (F.minimal_approximant_basis(3, row_wise=True) ==....: F.transpose().minimal_approximant_basis(....:
3, row_wise=False).transpose())
True>>> from sage.all import *>>> P = F.minimal_approximant_basis([Integer(5),Integer(2),Integer(2)],␣
˓→[Integer(0),Integer(1)],...
row_wise=False)>>> P.is_minimal_approximant_basis(F, [Integer(5),Integer(2),Integer(2)],␣
˓→shifts=[Integer(0),Integer(1)],...
row_wise=False)
True>>> (F.minimal_approximant_basis(Integer(3), row_wise=True) ==... F.transpose().minimal_approximant_basis(...
Integer(3), row_wise=False).transpose())
True

Errors are raised if the input dimensions are not sound:sage: P = F.minimal_approximant_basis([4], shifts)
Traceback (most recent call last):...
ValueError: order length should be the column dimension
sage: P = F.minimal_approximant_basis(order, [0,0,0,0])Traceback (most recent call last):...
ValueError: shifts length should be the row dimension

952

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> P = F.minimal_approximant_basis([Integer(4)], shifts)
Traceback (most recent call last):...
ValueError: order length should be the column dimension>>> P = F.minimal_approximant_basis(order, [Integer(0),Integer(0),Integer(0),˓→Integer(0)])
Traceback (most recent call last):...
ValueError: shifts length should be the row dimension

An error is raised if order does not contain only positive integers:
sage: P = F.minimal_approximant_basis([1,0], shifts)
Traceback (most recent call last):...
ValueError: order should consist of positive integers>>> from sage.all import *>>> P = F.minimal_approximant_basis([Integer(1),Integer(0)], shifts)
Traceback (most recent call last):...
ValueError: order should consist of positive integers

minimal_kernel_basis(shifts=None, row_wise=True, normal_form=False)
Return a left kernel basis in shifts-ordered weak Popov form for this polynomial matrix.
Assuming we work row-wise, if 𝐹 is an 𝑚×𝑛 polynomial matrix, then a left kernel basis for 𝐹 is a polynomial
matrix whose rows form a basis of the left kernel of 𝐹 , which is the module of polynomial vectors 𝑝 of size𝑚 such that 𝑝𝐹 is zero.
If normal_form is True, then the output basis 𝑃 is furthermore in shifts-Popov form. By default, 𝑃
is considered row-wise, that is, its rows are left kernel vectors for self; if row_wise is False then its
columns are right kernel vectors for self.
An error is raised if the input dimensions are not sound: if working row-wise (resp. column-wise), the lengthof shifts must be the number of rows (resp. columns) of self.
INPUT:• shifts – (default: None) list of integers; None is interpreted as shifts=[0,...,0].
• row_wise – (default: True) boolean, if True then the output basis considered row-wise and operates
on the left of self; otherwise it is column-wise and operates on the right of self.
• normal_form – (default: False) boolean, if True then the output basis is in shifts-Popov form.
OUTPUT: a polynomial matrix.
ALGORITHM: uses minimal approximant basis computation at a sufficiently large order so that the approximant basis contains a kernel basis as a submatrix.
EXAMPLES:
sage: pR.<x> = GF(7)[]sage: pmat = Matrix([[(x+1)*(x+3)], [(x+1)*(x+3)+1]])
sage: pmat.minimal_kernel_basis()[6*x^2 + 3*x + 3
x^2 + 4*x + 3]
(continues on next page)953

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: pmat = Matrix([[(x+1)*(x+3)], [(x+1)*(x+4)]])sage: pmat.minimal_kernel_basis()[6*x + 3
x + 3]
sage: pmat.minimal_kernel_basis(row_wise=False)[]
sage: pmat = Matrix(pR, [[1, x, x**2]])
sage: pmat.minimal_kernel_basis(row_wise=False, normal_form=True)
[x 0]
[6 x]
[0 6]
sage: pmat.minimal_kernel_basis(row_wise=False, normal_form=True,....:
shifts=[0,1,2])[ 6*x 6*x^2]
[
1
0]
[
0
1]
>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> pmat = Matrix([[(x+Integer(1))*(x+Integer(3))],␣
˓→[(x+Integer(1))*(x+Integer(3))+Integer(1)]])>>> pmat.minimal_kernel_basis()[6*x^2 + 3*x + 3
x^2 + 4*x + 3]>>> pmat = Matrix([[(x+Integer(1))*(x+Integer(3))],␣
˓→[(x+Integer(1))*(x+Integer(4))]])>>> pmat.minimal_kernel_basis()[6*x + 3
x + 3]>>> pmat.minimal_kernel_basis(row_wise=False)[]>>> pmat = Matrix(pR, [[Integer(1), x, x**Integer(2)]])>>> pmat.minimal_kernel_basis(row_wise=False, normal_form=True)
[x 0]
[6 x]
[0 6]
>>> pmat.minimal_kernel_basis(row_wise=False, normal_form=True,...
shifts=[Integer(0),Integer(1),Integer(2)])[ 6*x 6*x^2]
[
1
0]
[
0
1]

Some particular cases (matrix is zero, dimension is zero, column is zero):sage: Matrix(pR, 2, 1).minimal_kernel_basis()
[1 0]
[0 1]
sage: Matrix(pR, 2, 0).minimal_kernel_basis()
[1 0]
[0 1]
(continues on next page)954

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: Matrix(pR, 0, 2).minimal_kernel_basis()[]
sage: Matrix(pR, 3, 2, [[1,0],[1,0],[1,0]]).minimal_kernel_basis()[6 1 0][6 0 1]
sage: Matrix(pR, 3, 2, [[x,0],[1,0],[x+1,0]]).minimal_kernel_basis()[6 x 0][6 6 1]>>> from sage.all import *>>> Matrix(pR, Integer(2), Integer(1)).minimal_kernel_basis()
[1 0]
[0 1]
>>> Matrix(pR, Integer(2), Integer(0)).minimal_kernel_basis()
[1 0]
[0 1]
>>> Matrix(pR, Integer(0), Integer(2)).minimal_kernel_basis()[]>>> Matrix(pR, Integer(3), Integer(2), [[Integer(1),Integer(0)],[Integer(1),˓→Integer(0)],[Integer(1),Integer(0)]]).minimal_kernel_basis()[6 1 0][6 0 1]>>> Matrix(pR, Integer(3), Integer(2), [[x,Integer(0)],[Integer(1),˓→Integer(0)],[x+Integer(1),Integer(0)]]).minimal_kernel_basis()[6 x 0][6 6 1]

popov_form(transformation=False, shifts=None, row_wise=True, include_zero_vectors=True)
Return the (shifted) Popov form of this matrix.
See is_popov() for a definition of Popov forms. If the input matrix is 𝐴, the (shifted) Popov form of
𝐴 is the unique matrix 𝑃 in (shifted) Popov form and such that 𝑈 𝐴 = 𝑃 for some unimodular matrix 𝑈 .
The latter matrix is called the transformation, and the first optional argument allows one to specify whether
to return this transformation. We refer to the description of weak_popov_form() for an explanation of
the option include_zero_vectors .
INPUT:• transformation – (default: False). If this is True, the transformation matrix 𝑈 will be returned
as well.
• shifts – (default: None) list of integers; None is interpreted as shifts=[0,...,0].
• row_wise – (default: True) boolean, True if working row-wise (see the class description).
• include_zero_vectors – (default: True) boolean, False if zero rows (resp. zero columns)
should be discarded from the Popov forms.
OUTPUT:• A polynomial matrix which is the Popov form of self if transformation is False; otherwise955

Matrices and Spaces of Matrices, Release 10.4

two polynomial matrices which are the Popov form of self and the corresponding unimodular transformation.
ALGORITHM:
This method implements the Mulders-Storjohann algorithm of [MS2003] for transforming a weak Popovform into Popov form, straightforwardly extended to the case of shifted forms.
EXAMPLES:
sage: pR.<x> = GF(7)[]sage: M = Matrix(pR, [....:[6*x+4,
5*x^3+5*x,
6*x^2+2*x+2],....:[4*x^2+5*x+2, x^4+5*x^2+2*x+4, 4*x^3+6*x^2+6*x+5]])
sage: # needs sage.combinat
sage: P, U = M.popov_form(transformation=True)
sage: P[
4 x^2 + 4*x + 1
3][0
4*x + 1 x^2 + 6*x + 1]
sage: U[x2]
[5*x^2 + x + 6
3*x + 2]sage: P.is_popov() and U.is_invertible() and U*M == P
True>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> M = Matrix(pR, [...
[Integer(6)*x+Integer(4),␣˓→Integer(5)*x**Integer(3)+Integer(5)*x,␣
˓→Integer(6)*x**Integer(2)+Integer(2)*x+Integer(2)],...
[Integer(4)*x**Integer(2)+Integer(5)*x+Integer(2),␣
˓→x**Integer(4)+Integer(5)*x**Integer(2)+Integer(2)*x+Integer(4),␣
˓→Integer(4)*x**Integer(3)+Integer(6)*x**Integer(2)+Integer(6)*x+Integer(5)]])>>> # needs sage.combinat>>> P, U = M.popov_form(transformation=True)>>> P[
4 x^2 + 4*x + 1
3][0
4*x + 1 x^2 + 6*x + 1]
>>> U
[
x
2]
[5*x^2 + x + 6
3*x + 2]>>> P.is_popov() and U.is_invertible() and U*M == P
True

Demonstrating shifts and specific case of Hermite form:
sage: # needs sage.combinat
sage: P = M.popov_form(shifts=[0,2,4]); P[
4*x^2 + 3*x + 4 x^4 + 3*x^3 + 5*x^2 + 5*x + 5
˓→
0]
[
6
5*x^2 + 6*x + 5
˓→1]
sage: P.is_popov(shifts=[0,2,4])
True
sage: P == M.popov_form(shifts=[-6,-4,-2])
True

␣
␣

(continues on next page)

956

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: dd = sum(M.row_degrees()) + 1
sage: M.popov_form(shifts=[2*dd,dd,0]) == M.hermite_form()True>>> from sage.all import *>>> # needs sage.combinat>>> P = M.popov_form(shifts=[Integer(0),Integer(2),Integer(4)]); P[
4*x^2 + 3*x + 4 x^4 + 3*x^3 + 5*x^2 + 5*x + 5
˓→
0]
[
6
5*x^2 + 6*x + 5
˓→1]>>> P.is_popov(shifts=[Integer(0),Integer(2),Integer(4)])
True>>> P == M.popov_form(shifts=[-Integer(6),-Integer(4),-Integer(2)])
True>>> dd = sum(M.row_degrees()) + Integer(1)>>> M.popov_form(shifts=[Integer(2)*dd,dd,Integer(0)]) == M.hermite_form()
True

␣
␣

Column-wise form is the row-wise form of the transpose:
sage: M.popov_form() == M.T.popov_form(row_wise=False).T
True>>> from sage.all import *>>> M.popov_form() == M.T.popov_form(row_wise=False).T
True

Zero vectors can be discarded:sage: M.popov_form(row_wise=False)[x + 2
6
0]
[
0
1
0]
sage: # needs sage.combinat
sage: P, U = M.popov_form(transformation=True,....:
row_wise=False,....:
include_zero_vectors=False)
sage: P[x + 26][0
1]
sage: U[
3*x^2 + 6*x + 3
5*x^2 + 4*x + 4 3*x^3 + 3*x^2 + 2*x + 4][
31
2*x + 1][
5*x + 22
6]sage: M*U[:,:2] == P and (M*U[:,2]).is_zero()True>>> from sage.all import *>>> M.popov_form(row_wise=False)[x + 2
6
0]
[
0
1
0]
>>> # needs sage.combinat>>> P, U = M.popov_form(transformation=True,(continues on next page)957

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
row_wise=False,...
include_zero_vectors=False)>>> P[x + 2
6]
[
0
1]
>>> U
[
3*x^2 + 6*x + 3
5*x^2 + 4*x + 4 3*x^3 + 3*x^2 + 2*x + 4][
31
2*x + 1][
5*x + 2
2
6]>>> M*U[:,:Integer(2)] == P and (M*U[:,Integer(2)]).is_zero()
True

See also:
is_popov() , reduced_form() , weak_popov_form() , hermite_form() .
reduce(B, shifts=None, row_wise=True, return_quotient=False)
Reduce self, i.e. compute its normal form, modulo the row space of 𝐵 with respect to shifts.
If self is a 𝑘 × 𝑛 polynomial matrix (written 𝐴 below), and the input 𝐵 is an 𝑚 × 𝑛 polynomial matrix,
this computes the normal form 𝑅 of 𝐴 with respect the row space of 𝐵 and the monomial order defined byshifts (written 𝑠 below). This means that the 𝑖 th row of 𝑅 is equal to the 𝑖 th row of 𝐴 up to addition ofan element in the row space of 𝐵, and if 𝐽 = (𝑗1 , . . . , 𝑗𝑟 ) are the 𝑠-leading positions of the 𝑠-Popov form
𝑃 of 𝐴, then the submatrix 𝑅*,𝐽 (submatrix of 𝑅 formed by its columns in 𝐽) has column degrees smaller
entrywise than the column degrees of 𝑃*,𝐽 .
If the option row_wise is set to False, the same operation is performed, but with everything consideredcolumn-wise: column space of 𝐵, 𝑖 th column of 𝑅 and 𝐴, column-wise 𝑠-leading positions and 𝑠-Popovform, and submatrices 𝑅𝐽,* and 𝑃𝐽,* .
The operation above can be seen as a matrix generalization of division with remainder for univariate polynomials. If the option return_quotient is set to True, this method returns both the normal form 𝑅
and a quotient matrix 𝑄 such that 𝐴 = 𝑄𝐵 + 𝑅 (or 𝐴 = 𝐵𝑄 + 𝑅 if row_wise is False). Whereas
the remainder is unique, this quotient is not unique unless 𝐵 has a trivial left kernel i.e. has full row rank (orright kernel, full column rank if row_wise is False).
This method checks whether 𝐵 is in 𝑠-Popov form, and if not, computes the 𝑠-Popov form 𝑃 of 𝐵, which cantake some time. Therefore, if 𝑃 is already known or is to be re-used, this method should be called directlywith 𝑃 , yielding the same normal form 𝑅 since 𝑃 and 𝐵 have the same row space (or column space, if
row_wise is False).
A ValueError is raised if the dimensions of the shifts and/or of the matrices are not conformal.
INPUT:• B – polynomial matrix.
• shifts – (default: None) list of integers; None is interpreted as shifts=[0,...,0].
• row_wise – (default: True) boolean, True if working row-wise (see the class description).
• return_quotient – (default: False). If this is True, the quotient will be returned as well.
OUTPUT: a polynomial matrix if return_quotient=False, two polynomial matrices otherwise.
EXAMPLES:
sage: pR.<x> = GF(7)[]sage: B = Matrix(pR, [....:[6*x+4,

5*x^3+5*x,

6*x^2+2*x+2],(continues on next page)

958

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)....:[4*x^2+5*x+2, x^4+5*x^2+2*x+4, 4*x^3+6*x^2+6*x+5]])
sage: A = Matrix(pR, 1, 3, [....:[3*x^4+3*x^3+4*x^2+5*x+1, x^4+x^3+5*x^2+4*x+4, 4*x^4+2*x^3+x]])
sage: Q, R = A.reduce(B,return_quotient=True); R[3*x^4 + 3*x^3 + 4*x + 3
2*x + 2
2*x + 6]sage: A == Q*B + R
True
sage: P = B.popov_form(); P.leading_positions(return_degree=True)([1, 2], [2, 2])
sage: R.degree_matrix()[4 1 1]
sage: A.reduce(P) == R
True
sage: A.reduce(P[:,:2])Traceback (most recent call last):...
ValueError: column dimension of self should be the column
dimension of the input matrix>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> B = Matrix(pR, [...
[Integer(6)*x+Integer(4),␣˓→Integer(5)*x**Integer(3)+Integer(5)*x,␣
˓→Integer(6)*x**Integer(2)+Integer(2)*x+Integer(2)],...
[Integer(4)*x**Integer(2)+Integer(5)*x+Integer(2),␣
˓→x**Integer(4)+Integer(5)*x**Integer(2)+Integer(2)*x+Integer(4),␣
˓→Integer(4)*x**Integer(3)+Integer(6)*x**Integer(2)+Integer(6)*x+Integer(5)]])>>> A = Matrix(pR, Integer(1), Integer(3), [...
[Integer(3)*x**Integer(4)+Integer(3)*x**Integer(3)+Integer(4)*x**Integer(2)+Integer(5)*x+Integer(1),␣
˓→x**Integer(4)+x**Integer(3)+Integer(5)*x**Integer(2)+Integer(4)*x+Integer(4),˓→ Integer(4)*x**Integer(4)+Integer(2)*x**Integer(3)+x]])>>> Q, R = A.reduce(B,return_quotient=True); R[3*x^4 + 3*x^3 + 4*x + 3
2*x + 2>>> A == Q*B + R
True>>> P = B.popov_form(); P.leading_positions(return_degree=True)([1, 2], [2, 2])>>> R.degree_matrix()[4 1 1]>>> A.reduce(P) == R
True>>> A.reduce(P[:,:Integer(2)])
Traceback (most recent call last):...
ValueError: column dimension of self should be the column
dimension of the input matrix

2*x + 6]

Demonstrating shifts:
sage: Qs, Rs = A.reduce(B, shifts=[0,2,4], return_quotient=True); Rs[3*x^4 + 3*x^3 + 6*x + 2
4*x^3 + 5*x
sage: A == Qs*B + Rs

0](continues on next page)959

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)True
sage: Ps = B.popov_form(shifts=[0,2,4])
sage: Ps.leading_positions(shifts=[0,2,4], return_degree=True)([1, 2], [4, 0])
sage: Rs.degree_matrix()[ 4 3 -1]
sage: A.reduce(Ps, shifts=[0,2,4]) == Rs
True>>> from sage.all import *>>> Qs, Rs = A.reduce(B, shifts=[Integer(0),Integer(2),Integer(4)], return_
˓→quotient=True); Rs[3*x^4 + 3*x^3 + 6*x + 2
4*x^3 + 5*x
0]>>> A == Qs*B + Rs
True>>> Ps = B.popov_form(shifts=[Integer(0),Integer(2),Integer(4)])>>> Ps.leading_positions(shifts=[Integer(0),Integer(2),Integer(4)], return_˓→degree=True)([1, 2], [4, 0])>>> Rs.degree_matrix()[ 4 3 -1]>>> A.reduce(Ps, shifts=[Integer(0),Integer(2),Integer(4)]) == Rs
True

If return_quotient is False, only the normal form is returned:
sage: R == A.reduce(B) and Rs == A.reduce(B, shifts=[0,2,4])
True>>> from sage.all import *>>> R == A.reduce(B) and Rs == A.reduce(B, shifts=[Integer(0),Integer(2),˓→Integer(4)])
True

Demonstrating column-wise normal forms, with a matrix 𝐴 which has several columns, and a matrix 𝐵 which
does not have full column rank (its column-wise Popov form has a zero column):
sage: A = Matrix(pR, 2, 2,....:[[5*x^3 + 2*x^2 + 4*x + 1,x^3 + 4*x + 4],....:[2*x^3 + 5*x^2 + 2*x + 4,
2*x^3 + 3*x + 2]])sage: (Q,R) = A.reduce(B,row_wise=False, return_quotient=True); R
[0 3]
[0 0]
sage: A == B*Q + R
True
sage: P = B.popov_form(row_wise=False); P[x + 2
6
0]
[
0
1
0]
sage: P.leading_positions(row_wise=False, return_degree=True)([0, 1, -1], [1, 0, -1])
sage: R.degree_matrix()[-1 0][-1 -1]>>> from sage.all import *(continues on next page)

960

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> A = Matrix(pR, Integer(2), Integer(2),...
[[Integer(5)*x**Integer(3) + Integer(2)*x**Integer(2) + Integer(4)*x␣
˓→+ Integer(1),x**Integer(3) + Integer(4)*x + Integer(4)],...
[Integer(2)*x**Integer(3) + Integer(5)*x**Integer(2) + Integer(2)*x␣
˓→+ Integer(4),Integer(2)*x**Integer(3) + Integer(3)*x +␣˓→Integer(2)]])>>> (Q,R) = A.reduce(B,row_wise=False, return_quotient=True); R
[0 3]
[0 0]
>>> A == B*Q + R
True>>> P = B.popov_form(row_wise=False); P[x + 2
6
0]
[
0
1
0]
>>> P.leading_positions(row_wise=False, return_degree=True)([0, 1, -1], [1, 0, -1])>>> R.degree_matrix()[-1 0][-1 -1]

See also:
left_quo_rem() , right_quo_rem() .
reduced_form(transformation=None, shifts=None, row_wise=True, include_zero_vectors=True)
Return a row reduced form of this matrix (resp. a column reduced form if the optional parameter row_wise
is set to False).
An 𝑚 × 𝑛 univariate polynomial matrix 𝑀 is said to be in (shifted) row reduced form if it has 𝑘 nonzero
rows with 𝑘 ≤ 𝑛 and its (shifted) leading matrix has rank 𝑘. See is_reduced() for more information.
Currently, the implementation of this method is a direct call to weak_popov_form().
INPUT:• transformation – (default: False). If this is True, the transformation matrix 𝑈 will be returned
as well: this is a unimodular matrix over [𝑥] such that self equals 𝑈 𝑅, where 𝑅 is the output matrix.
• shifts – (default: None) list of integers; None is interpreted as shifts=[0,...,0].
• row_wise – (default: True) boolean, True if working row-wise (see the class description).
• include_zero_vectors – (default: True) boolean, False if one does not allow zero rows inrow reduced forms (resp. zero columns in column reduced forms).
OUTPUT:• A polynomial matrix 𝑅 which is a reduced form of self if transformation=False; otherwise
two polynomial matrices 𝑅, 𝑈 such that 𝑈 𝐴 = 𝑅 and 𝑅 is reduced and 𝑈 is unimodular where 𝐴 is
self.
EXAMPLES:
sage: pR.<x> = GF(3)[]sage: A = matrix(pR, 3, [x,x^2, x^3,....:
x^2, x^1, 0,....:x^3, x^3, x^3])
sage: R = A.reduced_form(); R
[
x
x^2
x^3]
[
x^2
x
0]
(continues on next page)961

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ x^3 + 2*x x^3 + 2*x^20]sage: R.is_reduced()True
sage: R2 = A.reduced_form(shifts=[6,3,0]); R2
[
x
x^2
x^3]
[
0
2*x^2 + x
2*x^4 + x^3][00 2*x^5 + x^4 + x^3]
sage: R2.is_reduced(shifts=[6,3,0])
True
sage: R2.is_reduced()
False>>> from sage.all import *>>> pR = GF(Integer(3))[ x ]; (x,) = pR._first_ngens(1)>>> A = matrix(pR, Integer(3), [x,x**Integer(2), x**Integer(3),...
x**Integer(2), x**Integer(1), Integer(0),...
x**Integer(3), x**Integer(3), x**Integer(3)])>>> R = A.reduced_form(); R
[
x
x^2
x^3]
[
x^2
x
0]
[ x^3 + 2*x x^3 + 2*x^20]>>> R.is_reduced()
True>>> R2 = A.reduced_form(shifts=[Integer(6),Integer(3),Integer(0)]); R2
[
x
x^2
x^3]
[
0
2*x^2 + x
2*x^4 + x^3][00 2*x^5 + x^4 + x^3]>>> R2.is_reduced(shifts=[Integer(6),Integer(3),Integer(0)])
True>>> R2.is_reduced()
False

If the matrix is an 𝑛 × 1 matrix with at least one non-zero entry, 𝑅 has a single non-zero entry and that entry
is a scalar multiple of the greatest-common-divisor of the entries of the matrix:
sage: A = matrix([[x*(x-1)*(x+1)], [x*(x-2)*(x+2)], [x]])sage: R = A.reduced_form()
sage: R[x]
[0][0]>>> from sage.all import *>>> A = matrix([[x*(x-Integer(1))*(x+Integer(1))], [x*(x˓→Integer(2))*(x+Integer(2))], [x]])>>> R = A.reduced_form()
>>> R
[x]
[0]
[0]

A zero matrix is already reduced:
sage: A = matrix(pR, 2, [0,0,0,0])
sage: A.reduced_form()[0 0](continues on next page)

962

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 0]>>> from sage.all import *>>> A = matrix(pR, Integer(2), [Integer(0),Integer(0),Integer(0),Integer(0)])>>> A.reduced_form()
[0 0]
[0 0]

In the following example, the original matrix is already reduced, but the output is a different matrix: currently
this method is an alias for weak_popov_form(), which is a stronger reduced form:
sage: R.<x> = QQ[ x ]sage: A = matrix([[x,x,x],[0,0,x]]); A[x x x][0 0 x]sage: A.is_reduced()True
sage: W = A.reduced_form(); W[ x x x][-x -x 0]
sage: W.is_weak_popov()
True>>> from sage.all import *>>> R = QQ[ x ]; (x,) = R._first_ngens(1)>>> A = matrix([[x,x,x],[Integer(0),Integer(0),x]]); A[x x x][0 0 x]>>> A.is_reduced()
True>>> W = A.reduced_form(); W[ x x x][-x -x 0]>>> W.is_weak_popov()
True

The last example shows the usage of the transformation parameter:
sage: # needs sage.rings.finite_rings
sage: Fq.<a> = GF(2^3)
sage: pR.<x> = Fq[]sage: A = matrix(pR, [[x^2+a, x^4+a],....:[ x^3, a*x^4]])sage: W, U = A.reduced_form(transformation=True)
sage: W, U([
x^2 + ax^4 + a] [1 0][x^3 + a*x^2 + a^2a^2], [a 1])sage: W.is_reduced()True
sage: U*W == A
True
sage: U.is_invertible()
True

963

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> # needs sage.rings.finite_rings>>> Fq = GF(Integer(2)**Integer(3), names=( a ,)); (a,) = Fq._first_ngens(1)>>> pR = Fq[ x ]; (x,) = pR._first_ngens(1)>>> A = matrix(pR, [[x**Integer(2)+a, x**Integer(4)+a],...
[ x**Integer(3), a*x**Integer(4)]])>>> W, U = A.reduced_form(transformation=True)>>> W, U([x^2 + ax^4 + a] [1 0][x^3 + a*x^2 + a^2a^2], [a 1])>>> W.is_reduced()True>>> U*W == A
True>>> U.is_invertible()True

See also:
is_reduced() , weak_popov_form() , popov_form() , hermite_form() .
reverse(degree=None, row_wise=True, entry_wise=False)
Return the matrix which is obtained from this matrix after reversing all its entries with respect to the degree
as specified by degree.
Reversing a polynomial with respect to an integer 𝑑 follows the convention for univariate polynomials, inparticular it uses truncation or zero-padding as necessary if 𝑑 differs from the degree of this polynomial.
If entry_wise is True: the input degree and row_wise are ignored, and all entries of the matrix arereversed with respect to their respective degrees.
If entry_wise is False (the default):• if degree is an integer, all entries are reversed with respect to it;• if degree is not provided, then all entries are reversed with respect to the degree of the whole matrix;• if degree is a list (𝑑1 , . . . , 𝑑𝑚 ) and row_wise𝑖`𝑡ℎ𝑟𝑜𝑤𝑎𝑟𝑒𝑟𝑒𝑣𝑒𝑟𝑠𝑒𝑑𝑤𝑖𝑡ℎ𝑟𝑒𝑠𝑝𝑒𝑐𝑡𝑡𝑜`𝑑𝑖 for each 𝑖;

is

True,

• if degree is a list (𝑑1 , . . . , 𝑑𝑛 ) and row_wise is False,𝑗`𝑡ℎ𝑐𝑜𝑙𝑢𝑚𝑛𝑎𝑟𝑒𝑟𝑒𝑣𝑒𝑟𝑠𝑒𝑑𝑤𝑖𝑡ℎ𝑟𝑒𝑠𝑝𝑒𝑐𝑡𝑡𝑜`𝑑𝑗 for each 𝑗.

all

entriesoftheall entries of the

INPUT:• degree – (default: None) a list of nonnegative integers, or a nonnegative integer,• row_wise – (default: True) boolean, if True (resp. False) then degree should be a list of length
equal to the row (resp. column) dimension of this matrix.
• entry_wise – (default: False) boolean, if True then the input degree and row_wise are
ignored.
OUTPUT: a polynomial matrix.
EXAMPLES:
sage: pR.<x> = GF(7)[]sage: M = Matrix([(continues on next page)

964

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)....:[ x^3+5*x^2+5*x+1,
5,
6*x+4,
0],....:[
6*x^2+3*x+1,
1,
2,
0],
....:
[2*x^3+4*x^2+6*x+4, 5*x + 1, 2*x^2+5*x+5, x^2+5*x+6]....:])
sage: M.reverse()[ x^3 + 5*x^2 + 5*x + 1
5*x^3
4*x^3 +
6*x^2
0][x^3 + 3*x^2 + 6*x
x^3
2*x^3
0]
[4*x^3 + 6*x^2 + 4*x + 2
x^3 + 5*x^2
5*x^3 + 5*x^2+ 2*x
6*x^3 + 5*x^2 + x]
sage: M.reverse(1)[ x + 5
5*x 4*x + 6
0][ x + 3x
2*x
0]
[4*x + 6
x + 5 5*x + 5 6*x + 5]
sage: M.reverse(0) == M.constant_matrix()True>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> M = Matrix([...
[ x**Integer(3)+Integer(5)*x**Integer(2)+Integer(5)*x+Integer(1),␣˓→Integer(5),Integer(6)*x+Integer(4),Integer(0)],...
[Integer(6)*x**Integer(2)+Integer(3)*x+Integer(1),␣˓→Integer(1),Integer(2),Integer(0)],...
␣˓→[Integer(2)*x**Integer(3)+Integer(4)*x**Integer(2)+Integer(6)*x+Integer(4),␣
˓→Integer(5)*x + Integer(1), Integer(2)*x**Integer(2)+Integer(5)*x+Integer(5),˓→ x**Integer(2)+Integer(5)*x+Integer(6)]...
])>>> M.reverse()[ x^3 + 5*x^2 + 5*x + 1
5*x^3
4*x^3 +
6*x^2
0][x^3 + 3*x^2 + 6*x
x^3
2*x^3
0]
[4*x^3 + 6*x^2 + 4*x + 2
x^3 + 5*x^2
5*x^3 + 5*x^2+ 2*x
6*x^3 + 5*x^2 + x]>>> M.reverse(Integer(1))[ x + 5
5*x 4*x + 6
0][ x + 3x
2*x
0]
[4*x + 6
x + 5 5*x + 5 6*x + 5]>>> M.reverse(Integer(0)) == M.constant_matrix()
True

Entry-wise reversing with respect to each entry’s degree:
sage: M.reverse(entry_wise=True)[ x^3 + 5*x^2 + 5*x + 1
4*x + 60][x^2 + 3*x + 6
2
0]

5
1
(continues on next page)965

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[4*x^3 + 6*x^2 + 4*x + 2
5*x + 2
6*x^2 + 5*x + 1]

x + 5>>> from sage.all import *>>> M.reverse(entry_wise=True)[ x^3 + 5*x^2 + 5*x + 1
4*x + 60][x^2 + 3*x + 62
0][4*x^3 + 6*x^2 + 4*x + 2
5*x + 2
6*x^2 + 5*x + 1]

5*x^2 +

51x + 5

5*x^2 +

Row-wise and column-wise degree reversing are available:
sage: M.reverse([2,3,1])[x^2 + 5*x + 5
0][x^3 + 3*x^2 + 6*x0][
4*x + 6
6*x + 5]

5*x^2

4*x^2 + 6*x

x^3

2*x^3

x + 5

5*x + 5sage: M.reverse(M.column_degrees(), row_wise=False)[ x^3 + 5*x^2 + 5*x + 1
5*x
+ 6*x
0]
[
x^3 + 3*x^2 + 6*x
x
2*x^2
0]
[4*x^3 + 6*x^2 + 4*x + 2
x + 5
5*x + 2
6*x^2 + 5*x + 1]

4*x^2

5*x^2 +>>> from sage.all import *>>> M.reverse([Integer(2),Integer(3),Integer(1)])[
x^2 + 5*x + 5
5*x^2
4*x^2 + 6*x0][x^3 + 3*x^2 + 6*x
x^3
2*x^3
0]
[
4*x + 6x + 5
5*x + 5
6*x + 5]>>> M.reverse(M.column_degrees(), row_wise=False)[ x^3 + 5*x^2 + 5*x + 1
5*x
+ 6*x
0]
[
x^3 + 3*x^2 + 6*x
x
2*x^2
0]
[4*x^3 + 6*x^2 + 4*x + 2
x + 5
5*x + 2
6*x^2 + 5*x + 1]

4*x^2

5*x^2 +

Wrong length or negativity of input degree raise errors:
sage: M.reverse([1,3,1,4]) Traceback (most recent call last): … ValueError: length of input degree
list should be the row dimension of the input matrix
sage: M.reverse([5,2,1], row_wise=False) Traceback (most recent call last): … ValueError: lengthof input degree list should be the column dimension of the input matrix
sage: M.reverse([2,3,-1]) Traceback (most recent call last): … ValueError: degree argument must
be a non-negative integer, got -1

966

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

See also:
sage.rings.polynomial.polynomial_element.Polynomial.reverse() .
right_quo_rem(B)Return, if it exists, the quotient and remainder (𝑄, 𝑅) such that self is 𝑄𝐵 + 𝑅, where 𝑅 has column
degrees less than those of 𝐵 entrywise.
If self is a 𝑘 × 𝑚 polynomial matrix (written 𝐴 below), and the input 𝐵 is an 𝑚 × 𝑚 polynomial matrix
in column reduced form, then (𝑄, 𝑅) is unique. Both 𝑄 and 𝑅 have dimensions 𝑘 × 𝑚. In this case, thismethod implements Newton iteration of a reversed polynomial matrix 𝐵, generalizing to matrices the fastdivision of univariate polynomials.
If 𝐴 is a 𝑘 × 𝑛 polynomial matrix, and the input 𝐵 is an 𝑚 × 𝑛 polynomial matrix such that 𝐵 has full column
rank, or more generally such that the matrix equation 𝐴 = 𝑋𝐵 has a rational solution, then there exists sucha (𝑄, 𝑅) but it may not be unique; the algorithm returns one such quotient and remainder. Here 𝑄 is 𝑘 × 𝑚
and 𝑅 is 𝑘 × 𝑛. In this case, this method follows the folklore approach based on solving the matrix equation
𝐴 = 𝑋𝐵 and splitting 𝑋 into its polynomial part and proper fraction part.
Finally, if the matrix equation 𝐴 = 𝑋𝐵 has no rational solution, this method computes the normal form
𝑅 and quotient 𝑄 of the rows of 𝐴 with respect to the row space of 𝐵 (see reduce()). Doing this for awell-chosen shift ensures that either 𝑅 does not have column degrees less than those of 𝐵, and then there isno valid quotient and remainder, or it does satisfy this degree constraint, and then this 𝑅 can be returned asa remainder along with the quotient 𝑄.
A ValueError is raised if the dimensions of self and 𝐵 are not conformal, or if there exists no quotient
and remainder.
EXAMPLES:
Case where 𝐵 is a square, column reduced matrix:
sage: pR.<x> = GF(7)[]sage: A = Matrix(pR, 2, 3,....:[[3*x^3 + 3*x, 3*x^3 + 6*x + 5,
2*x^3 + 2*x + 6],....:[2*x^3 + 4,
6*x^3 + 5*x^2 + 1, 3*x^2 + 2*x + 2]])sage: B = Matrix(pR, 3, 3,....:[[4*x^2 + 3*x + 3, 3*x^2 + 3*x + 1,
4*x^2 + x + 4],....:[6*x^2 + 2*x + 3,
4*x^2 + 3*x,3*x^2 + 4*x],....:[5*x^2 + 3*x + 6,
6*x^2 + x + 4, 3*x^2 + 3*x + 2]])sage: B.is_reduced(row_wise=False)
True
sage: Q, R = A.right_quo_rem(B); Q, R([
4*x
x + 2 6*x + 1] [ x + 2 6*x + 1 5*x + 4]
[4*x + 3
x + 6 3*x + 4], [4*x + 2 2*x + 3 4*x + 3])
sage: A == Q*B+R and R.degree() < 2
Truesage: A[:,:2].right_quo_rem(B)Traceback (most recent call last):...
ValueError: column dimension of self should be the column dimensionof the input matrix
sage: B = Matrix(pR, 3, 3,
....:
[[3,
3*x^3 + 3*x + 1, 4*x^2 + x + 4],....:[x + 3, 4*x^2 + 3*x,3*x^2 + 4*x],
....:
[6,
6*x^3 + x + 4,
3*x^2 + 3*x + 2]])
(continues on next page)967

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: B.is_reduced(row_wise=False)
True
sage: Q, R = A.right_quo_rem(B); Q, R(
[2*x^2 + 4*x + 6
3*x^2 + 5*x
6*x^2 + 3*x][6*x^2 + 4*x + 1
2*x^2 + x + 5 4*x^2 + 6*x + 1],[
3
6
2*x + 3][
1 5*x^2 + 2*x + 3
6*x + 3])sage: cdegR = R.column_degrees(); cdegB = B.column_degrees()
sage: A == Q*B+R and all([cdegR[i] < cdegB[i] for i in range(3)])
True>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> A = Matrix(pR, Integer(2), Integer(3),...
[[Integer(3)*x**Integer(3) + Integer(3)*x, Integer(3)*x**Integer(3) +␣˓→Integer(6)*x + Integer(5),Integer(2)*x**Integer(3) + Integer(2)*x +␣˓→Integer(6)],...
[Integer(2)*x**Integer(3) + Integer(4),Integer(6)*x**Integer(3) +␣˓→Integer(5)*x**Integer(2) + Integer(1), Integer(3)*x**Integer(2) +␣˓→Integer(2)*x + Integer(2)]])>>> B = Matrix(pR, Integer(3), Integer(3),...
[[Integer(4)*x**Integer(2) + Integer(3)*x + Integer(3),␣
˓→Integer(3)*x**Integer(2) + Integer(3)*x + Integer(1),␣˓→Integer(4)*x**Integer(2) + x + Integer(4)],...
[Integer(6)*x**Integer(2) + Integer(2)*x + Integer(3),␣˓→Integer(4)*x**Integer(2) + Integer(3)*x,
Integer(3)*x**Integer(2) +␣˓→Integer(4)*x],...
[Integer(5)*x**Integer(2) + Integer(3)*x + Integer(6), ␣
˓→Integer(6)*x**Integer(2) + x + Integer(4), Integer(3)*x**Integer(2) +␣˓→Integer(3)*x + Integer(2)]])>>> B.is_reduced(row_wise=False)
True>>> Q, R = A.right_quo_rem(B); Q, R([
4*x
x + 2 6*x + 1] [ x + 2 6*x + 1 5*x + 4]
[4*x + 3
x + 6 3*x + 4], [4*x + 2 2*x + 3 4*x + 3])>>> A == Q*B+R and R.degree() < Integer(2)True>>> A[:,:Integer(2)].right_quo_rem(B)Traceback (most recent call last):...
ValueError: column dimension of self should be the column dimensionof the input matrix>>> B = Matrix(pR, Integer(3), Integer(3),...
[[Integer(3),Integer(3)*x**Integer(3) + Integer(3)*x +␣˓→Integer(1), Integer(4)*x**Integer(2) + x + Integer(4)],...
[x + Integer(3), Integer(4)*x**Integer(2) + Integer(3)*x,
˓→Integer(3)*x**Integer(2) + Integer(4)*x],...
[Integer(6),Integer(6)*x**Integer(3) + x + Integer(4),˓→Integer(3)*x**Integer(2) + Integer(3)*x + Integer(2)]])>>> B.is_reduced(row_wise=False)␣␣(continues on next page)

968

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

True>>> Q, R = A.right_quo_rem(B); Q, R(
[2*x^2 + 4*x + 6
3*x^2 + 5*x
6*x^2 + 3*x][6*x^2 + 4*x + 1
2*x^2 + x + 5 4*x^2 + 6*x + 1],<BLANKLINE>[3
6
2*x + 3][
1 5*x^2 + 2*x + 3
6*x + 3])>>> cdegR = R.column_degrees(); cdegB = B.column_degrees()>>> A == Q*B+R and all([cdegR[i] < cdegB[i] for i in range(Integer(3))])
True

With a nonsingular but also non-reduced matrix, there exists a solution, but it might not be unique:sage: B = Matrix(pR, 3, 3,
....:
[[
5,
0, 2*x + 6],....:[
4*x, 3*x^2 + 4*x + 5,
x + 1],....:[3*x^2 + 5*x + 2, 6*x^3 + 4*x + 6,
3]])
sage: B.det() != 0 and (not B.is_reduced(row_wise=False))
True
sage: Q, R = A.right_quo_rem(B); Q, R([
6*x^2 + 3*x 4*x^2 + 3*x + 1
5*x + 1]
[ x^2 + 5*x + 5 5*x^2 + 3*x + 5
x + 2],[
4*x + 5 x^2 + 2*x + 1
2][
6*x + 35*x^2 + 6
3])
sage: cdegR = R.column_degrees(); cdegB = B.column_degrees()
sage: A == Q*B+R and all(cdegR[i] < cdegB[i] for i in range(3))
True
sage: Q2 = Matrix(pR, 2, 3,....:[[6*x^2 + 3*x + 1, 4*x^2 + 3*x + 6, 5*x + 1],....:[ x^2 + 5*x + 3, 5*x^2 + 3*x + 2,
x + 2]])
sage: R2 = Matrix(pR, 2, 3,....:[[
5*x, 3*x + 4, 5],....:[4*x + 6,
5*x, 4]])sage: A == Q2*B + R2
True>>> from sage.all import *>>> B = Matrix(pR, Integer(3), Integer(3),...
[[Integer(5),Integer(0), Integer(2)*x +␣˓→Integer(6)],...
[Integer(4)*x, Integer(3)*x**Integer(2) + Integer(4)*x +␣˓→Integer(5),x + Integer(1)],...
[Integer(3)*x**Integer(2) + Integer(5)*x + Integer(2),␣
˓→Integer(6)*x**Integer(3) + Integer(4)*x + Integer(6),Integer(3)]])>>> B.det() != Integer(0) and (not B.is_reduced(row_wise=False))
True>>> Q, R = A.right_quo_rem(B); Q, R([
6*x^2 + 3*x 4*x^2 + 3*x + 1
5*x + 1]
[ x^2 + 5*x + 5 5*x^2 + 3*x + 5
x + 2],(continues on next page)969

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)<BLANKLINE>[
4*x + 5 x^2 + 2*x + 1
2][
6*x + 35*x^2 + 6
3])>>> cdegR = R.column_degrees(); cdegB = B.column_degrees()>>> A == Q*B+R and all(cdegR[i] < cdegB[i] for i in range(Integer(3)))
True>>> Q2 = Matrix(pR, Integer(2), Integer(3),...
[[Integer(6)*x**Integer(2) + Integer(3)*x + Integer(1),␣
˓→Integer(4)*x**Integer(2) + Integer(3)*x + Integer(6), Integer(5)*x +␣˓→Integer(1)],...
[ x**Integer(2) + Integer(5)*x + Integer(3),␣
˓→Integer(5)*x**Integer(2) + Integer(3)*x + Integer(2),x + Integer(2)]])>>> R2 = Matrix(pR, Integer(2), Integer(3),...
[[Integer(5)*x, Integer(3)*x + Integer(4), Integer(5)],...
[Integer(4)*x + Integer(6),Integer(5)*x, Integer(4)]])>>> A == Q2*B + R2
True

The same remark holds more generally for full column rank matrices: there exists a solution, but it might not
be unique. However, for all other cases (rank-deficient matrix 𝐵 or matrix 𝐵 having strictly fewer rows thancolumns) there may be no solution:
sage: C = B.stack(B[1,:] + B[2,:]) # 4 x 3, full column rank
sage: Q, R = A.right_quo_rem(C); Q, R([
6*x^2 + 3*x 4*x^2 + 3*x + 1
5*x + 1
[ x^2 + 5*x + 5 5*x^2 + 3*x + 5
x + 2
[
[
)

4*x + 5 x^2 + 2*x + 1
6*x + 35*x^2 + 6

0]
0],

2]
3]

sage: A.right_quo_rem(B[:2,:]) # matrix 2 x 3, full row rank
˓→needs sage.rings.finite_rings
Traceback (most recent call last):...
ValueError: division of these matrices does not admit a remainder
with the required degree property
sage: D = copy(B); D[2,:] = B[0,:]+B[1,:] # square, singularsage: A.right_quo_rem(D)Traceback (most recent call last):...
ValueError: division of these matrices does not admit a remainder
with the required degree property>>> from sage.all import *>>> C = B.stack(B[Integer(1),:] + B[Integer(2),:])>>> Q, R = A.right_quo_rem(C); Q, R([
6*x^2 + 3*x 4*x^2 + 3*x + 1
5*x + 1
[ x^2 + 5*x + 5 5*x^2 + 3*x + 5
x + 2<BLANKLINE>[
4*x + 5 x^2 + 2*x + 1
2][
6*x + 35*x^2 + 63]#␣

# 4 x 3, full column rank0]0],(continues on next page)

970

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page))>>> A.right_quo_rem(B[:Integer(2),:]) # matrix 2 x 3, full row rank␣˓→
# needs sage.rings.finite_rings
Traceback (most recent call last):...
ValueError: division of these matrices does not admit a remainder
with the required degree property>>> D = copy(B); D[Integer(2),:] = B[Integer(0),:]+B[Integer(1),:] # square,␣
˓→singular>>> A.right_quo_rem(D)Traceback (most recent call last):...
ValueError: division of these matrices does not admit a remainder
with the required degree property

In the latter case (rank-deficient or strictly fewer rows than columns, with no solution to 𝐴 = 𝑋𝐵), there
might stil be a quotient and remainder, in which case this method will find it via normal form computation:
sage: B = Matrix(pR, 1, 2, [[x, x]])sage: A = Matrix(pR, 1, 2, [[x, x+2]])
sage: A.right_quo_rem(B)([1], [0 2])
sage: A == 1*B + Matrix([[0,2]])True>>> from sage.all import *>>> B = Matrix(pR, Integer(1), Integer(2), [[x, x]])>>> A = Matrix(pR, Integer(1), Integer(2), [[x, x+Integer(2)]])>>> A.right_quo_rem(B)([1], [0 2])>>> A == Integer(1)*B + Matrix([[Integer(0),Integer(2)]])
True

See also:
left_quo_rem() , reduce() .
row_degrees(shifts=None)
Return the (shifted) row degrees of this matrix.
For a given polynomial matrix 𝑀 = (𝑀𝑖,𝑗 )𝑖,𝑗 with 𝑚 rows and 𝑛 columns, its row degrees is the tuple(𝑑1 , . . . , 𝑑𝑚 ) where 𝑑𝑖 = max𝑗 (deg(𝑀𝑖,𝑗 )) for 1 ≤ 𝑖 ≤ 𝑚. Thus, 𝑑𝑖 = −1 if the 𝑖-th row of 𝑀 is zero,and 𝑑𝑖 ≥ 0 otherwise.
For given shifts 𝑠1 , . . . , 𝑠𝑛 ∈ Z, the shifted row degrees of 𝑀 is (𝑑1 , . . . , 𝑑𝑚 ) where 𝑑𝑖 = max𝑗 (deg(𝑀𝑖,𝑗 )+𝑠𝑗 ). Here, if the 𝑖-th row of 𝑀 is zero then 𝑑𝑖 = min(𝑠1 , . . . , 𝑠𝑛 ) − 1; otherwise, 𝑑𝑖 is larger than this value.
INPUT:• shifts – (default: None) list of integers; None is interpreted as shifts=[0,...,0].
OUTPUT: a list of integers.
REFERENCES:• [Wol1974] (Section 2.5, without shifts), and [VBB1992] (Section 3).
• Up to changes of signs, shifted row degrees coincide with the notion of defect commonly used in therational approximation literature (see for example [Bec1992] ).
971

Matrices and Spaces of Matrices, Release 10.4

EXAMPLES:
sage: pR.<x> = GF(7)[]sage: M = Matrix(pR, [[3*x+1, 0, 1], [x^3+3, 0, 0]])sage: M.row_degrees()[1, 3]
sage: M.row_degrees(shifts=[0,1,2])[2, 3]>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> M = Matrix(pR, [[Integer(3)*x+Integer(1), Integer(0), Integer(1)],␣
˓→[x**Integer(3)+Integer(3), Integer(0), Integer(0)]])>>> M.row_degrees()[1, 3]>>> M.row_degrees(shifts=[Integer(0),Integer(1),Integer(2)])[2, 3]

A zero row in a polynomial matrix can be identified in the (shifted) row degrees as the entries equal tomin(shifts)-1:
sage: M = Matrix(pR, [[3*x+1, 0, 1], [x^3+3, 0, 0], [0, 0, 0]])sage: M.row_degrees()[1, 3, -1]
sage: M.row_degrees(shifts=[-2,1,2])[2, 1, -3]>>> from sage.all import *>>> M = Matrix(pR, [[Integer(3)*x+Integer(1), Integer(0), Integer(1)],␣
˓→[x**Integer(3)+Integer(3), Integer(0), Integer(0)], [Integer(0), Integer(0),˓→ Integer(0)]])>>> M.row_degrees()[1, 3, -1]>>> M.row_degrees(shifts=[-Integer(2),Integer(1),Integer(2)])[2, 1, -3]

The row degrees of an empty matrix (0 × 𝑛 or 𝑚 × 0) is not defined:
sage: M = Matrix(pR, 0, 3)
sage: M.row_degrees()
Traceback (most recent call last):...
ValueError: empty matrix does not have row degrees
sage: M = Matrix(pR, 3, 0)
sage: M.row_degrees()
Traceback (most recent call last):...
ValueError: empty matrix does not have row degrees>>> from sage.all import *>>> M = Matrix(pR, Integer(0), Integer(3))>>> M.row_degrees()(continues on next page)

972

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Traceback (most recent call last):...
ValueError: empty matrix does not have row degrees>>> M = Matrix(pR, Integer(3), Integer(0))>>> M.row_degrees()
Traceback (most recent call last):...
ValueError: empty matrix does not have row degrees

shift(d, row_wise=True)
Return the matrix which is obtained from this matrix after shifting all its entries as specified by 𝑑.
• if 𝑑 is an integer, the shift is by 𝑑 for all entries;• if 𝑑 is a list (𝑑1 , . . . , 𝑑𝑚 ) and row_wise is True, all entries of the 𝑖`𝑡ℎ𝑟𝑜𝑤𝑎𝑟𝑒𝑠ℎ𝑖𝑓 𝑡𝑒𝑑𝑏𝑦`𝑑𝑖 for each𝑖;
• if 𝑑 is a list (𝑑1 , . . . , 𝑑𝑛 ) and row_wise is False, all entries of the 𝑗`𝑡ℎ𝑐𝑜𝑙𝑢𝑚𝑛𝑎𝑟𝑒𝑠ℎ𝑖𝑓 𝑡𝑒𝑑𝑏𝑦`𝑑𝑗 foreach 𝑗.
Shifting by 𝑑 means multiplying by the variable to the power 𝑑; if 𝑑 is negative then terms of negative degree
after shifting are discarded.
INPUT:• d – a list of integers, or an integer,• row_wise – (default: True) boolean, if True (resp. False) then 𝑑 should be a list of length equal
to the row (resp. column) dimension of this matrix.
OUTPUT: a polynomial matrix.
EXAMPLES:
sage: pR.<x> = GF(7)[]sage: M = Matrix([....:[ x^3+5*x^2+5*x+1,
5,
6*x+4,
0],....:[
6*x^2+3*x+1,
1,
2,
0],
....:
[2*x^3+4*x^2+6*x+4, 5*x + 1, 2*x^2+5*x+5, x^2+5*x+6]....:])
sage: M.shift(-2)[ x + 5
0
0
0]
[
6
0
0
0]
[2*x + 4
0
2
1]>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> M = Matrix([...
[ x**Integer(3)+Integer(5)*x**Integer(2)+Integer(5)*x+Integer(1),␣˓→Integer(5),Integer(6)*x+Integer(4),Integer(0)],...
[Integer(6)*x**Integer(2)+Integer(3)*x+Integer(1),␣˓→Integer(1),Integer(2),Integer(0)],...
␣˓→[Integer(2)*x**Integer(3)+Integer(4)*x**Integer(2)+Integer(6)*x+Integer(4),␣
˓→Integer(5)*x + Integer(1), Integer(2)*x**Integer(2)+Integer(5)*x+Integer(5),˓→ x**Integer(2)+Integer(5)*x+Integer(6)](continues on next page)973

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
])>>> M.shift(-Integer(2))[ x + 500[
600
[2*x + 4
0
2

0]
0]
1]

Row-wise and column-wise shifting are available:
sage: M.shift([-1,2,-2])[x^2 + 5*x + 5
˓→ 0][6*x^4 + 3*x^3 + x^2
˓→ 0][
2*x + 4
˓→ 1]

0

6

␣

x^2

2*x^2

␣

0

2

␣

sage: M.shift([-1,1,0,0], row_wise=False)[ x^2 + 5*x + 5
5*x
6*x + 4[
6*x + 3x2
[2*x^2 + 4*x + 6
5*x^2 + x 2*x^2 + 5*x + 50]0]x^2 + 5*x + 6]

sage: M.shift([-d for d in M.row_degrees()]) == M.leading_matrix()True>>> from sage.all import *>>> M.shift([-Integer(1),Integer(2),-Integer(2)])[
x^2 + 5*x + 50
˓→ 0][6*x^4 + 3*x^3 + x^2
x^2
˓→ 0]
[
2*x + 4
0
˓→ 1]

6

␣

2*x^2

␣

2

␣

>>> M.shift([-Integer(1),Integer(1),Integer(0),Integer(0)], row_wise=False)[ x^2 + 5*x + 5
5*x
6*x + 40][
6*x + 3x20][2*x^2 + 4*x + 6
5*x^2 + x 2*x^2 + 5*x + 5
x^2 + 5*x + 6]>>> M.shift([-d for d in M.row_degrees()]) == M.leading_matrix()
True

Length of input shift degree list is checked:
sage: M.shift([1,3,1,4])
Traceback (most recent call last):...
ValueError: length of input shift list should be the row
dimension of the input matrix
sage: M.shift([5,2,-1], row_wise=False)
Traceback (most recent call last):...
ValueError: length of input shift list should be the column
dimension of the input matrix

974

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> M.shift([Integer(1),Integer(3),Integer(1),Integer(4)])
Traceback (most recent call last):...
ValueError: length of input shift list should be the row
dimension of the input matrix>>> M.shift([Integer(5),Integer(2),-Integer(1)], row_wise=False)
Traceback (most recent call last):...
ValueError: length of input shift list should be the column
dimension of the input matrix

See also:
sage.rings.polynomial.polynomial_element.Polynomial.shift() .
solve_left_series_trunc(B, d)
Try to find a solution 𝑋 to the equation 𝑋𝐴 = 𝐵, at precision d.
If self is a matrix 𝐴, then this function returns a vector or matrix 𝑋 such that 𝑋𝐴 = 𝐵 mod 𝑥𝑑 . If 𝐵 is avector then 𝑋 is a vector, and if 𝐵 is a matrix then 𝑋 is a matrix.
Raises ValueError if d is not strictly positive, or if there is a dimension mismatch between 𝐴 and 𝐵, or
if there is no solution to the given matrix equation at the specified precision.
INPUT:• B – a polynomial matrix or polynomial vector.
• d – a positive integer.
OUTPUT:
A solution to the matrix equation, returned as polynomial matrix of degree less than d if B is a polynomial
matrix; a polynomial vector of degree less than d if 𝐵 is a polynomial vector.
ALGORITHM:
If 𝐴 is square with invertible constant term, then the unique solution is found by calling inverse_series_trunc() and using the Dixon & Moenck-Carter iteration. Otherwise, a left minimal approximantbasis of a matrix formed by 𝐴 and 𝐵 is computed, for an appropriate shift which ensures that this basis reveals
either a solution 𝑋 or the fact that no such solution exists.
EXAMPLES:
sage: pR.<x> = GF(7)[]sage: A = Matrix(pR, 3, 3,....:[[4*x+5,5*x^2 + x + 1, 4*x^2 + 4],....:[6*x^2 + 6*x + 6, 4*x^2 + 5*x,4*x^2 + x + 3],....:[3*x^2 + 2,
4*x + 1,x^2 + 3*x]])
sage: A.is_square() and A.constant_matrix().is_invertible()True
sage: B = vector([2*x^2 + 6*x + 6, 0, x + 6])
sage: X = A.solve_left_series_trunc(B, 4); X(3*x^3 + 3*x^2 + 2*x + 4, 4*x^3 + x^2 + 2*x + 6, 6*x^3 + x + 3)
sage: B == X*A % x**4
True
sage: B = Matrix(pR, 2, 3,....:[[3*x, x^2 + x + 2, x^2 + 2*x + 3],(continues on next page)975

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

....:
[ 0,
6*x^2 + 1,
1]])
sage: A.solve_left_series_trunc(B, 3)[6*x^2 + 2*x + 2
4*x + 32*x^2 + 3*x][3*x^2 + 4*x + 5
4*x^2 + 3x^2 + 6*x + 3]
sage: X = A.solve_left_series_trunc(B, 37); B == X*A % x**37
True>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> A = Matrix(pR, Integer(3), Integer(3),...
[[Integer(4)*x+Integer(5),Integer(5)*x**Integer(2)␣
˓→+ x + Integer(1), Integer(4)*x**Integer(2) + Integer(4)],...
[Integer(6)*x**Integer(2) + Integer(6)*x + Integer(6),␣
˓→Integer(4)*x**Integer(2) + Integer(5)*x,
Integer(4)*x**Integer(2) + x +␣˓→Integer(3)],...
[Integer(3)*x**Integer(2) + Integer(2),Integer(4)*x +␣˓→Integer(1),x**Integer(2) + Integer(3)*x]])>>> A.is_square() and A.constant_matrix().is_invertible()
True>>> B = vector([Integer(2)*x**Integer(2) + Integer(6)*x + Integer(6),␣
˓→Integer(0), x + Integer(6)])>>> X = A.solve_left_series_trunc(B, Integer(4)); X(3*x^3 + 3*x^2 + 2*x + 4, 4*x^3 + x^2 + 2*x + 6, 6*x^3 + x + 3)>>> B == X*A % x**Integer(4)True>>> B = Matrix(pR, Integer(2), Integer(3),...
[[Integer(3)*x, x**Integer(2) + x + Integer(2), x**Integer(2)␣
˓→+ Integer(2)*x + Integer(3)],...
[ Integer(0),Integer(6)*x**Integer(2) + Integer(1),␣˓→Integer(1)]])>>> A.solve_left_series_trunc(B, Integer(3))[6*x^2 + 2*x + 2
4*x + 32*x^2 + 3*x][3*x^2 + 4*x + 5
4*x^2 + 3x^2 + 6*x + 3]>>> X = A.solve_left_series_trunc(B, Integer(37)); B == X*A % x**Integer(37)
True

Dimensions of input are checked:
sage: A.solve_left_series_trunc(B[:,:2], 3)
Traceback (most recent call last):...
ValueError: number of columns of self must equal number of columns of right˓→hand side>>> from sage.all import *>>> A.solve_left_series_trunc(B[:,:Integer(2)], Integer(3))
Traceback (most recent call last):...
ValueError: number of columns of self must equal number of columns of right˓→hand side

Raises an exception when no solution:
sage: A[2:,:].solve_left_series_trunc(B, 4)
Traceback (most recent call last):(continues on next page)

976

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
ValueError: matrix equation has no solutions
sage: Ax = x*A; C = vector(pR, [1,1,1])
sage: Ax.solve_left_series_trunc(C, 5)
Traceback (most recent call last):...
ValueError: matrix equation has no solutions>>> from sage.all import *>>> A[Integer(2):,:].solve_left_series_trunc(B, Integer(4))
Traceback (most recent call last):...
ValueError: matrix equation has no solutions>>> Ax = x*A; C = vector(pR, [Integer(1),Integer(1),Integer(1)])>>> Ax.solve_left_series_trunc(C, Integer(5))
Traceback (most recent call last):...
ValueError: matrix equation has no solutions

Supports rectangular and rank-deficient cases:
sage: A[:,:2].solve_left_series_trunc(B[:,:2], 4)[5*x^2 + 2*x + 5
5*x + 52*x + 4][5*x^3 + 2*x + 1 2*x^2 + 2*x + 5
4*x^2]
sage: V = Matrix([[3*x^2 + 4*x + 1, 4*x]])
sage: A[:2,:].solve_left_series_trunc(V*A[:2,:], 4) == V
True
sage: A[1,:] = (x+1) * A[0,:]; A[2,:] = (x+5) * A[0,:]sage: B = (3*x^3+x^2+2)*A[0,:]sage: A.solve_left_series_trunc(B, 6)[4*x^2 + 6*x + 2
3*x^2 + x
0]>>> from sage.all import *>>> A[:,:Integer(2)].solve_left_series_trunc(B[:,:Integer(2)], Integer(4))[5*x^2 + 2*x + 5
5*x + 52*x + 4][5*x^3 + 2*x + 1 2*x^2 + 2*x + 5
4*x^2]>>> V = Matrix([[Integer(3)*x**Integer(2) + Integer(4)*x + Integer(1),␣
˓→Integer(4)*x]])>>> A[:Integer(2),:].solve_left_series_trunc(V*A[:Integer(2),:], Integer(4))␣
˓→== V
True>>> A[Integer(1),:] = (x+Integer(1)) * A[Integer(0),:]; A[Integer(2),:] =␣˓→(x+Integer(5)) * A[Integer(0),:]>>> B = (Integer(3)*x**Integer(3)+x**Integer(2)+Integer(2))*A[Integer(0),:]>>> A.solve_left_series_trunc(B, Integer(6))[4*x^2 + 6*x + 2
3*x^2 + x0]

See also:
solve_right_series_trunc() .

977

Matrices and Spaces of Matrices, Release 10.4

solve_right_series_trunc(B, d)
Try to find a solution 𝑋 to the equation 𝐴𝑋 = 𝐵, at precision d.
If self is a matrix 𝐴, then this function returns a vector or matrix 𝑋 such that 𝐴𝑋 = 𝐵 mod 𝑥𝑑 . If 𝐵 is avector then 𝑋 is a vector, and if 𝐵 is a matrix then 𝑋 is a matrix.
Raises ValueError if d is not strictly positive, or if there is a dimension mismatch between 𝐴 and 𝐵, or
if there is no solution to the given matrix equation at the specified precision.
INPUT:• B – a polynomial matrix or polynomial vector.
• d – a positive integer.
OUTPUT:
A solution to the matrix equation, returned as polynomial matrix of degree less than d if B is a polynomial
matrix; a polynomial vector of degree less than d if 𝐵 is a polynomial vector.
ALGORITHM:
If 𝐴 is square with invertible constant term, then the unique solution is found by calling inverse_series_trunc() and using the Dixon & Moenck-Carter iteration. Otherwise, a right minimal approximantbasis of a matrix formed by 𝐴 and 𝐵 is computed, for an appropriate shift which ensures that this basis reveals
either a solution 𝑋 or the fact that no such solution exists.
EXAMPLES:
sage: pR.<x> = GF(7)[]sage: A = Matrix(pR, 3, 3,....:[[4*x+5,5*x^2 + x + 1, 4*x^2 + 4],....:[6*x^2 + 6*x + 6, 4*x^2 + 5*x,4*x^2 + x + 3],....:[3*x^2 + 2,
4*x + 1,x^2 + 3*x]])
sage: A.is_square() and A.constant_matrix().is_invertible()True
sage: B = vector([2*x^2 + 6*x + 6, 0, x + 6])
sage: X = A.solve_right_series_trunc(B, 4); X(2*x^3 + x^2, 5*x^3 + x^2 + 5*x + 6, 4*x^3 + 6*x^2 + 4*x)
sage: B == A*X % x**4
True
sage: B = Matrix(pR, 3, 2,....:[[5*x^2 + 6*x + 3, 4*x^2 + 6*x + 4],....:[ x^2 + 4*x + 2,
5*x + 2],....:[
5*x + 3,0]])sage: A.solve_right_series_trunc(B, 3)[ 3*x^2 + x + 1 5*x^2 + 4*x + 3]
[6*x^2 + 3*x + 1
4*x + 1][
6*x^2 + 1
2*x^2 + x + 4]
sage: X = A.solve_right_series_trunc(B, 37); B == A*X % x**37
True>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> A = Matrix(pR, Integer(3), Integer(3),...
[[Integer(4)*x+Integer(5),Integer(5)*x**Integer(2) + x +␣˓→Integer(1), Integer(4)*x**Integer(2) + Integer(4)],...
[Integer(6)*x**Integer(2) + Integer(6)*x + Integer(6),␣
˓→Integer(4)*x**Integer(2) + Integer(5)*x,
Integer(4)*x**Integer(2) + x +␣˓→Integer(3)],(continues on next page)

978

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
[Integer(3)*x**Integer(2) + Integer(2),Integer(4)*x +␣˓→Integer(1),x**Integer(2) + Integer(3)*x]])>>> A.is_square() and A.constant_matrix().is_invertible()
True>>> B = vector([Integer(2)*x**Integer(2) + Integer(6)*x + Integer(6),␣
˓→Integer(0), x + Integer(6)])>>> X = A.solve_right_series_trunc(B, Integer(4)); X(2*x^3 + x^2, 5*x^3 + x^2 + 5*x + 6, 4*x^3 + 6*x^2 + 4*x)>>> B == A*X % x**Integer(4)True>>> B = Matrix(pR, Integer(3), Integer(2),...
[[Integer(5)*x**Integer(2) + Integer(6)*x + Integer(3),␣
˓→Integer(4)*x**Integer(2) + Integer(6)*x + Integer(4)],...
[ x**Integer(2) + Integer(4)*x + Integer(2),␣˓→Integer(5)*x + Integer(2)],...
[Integer(5)*x + Integer(3),␣˓→Integer(0)]])>>> A.solve_right_series_trunc(B, Integer(3))[ 3*x^2 + x + 1 5*x^2 + 4*x + 3]
[6*x^2 + 3*x + 1
4*x + 1][
6*x^2 + 1
2*x^2 + x + 4]>>> X = A.solve_right_series_trunc(B, Integer(37)); B == A*X % x**Integer(37)
True

Dimensions of input are checked:
sage: A.solve_right_series_trunc(B[:2,:], 3)
Traceback (most recent call last):...
ValueError: number of rows of self must equal number of rows of right-hand␣˓→side>>> from sage.all import *>>> A.solve_right_series_trunc(B[:Integer(2),:], Integer(3))
Traceback (most recent call last):...
ValueError: number of rows of self must equal number of rows of right-hand␣˓→sideRaises an exception when no solution:
sage: A[:,2:].solve_right_series_trunc(B, 4)
Traceback (most recent call last):...
ValueError: matrix equation has no solutions
sage: Ax = x*A; C = vector(pR, [1,1,1])
sage: Ax.solve_right_series_trunc(C, 5)
Traceback (most recent call last):...
ValueError: matrix equation has no solutions>>> from sage.all import *>>> A[:,Integer(2):].solve_right_series_trunc(B, Integer(4))
Traceback (most recent call last):...
(continues on next page)979

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

ValueError: matrix equation has no solutions>>> Ax = x*A; C = vector(pR, [Integer(1),Integer(1),Integer(1)])>>> Ax.solve_right_series_trunc(C, Integer(5))
Traceback (most recent call last):...
ValueError: matrix equation has no solutions

Supports rectangular and rank-deficient cases:
sage: A[:2,:].solve_right_series_trunc(B[:2,:],4)[5*x^2 + 4*x
x + 4][ x^2 + 3*x + 5 3*x^2 + 4*x + 4][
5*x + 3
3*x + 2]sage: V = Matrix([[2*x^2 + 5*x + 1], [3*x^2+4]])
sage: A[:,:2].solve_right_series_trunc(A[:,:2]*V, 4) == V
True
sage: A[:,1] = (x+1) * A[:,0]; A[:,2] = (x+5) * A[:,0]sage: B = (3*x^3+x^2+2)*A[:,0]sage: A.solve_right_series_trunc(B, 6)[4*x^2 + 6*x + 2][
3*x^2 + x][
0]>>> from sage.all import *>>> A[:Integer(2),:].solve_right_series_trunc(B[:Integer(2),:],Integer(4))[
5*x^2 + 4*x
x + 4][ x^2 + 3*x + 5 3*x^2 + 4*x + 4][
5*x + 3
3*x + 2]>>> V = Matrix([[Integer(2)*x**Integer(2) + Integer(5)*x + Integer(1)],␣
˓→[Integer(3)*x**Integer(2)+Integer(4)]])>>> A[:,:Integer(2)].solve_right_series_trunc(A[:,:Integer(2)]*V, Integer(4))␣
˓→== V
True>>> A[:,Integer(1)] = (x+Integer(1)) * A[:,Integer(0)]; A[:,Integer(2)] =␣
˓→(x+Integer(5)) * A[:,Integer(0)]>>> B = (Integer(3)*x**Integer(3)+x**Integer(2)+Integer(2))*A[:,Integer(0)]>>> A.solve_right_series_trunc(B, Integer(6))[4*x^2 + 6*x + 2][
3*x^2 + x][0]

See also:
solve_left_series_trunc() .
truncate(d, row_wise=True)
Return the matrix which is obtained from this matrix after truncating all its entries according to precisions
specified by 𝑑.
• if 𝑑 is an integer, the truncation is at precision 𝑑 for all entries;• if 𝑑 is a list (𝑑1 , . . . , 𝑑𝑚 ) and row_wise𝑖`𝑡ℎ𝑟𝑜𝑤𝑎𝑟𝑒𝑡𝑟𝑢𝑛𝑐𝑎𝑡𝑒𝑑𝑎𝑡𝑝𝑟𝑒𝑐𝑖𝑠𝑖𝑜𝑛`𝑑𝑖 for each 𝑖;
980

is

True,

all

entriesoftheChapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

• if 𝑑 is a list (𝑑1 , . . . , 𝑑𝑛 ) and row_wise𝑗`𝑡ℎ𝑐𝑜𝑙𝑢𝑚𝑛𝑎𝑟𝑒𝑡𝑟𝑢𝑛𝑐𝑎𝑡𝑒𝑑𝑎𝑡𝑝𝑟𝑒𝑐𝑖𝑠𝑖𝑜𝑛`𝑑𝑗 for each 𝑗.

isFalse,

allentriesoftheHere the convention for univariate polynomials is to take zero for the truncation for a negative 𝑑.
INPUT:• d – a list of integers, or an integer,• row_wise – (default: True) boolean, if True (resp. False) then 𝑑 should be a list of length equal
to the row (resp. column) dimension of this matrix.
OUTPUT: a polynomial matrix.
EXAMPLES:
sage: pR.<x> = GF(7)[]sage: M = Matrix([....:[ x^3+5*x^2+5*x+1,
5,
6*x+4,
0],....:[
6*x^2+3*x+1,
1,
2,
0],
....:
[2*x^3+4*x^2+6*x+4, 5*x + 1, 2*x^2+5*x+5, x^2+5*x+6]....:])
sage: M.truncate(2)[5*x + 1
5 6*x + 40]
[3*x + 1
12
0][6*x + 4 5*x + 1 5*x + 5 5*x + 6]
sage: M.truncate(1) == M.constant_matrix()True>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> M = Matrix([...
[ x**Integer(3)+Integer(5)*x**Integer(2)+Integer(5)*x+Integer(1),␣˓→Integer(5),Integer(6)*x+Integer(4),Integer(0)],...
[Integer(6)*x**Integer(2)+Integer(3)*x+Integer(1),␣˓→Integer(1),Integer(2),Integer(0)],...
␣˓→[Integer(2)*x**Integer(3)+Integer(4)*x**Integer(2)+Integer(6)*x+Integer(4),␣
˓→Integer(5)*x + Integer(1), Integer(2)*x**Integer(2)+Integer(5)*x+Integer(5),˓→ x**Integer(2)+Integer(5)*x+Integer(6)]...
])>>> M.truncate(Integer(2))[5*x + 1
5 6*x + 40]
[3*x + 1
12
0][6*x + 4 5*x + 1 5*x + 5 5*x + 6]>>> M.truncate(Integer(1)) == M.constant_matrix()
True

Row-wise and column-wise truncation are available:
sage: M.truncate([3,2,1])[5*x^2 + 5*x + 1[
3*x + 1[451
1

6*x + 4
2
5

0]
0]
6]

sage: M.truncate([2,1,1,2], row_wise=False)[5*x + 1
540](continues on next page)981

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[3*x + 1[6*x + 4

1
1

2
0]
5 5*x + 6]>>> from sage.all import *>>> M.truncate([Integer(3),Integer(2),Integer(1)])[5*x^2 + 5*x + 1
5
6*x + 4[
3*x + 1
1
2
[
4
1
5

0]
0]
6]

>>> M.truncate([Integer(2),Integer(1),Integer(1),Integer(2)], row_wise=False)[5*x + 1
54
0][3*x + 1
12
0][6*x + 41
5 5*x + 6]

Length of list of truncation orders is checked:
sage: M.truncate([2,1,1,2])
Traceback (most recent call last):...
ValueError: length of input precision list should be the row
dimension of the input matrix
sage: M.truncate([3,2,1], row_wise=False)
Traceback (most recent call last):...
ValueError: length of input precision list should be the column
dimension of the input matrix>>> from sage.all import *>>> M.truncate([Integer(2),Integer(1),Integer(1),Integer(2)])
Traceback (most recent call last):...
ValueError: length of input precision list should be the row
dimension of the input matrix>>> M.truncate([Integer(3),Integer(2),Integer(1)], row_wise=False)
Traceback (most recent call last):...
ValueError: length of input precision list should be the column
dimension of the input matrix

See also:
sage.rings.polynomial.polynomial_element.Polynomial.truncate() .
weak_popov_form(transformation=False, shifts=None, row_wise=True, ordered=False,
include_zero_vectors=True)
Return a (shifted) (ordered) weak Popov form of this matrix.
See is_weak_popov() for a definition of weak Popov forms. If the input matrix is 𝐴, a weak Popov formof 𝐴 is any matrix 𝑃 in weak Popov form and such that 𝑈 𝐴 = 𝑃 for some unimodular matrix 𝑈 . The latter
matrix is called the transformation, and the first optional argument allows one to specify whether to return
this transformation.
Sometimes, one forbids weak Popov forms to have zero rows (resp. columns) in the above definitions; an
optional parameter allows one to adopt this more restrictive setting. If zero rows (resp. columns) are allowed,

982

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

the convention here is to place them as the bottommost rows (resp. the rightmost columns) of the output
weak Popov form.
Note that, if asking for the transformation and discarding zero vectors (i.e. transformation=Trueand include_zero_vectors=False), then the returned transformation is still the complete unimodular matrix, including its bottommost rows (resp. rightmost columns) which correspond to zero rows (resp.
columns) of the complete weak Popov form. In fact, this bottom part of the transformation yields a basis of
the left (resp. right) kernel of the input matrix.
INPUT:• transformation – (default: False). If this is True, the transformation matrix 𝑈 will be returned
as well.
• shifts – (default: None) list of integers; None is interpreted as shifts=[0,...,0].
• row_wise – (default: True) boolean, True if working row-wise (see the class description).
• ordered – (default: False) boolean, True if seeking an ordered weak Popov form.
• include_zero_vectors – (default: True) boolean, False if zero rows (resp. zero columns)
should be discarded from the (ordered) weak Popov forms.
OUTPUT:• A polynomial matrix which is a weak Popov form of self if transformation is False; otherwise
two polynomial matrices which are a weak Popov form of self and the corresponding unimodulartransformation.
ALGORITHM:
This method implements the Mulders-Storjohann algorithm of [MS2003], straightforwardly extended to thecase of shifted forms.
EXAMPLES:
sage: pR.<x> = GF(7)[]sage: M = Matrix(pR, [....:[6*x+4,
5*x^3+5*x,
6*x^2+2*x+2],....:[4*x^2+5*x+2, x^4+5*x^2+2*x+4, 4*x^3+6*x^2+6*x+5]])
sage: P, U = M.weak_popov_form(transformation=True)
sage: P[
4x^2
6*x^2 + x + 2][
2 4*x^2 + 2*x + 4
5]
sage: U
[2*x^2 + 1
4*x]
[
4*x
1]
sage: P.is_weak_popov() and U.is_invertible() and U*M == P
True>>> from sage.all import *>>> pR = GF(Integer(7))[ x ]; (x,) = pR._first_ngens(1)>>> M = Matrix(pR, [...
[Integer(6)*x+Integer(4),␣˓→Integer(5)*x**Integer(3)+Integer(5)*x,␣
˓→Integer(6)*x**Integer(2)+Integer(2)*x+Integer(2)],...
[Integer(4)*x**Integer(2)+Integer(5)*x+Integer(2),␣
˓→x**Integer(4)+Integer(5)*x**Integer(2)+Integer(2)*x+Integer(4),␣
˓→Integer(4)*x**Integer(3)+Integer(6)*x**Integer(2)+Integer(6)*x+Integer(5)]])>>> P, U = M.weak_popov_form(transformation=True)>>> P(continues on next page)983

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[
4x^2
6*x^2 + x + 2][
2 4*x^2 + 2*x + 4
5]>>> U[2*x^2 + 1
4*x]
[
4*x
1]
>>> P.is_weak_popov() and U.is_invertible() and U*M == P
True

Demonstrating the ordered option:
sage: P.leading_positions()[2, 1]
sage: PP = M.weak_popov_form(ordered=True); PP[
2 4*x^2 + 2*x + 4
5]
[
4
x^2
6*x^2 + x + 2]
sage: PP.leading_positions()[1, 2]>>> from sage.all import *>>> P.leading_positions()[2, 1]>>> PP = M.weak_popov_form(ordered=True); PP[
2 4*x^2 + 2*x + 4
5]
[
4
x^2
6*x^2 + x + 2]>>> PP.leading_positions()[1, 2]

Demonstrating shifts:
sage: P = M.weak_popov_form(shifts=[0,2,4]); P[
6*x^2 + 6*x + 4 5*x^4 + 4*x^3 + 5*x^2 + 5*x
˓→2*x + 2][2
4*x^2 + 2*x + 4
˓→5]
sage: P == M.weak_popov_form(shifts=[-10,-8,-6])
True>>> from sage.all import *>>> P = M.weak_popov_form(shifts=[Integer(0),Integer(2),Integer(4)]); P[
6*x^2 + 6*x + 4 5*x^4 + 4*x^3 + 5*x^2 + 5*x
˓→2*x + 2][2
4*x^2 + 2*x + 4
˓→5]>>> P == M.weak_popov_form(shifts=[-Integer(10),-Integer(8),-Integer(6)])
True

␣
␣

␣
␣

Column-wise form is the row-wise form of the transpose:
sage: M.weak_popov_form() == M.T.weak_popov_form(row_wise=False).T
True>>> from sage.all import *>>> M.weak_popov_form() == M.T.weak_popov_form(row_wise=False).T
True

Zero vectors can be discarded:
984

Chapter 32. Dense matrices over univariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

sage: M.weak_popov_form(row_wise=False)[x + 4
6
0]
[
5
1
0]
sage: # needs sage.combinat
sage: P, U = M.weak_popov_form(transformation=True,....:
row_wise=False,....:
include_zero_vectors=False)
sage: P[x + 46][
5
1]
sage: U[
5*x + 2
5*x^2 + 4*x + 4 3*x^3 + 3*x^2 + 2*x + 4][
11
2*x + 1][
5*x + 52
6]sage: M*U[:,:2] == P and (M*U[:,2]).is_zero()True>>> from sage.all import *>>> M.weak_popov_form(row_wise=False)[x + 4
6
0]
[
5
1
0]
>>> # needs sage.combinat>>> P, U = M.weak_popov_form(transformation=True,...
row_wise=False,...
include_zero_vectors=False)>>> P[x + 4
6]
[
5
1]
>>> U
[
5*x + 2
5*x^2 + 4*x + 4 3*x^3 + 3*x^2 + 2*x + 4][
11
2*x + 1][
5*x + 52
6]>>> M*U[:,:Integer(2)] == P and (M*U[:,Integer(2)]).is_zero()
True

See also:
is_weak_popov() , reduced_form() , popov_form() , hermite_form() .

985

Matrices and Spaces of Matrices, Release 10.4

986

Chapter 32. Dense matrices over univariate polynomials over fields

CHAPTERTHIRTYTHREE

DENSE MATRICES OVER MULTIVARIATE POLYNOMIALS OVER
FIELDSThis implementation inherits from Matrix_generic_dense, i.e. it is not optimized for speed only some methods wereadded.
AUTHOR:• Martin Albrecht <malb@informatik.uni-bremen.de>class sage.matrix.matrix_mpolynomial_dense.Matrix_mpolynomial_dense
Bases: Matrix_generic_dense
Dense matrix over a multivariate polynomial ring over a field.
determinant(algorithm=None)
Return the determinant of this matrix.
INPUT:• algorithm – ignored
EXAMPLES:
We compute the determinant of the arbitrary 3𝑥3 matrix:
sage: R = PolynomialRing(QQ, 9, x )sage: A = matrix(R, 3, R.gens())
sage: A[x0 x1 x2][x3 x4 x5][x6 x7 x8]
sage: A.determinant()-x2*x4*x6 + x1*x5*x6 + x2*x3*x7 - x0*x5*x7 - x1*x3*x8 + x0*x4*x8>>> from sage.all import *>>> R = PolynomialRing(QQ, Integer(9), x )>>> A = matrix(R, Integer(3), R.gens())>>> A[x0 x1 x2][x3 x4 x5][x6 x7 x8]>>> A.determinant()-x2*x4*x6 + x1*x5*x6 + x2*x3*x7 - x0*x5*x7 - x1*x3*x8 + x0*x4*x8

We check if two implementations agree on the result:987

Matrices and Spaces of Matrices, Release 10.4

sage: R.<x,y> = QQ[]
sage: C = matrix(R, [[-6/5*x*y - y^2, -6*y^2 - 1/4*y],....:[ -1/3*x*y - 3, x*y - x]])sage: C.determinant()-6/5*x^2*y^2 - 3*x*y^3 + 6/5*x^2*y + 11/12*x*y^2 - 18*y^2 - 3/4*ysage: C.change_ring(R.change_ring(QQbar)).det()(-6/5)*x^2*y^2 + (-3)*x*y^3 + 6/5*x^2*y + 11/12*x*y^2 + (-18)*y^2 + (-3/4)*y>>> from sage.all import *>>> R = QQ[ x, y ]; (x, y,) = R._first_ngens(2)>>> C = matrix(R, [[-Integer(6)/Integer(5)*x*y - y**Integer(2), ˓→Integer(6)*y**Integer(2) - Integer(1)/Integer(4)*y],...
[ -Integer(1)/Integer(3)*x*y - Integer(3), x*y - x]])>>> C.determinant()-6/5*x^2*y^2 - 3*x*y^3 + 6/5*x^2*y + 11/12*x*y^2 - 18*y^2 - 3/4*y>>> C.change_ring(R.change_ring(QQbar)).det()(-6/5)*x^2*y^2 + (-3)*x*y^3 + 6/5*x^2*y + 11/12*x*y^2 + (-18)*y^2 + (-3/4)*yFinally, we check whether the Singular interface is working:sage: R.<x,y> = RR[]
sage: C = matrix(R, [[0.368965517352886*y^2 + 0.425700773972636*x, -0.
˓→800362171389760*y^2 - 0.807635502485287],....:[0.706173539423122*y^2 - 0.915986060298440, 0.
˓→897165181570476*y + 0.107903328188376]])
sage: C.determinant()
0.565194587390682*y^4 + 0.33102301536914...*y^3 + 0.381923912175852*x*y - 0.
˓→122977163520282*y^2 + 0.0459345303240150*x - 0.739782862078649>>> from sage.all import *>>> R = RR[ x, y ]; (x, y,) = R._first_ngens(2)>>> C = matrix(R, [[RealNumber( 0.368965517352886 )*y**Integer(2) +␣˓→RealNumber( 0.425700773972636 )*x, -RealNumber( 0.800362171389760
˓→ )*y**Integer(2) - RealNumber( 0.807635502485287 )],...
[RealNumber( 0.706173539423122 )*y**Integer(2) -␣˓→RealNumber( 0.915986060298440 ), RealNumber( 0.897165181570476 )*y +␣˓→RealNumber( 0.107903328188376 )]])>>> C.determinant()
0.565194587390682*y^4 + 0.33102301536914...*y^3 + 0.381923912175852*x*y - 0.
˓→122977163520282*y^2 + 0.0459345303240150*x - 0.739782862078649

ALGORITHM: Calls Singular, libSingular or native implementation.
echelon_form(algorithm='row_reduction', **kwds)
Return an echelon form of self using chosen algorithm.
By default only a usual row reduction with no divisions or column swaps is returned.
If Gauss-Bareiss algorithm is chosen, column swaps are recorded and can be retrieved via
swapped_columns().
INPUT:• algorithm – string, which algorithm to use (default: ‘row_reduction’). Valid options are:–988

row_reduction (default) – reduce as far as possible, only divide by constant entries

Chapter 33. Dense matrices over multivariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4–

frac – reduced echelon form over fraction field–bareiss – fraction free Gauss-Bareiss algorithm with column swaps

OUTPUT:The row echelon form of A depending on the chosen algorithm, as an immutable matrix. Note that self is
not changed by this command. Use A.echelonize() to change 𝐴 in place.
EXAMPLES:
sage: P.<x,y> = PolynomialRing(GF(127), 2)
sage: A = matrix(P, 2, 2, [1, x, 1, y])sage: A[1 x]
[1 y]
sage: A.echelon_form()[
1x][
0 -x + y]>>> from sage.all import *>>> P = PolynomialRing(GF(Integer(127)), Integer(2), names=( x , y ,)); (x,␣˓→y,) = P._first_ngens(2)>>> A = matrix(P, Integer(2), Integer(2), [Integer(1), x, Integer(1), y])
>>> A
[1 x]
[1 y]
>>> A.echelon_form()[
1x][
0 -x + y]

The reduced row echelon form over the fraction field is as follows:
sage: A.echelon_form( frac ) # over fraction field
[1 0]
[0 1]
>>> from sage.all import *>>> A.echelon_form( frac ) # over fraction field
[1 0]
[0 1]

Alternatively, the Gauss-Bareiss algorithm may be chosen:
sage: E = A.echelon_form( bareiss ); E[1y][
0 x - y]>>> from sage.all import *>>> E = A.echelon_form( bareiss ); E[1y][
0 x - y]After the application of the Gauss-Bareiss algorithm the swapped columns may inspected:
sage: E.swapped_columns(), E.pivots()((0, 1), (0, 1))
sage: A.swapped_columns(), A.pivots()(None, (0, 1))

989

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> E.swapped_columns(), E.pivots()((0, 1), (0, 1))>>> A.swapped_columns(), A.pivots()(None, (0, 1))

Another approach is to row reduce as far as possible:
sage: A.echelon_form( row_reduction )[1x][
0 -x + y]>>> from sage.all import *>>> A.echelon_form( row_reduction )[1x][
0 -x + y]echelonize(algorithm='row_reduction', **kwds)
Transform self into a matrix in echelon form over the same base ring as self.
If Gauss-Bareiss algorithm is chosen, column swaps are recorded and can be retrieved via
swapped_columns().
INPUT:• algorithm – string, which algorithm to use. Valid options are:–row_reduction – reduce as far as possible, only divide by constant entries–

bareiss – fraction free Gauss-Bareiss algorithm with column swaps

EXAMPLES:
sage: P.<x,y> = PolynomialRing(QQ, 2)
sage: A = matrix(P, 2, 2, [1/2, x, 1, 3/4*y+1])
sage: A[1/2
x][
1 3/4*y + 1]
sage: B = copy(A)sage: B.echelonize( bareiss ); B[
1
3/4*y + 1][
0 x - 3/8*y - 1/2]
sage: B = copy(A)sage: B.echelonize( row_reduction ); B
[
1
2*x]
[
0 -2*x + 3/4*y + 1]
sage: P.<x,y> = PolynomialRing(QQ, 2)
sage: A = matrix(P,2,3,[2,x,0,3,y,1]); A[2 x 0][3 y 1]
sage: E = A.echelon_form( bareiss ); E
[1 3 y][0 2 x]sage: E.swapped_columns()(2, 0, 1)(continues on next page)

990

Chapter 33. Dense matrices over multivariate polynomials over fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: A.pivots()(0, 1, 2)>>> from sage.all import *>>> P = PolynomialRing(QQ, Integer(2), names=( x , y ,)); (x, y,) = P._first_
˓→ngens(2)>>> A = matrix(P, Integer(2), Integer(2), [Integer(1)/Integer(2), x,␣
˓→Integer(1), Integer(3)/Integer(4)*y+Integer(1)])
>>> A
[
1/2
x]
[
1 3/4*y + 1]>>> B = copy(A)>>> B.echelonize( bareiss ); B[
1
3/4*y + 1][
0 x - 3/8*y - 1/2]>>> B = copy(A)>>> B.echelonize( row_reduction ); B
[
1
2*x]
[
0 -2*x + 3/4*y + 1]>>> P = PolynomialRing(QQ, Integer(2), names=( x , y ,)); (x, y,) = P._first_
˓→ngens(2)>>> A = matrix(P,Integer(2),Integer(3),[Integer(2),x,Integer(0),Integer(3),y,˓→Integer(1)]); A[2 x 0][3 y 1]>>> E = A.echelon_form( bareiss ); E
[1 3 y][0 2 x]>>> E.swapped_columns()(2, 0, 1)>>> A.pivots()(0, 1, 2)pivots()Return the pivot column positions of this matrix as a list of integers.
This returns a list, of the position of the first nonzero entry in each row of the echelon form.
OUTPUT:
A list of Python ints.
EXAMPLES:
sage: matrix([PolynomialRing(GF(2), 2, x ).gen()]).pivots()(0,)
sage: K = QQ[ x,y ]sage: x, y = K.gens()
sage: m = matrix(K, [(-x, 1, y, x - y), (-x*y, y, y^2 - 1, x*y - y^2 + x), (˓→x*y + x, y - 1, y^2 - y - 2, x*y - y^2 + x + y)])sage: m.pivots()(0, 2)
sage: m.rank()
2991

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> matrix([PolynomialRing(GF(Integer(2)), Integer(2), x ).gen()]).pivots()(0,)>>> K = QQ[ x,y ]>>> x, y = K.gens()>>> m = matrix(K, [(-x, Integer(1), y, x - y), (-x*y, y, y**Integer(2) -␣˓→Integer(1), x*y - y**Integer(2) + x), (-x*y + x, y - Integer(1),␣
˓→y**Integer(2) - y - Integer(2), x*y - y**Integer(2) + x + y)])>>> m.pivots()(0, 2)>>> m.rank()
2swapped_columns()
Return which columns were swapped during the Gauss-Bareiss reduction
OUTPUT:
Return a tuple representing the column swaps during the last application of the Gauss-Bareiss algorithm (seeechelon_form() for details).
The tuple as length equal to the rank of self and the value at the 𝑖-th position indicates the source column
which was put as the 𝑖-th column.
If no Gauss-Bareiss reduction was performed yet, None is returned.
EXAMPLES:
sage: R.<x,y> = QQ[]
sage: C = random_matrix(R, 2, 2, terms=2)
sage: while C.rank() != 2:....:
C = random_matrix(R, 2, 2, terms=2)
sage: C.swapped_columns()
sage: E = C.echelon_form( bareiss )sage: sorted(E.swapped_columns())[0, 1]>>> from sage.all import *>>> R = QQ[ x, y ]; (x, y,) = R._first_ngens(2)>>> C = random_matrix(R, Integer(2), Integer(2), terms=Integer(2))>>> while C.rank() != Integer(2):...
C = random_matrix(R, Integer(2), Integer(2), terms=Integer(2))>>> C.swapped_columns()>>> E = C.echelon_form( bareiss )>>> sorted(E.swapped_columns())[0, 1]

992

Chapter 33. Dense matrices over multivariate polynomials over fields

CHAPTERTHIRTYFOUR

MATRICES OVER CYCLOTOMIC FIELDS

The underlying matrix for a Matrix_cyclo_dense object is stored as follows: given an n x m matrix over a cyclotomic fieldof degree d, we store a d x (nm) matrix over QQ, each column of which corresponds to an element of the original matrix.
This can be retrieved via the _rational_matrix method. Here is an example illustrating this:EXAMPLES:
sage: F.<zeta> = CyclotomicField(5)sage: M = Matrix(F, 2, 3, [zeta, 3, zeta**4+5, (zeta+1)**4, 0, 1])
sage: M[zeta
3 -zeta^3 - zeta^2 - zeta +␣˓→4][3*zeta^3 + 5*zeta^2 + 3*zeta
0␣
˓→1]
sage: M._rational_matrix()[ 0 3 4 0 0 1]
[ 1 0 -1 3 0 0]
[ 0 0 -1 5 0 0]
[ 0 0 -1 3 0 0]>>> from sage.all import *>>> F = CyclotomicField(Integer(5), names=( zeta ,)); (zeta,) = F._first_ngens(1)>>> M = Matrix(F, Integer(2), Integer(3), [zeta, Integer(3),␣
˓→zeta**Integer(4)+Integer(5), (zeta+Integer(1))**Integer(4), Integer(0), Integer(1)])
>>> M
[
zeta
3 -zeta^3 - zeta^2 - zeta +␣˓→4][3*zeta^3 + 5*zeta^2 + 3*zeta
0␣
˓→1]>>> M._rational_matrix()[ 0 3 4 0 0 1]
[ 1 0 -1 3 0 0]
[ 0 0 -1 5 0 0]
[ 0 0 -1 3 0 0]

AUTHORS:• William Stein• Craig Citro
class sage.matrix.matrix_cyclo_dense.Matrix_cyclo_dense
Bases: Matrix_dense
Initialize a newly created cyclotomic matrix.
993

Matrices and Spaces of Matrices, Release 10.4

INPUT:• parent – a matrix space over a cyclotomic number field• entries – see matrix()• copy – ignored (for backwards compatibility)• coerce – if False, assume without checking that the entries lie in the base ring
EXAMPLES:This function is called implicitly when you create new cyclotomic dense matrices:sage: W.<a> = CyclotomicField(100)sage: A = matrix(2, 3, [1, 1/a, 1-a,a, -2/3*a, a^19])
sage: A[
1 -a^39 + a^29 - a^19 + a^9[a-2/3*asage: TestSuite(A).run()-a + 1]a^19]>>> from sage.all import *>>> W = CyclotomicField(Integer(100), names=( a ,)); (a,) = W._first_ngens(1)>>> A = matrix(Integer(2), Integer(3), [Integer(1), Integer(1)/a, Integer(1)-a,a,␣˓→-Integer(2)/Integer(3)*a, a**Integer(19)])>>> A[
1 -a^39 + a^29 - a^19 + a^9-a + 1][a-2/3*aa^19]>>> TestSuite(A).run()charpoly(var='x', algorithm='multimodular', proof=None)
Return the characteristic polynomial of self, as a polynomial over the base ring.
INPUT:• algorithm– ‘multimodular’ (default): reduce modulo primes, compute charpoly mod p, and lift (very fast)– ‘pari’: use pari (quite slow; comparable to Magma v2.14 though)– ‘hessenberg’: put matrix in Hessenberg form (double dog slow)• proof – bool (default: None) proof flag determined by global linalg proof.
OUTPUT:
polynomial
EXAMPLES:
sage: K.<z> = CyclotomicField(5)sage: a = matrix(K, 3, [1,z,1+z^2, z/3,1,2,3,z^2,1-z])
sage: f = a.charpoly(); fx^3 + (z - 3)*x^2 + (-16/3*z^2 - 2*z)*x - 2/3*z^3 + 16/3*z^2 - 5*z + 5/3
sage: f(a)[0 0 0][0 0 0][0 0 0]sage: a.charpoly(algorithm= pari )x^3 + (z - 3)*x^2 + (-16/3*z^2 - 2*z)*x - 2/3*z^3 + 16/3*z^2 - 5*z + 5/3
sage: a.charpoly(algorithm= hessenberg )x^3 + (z - 3)*x^2 + (-16/3*z^2 - 2*z)*x - 2/3*z^3 + 16/3*z^2 - 5*z + 5/3(continues on next page)994

Chapter 34. Matrices over Cyclotomic Fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: Matrix(K, 1, [0]).charpoly()xsage: Matrix(K, 1, [5]).charpoly(var= y )y - 5
sage: Matrix(CyclotomicField(13),3).charpoly()x^3
sage: Matrix(CyclotomicField(13),3).charpoly()[2].parent()
Cyclotomic Field of order 13 and degree 12>>> from sage.all import *>>> K = CyclotomicField(Integer(5), names=( z ,)); (z,) = K._first_ngens(1)>>> a = matrix(K, Integer(3), [Integer(1),z,Integer(1)+z**Integer(2), z/
˓→Integer(3),Integer(1),Integer(2),Integer(3),z**Integer(2),Integer(1)-z])>>> f = a.charpoly(); fx^3 + (z - 3)*x^2 + (-16/3*z^2 - 2*z)*x - 2/3*z^3 + 16/3*z^2 - 5*z + 5/3>>> f(a)[0 0 0][0 0 0][0 0 0]>>> a.charpoly(algorithm= pari )x^3 + (z - 3)*x^2 + (-16/3*z^2 - 2*z)*x - 2/3*z^3 + 16/3*z^2 - 5*z + 5/3>>> a.charpoly(algorithm= hessenberg )x^3 + (z - 3)*x^2 + (-16/3*z^2 - 2*z)*x - 2/3*z^3 + 16/3*z^2 - 5*z + 5/3>>> Matrix(K, Integer(1), [Integer(0)]).charpoly()x>>> Matrix(K, Integer(1), [Integer(5)]).charpoly(var= y )y - 5>>> Matrix(CyclotomicField(Integer(13)),Integer(3)).charpoly()x^3>>> Matrix(CyclotomicField(Integer(13)),Integer(3)).charpoly()[Integer(2)].
˓→parent()
Cyclotomic Field of order 13 and degree 12

coefficient_bound()Return an upper bound for the (complex) absolute values of all entries of self with respect to all embeddings.
Use self.height() for a sharper bound.
This is computed using just the Cauchy-Schwarz inequality, i.e., we use the fact that\left| \sum_i a_i\zeta^i \right| \leq \sum_i |a_i|,

as |𝜁| = 1.
EXAMPLES:
sage: W.<z> = CyclotomicField(5)sage: A = matrix(W, 2, 2, [1+z, 0, 9*z+7, -3 + 4*z]); A[ z + 10]
[9*z + 7 4*z - 3]sage: A.coefficient_bound()16995

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> W = CyclotomicField(Integer(5), names=( z ,)); (z,) = W._first_ngens(1)>>> A = matrix(W, Integer(2), Integer(2), [Integer(1)+z, Integer(0),␣
˓→Integer(9)*z+Integer(7), -Integer(3) + Integer(4)*z]); A[ z + 10]
[9*z + 7 4*z - 3]>>> A.coefficient_bound()
16

The above bound is just 9 + 7, coming from the lower left entry. A better bound would be the following:
sage: (A[1,0]).abs()
12.997543663...
>>> from sage.all import *>>> (A[Integer(1),Integer(0)]).abs()
12.997543663...

denominator()
Return the denominator of the entries of this matrix.
OUTPUT:
integer – the smallest integer d so that d * self has
entries in the ring of integers
EXAMPLES:
sage: W.<z> = CyclotomicField(5)sage: A = matrix(W, 2, 2, [-2/7,2/3*z+z^2,-z,1+z/19]); A[-2/7 z^2 + 2/3*z][-z 1/19*z + 1]
sage: d = A.denominator(); d399>>> from sage.all import *>>> W = CyclotomicField(Integer(5), names=( z ,)); (z,) = W._first_ngens(1)>>> A = matrix(W, Integer(2), Integer(2), [-Integer(2)/Integer(7),Integer(2)/˓→Integer(3)*z+z**Integer(2),-z,Integer(1)+z/Integer(19)]); A[-2/7 z^2 + 2/3*z][-z 1/19*z + 1]>>> d = A.denominator(); d399echelon_form(algorithm='multimodular', height_guess=None)
Find the echelon form of self, using the specified algorithm.
The result is cached for each algorithm separately.
EXAMPLES:
sage: W.<z> = CyclotomicField(3)sage: A = matrix(W, 2, 3, [1+z, 2/3, 9*z+7, -3 + 4*z, z, -7*z]); A[ z + 1
2/3 9*z + 7]
[4*z - 3z-7*z]
sage: A.echelon_form()[
1
0 -192/97*z - 361/97](continues on next page)

996

Chapter 34. Matrices over Cyclotomic Fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0
1 1851/97*z + 1272/97]
sage: A.echelon_form(algorithm= classical )[1
0 -192/97*z - 361/97][
0
1 1851/97*z + 1272/97]>>> from sage.all import *>>> W = CyclotomicField(Integer(3), names=( z ,)); (z,) = W._first_ngens(1)>>> A = matrix(W, Integer(2), Integer(3), [Integer(1)+z, Integer(2)/˓→Integer(3), Integer(9)*z+Integer(7), -Integer(3) + Integer(4)*z, z, ˓→Integer(7)*z]); A[ z + 1
2/3 9*z + 7]
[4*z - 3z-7*z]>>> A.echelon_form()[
1
0 -192/97*z - 361/97][
0
1 1851/97*z + 1272/97]>>> A.echelon_form(algorithm= classical )[1
0 -192/97*z - 361/97][
0
1 1851/97*z + 1272/97]

We verify that the result is cached and that the caches are separate:
sage: A.echelon_form() is A.echelon_form()True
sage: A.echelon_form() is A.echelon_form(algorithm= classical )False>>> from sage.all import *>>> A.echelon_form() is A.echelon_form()
True>>> A.echelon_form() is A.echelon_form(algorithm= classical )Falseheight()Return the height of self.
If we let 𝑎𝑖𝑗 be the 𝑖, 𝑗 entry of self, then we define the height of self to be
max𝑣 max𝑖,𝑗 |𝑎𝑖𝑗 |𝑣 ,where 𝑣 runs over all complex embeddings of self.base_ring().
EXAMPLES:
sage: W.<z> = CyclotomicField(5)sage: A = matrix(W, 2, 2, [1+z, 0, 9*z+7, -3 + 4*z]); A[ z + 10]
[9*z + 7 4*z - 3]sage: A.height()
12.997543663...
sage: (A[1,0]).abs()
12.997543663...
>>> from sage.all import *>>> W = CyclotomicField(Integer(5), names=( z ,)); (z,) = W._first_ngens(1)>>> A = matrix(W, Integer(2), Integer(2), [Integer(1)+z, Integer(0),␣
˓→Integer(9)*z+Integer(7), -Integer(3) + Integer(4)*z]); A(continues on next page)997

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ z + 10]
[9*z + 7 4*z - 3]>>> A.height()
12.997543663...
>>> (A[Integer(1),Integer(0)]).abs()
12.997543663...

randomize(density=1, num_bound=2, den_bound=2, distribution=None, nonzero=False, *args, **kwds)
Randomize the entries of self.
Choose rational numbers according to distribution, whose numerators are bounded by num_boundand whose denominators are bounded by den_bound.
EXAMPLES:
sage: A = Matrix(CyclotomicField(5),2,2,range(4)) ; A
[0 1]
[2 3]
sage: A.randomize()
sage: A# random output[
1/2*zeta5^2 + zeta5
1/2][-zeta5^2 + 2*zeta5 -2*zeta5^3 + 2*zeta5^2 + 2]>>> from sage.all import *>>> A = Matrix(CyclotomicField(Integer(5)),Integer(2),Integer(2),˓→range(Integer(4))) ; A
[0 1]
[2 3]
>>> A.randomize()>>> A# random output[
1/2*zeta5^2 + zeta5
1/2][-zeta5^2 + 2*zeta5 -2*zeta5^3 + 2*zeta5^2 + 2]

set_immutable()
Change this matrix so that it is immutable.
EXAMPLES:
sage: W.<z> = CyclotomicField(5)sage: A = matrix(W, 2, 2, [1,2/3*z+z^2,-z,1+z/2])
sage: A[0,0] = 10
sage: A.set_immutable()sage: A[0,0] = 20
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).
>>> from sage.all import *>>> W = CyclotomicField(Integer(5), names=( z ,)); (z,) = W._first_ngens(1)>>> A = matrix(W, Integer(2), Integer(2), [Integer(1),Integer(2)/˓→Integer(3)*z+z**Integer(2),-z,Integer(1)+z/Integer(2)])>>> A[Integer(0),Integer(0)] = Integer(10)>>> A.set_immutable()>>> A[Integer(0),Integer(0)] = Integer(20)Traceback (most recent call last):(continues on next page)

998

Chapter 34. Matrices over Cyclotomic Fields

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)...
ValueError: matrix is immutable; please change a copy instead (i.e., use␣˓→copy(M) to change a copy of M).

Note that there is no function to set a matrix to be mutable again, since such a function would violate thewhole point. Instead make a copy, which is always mutable by default.:
sage: A.set_mutable()
Traceback (most recent call last):...
AttributeError: sage.matrix.matrix_cyclo_dense.Matrix_cyclo_dense
˓→has no attribute
set_mutable ...
sage: B = A.__copy__()sage: B[0,0] = 20
sage: B[0,0]20>>> from sage.all import *>>> A.set_mutable()
Traceback (most recent call last):...
AttributeError: sage.matrix.matrix_cyclo_dense.Matrix_cyclo_dense
˓→has no attribute
set_mutable ...
>>> B = A.__copy__()>>> B[Integer(0),Integer(0)] = Integer(20)>>> B[Integer(0),Integer(0)]20object␣object␣tensor_product(A, subdivide=True)
Return the tensor product of two matrices.
INPUT:• A – a matrix• subdivide – (default: True) whether or not to return natural subdivisions with the matrix
OUTPUT:
Replace each element of self by a copy of A, but first create a scalar multiple of A by the element it replaces.
So if self is an 𝑚 × 𝑛 matrix and A is a 𝑝 × 𝑞 matrix, then the tensor product is an 𝑚𝑝 × 𝑛𝑞 matrix. By
default, the matrix will be subdivided into submatrices of size 𝑝 × 𝑞.
EXAMPLES:
sage: C = CyclotomicField(12)sage: M = matrix.random(C, 3, 3)
sage: N = matrix.random(C, 50, 50)
sage: M.tensor_product(M) == super(type(M), M).tensor_product(M)Truesage: N = matrix.random(C, 15, 20)
sage: M.tensor_product(N) == super(type(M), M).tensor_product(N)True>>> from sage.all import *>>> C = CyclotomicField(Integer(12))>>> M = matrix.random(C, Integer(3), Integer(3))(continues on next page)999

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> N = matrix.random(C, Integer(50), Integer(50))>>> M.tensor_product(M) == super(type(M), M).tensor_product(M)True>>> N = matrix.random(C, Integer(15), Integer(20))>>> M.tensor_product(N) == super(type(M), M).tensor_product(N)
True

1000

Chapter 34. Matrices over Cyclotomic Fields

CHAPTERTHIRTYFIVEOPERATION TABLES

This module implements general operation tables, which are very matrix-like.
class sage.matrix.operation_table.OperationTable(S, operation, names='letters',
elements=None)
Bases: SageObject
An object that represents a binary operation as a table.
Primarily this object is used to provide a multiplication_table() for objects in the category of magmas(monoids, groups, …) and addition_table() for objects in the category of commutative additive magmas(additive monoids, groups, …).
INPUT:• S – a finite algebraic structure (or finite iterable)• operation – a function of two variables that accepts pairsof elements from S. A natural source of such functions is the Python operator module, and in particular operator.add() and operator.mul(). This may also be a function defined with lambda
or def.
• names – (default: letters ) The type of names used, values are:–letters – lowercase ASCII letters are used for a base 26 representation of the elements’ positionsin the list given by column_keys(), padded to a common width with leading ‘a’s.

–

digits – base 10 representation of the elements’ positions in the list given by column_keys(),padded to a common width with leading zeros.

–

elements – the string representations of the elements themselves.

– a list - a list of strings, where the length of the list equals the number of elements.
• elements – (default: None) A list of elements of S, in forms that can be coerced into the structure, eg.
their string representations. This may be used to impose an alternate ordering on the elements of 𝑆`, perhaps
when this is used in the context of a particular structure. The default is to use whatever ordering the S.
list() method returns. 𝑒𝑙𝑒𝑚𝑒𝑛𝑡𝑠` can also be a subset which is closed under the operation, useful perhaps
when the set is infinite.
OUTPUT: An object with methods that abstracts multiplication tables, addition tables, Cayley tables, etc. It shouldbe general enough to be useful for any finite algebraic structure whose elements can be combined with a binary
operation. This is not necessarily meant be constructed directly, but instead should be useful for constructing
operation tables of various algebraic structures that have binary operations.
EXAMPLES:
In its most basic use, the table needs a structure and an operation:

1001

Matrices and Spaces of Matrices, Release 10.4

sage: from sage.matrix.operation_table import OperationTablesage: G = SymmetricGroup(3)˓→needs sage.groups
sage: OperationTable(G, operation=operator.mul)
˓→needs sage.groups* a b c d e f+-----------a| a b c d e f
b| b a d c f e
c| c e a f b d
d| d f b e a c
e| e c f a d b
f| f d e b c a>>> from sage.all import *>>> from sage.matrix.operation_table import OperationTable>>> G = SymmetricGroup(Integer(3))˓→# needs sage.groups>>> OperationTable(G, operation=operator.mul)
˓→needs sage.groups* a b c d e f+-----------a| a b c d e f
b| b a d c f e
c| c e a f b d
d| d f b e a c
e| e c f a d b
f| f d e b c a

#␣
#␣

␣
#␣

With two operations present, we can specify which operation we want:sage: from sage.matrix.operation_table import OperationTablesage: R = Integers(6)sage: OperationTable(R, operation=operator.add)+ a b c d e f+-----------a| a b c d e f
b| b c d e f ac| c d e f a b
d| d e f a b ce| e f a b c d
f| f a b c d e>>> from sage.all import *>>> from sage.matrix.operation_table import OperationTable>>> R = Integers(Integer(6))>>> OperationTable(R, operation=operator.add)+ a b c d e f+-----------a| a b c d e f
b| b c d e f ac| c d e f a b
d| d e f a b ce| e f a b c d
f| f a b c d e

The default symbol set for elements is lowercase ASCII letters, which take on a base 26 flavor for structures with

1002

Chapter 35. Operation Tables

Matrices and Spaces of Matrices, Release 10.4

more than 26 elements.
sage: from sage.matrix.operation_table import OperationTablesage: G = DihedralGroup(14)#␣˓→needs sage.groups
sage: OperationTable(G, operator.mul, names= letters )#␣˓→needs sage.groups* aa ab ac ad ae af ag ah ai aj ak al am an ao ap aq ar as at au av aw ax ay az␣
˓→ba bb+------------------------------------------------------------------------------˓→----aa| aa ab ac ad ae af ag ah ai aj ak al am an ao ap aq ar as at au av aw ax ay az␣
˓→ba bbab| ab aa ad ac af ae ah ag aj ai al ak an am ap ao ar aq at as av au ax aw az ay␣
˓→bb baac| ac ba aa ae ad ag af ai ah ak aj am al ao an aq ap as ar au at aw av ay ax bb␣
˓→ab azad| ad bb ab af ac ah ae aj ag al ai an ak ap am ar ao at aq av as ax au az aw ba␣
˓→aa ay
ae| ae az ba ag aa ai ad ak af am ah ao aj aq al as an au ap aw ar ay at bb av ab␣˓→ac ax
af| af ay bb ah ab aj ac al ae an ag ap ai ar ak at am av ao ax aq az as ba au aa␣
˓→ad aw
ag| ag ax az ai ba ak aa am ad ao af aq ah as aj au al aw an ay ap bb ar ab at ac␣˓→ae av
ah| ah aw ay aj bb al ab an ac ap ae ar ag at ai av ak ax am az ao ba aq aa as ad␣
˓→af auai| ai av ax ak az am ba ao aa aq ad as af au ah aw aj ay al bb an ab ap ac ar ae␣˓→ag ataj| aj au aw al ay an bb ap ab ar ac at ae av ag ax ai az ak ba am aa ao ad aq af␣˓→ah asak| ak at av am ax ao az aq ba as aa au ad aw af ay ah bb aj ab al ac an ae ap ag␣
˓→ai aral| al as au an aw ap ay ar bb at ab av ac ax ae az ag ba ai aa ak ad am af ao ah␣˓→aj aq
am| am ar at ao av aq ax as az au ba aw aa ay ad bb af ab ah ac aj ae al ag an ai␣
˓→ak ap
an| an aq as ap au ar aw at ay av bb ax ab az ac ba ae aa ag ad ai af ak ah am aj␣
˓→al ao
ao| ao ap ar aq at as av au ax aw az ay ba bb aa ab ad ac af ae ah ag aj ai al ak␣
˓→am anap| ap ao aq ar as at au av aw ax ay az bb ba ab aa ac ad ae af ag ah ai aj ak al␣˓→an amaq| aq an ap as ar au at aw av ay ax bb az ab ba ac aa ae ad ag af ai ah ak aj am␣˓→ao alar| ar am ao at aq av as ax au az aw ba ay aa bb ad ab af ac ah ae aj ag al ai an␣
˓→ap ak
as| as al an au ap aw ar ay at bb av ab ax ac az ae ba ag aa ai ad ak af am ah ao␣˓→aq aj
at| at ak am av ao ax aq az as ba au aa aw ad ay af bb ah ab aj ac al ae an ag ap␣
˓→ar ai
au| au aj al aw an ay ap bb ar ab at ac av ae ax ag az ai ba ak aa am ad ao af aq␣
˓→as ahav| av ai ak ax am az ao ba aq aa as ad au af aw ah ay aj bb al ab an ac ap ae ar␣˓→at ag
aw| aw ah aj ay al bb an ab ap ac ar ae at ag av ai ax ak az am ba ao aa aq ad as␣
˓→au af
ax| ax ag ai az ak ba am aa ao ad aq af as ah au aj aw al ay an bb ap ab ar ac at␣
(continues on next page)1003

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

av ae
ay| ay af ah bb aj ab al ac an ae ap ag ar ai at ak av am ax ao az aq ba as aa au␣
˓→aw adaz| az ae ag ba ai aa ak ad am af ao ah aq aj as al au an aw ap ay ar bb at ab av␣
˓→ax acba| ba ac ae aa ag ad ai af ak ah am aj ao al aq an as ap au ar aw at ay av bb ax␣
˓→az abbb| bb ad af ab ah ac aj ae al ag an ai ap ak ar am at ao av aq ax as az au ba aw␣
˓→ay aa˓→>>> from sage.all import *>>> from sage.matrix.operation_table import OperationTable>>> G = DihedralGroup(Integer(14))␣˓→# needs sage.groups>>> OperationTable(G, operator.mul, names= letters )#␣˓→needs sage.groups* aa ab ac ad ae af ag ah ai aj ak al am an ao ap aq ar as at au av aw ax ay az␣
˓→ba bb+------------------------------------------------------------------------------˓→----aa| aa ab ac ad ae af ag ah ai aj ak al am an ao ap aq ar as at au av aw ax ay az␣
˓→ba bbab| ab aa ad ac af ae ah ag aj ai al ak an am ap ao ar aq at as av au ax aw az ay␣
˓→bb baac| ac ba aa ae ad ag af ai ah ak aj am al ao an aq ap as ar au at aw av ay ax bb␣
˓→ab azad| ad bb ab af ac ah ae aj ag al ai an ak ap am ar ao at aq av as ax au az aw ba␣
˓→aa ay
ae| ae az ba ag aa ai ad ak af am ah ao aj aq al as an au ap aw ar ay at bb av ab␣˓→ac ax
af| af ay bb ah ab aj ac al ae an ag ap ai ar ak at am av ao ax aq az as ba au aa␣
˓→ad aw
ag| ag ax az ai ba ak aa am ad ao af aq ah as aj au al aw an ay ap bb ar ab at ac␣˓→ae av
ah| ah aw ay aj bb al ab an ac ap ae ar ag at ai av ak ax am az ao ba aq aa as ad␣
˓→af auai| ai av ax ak az am ba ao aa aq ad as af au ah aw aj ay al bb an ab ap ac ar ae␣˓→ag ataj| aj au aw al ay an bb ap ab ar ac at ae av ag ax ai az ak ba am aa ao ad aq af␣˓→ah asak| ak at av am ax ao az aq ba as aa au ad aw af ay ah bb aj ab al ac an ae ap ag␣
˓→ai aral| al as au an aw ap ay ar bb at ab av ac ax ae az ag ba ai aa ak ad am af ao ah␣˓→aj aq
am| am ar at ao av aq ax as az au ba aw aa ay ad bb af ab ah ac aj ae al ag an ai␣
˓→ak ap
an| an aq as ap au ar aw at ay av bb ax ab az ac ba ae aa ag ad ai af ak ah am aj␣
˓→al ao
ao| ao ap ar aq at as av au ax aw az ay ba bb aa ab ad ac af ae ah ag aj ai al ak␣
˓→am anap| ap ao aq ar as at au av aw ax ay az bb ba ab aa ac ad ae af ag ah ai aj ak al␣˓→an amaq| aq an ap as ar au at aw av ay ax bb az ab ba ac aa ae ad ag af ai ah ak aj am␣˓→ao alar| ar am ao at aq av as ax au az aw ba ay aa bb ad ab af ac ah ae aj ag al ai an␣
˓→ap ak(continues on next page)

1004

Chapter 35. Operation Tables

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)as| as al an au ap aw ar ay at bb av ab ax ac az ae ba ag aa ai ad ak af am ah ao␣˓→aq aj
at| at ak am av ao ax aq az as ba au aa aw ad ay af bb ah ab aj ac al ae an ag ap␣
˓→ar ai
au| au aj al aw an ay ap bb ar ab at ac av ae ax ag az ai ba ak aa am ad ao af aq␣
˓→as ahav| av ai ak ax am az ao ba aq aa as ad au af aw ah ay aj bb al ab an ac ap ae ar␣˓→at ag
aw| aw ah aj ay al bb an ab ap ac ar ae at ag av ai ax ak az am ba ao aa aq ad as␣
˓→au af
ax| ax ag ai az ak ba am aa ao ad aq af as ah au aj aw al ay an bb ap ab ar ac at␣˓→av aeay| ay af ah bb aj ab al ac an ae ap ag ar ai at ak av am ax ao az aq ba as aa au␣
˓→aw adaz| az ae ag ba ai aa ak ad am af ao ah aq aj as al au an aw ap ay ar bb at ab av␣
˓→ax acba| ba ac ae aa ag ad ai af ak ah am aj ao al aq an as ap au ar aw at ay av bb ax␣
˓→az abbb| bb ad af ab ah ac aj ae al ag an ai ap ak ar am at ao av aq ax as az au ba aw␣
˓→ay aa

Another symbol set is base 10 digits, padded with leading zeros to make a common width.
sage: from sage.matrix.operation_table import OperationTablesage: G = AlternatingGroup(4)˓→needs sage.groups
sage: OperationTable(G, operator.mul, names= digits )˓→needs sage.groups* 00 01 02 03 04 05 06 07 08 09 10 11+-----------------------------------00| 00 01 02 03 04 05 06 07 08 09 10 11
01| 01 02 00 05 03 04 07 08 06 11 09 10
02| 02 00 01 04 05 03 08 06 07 10 11 09
03| 03 06 09 00 07 10 01 04 11 02 05 08
04| 04 08 10 02 06 11 00 05 09 01 03 07
05| 05 07 11 01 08 09 02 03 10 00 04 06
06| 06 09 03 10 00 07 04 11 01 08 02 05
07| 07 11 05 09 01 08 03 10 02 06 00 04
08| 08 10 04 11 02 06 05 09 00 07 01 03
09| 09 03 06 07 10 00 11 01 04 05 08 02
10| 10 04 08 06 11 02 09 00 05 03 07 01
11| 11 05 07 08 09 01 10 02 03 04 06 00>>> from sage.all import *>>> from sage.matrix.operation_table import OperationTable>>> G = AlternatingGroup(Integer(4))˓→# needs sage.groups>>> OperationTable(G, operator.mul, names= digits )˓→needs sage.groups* 00 01 02 03 04 05 06 07 08 09 10 11+-----------------------------------00| 00 01 02 03 04 05 06 07 08 09 10 11
01| 01 02 00 05 03 04 07 08 06 11 09 10
02| 02 00 01 04 05 03 08 06 07 10 11 09
03| 03 06 09 00 07 10 01 04 11 02 05 08
04| 04 08 10 02 06 11 00 05 09 01 03 07

#␣
#␣

␣
#␣

(continues on next page)1005

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)05| 05 07 11 01 08 09 02 03 10 00 04 06
06| 06 09 03 10 00 07 04 11 01 08 02 05
07| 07 11 05 09 01 08 03 10 02 06 00 04
08| 08 10 04 11 02 06 05 09 00 07 01 03
09| 09 03 06 07 10 00 11 01 04 05 08 02
10| 10 04 08 06 11 02 09 00 05 03 07 01
11| 11 05 07 08 09 01 10 02 03 04 06 00

If the group’s elements are not too cumbersome, or the group is small, then the string representation of the elements
can be used.
sage: from sage.matrix.operation_table import OperationTablesage: G = AlternatingGroup(3)˓→needs sage.groups
sage: OperationTable(G, operator.mul, names= elements )˓→needs sage.groups*() (1,2,3) (1,3,2)+-----------------------()|() (1,2,3) (1,3,2)(1,2,3)| (1,2,3) (1,3,2)()(1,3,2)| (1,3,2)() (1,2,3)>>> from sage.all import *>>> from sage.matrix.operation_table import OperationTable>>> G = AlternatingGroup(Integer(3))˓→# needs sage.groups>>> OperationTable(G, operator.mul, names= elements )˓→needs sage.groups*() (1,2,3) (1,3,2)+-----------------------()|() (1,2,3) (1,3,2)(1,2,3)| (1,2,3) (1,3,2)()(1,3,2)| (1,3,2)() (1,2,3)

#␣
#␣

␣
#␣

You can give the elements any names you like, but they need to be ordered in the same order as returned by thecolumn_keys() method.
sage: # needs sage.groups
sage: from sage.matrix.operation_table import OperationTablesage: G = QuaternionGroup()
sage: T = OperationTable(G, operator.mul)
sage: T.column_keys()((), (1,2,3,4)(5,6,7,8), ..., (1,8,3,6)(2,7,4,5))
sage: names=[ 1 , I , -1 , -I , J , -K , -J , K ]sage: T.change_names(names=names)
sage: sorted(T.translation().items())[( -1 , (1,3)(2,4)(5,7)(6,8)), ..., ( K , (1,8,3,6)(2,7,4,5))]
sage: T*
1 I -1 -I J -K -J K+-----------------------1| 1 I -1 -I J -K -J K
I| I -1 -I 1 K J -K -J-1| -1 -I 1 I -J K J -K
-I| -I 1 I -1 -K -J K J
J| J -K -J K -1 -I 1 I-K| -K -J K J I -1 -I 1
(continues on next page)

1006

Chapter 35. Operation Tables

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)-J| -JK| K

K J -K 1
J -K -J -I

I -1 -I
1 I -1>>> from sage.all import *>>> # needs sage.groups>>> from sage.matrix.operation_table import OperationTable>>> G = QuaternionGroup()>>> T = OperationTable(G, operator.mul)>>> T.column_keys()((), (1,2,3,4)(5,6,7,8), ..., (1,8,3,6)(2,7,4,5))>>> names=[ 1 , I , -1 , -I , J , -K , -J , K ]>>> T.change_names(names=names)>>> sorted(T.translation().items())[( -1 , (1,3)(2,4)(5,7)(6,8)), ..., ( K , (1,8,3,6)(2,7,4,5))]>>> T*
1 I -1 -I J -K -J K+-----------------------1| 1 I -1 -I J -K -J K
I| I -1 -I 1 K J -K -J-1| -1 -I 1 I -J K J -K
-I| -I 1 I -1 -K -J K J
J| J -K -J K -1 -I 1 I-K| -K -J K J I -1 -I 1
-J| -J K J -K 1 I -1 -I
K| K J -K -J -I 1 I -1

With the right functions and a list comprehension, custom names can be easier. A multiplication table for hex digits(without carries):
sage: from sage.matrix.operation_table import OperationTablesage: R = Integers(16)sage: names=[ {:x} .format(Integer(a)) for a in R]
sage: OperationTable(R, operation=operator.mul, names=names)* 0 1 2 3 4 5 6 7 8 9 a b c d e f+-------------------------------0| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1| 0 1 2 3 4 5 6 7 8 9 a b c d e f
2| 0 2 4 6 8 a c e 0 2 4 6 8 a c e
3| 0 3 6 9 c f 2 5 8 b e 1 4 7 a d
4| 0 4 8 c 0 4 8 c 0 4 8 c 0 4 8 c
5| 0 5 a f 4 9 e 3 8 d 2 7 c 1 6 b
6| 0 6 c 2 8 e 4 a 0 6 c 2 8 e 4 a
7| 0 7 e 5 c 3 a 1 8 f 6 d 4 b 2 9
8| 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8
9| 0 9 2 b 4 d 6 f 8 1 a 3 c 5 e 7
a| 0 a 4 e 8 2 c 6 0 a 4 e 8 2 c 6
b| 0 b 6 1 c 7 2 d 8 3 e 9 4 f a 5
c| 0 c 8 4 0 c 8 4 0 c 8 4 0 c 8 4
d| 0 d a 7 4 1 e b 8 5 2 f c 9 6 3
e| 0 e c a 8 6 4 2 0 e c a 8 6 4 2
f| 0 f e d c b a 9 8 7 6 5 4 3 2 1>>> from sage.all import *>>> from sage.matrix.operation_table import OperationTable>>> R = Integers(Integer(16))>>> names=[ {:x} .format(Integer(a)) for a in R](continues on next page)1007

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> OperationTable(R, operation=operator.mul, names=names)* 0 1 2 3 4 5 6 7 8 9 a b c d e f+-------------------------------0| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1| 0 1 2 3 4 5 6 7 8 9 a b c d e f
2| 0 2 4 6 8 a c e 0 2 4 6 8 a c e
3| 0 3 6 9 c f 2 5 8 b e 1 4 7 a d
4| 0 4 8 c 0 4 8 c 0 4 8 c 0 4 8 c
5| 0 5 a f 4 9 e 3 8 d 2 7 c 1 6 b
6| 0 6 c 2 8 e 4 a 0 6 c 2 8 e 4 a
7| 0 7 e 5 c 3 a 1 8 f 6 d 4 b 2 9
8| 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8
9| 0 9 2 b 4 d 6 f 8 1 a 3 c 5 e 7
a| 0 a 4 e 8 2 c 6 0 a 4 e 8 2 c 6
b| 0 b 6 1 c 7 2 d 8 3 e 9 4 f a 5
c| 0 c 8 4 0 c 8 4 0 c 8 4 0 c 8 4
d| 0 d a 7 4 1 e b 8 5 2 f c 9 6 3
e| 0 e c a 8 6 4 2 0 e c a 8 6 4 2
f| 0 f e d c b a 9 8 7 6 5 4 3 2 1This should be flexible enough to create a variety of such tables.
sage: from sage.matrix.operation_table import OperationTablesage: from operator import xor
sage: T=OperationTable(ZZ, xor, elements=range(8))
sage: T. a b c d e f g h+---------------a| a b c d e f g hb| b a d c f e h g
c| c d a b g h e f
d| d c b a h g f e
e| e f g h a b c d
f| f e h g b a d c
g| g h e f c d a b
h| h g f e d c b a
sage: names=[ 000 , 001 , 010 , 011 , 100 , 101 , 110 , 111 ]sage: T.change_names(names)
sage: T.set_print_symbols( ^ , \\land )sage: T
^ 000 001 010 011 100 101 110 111+-------------------------------000| 000 001 010 011 100 101 110 111
001| 001 000 011 010 101 100 111 110010| 010 011 000 001 110 111 100 101
011| 011 010 001 000 111 110 101 100
100| 100 101 110 111 000 001 010 011
101| 101 100 111 110 001 000 011 010
110| 110 111 100 101 010 011 000 001
111| 111 110 101 100 011 010 001 000
sage: T = OperationTable([False, True], operator.or_, names =sage: T
. False True+-----------False| False True
True| True True

1008

elements )Chapter 35. Operation Tables

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> from sage.matrix.operation_table import OperationTable>>> from operator import xor>>> T=OperationTable(ZZ, xor, elements=range(Integer(8)))>>> T. a b c d e f g h+---------------a| a b c d e f g hb| b a d c f e h g
c| c d a b g h e f
d| d c b a h g f e
e| e f g h a b c d
f| f e h g b a d c
g| g h e f c d a b
h| h g f e d c b a>>> names=[ 000 , 001 , 010 , 011 , 100 , 101 , 110 , 111 ]>>> T.change_names(names)>>> T.set_print_symbols( ^ , \\land )>>> T^ 000 001 010 011 100 101 110 111+-------------------------------000| 000 001 010 011 100 101 110 111
001| 001 000 011 010 101 100 111 110010| 010 011 000 001 110 111 100 101
011| 011 010 001 000 111 110 101 100
100| 100 101 110 111 000 001 010 011
101| 101 100 111 110 001 000 011 010
110| 110 111 100 101 010 011 000 001
111| 111 110 101 100 011 010 001 000>>> T = OperationTable([False, True], operator.or_, names =>>> T. False True+-----------False| False True
True| True Trueelements )AUTHORS:• Rob Beezer (2010-03-15)• Bruno Edwards (2022-10-31)
change_names(names)
For an existing operation table, change the names used for the elements.
INPUT:• names – the type of names used, values are:–letters – lowercase ASCII letters are used for a base 26 representation of the elements’ positions in the list given by list(), padded to a common width with leading ‘a’s.

–

digits – base 10 representation of the elements’ positions in the list given by list(), padded
to a common width with leading zeros.

–

elements – the string representations of the elements themselves.

– a list - a list of strings, where the length of the list equals the number of elements.

1009

Matrices and Spaces of Matrices, Release 10.4

OUTPUT: None. This method changes the table “in-place”, so any printed version will change and the outputof the dict() will also change. So any items of interest about a particular table need to be copied/savedprior to calling this method.
EXAMPLES:
More examples can be found in the documentation for OperationTable since creating a new operationtable uses the same routine.
sage: # needs sage.groups
sage: from sage.matrix.operation_table import OperationTablesage: D = DihedralGroup(2)sage: T = OperationTable(D, operator.mul)
sage: T* a b c d+-------a| a b c d
b| b a d c
c| c d a b
d| d c b a
sage: T.translation()[ c ](1,2)
sage: T.change_names( digits )sage: T* 0 1 2 3+-------0| 0 1 2 3
1| 1 0 3 2
2| 2 3 0 1
3| 3 2 1 0
sage: T.translation()[ 2 ](1,2)
sage: T.change_names( elements )sage: T*()
(3,4)
(1,2) (1,2)(3,4)+-------------------------------------------()|()(3,4)(1,2) (1,2)(3,4)(3,4)|(3,4)() (1,2)(3,4)(1,2)(1,2)|(1,2) (1,2)(3,4)()(3,4)(1,2)(3,4)| (1,2)(3,4)
(1,2)
(3,4)
()
sage: T.translation()[ (1,2) ](1,2)
sage: T.change_names([ w , x , y , z ])sage: T* w x y z+-------w| w x y z
x| x w z y
y| y z w x
z| z y x w
sage: T.translation()[ y ](1,2)>>> from sage.all import *>>> # needs sage.groups>>> from sage.matrix.operation_table import OperationTable>>> D = DihedralGroup(Integer(2))>>> T = OperationTable(D, operator.mul)(continues on next page)

1010

Chapter 35. Operation Tables

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> T* a b c d+-------a| a b c d
b| b a d c
c| c d a b
d| d c b a>>> T.translation()[ c ](1,2)>>> T.change_names( digits )>>> T* 0 1 2 3+-------0| 0 1 2 3
1| 1 0 3 2
2| 2 3 0 1
3| 3 2 1 0>>> T.translation()[ 2 ](1,2)>>> T.change_names( elements )
>>> T
*
()
(3,4)
(1,2) (1,2)(3,4)+-------------------------------------------()|()(3,4)(1,2) (1,2)(3,4)(3,4)|(3,4)() (1,2)(3,4)(1,2)(1,2)|(1,2) (1,2)(3,4)()(3,4)(1,2)(3,4)| (1,2)(3,4)
(1,2)
(3,4)
()
>>> T.translation()[ (1,2) ](1,2)>>> T.change_names([ w , x , y , z ])>>> T
* w x y z+-------w| w x y z
x| x w z y
y| y z w x
z| z y x w>>> T.translation()[ y ](1,2)

color_table(element_names=True, cmap=None, **options)
Return a graphic image as a square grid where entries are color coded.
INPUT:• element_names – (default : True) Whether to display text with element names on the image• cmap – (default: matplotlib.cm.gist_rainbow) color map for plot, see matplotlib.cm• **options – passed on to matrix_plot()
EXAMPLES:
sage: from sage.matrix.operation_table import OperationTablesage: OTa = OperationTable(SymmetricGroup(3), operation=operator.mul)
˓→needs sage.groups
sage: OTa.color_table()
˓→needs sage.groups sage.plot#␣#␣(continues on next page)1011

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Graphics object consisting of 37 graphics primitives>>> from sage.all import *>>> from sage.matrix.operation_table import OperationTable>>> OTa = OperationTable(SymmetricGroup(Integer(3)), operation=operator.mul) ␣˓→# needs sage.groups>>> OTa.color_table()#␣˓→needs sage.groups sage.plot
Graphics object consisting of 37 graphics primitives

a

b

c

d

e

f

b

a

d

c

f

e

c

e

a

f

b

d

d

f

b

e

a

c

e

c

f

a

d

b

f

d

e

b

c

a

column_keys()
Returns a tuple of the elements used to build the table.
Note: column_keys and row_keys are identical. Both list the elements in the order used to label thetable.
OUTPUT:
The elements of the algebraic structure used to build the table, as a list. But most importantly, elements arepresent in the list in the order which they appear in the table’s column headings.
EXAMPLES:
sage: from sage.matrix.operation_table import OperationTablesage: G = AlternatingGroup(3)˓→needs sage.groups
sage: T = OperationTable(G, operator.mul)
˓→needs sage.groups
sage: T.column_keys()
˓→needs sage.groups((), (1,2,3), (1,3,2))

1012

#␣
#␣
#␣

Chapter 35. Operation Tables

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> from sage.matrix.operation_table import OperationTable>>> G = AlternatingGroup(Integer(3))˓→# needs sage.groups>>> T = OperationTable(G, operator.mul)
˓→needs sage.groups>>> T.column_keys()
˓→needs sage.groups((), (1,2,3), (1,3,2))

␣
#␣
#␣

gray_table(**options)
Return a graphic image as a square grid where entries are displayed in grayscale.
INPUT:• element_names – (default: True) whether to display text with element names on the image• **options – passed on to matrix_plot()
EXAMPLES:
sage: from sage.matrix.operation_table import OperationTablesage: OTa = OperationTable(SymmetricGroup(3), operation=operator.mul)
˓→needs sage.groups
sage: OTa.gray_table()
˓→needs sage.groups sage.plot
Graphics object consisting of 37 graphics primitives#␣#␣>>> from sage.all import *>>> from sage.matrix.operation_table import OperationTable>>> OTa = OperationTable(SymmetricGroup(Integer(3)), operation=operator.mul) ␣˓→# needs sage.groups>>> OTa.gray_table()#␣˓→needs sage.groups sage.plot
Graphics object consisting of 37 graphics primitives

a

b

c

d

e

f

b

a

d

c

f

e

c

e

a

f

b

d

d

f

b

e

a

c

e

c

f

a

d

b

f

d

e

b

c

a

matrix_of_variables()1013

Matrices and Spaces of Matrices, Release 10.4

This method provides some backward compatibility for Cayley tables of groups, whose output was restricted
to this single format.
EXAMPLES:
The output here is from the doctests for the old cayley_table() method for permutation groups.
sage: # needs sage.groups
sage: from sage.matrix.operation_table import OperationTablesage: G = PermutationGroup([ (1,2,3) , (2,3) ])sage: T = OperationTable(G, operator.mul)
sage: T.matrix_of_variables()[x0 x1 x2 x3 x4 x5][x1 x0 x3 x2 x5 x4][x2 x4 x0 x5 x1 x3][x3 x5 x1 x4 x0 x2][x4 x2 x5 x0 x3 x1][x5 x3 x4 x1 x2 x0]
sage: T.column_keys()[2]*T.column_keys()[2] == T.column_keys()[0]True>>> from sage.all import *>>> # needs sage.groups>>> from sage.matrix.operation_table import OperationTable>>> G = PermutationGroup([ (1,2,3) , (2,3) ])>>> T = OperationTable(G, operator.mul)>>> T.matrix_of_variables()[x0 x1 x2 x3 x4 x5][x1 x0 x3 x2 x5 x4][x2 x4 x0 x5 x1 x3][x3 x5 x1 x4 x0 x2][x4 x2 x5 x0 x3 x1][x5 x3 x4 x1 x2 x0]>>> T.column_keys()[Integer(2)]*T.column_keys()[Integer(2)] == T.column_
˓→keys()[Integer(0)]True

row_keys()
Returns a tuple of the elements used to build the table.
Note: column_keys and row_keys are identical. Both list the elements in the order used to label thetable.
OUTPUT:
The elements of the algebraic structure used to build the table, as a list. But most importantly, elements arepresent in the list in the order which they appear in the table’s column headings.
EXAMPLES:
sage: from sage.matrix.operation_table import OperationTablesage: G = AlternatingGroup(3)˓→needs sage.groups
sage: T = OperationTable(G, operator.mul)
˓→needs sage.groups
sage: T.column_keys()

#␣
#␣
#␣
(continues on next page)

1014

Chapter 35. Operation Tables

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)needs sage.groups((), (1,2,3), (1,3,2))
˓→>>> from sage.all import *>>> from sage.matrix.operation_table import OperationTable>>> G = AlternatingGroup(Integer(3))˓→# needs sage.groups>>> T = OperationTable(G, operator.mul)
˓→needs sage.groups>>> T.column_keys()
˓→needs sage.groups((), (1,2,3), (1,3,2))

␣
#␣
#␣

set_print_symbols(ascii, latex)
Set the symbols used for text and LaTeX printing of operation tables.
INPUT:• ascii – a single character for text table• latex – a string to represent an operation in LaTeX math mode. Note the need for double-backslashes
to escape properly.
EXAMPLES:
sage: # needs sage.groups
sage: from sage.matrix.operation_table import OperationTablesage: G = AlternatingGroup(3)sage: T = OperationTable(G, operator.mul)
sage: T.set_print_symbols( @ , \\times )sage: T@ a b c+-----a| a b c
b| b c ac| c a b
sage: T._latex_(){\\setlength{\\arraycolsep}{2ex}\n\\begin{array}{r|*{3}{r}}\n\\multicolumn{1}˓→{c|}{\\times}&a&b&c\\\\\\hline\n{}a&a&b&c\\\\\n{}b&b&c&a\\\\\n{}c&c&a&b\\\\\
˓→n\\end{array}}>>> from sage.all import *>>> # needs sage.groups>>> from sage.matrix.operation_table import OperationTable>>> G = AlternatingGroup(Integer(3))>>> T = OperationTable(G, operator.mul)>>> T.set_print_symbols( @ , \\times )>>> T@ a b c+-----a| a b c
b| b c ac| c a b>>> T._latex_(){\\setlength{\\arraycolsep}{2ex}\n\\begin{array}{r|*{3}{r}}\n\\multicolumn{1}˓→{c|}{\\times}&a&b&c\\\\\\hline\n{}a&a&b&c\\\\\n{}b&b&c&a\\\\\n{}c&c&a&b\\\\\
˓→n\\end{array}}1015

Matrices and Spaces of Matrices, Release 10.4

table()
Returns the table as a list of lists, using integers to reference the elements.
OUTPUT: The rows of the table, as a list of rows, each row being a list of integer entries. The integers
correspond to the order of the elements in the headings of the table and the order of the output of the list()
method.
EXAMPLES:
sage: from sage.matrix.operation_table import OperationTablesage: C = CyclicPermutationGroup(3)˓→needs sage.groups
sage: T=OperationTable(C, operator.mul)
˓→needs sage.groups
sage: T.table()
˓→needs sage.groups[[0, 1, 2], [1, 2, 0], [2, 0, 1]]>>> from sage.all import *>>> from sage.matrix.operation_table import OperationTable>>> C = CyclicPermutationGroup(Integer(3))˓→# needs sage.groups>>> T=OperationTable(C, operator.mul)
˓→needs sage.groups>>> T.table()
˓→needs sage.groups[[0, 1, 2], [1, 2, 0], [2, 0, 1]]

#␣
#␣
#␣

␣
#␣
#␣

translation()
Returns a dictionary associating names with elements.
OUTPUT: A dictionary whose keys are strings used as names for entries of the table and values that are theactual elements of the algebraic structure.
EXAMPLES:
sage: from sage.matrix.operation_table import OperationTablesage: G = AlternatingGroup(3)˓→needs sage.groups
sage: T = OperationTable(G, operator.mul, names=[ p , q , r ])˓→needs sage.groups
sage: T.translation()
˓→needs sage.groups{ p : (), q : (1,2,3), r : (1,3,2)}>>> from sage.all import *>>> from sage.matrix.operation_table import OperationTable>>> G = AlternatingGroup(Integer(3))˓→# needs sage.groups>>> T = OperationTable(G, operator.mul, names=[ p , q , r ])˓→needs sage.groups>>> T.translation()
˓→needs sage.groups{ p : (), q : (1,2,3), r : (1,3,2)}

1016

#␣
#␣
#␣

␣
#␣
#␣

Chapter 35. Operation Tables

CHAPTERTHIRTYSIXACTIONS USED BY THE COERCION MODEL FOR MATRIX ANDVECTOR MULTIPLICATIONS

Warning: The class MatrixMulAction and its descendants extends the class Action. As a consequenceobjects from these classes only keep weak references to the underlying sets which are acted upon. This decision wasmade in Issue #715 in order to allow garbage collection within the coercion framework, where actions are mainly
used, and avoid memory leaks.
To ensure that the underlying set of such an object does not get garbage collected, it is sufficient to explicitly create astrong reference to it before creating the action.
sage: MSQ = MatrixSpace(QQ, 2)
sage: MSZ = MatrixSpace(ZZ[ x ], 2)
sage: A = MSQ.get_action(MSZ)
sage: A
Left action by Full MatrixSpace of 2 by 2 dense matrices over Rational Field
on Full MatrixSpace of 2 by 2 dense matrices
over Univariate Polynomial Ring in x over Integer Ringsage: import gc
sage: _ = gc.collect()
sage: A
Left action by Full MatrixSpace of 2 by 2 dense matrices over Rational Field
on Full MatrixSpace of 2 by 2 dense matrices
over Univariate Polynomial Ring in x over Integer Ring>>> from sage.all import *>>> MSQ = MatrixSpace(QQ, Integer(2))>>> MSZ = MatrixSpace(ZZ[ x ], Integer(2))>>> A = MSQ.get_action(MSZ)>>> A
Left action by Full MatrixSpace of 2 by 2 dense matrices over Rational Field
on Full MatrixSpace of 2 by 2 dense matrices
over Univariate Polynomial Ring in x over Integer Ring>>> import gc>>> _ = gc.collect()>>> A
Left action by Full MatrixSpace of 2 by 2 dense matrices over Rational Field
on Full MatrixSpace of 2 by 2 dense matrices
over Univariate Polynomial Ring in x over Integer Ring

Note: The MatrixSpace() function caches the objects it creates. Therefore, the underlying set MSZ in the above
example will not be garbage collected, even if it is not strongly ref’ed. Nonetheless, there is no guarantee that the set that1017

Matrices and Spaces of Matrices, Release 10.4

is acted upon will always be cached in such a way, so that following the above example is good practice.
EXAMPLES:
An action requires a common parent for the base rings, so the following doesn’t work (see Issue #17859):
sage: vector(QQ, [1]) * matrix(Zmod(2), [[1]])Traceback (most recent call last):...
TypeError: unsupported operand parent(s) for *: Vector space ofdimension 1 over Rational Field and Full MatrixSpace of 1 by 1
dense matrices over Ring of integers modulo 2>>> from sage.all import *>>> vector(QQ, [Integer(1)]) * matrix(Zmod(Integer(2)), [[Integer(1)]])
Traceback (most recent call last):...
TypeError: unsupported operand parent(s) for *: Vector space ofdimension 1 over Rational Field and Full MatrixSpace of 1 by 1
dense matrices over Ring of integers modulo 2

AUTHOR:• Robert Bradshaw (2007-09): Initial version.
class sage.matrix.action.MatrixMatrixAction
Bases: MatrixMulAction
Action of a matrix on another matrix.
This is always implemented as a left action.
EXAMPLES:
By Issue #715, there only is a weak reference on the underlying set, so that it can be garbage collected if only theaction itself is explicitly referred to. Hence, we first assign the involved matrix spaces to a variable:
sage: R.<x> = ZZ[]
sage: MSR = MatrixSpace(R, 3, 3)
sage: MSQ = MatrixSpace(QQ, 3, 2)
sage: from sage.matrix.action import MatrixMatrixAction
sage: A = MatrixMatrixAction(MSR, MSQ); A
Left action
by Full MatrixSpace of 3 by 3 dense matrices
over Univariate Polynomial Ring in x over Integer Ringon Full MatrixSpace of 3 by 2 dense matrices over Rational Field
sage: A.codomain()
Full MatrixSpace of 3 by 2 dense matrices
over Univariate Polynomial Ring in x over Rational Field
sage: A(matrix(R, 3, 3, x), matrix(QQ, 3, 2, range(6)))[ 0x][2*x 3*x][4*x 5*x]>>> from sage.all import *>>> R = ZZ[ x ]; (x,) = R._first_ngens(1)>>> MSR = MatrixSpace(R, Integer(3), Integer(3))>>> MSQ = MatrixSpace(QQ, Integer(3), Integer(2))>>> from sage.matrix.action import MatrixMatrixAction(continues on next page)

1018

Chapter 36. Actions used by the coercion model for matrix and vector multiplications

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> A = MatrixMatrixAction(MSR, MSQ); A
Left action
by Full MatrixSpace of 3 by 3 dense matrices
over Univariate Polynomial Ring in x over Integer Ringon Full MatrixSpace of 3 by 2 dense matrices over Rational Field>>> A.codomain()
Full MatrixSpace of 3 by 2 dense matrices
over Univariate Polynomial Ring in x over Rational Field>>> A(matrix(R, Integer(3), Integer(3), x), matrix(QQ, Integer(3), Integer(2),␣
˓→range(Integer(6))))[ 0x][2*x 3*x][4*x 5*x]

Note: The MatrixSpace() function caches the object it creates. Therefore, the underlying set MSZ in theabove example will not be garbage collected, even if it is not strongly ref’ed. Nonetheless, there is no guaranteethat the set that is acted upon will always be cached in such a way, so that following the above example is goodpractice.
class sage.matrix.action.MatrixMulAction
Bases: Action
Abstract base class for a matrix space acting on something.
EXAMPLES:
sage: MSQ = MatrixSpace(QQ, 2)
sage: MSZ = MatrixSpace(ZZ[ x ], 2)
sage: A = MSQ.get_action(MSZ); A
Left action by Full MatrixSpace of 2 by 2 dense matrices over Rational Field
on Full MatrixSpace of 2 by 2 dense matrices
over Univariate Polynomial Ring in x over Integer Ringsage: A.actor()
Full MatrixSpace of 2 by 2 dense matrices over Rational Field
sage: A.domain()
Full MatrixSpace of 2 by 2 dense matrices
over Univariate Polynomial Ring in x over Integer Ringsage: A.codomain()
Full MatrixSpace of 2 by 2 dense matrices
over Univariate Polynomial Ring in x over Rational Field>>> from sage.all import *>>> MSQ = MatrixSpace(QQ, Integer(2))>>> MSZ = MatrixSpace(ZZ[ x ], Integer(2))>>> A = MSQ.get_action(MSZ); A
Left action by Full MatrixSpace of 2 by 2 dense matrices over Rational Field
on Full MatrixSpace of 2 by 2 dense matrices
over Univariate Polynomial Ring in x over Integer Ring>>> A.actor()
Full MatrixSpace of 2 by 2 dense matrices over Rational Field>>> A.domain()
Full MatrixSpace of 2 by 2 dense matrices
over Univariate Polynomial Ring in x over Integer Ring>>> A.codomain()(continues on next page)1019

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Full MatrixSpace of 2 by 2 dense matrices
over Univariate Polynomial Ring in x over Rational Field

codomain()class sage.matrix.action.MatrixPolymapAction
Bases: MatrixMulAction
Left action of a matrix on a scheme polynomial morphismclass sage.matrix.action.MatrixSchemePointAction
Bases: MatrixMulAction
Action class for left multiplication of schemes points by matrices.
class sage.matrix.action.MatrixVectorAction
Bases: MatrixMulAction
Left action of a matrix on a vector
class sage.matrix.action.PolymapMatrixAction
Bases: MatrixMulAction
Right action of a matrix on a scheme polynomial morphismclass sage.matrix.action.VectorMatrixAction
Bases: MatrixMulAction
Right action of a matrix on a vector

1020

Chapter 36. Actions used by the coercion model for matrix and vector multiplications

CHAPTERTHIRTYSEVEN

FUNCTIONS FOR CHANGING THE BASE RING OF MATRICESQUICKLYsage.matrix.change_ring.integer_to_real_double_dense(A)Fast conversion of a matrix over the integers to a matrix with real double entries.
INPUT:
A – a dense matrix over the integers
OUTPUT:– a dense real double matrix
EXAMPLES:
sage: a = matrix(ZZ,2,3,[-2,-5,3,4,8,1030339830489349908])
sage: a.change_ring(RDF)
[
-2.0
-5.0
3.0]
[
4.0
8.0 1.0303398304893499e+18]
sage: import sage.matrix.change_ring
sage: sage.matrix.change_ring.integer_to_real_double_dense(a)
[
-2.0
-5.0
3.0]
[
4.0
8.0 1.0303398304893499e+18]>>> from sage.all import *>>> a = matrix(ZZ,Integer(2),Integer(3),[-Integer(2),-Integer(5),Integer(3),˓→Integer(4),Integer(8),Integer(1030339830489349908)])>>> a.change_ring(RDF)
[
-2.0
-5.0
3.0]
[
4.0
8.0 1.0303398304893499e+18]>>> import sage.matrix.change_ring>>> sage.matrix.change_ring.integer_to_real_double_dense(a)
[
-2.0
-5.0
3.0]
[
4.0
8.0 1.0303398304893499e+18]1021

Matrices and Spaces of Matrices, Release 10.4

1022

Chapter 37. Functions for changing the base ring of matrices quickly

CHAPTERTHIRTYEIGHTECHELON MATRICES OVER FINITE FIELDS.

sage.matrix.echelon_matrix.reduced_echelon_matrix_iterator(K, k, n, sparse=False,
copy=True,
set_immutable=False)
An iterator over (𝑘, 𝑛) reduced echelon matrices over the finite field 𝐾.
INPUT:• K – a finite field• k – number of rows (or the size of the subspace)• n – number of columns (or the dimension of the ambient space)• sparse – boolean (default is False)• copy – boolean. If set to False then iterator yields the same matrix over and over (but with different
entries). Default is True which is safer but might be slower.
• set_immutable – boolean. If set to True then the output matrices are immutable. This option automatically turns copy into True.
Note: We ensure that the iteration order is so that all matrices with given pivot columns are generated consecutively.
Furthermore, the order in which the pivot columns appear is lexicographic.
It would be faster to generate the pivots columns following a Gray code. There would be only one pivot changing
at a time, avoiding the possibly expensive m0.__copy__(). However that would modify the generation ordersome functions depend upon.
EXAMPLES:
sage: from sage.matrix.echelon_matrix import reduced_echelon_matrix_iterator
sage: it = reduced_echelon_matrix_iterator(GF(2), 2, 3)
sage: for m in it:....:
print(m)....:print(m.pivots())....:
print("*******")[1 0 0][0 1 0](0, 1)*******[1 0 0][0 1 1](0, 1)*******(continues on next page)1023

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[1 0 1][0 1 0](0, 1)*******[1 0 1][0 1 1](0, 1)*******[1 0 0][0 0 1](0, 2)*******[1 1 0][0 0 1](0, 2)*******[0 1 0][0 0 1](1, 2)*******>>> from sage.all import *>>> from sage.matrix.echelon_matrix import reduced_echelon_matrix_iterator>>> it = reduced_echelon_matrix_iterator(GF(Integer(2)), Integer(2), Integer(3))>>> for m in it:...
print(m)...
print(m.pivots())...
print("*******")[1 0 0][0 1 0](0, 1)*******[1 0 0][0 1 1](0, 1)*******[1 0 1][0 1 0](0, 1)*******[1 0 1][0 1 1](0, 1)*******[1 0 0][0 0 1](0, 2)*******[1 1 0][0 0 1](0, 2)*******[0 1 0][0 0 1](1, 2)*******

1024

Chapter 38. Echelon matrices over finite fields.

CHAPTERTHIRTYNINEMISCELLANEOUS MATRIX FUNCTIONS

sage.matrix.matrix_misc.permanental_minor_polynomial(A, permanent_only=False, var='t',
prec=None)
Return the polynomial of the sums of permanental minors of A.
INPUT:• 𝐴 – a matrix• 𝑝𝑒𝑟𝑚𝑎𝑛𝑒𝑛𝑡𝑜 𝑛𝑙𝑦 – if True, return only the permanent of 𝐴
• 𝑣𝑎𝑟 – name of the polynomial variable• 𝑝𝑟𝑒𝑐 – if prec is not None, truncate the polynomial at precision 𝑝𝑟𝑒𝑐
The polynomial of the sums of permanental minors is𝑚𝑖𝑛(𝑛𝑟𝑜𝑤𝑠,𝑛𝑐𝑜𝑙𝑠)∑︁𝑝𝑖 (𝐴)𝑥𝑖

𝑖=0

where 𝑝𝑖 (𝐴) is the 𝑖-th permanental minor of 𝐴 (that can also be obtained through the method permanental_minor() via A.permanental_minor(i)).
The algorithm implemented by that function has been developed by P. Butera and M. Pernici, see [BP2015]. Itscomplexity is 𝑂(2𝑛 𝑚2 𝑛) where 𝑚 and 𝑛 are the number of rows and columns of 𝐴. Moreover, if 𝐴 is a bandedmatrix with width 𝑤, that is 𝐴𝑖𝑗 = 0 for |𝑖 − 𝑗| > 𝑤 and 𝑤 < 𝑛/2, then the complexity of the algorithm is𝑂(4𝑤 (𝑤 + 1)𝑛2 ).
INPUT:• A – matrix• permanent_only – optional boolean. If True, only the permanent is computed (might be faster).
• var – a variable name
EXAMPLES:
sage: from sage.matrix.matrix_misc import permanental_minor_polynomial
sage: m = matrix([[1,1],[1,2]])
sage: permanental_minor_polynomial(m)3*t^2 + 5*t + 1
sage: permanental_minor_polynomial(m, permanent_only=True)3
sage: permanental_minor_polynomial(m, prec=2)
5*t + 11025

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> from sage.matrix.matrix_misc import permanental_minor_polynomial>>> m = matrix([[Integer(1),Integer(1)],[Integer(1),Integer(2)]])>>> permanental_minor_polynomial(m)3*t^2 + 5*t + 1>>> permanental_minor_polynomial(m, permanent_only=True)3>>> permanental_minor_polynomial(m, prec=Integer(2))
5*t + 1
sage: M = MatrixSpace(ZZ,4,4)
sage: A = M([1,0,1,0,1,0,1,0,1,0,10,10,1,0,1,1])
sage: permanental_minor_polynomial(A)84*t^3 + 114*t^2 + 28*t + 1
sage: [A.permanental_minor(i) for i in range(5)][1, 28, 114, 84, 0]>>> from sage.all import *>>> M = MatrixSpace(ZZ,Integer(4),Integer(4))>>> A = M([Integer(1),Integer(0),Integer(1),Integer(0),Integer(1),Integer(0),˓→Integer(1),Integer(0),Integer(1),Integer(0),Integer(10),Integer(10),Integer(1),˓→Integer(0),Integer(1),Integer(1)])>>> permanental_minor_polynomial(A)84*t^3 + 114*t^2 + 28*t + 1>>> [A.permanental_minor(i) for i in range(Integer(5))][1, 28, 114, 84, 0]

An example over:sage: M = MatrixSpace(QQ,2,2)
sage: A = M([1/5,2/7,3/2,4/5])
sage: permanental_minor_polynomial(A, True)
103/175>>> from sage.all import *>>> M = MatrixSpace(QQ,Integer(2),Integer(2))>>> A = M([Integer(1)/Integer(5),Integer(2)/Integer(7),Integer(3)/Integer(2),˓→Integer(4)/Integer(5)])>>> permanental_minor_polynomial(A, True)
103/175

An example with polynomial coefficients:
sage: R.<a> = PolynomialRing(ZZ)
sage: A = MatrixSpace(R,2)([[a,1], [a,a+1]])
sage: permanental_minor_polynomial(A, True)a^2 + 2*a>>> from sage.all import *>>> R = PolynomialRing(ZZ, names=( a ,)); (a,) = R._first_ngens(1)>>> A = MatrixSpace(R,Integer(2))([[a,Integer(1)], [a,a+Integer(1)]])>>> permanental_minor_polynomial(A, True)a^2 + 2*a

A usage of the var argument:

1026

Chapter 39. Miscellaneous matrix functions

Matrices and Spaces of Matrices, Release 10.4

sage: m = matrix(ZZ,4,[0,1,2,3,1,2,3,0,2,3,0,1,3,0,1,2])
sage: permanental_minor_polynomial(m, var= x )164*x^4 + 384*x^3 + 172*x^2 + 24*x + 1>>> from sage.all import *>>> m = matrix(ZZ,Integer(4),[Integer(0),Integer(1),Integer(2),Integer(3),˓→Integer(1),Integer(2),Integer(3),Integer(0),Integer(2),Integer(3),Integer(0),˓→Integer(1),Integer(3),Integer(0),Integer(1),Integer(2)])>>> permanental_minor_polynomial(m, var= x )164*x^4 + 384*x^3 + 172*x^2 + 24*x + 1

ALGORITHM:
The permanent 𝑝𝑒𝑟𝑚(𝐴) of a 𝑛 × 𝑛 matrix 𝐴 is the coefficient of the 𝑥1 𝑥2 . . . 𝑥𝑛 monomial in
⎛
⎞
𝑛
𝑛
∏︁
∑︁
⎝
𝐴𝑖𝑗 𝑥𝑗 ⎠𝑖=1

𝑗=1

Evaluating this product one can neglect 𝑥2𝑖 , that is 𝑥𝑖 can be considered to be nilpotent of order 2.
To formalize this procedure, consider the algebra 𝑅 = 𝐾[𝜂1 , 𝜂2 , . . . , 𝜂𝑛 ] where the 𝜂𝑖 are commuting,nilpotent of order 2 (i.e. 𝜂𝑖2 = 0). Formally it is the quotient ring of the polynomial ring in 𝜂1 , 𝜂2 , . . . , 𝜂𝑛quotiented by the ideal generated by the 𝜂𝑖2 .
We will mostly consider the ring 𝑅[𝑡] of polynomials over 𝑅. We denote a generic element of 𝑅[𝑡] by𝑝(𝜂1 , . . . , 𝜂𝑛 ) or 𝑝(𝜂𝑖1 , . . . , 𝜂𝑖𝑘 ) if we want to emphasize that some monomials in the 𝜂𝑖 are missing.
Introduce an “integration” operation ⟨𝑝⟩ over 𝑅 and 𝑅[𝑡] consisting in the sum of the coefficients of thenon-vanishing monomials in 𝜂𝑖 (i.e. the result of setting all variables 𝜂𝑖 to 1). Let us emphasize that thisis not a morphism of algebras as ⟨𝜂1 ⟩2 = 1 while ⟨𝜂12 ⟩ = 0!
Let us consider an example of computation. Let 𝑝1 = 1 + 𝑡𝜂1 + 𝑡𝜂2 and 𝑝2 = 1 + 𝑡𝜂1 + 𝑡𝜂3 . Then𝑝1 𝑝2 = 1 + 2𝑡𝜂1 + 𝑡(𝜂2 + 𝜂3 ) + 𝑡2 (𝜂1 𝜂2 + 𝜂1 𝜂3 + 𝜂2 𝜂3 )and⟨𝑝1 𝑝2 ⟩ = 1 + 4𝑡 + 3𝑡2
In this formalism, the permanent is just𝑝𝑒𝑟𝑚(𝐴) = ⟨

𝑛 ∑︁
𝑛
∏︁

𝐴𝑖𝑗 𝜂𝑗 ⟩𝑖=1 𝑗=1

A useful property of ⟨.⟩ which makes this algorithm efficient for band matrices is the following: let
𝑝1 (𝜂1 , . . . , 𝜂𝑛 ) and 𝑝2 (𝜂𝑗 , . . . , 𝜂𝑛 ) be polynomials in 𝑅[𝑡] where 𝑗 ≥ 1. Then one has⟨𝑝1 (𝜂1 , . . . , 𝜂𝑛 )𝑝2 ⟩ = ⟨𝑝1 (1, . . . , 1, 𝜂𝑗 , . . . , 𝜂𝑛 )𝑝2 ⟩where 𝜂1 , .., 𝜂𝑗−1 are replaced by 1 in 𝑝1 . Informally, we can “integrate” these variables before performing the product. More generally, if a monomial 𝜂𝑖 is missing in one of the terms of a product of
two terms, then it can be integrated in the other term.
Now let us consider an 𝑚 × 𝑛 matrix with 𝑚 ≤ 𝑛. The sum of permanental `k`-minors of `A` is∑︁
𝑝𝑒𝑟𝑚(𝐴, 𝑘) =𝑝𝑒𝑟𝑚(𝐴𝑟,𝑐 )
𝑟,𝑐

1027

Matrices and Spaces of Matrices, Release 10.4

where the sum is over the 𝑘-subsets 𝑟 of rows and 𝑘-subsets 𝑐 of columns and 𝐴𝑟,𝑐 is the submatrix obtained from 𝐴 by keeping only the rows 𝑟 and columns 𝑐. Of course 𝑝𝑒𝑟𝑚(𝐴, min(𝑚, 𝑛)) = 𝑝𝑒𝑟𝑚(𝐴)and note that 𝑝𝑒𝑟𝑚(𝐴, 1) is just the sum of all entries of the matrix.
The generating function of these sums of permanental minors is
⎞⟩
⟨𝑚 ⎛
𝑛
∏︁
∑︁
⎝1 + 𝑡𝑔(𝑡) =𝐴𝑖𝑗 𝜂𝑗 ⎠𝑖=1

𝑗=1

In fact the 𝑡𝑘 coefficient of 𝑔(𝑡) corresponds to choosing 𝑘 rows of 𝐴; 𝜂𝑖 is associated to the i-th column;
nilpotency avoids having twice the same column in a product of 𝐴’s.
For more details, see the article [BP2015].
From a technical point of view, the product in 𝐾[𝜂1 , . . . , 𝜂𝑛 ][𝑡] is implemented as a subroutine in
prm_mul(). The indices of the rows and columns actually start at 0, so the variables are 𝜂0 , . . . , 𝜂𝑛−1 .
Polynomials are represented in dictionary form: to a variable 𝜂𝑖 is associated the key 2𝑖 (or in Python
1 << i). The keys associated to products are obtained by considering the development in base 2:
to the monomial 𝜂𝑖1 . . . 𝜂𝑖𝑘 is associated the key 2𝑖1 + . . . + 2𝑖𝑘 . So the product 𝜂1 𝜂2 corresponds to
the key 6 = (110)2 while 𝜂0 𝜂3 has key 9 = (1001)2 . In particular all operations on monomials are
implemented via bitwise operations on the keys.
sage.matrix.matrix_misc.prm_mul(p1, p2, mask_free, prec)
Return the product of p1 and p2, putting free variables in mask_free to 1.
This function is mainly use as a subroutine of permanental_minor_polynomial().
INPUT:• 𝑝1, 𝑝2 – polynomials as dictionaries• mask_free – an integer mask that give the list of free variables (the 𝑖-th variable is free if the 𝑖-th bit ofmask_free is 1)• prec – if prec is not None, truncate the product at precision prec
EXAMPLES:
sage: from sage.matrix.matrix_misc import prm_mul
sage: t = polygen(ZZ, t )sage: p1 = {0: 1, 1: t, 4: t}
sage: p2 = {0: 1, 1: t, 2: t}
sage: prm_mul(p1, p2, 1, None){0: 2*t + 1, 2: t^2 + t, 4: t^2 + t, 6: t^2}>>> from sage.all import *>>> from sage.matrix.matrix_misc import prm_mul>>> t = polygen(ZZ, t )>>> p1 = {Integer(0): Integer(1), Integer(1): t, Integer(4): t}>>> p2 = {Integer(0): Integer(1), Integer(1): t, Integer(2): t}>>> prm_mul(p1, p2, Integer(1), None){0: 2*t + 1, 2: t^2 + t, 4: t^2 + t, 6: t^2}

sage.matrix.matrix_misc.row_iterator(A)1028

Chapter 39. Miscellaneous matrix functions

CHAPTERFORTY

MATRIX WINDOWS

class sage.matrix.matrix_window.MatrixWindow
Bases: object
add(A)
add_prod(A, B)
echelon_in_place()
Calculate the echelon form of this matrix, returning the list of pivot columns
element_is_zero(i, j)
get_unsafe(i, j)
matrix()Returns the underlying matrix that this window is a view of.
matrix_window(row, col, n_rows, n_cols)
Returns a matrix window relative to this window of the underlying matrix.
ncols()
new_empty_window(nrows, ncols)
new_matrix_window(matrix, row, col, n_rows, n_cols)
This method is here only to provide a fast cdef way of constructing new matrix windows. The only implicit
assumption is that self._matrix and matrix are over the same base ring (so share the zero).
nrows()
set(src)
set_to(A)Change self, making it equal A.
set_to_diff(A, B)
set_to_prod(A, B)
set_to_sum(A, B)
set_to_zero()
set_unsafe(i, j, x)1029

Matrices and Spaces of Matrices, Release 10.4

subtract(A)subtract_prod(A, B)
swap_rows(a, b)
to_matrix()
Returns an actual matrix object representing this view.

1030

Chapter 40. Matrix windows

CHAPTERFORTYONEMISC MATRIX ALGORITHMS

sage.matrix.misc.cmp_pivots(x, y)Compare two sequences of pivot columns.
If 𝑥 is shorter than 𝑦, return −1, i.e., 𝑥 < 𝑦, “not as good”. If 𝑥 is longer than 𝑦, then 𝑥 > 𝑦, so “better” and return+1. If the length is the same, then 𝑥 is better, i.e., 𝑥 > 𝑦 if the entries of 𝑥 are correspondingly ≤ those of 𝑦 with
one being strictly less.
INPUT:• x, y – lists or tuples of integers
EXAMPLES:
We illustrate each of the above comparisons.
sage: from sage.matrix.misc import cmp_pivots
sage: cmp_pivots([1,2,3], [4,5,6,7])-1
sage: cmp_pivots([1,2,3,5], [4,5,6])
1
sage: cmp_pivots([1,2,4], [1,2,3])-1
sage: cmp_pivots([1,2,3], [1,2,3])0
sage: cmp_pivots([1,2,3], [1,2,4])
1>>> from sage.all import *>>> from sage.matrix.misc import cmp_pivots>>> cmp_pivots([Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),˓→Integer(6),Integer(7)])-1>>> cmp_pivots([Integer(1),Integer(2),Integer(3),Integer(5)], [Integer(4),˓→Integer(5),Integer(6)])
1>>> cmp_pivots([Integer(1),Integer(2),Integer(4)], [Integer(1),Integer(2),˓→Integer(3)])-1>>> cmp_pivots([Integer(1),Integer(2),Integer(3)], [Integer(1),Integer(2),˓→Integer(3)])
0>>> cmp_pivots([Integer(1),Integer(2),Integer(3)], [Integer(1),Integer(2),˓→Integer(4)])
11031

Matrices and Spaces of Matrices, Release 10.4

sage.matrix.misc.matrix_integer_sparse_rational_reconstruction(A, N)
Given a sparse matrix over the integers and an integer modulus, do rational reconstruction on all entries of thematrix, viewed as numbers mod 𝑁 .
EXAMPLES:
sage: A = matrix(ZZ, 3, 4, [(1/3)%500, 2, 3, (-4)%500, 7, 2, 2, 3, 4, 3, 4, (5/7)
˓→%500], sparse=True)
sage: from sage.matrix.misc import matrix_integer_sparse_rational_reconstruction
sage: matrix_integer_sparse_rational_reconstruction(A, 500)
[1/3
2
3 -4]
[ 7
2
2
3]
[ 4
3
4 5/7]>>> from sage.all import *>>> A = matrix(ZZ, Integer(3), Integer(4), [(Integer(1)/Integer(3))%Integer(500),␣
˓→Integer(2), Integer(3), (-Integer(4))%Integer(500), Integer(7), Integer(2),␣
˓→Integer(2), Integer(3), Integer(4), Integer(3), Integer(4), (Integer(5)/˓→Integer(7))%Integer(500)], sparse=True)>>> from sage.matrix.misc import matrix_integer_sparse_rational_reconstruction>>> matrix_integer_sparse_rational_reconstruction(A, Integer(500))
[1/3
2
3 -4]
[ 7
2
2
3]
[ 4
3
4 5/7]

sage.matrix.misc.matrix_rational_echelon_form_multimodular(self, height_guess=None,
proof=None)
Returns reduced row-echelon form using a multi-modular algorithm. Does not change self.
REFERENCE: Chapter 7 of Stein’s “Explicitly Computing Modular Forms”.
INPUT:• height_guess – integer or None
• proof – boolean or None (default: None, see proof.linear_algebra or sage.structure.proof). Note that the
global Sage default is proof=True
OUTPUT: a pair consisting of a matrix in echelon form and a tuple of pivot positions.
ALGORITHM:
The following is a modular algorithm for computing the echelon form. Define the height of a matrix to be the maxof the absolute values of the entries.
Given Matrix A with n columns (self).
0. Rescale input matrix A to have integer entries. This does not change echelon form and makes reduction
modulo lots of primes significantly easier if there were denominators. Henceforth we assume A has integer
entries.
1. Let c be a guess for the height of the echelon form. E.g., c=1000, e.g., if matrix is very sparse and application
is to computing modular symbols.
2. Let M = n * c * H(A) + 1, where n is the number of columns of A.
3. List primes p_1, p_2, …, such that the product of the p_i is at least M.
4. Try to compute the rational reconstruction CRT echelon form of A mod the product of the p_i. If rational
reconstruction fails, compute 1 more echelon forms mod the next prime, and attempt again. Make sure tokeep the result of CRT on the primes from before, so we don’t have to do that computation again. Let E be
this matrix.
1032

Chapter 41. Misc matrix algorithms

Matrices and Spaces of Matrices, Release 10.4

5. Compute the denominator d of E. Attempt to prove that result is correct by checking that
H(d*E)*ncols(A)*H(A) < (prod of reduction primes)
where H denotes the height. If this fails, do step 4 with a few more primes.
EXAMPLES:
sage: A = matrix(QQ, 3, 7, [1..21])
sage: from sage.matrix.misc import matrix_rational_echelon_form_multimodular
sage: E, pivots = matrix_rational_echelon_form_multimodular(A)sage: E
[ 1 0 -1 -2 -3 -4 -5][ 0 1 2 3 4 5 6]
[ 0 0 0 0 0 0 0]
sage: pivots(0, 1)
sage: A = matrix(QQ, 3, 4, [0,0] + [1..9] + [-1/2^20])
sage: E, pivots = matrix_rational_echelon_form_multimodular(A)sage: E[10
0 -10485761/1048576][
01
0 27262979/4194304]
[
0
0
1
2]
sage: pivots(0, 1, 2)
sage: A.echelon_form()
[
1
[
0
[
0
sage: A.pivots()(0, 1, 2)010

0 -10485761/1048576]
0 27262979/4194304]
1
2]>>> from sage.all import *>>> A = matrix(QQ, Integer(3), Integer(7), (ellipsis_range(Integer(1),Ellipsis,
˓→Integer(21))))>>> from sage.matrix.misc import matrix_rational_echelon_form_multimodular>>> E, pivots = matrix_rational_echelon_form_multimodular(A)>>> E[ 1 0 -1 -2 -3 -4 -5][ 0 1 2 3 4 5 6]
[ 0 0 0 0 0 0 0]>>> pivots(0, 1)>>> A = matrix(QQ, Integer(3), Integer(4), [Integer(0),Integer(0)] + (ellipsis_
˓→range(Integer(1),Ellipsis,Integer(9))) + [-Integer(1)/Integer(2)**Integer(20)])>>> E, pivots = matrix_rational_echelon_form_multimodular(A)
>>> E
[
1
0
0 -10485761/1048576][
01
0 27262979/4194304]
[
0
0
1
2]
>>> pivots(0, 1, 2)>>> A.echelon_form()
[
1
[
0

0
1

0 -10485761/1048576]
0 27262979/4194304](continues on next page)1033

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[>>> A.pivots()(0, 1, 2)

1034

0

0

1

2]

Chapter 41. Misc matrix algorithms

CHAPTERFORTYTWOMISC MATRIX ALGORITHMS USING MPFR

sage.matrix.misc_mpfr.hadamard_row_bound_mpfr(A)Given a matrix 𝐴 with entries that coerce to RR, compute the row Hadamard bound on the determinant.
INPUT:• A – a matrix over RR
OUTPUT:
integer – an integer n such that the absolute value of the determinant of this matrix is at most 10𝑛 .
EXAMPLES:
We create a very large matrix, compute the row Hadamard bound, and also compute the row Hadamard bound of
the transpose, which happens to be sharp.
sage: a = matrix(ZZ, 2, [2^10000, 3^10000, 2^50, 3^19292])
sage: from sage.matrix.misc_mpfr import hadamard_row_bound_mpfr
sage: hadamard_row_bound_mpfr(a.change_ring(RR))
13976
sage: len(str(a.det()))
12215
sage: hadamard_row_bound_mpfr(a.transpose().change_ring(RR))
12215>>> from sage.all import *>>> a = matrix(ZZ, Integer(2), [Integer(2)**Integer(10000),␣
˓→Integer(3)**Integer(10000), Integer(2)**Integer(50),␣
˓→Integer(3)**Integer(19292)])>>> from sage.matrix.misc_mpfr import hadamard_row_bound_mpfr>>> hadamard_row_bound_mpfr(a.change_ring(RR))
13976>>> len(str(a.det()))
12215>>> hadamard_row_bound_mpfr(a.transpose().change_ring(RR))
12215

Note that in the above example using RDF would overflow:
sage: b = a.change_ring(RDF)
sage: b._hadamard_row_bound()Traceback (most recent call last):...
OverflowError: cannot convert float infinity to integer

1035

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> b = a.change_ring(RDF)>>> b._hadamard_row_bound()Traceback (most recent call last):...
OverflowError: cannot convert float infinity to integer

1036

Chapter 42. Misc matrix algorithms using MPFRCHAPTERFORTYTHREEMISC MATRIX ALGORITHMS USING FLINT

sage.matrix.misc_flint.matrix_integer_dense_rational_reconstruction(A, N)
Given a matrix over the integers and an integer modulus, do rational reconstruction on all entries of the matrix,
viewed as numbers mod 𝑁 . This is done efficiently by assuming there is a large common factor dividing thedenominators.
INPUT:• A – matrix• N – an integer
EXAMPLES:
sage: B = ((matrix(ZZ, 3,4, [1,2,3,-4,7,2,18,3,4,3,4,5])/3)%500).change_ring(ZZ)
sage: from sage.matrix.misc_flint import matrix_integer_dense_rational_
˓→reconstruction
sage: matrix_integer_dense_rational_reconstruction(B, 500)
[ 1/3 2/3
1 -4/3][ 7/3 2/3
6
1]
[ 4/3
1 4/3 5/3]>>> from sage.all import *>>> B = ((matrix(ZZ, Integer(3),Integer(4), [Integer(1),Integer(2),Integer(3),˓→Integer(4),Integer(7),Integer(2),Integer(18),Integer(3),Integer(4),Integer(3),˓→Integer(4),Integer(5)])/Integer(3))%Integer(500)).change_ring(ZZ)>>> from sage.matrix.misc_flint import matrix_integer_dense_rational_
˓→reconstruction>>> matrix_integer_dense_rational_reconstruction(B, Integer(500))[ 1/3 2/3
1 -4/3][ 7/3 2/3
6
1]
[ 4/3
1 4/3 5/3]

1037

Matrices and Spaces of Matrices, Release 10.4

1038

Chapter 43. Misc matrix algorithms using FLINTCHAPTERFORTYFOURCALCULATE SYMPLECTIC BASES FOR MATRICES OVER FIELDSAND THE INTEGERS.

This module finds a symplectic basis for an anti-symmetric, alternating matrix M defined over a field or the integers.
Anti-symmetric means that 𝑀 = −𝑀 𝑡 , where 𝑀 𝑡 denotes the transpose of 𝑀 . Alternating means that the diagonal of
𝑀 is identically zero.
A symplectic basis is a basis of the form 𝑒1 , . . . , 𝑒𝑗 , 𝑓1 , . . . , 𝑓𝑗 , 𝑧1 , . . . , 𝑧𝑘 such that• 𝑧𝑖 𝑀 𝑣 𝑡 = 0 for all vectors 𝑣;• 𝑒𝑖 𝑀 𝑒𝑗 𝑡 = 0 for all 𝑖, 𝑗;• 𝑓𝑖 𝑀 𝑓𝑗 𝑡 = 0 for all 𝑖, 𝑗;• 𝑒𝑖 𝑀 𝑓𝑗 𝑡 = 0 for all 𝑖 not equal 𝑗;and such that the non-zero terms• 𝑒𝑖 𝑀 𝑓𝑖 𝑡 are “as nice as possible”: 1 over fields, or integers satisfying divisibility properties otherwise.
REFERENCES:
Bourbaki gives a nice proof that can be made constructive but is not efficient (see Section 5, Number 1, Theorem 1, page79):
Bourbaki, N. Elements of Mathematics, Algebra III, Springer Verlag 2007.
Kuperberg gives a more efficient and constructive exposition (see Theorem 18).
Kuperberg, Greg. Kasteleyn Cokernels. Electr. J. Comb. 9(1), 2002.
Todo: The routine over the integers applies over general principal ideal domains.

Warning: This code is not a good candidate for conversion to Cython. The majority of the execution time is spentadding multiples of columns and rows, which is already fast. It would be better to devise a better algorithm, perhaps
modular or based on a fast smith_form implementation.
AUTHOR:• Nick Alexander: initial implementation• David Loeffler (2008-12-08): changed conventions for consistency with smith_form

1039

Matrices and Spaces of Matrices, Release 10.4

sage.matrix.symplectic_basis.symplectic_basis_over_ZZ(M)
Find a symplectic basis for an anti-symmetric, alternating matrix M defined over the integers.
Returns a pair (F, C) such that the rows of C form a symplectic basis for M and F = C * M * C.transpose().
Anti-symmetric means that 𝑀 = −𝑀 𝑡 . Alternating means that the diagonal of 𝑀 is identically zero.
A symplectic basis is a basis of the form 𝑒1 , . . . , 𝑒𝑗 , 𝑓1 , . . . , 𝑓𝑗 , 𝑧1 , . . . , 𝑧𝑘 such that• 𝑧𝑖 𝑀 𝑣 𝑡 = 0 for all vectors 𝑣;• 𝑒𝑖 𝑀 𝑒𝑗 𝑡 = 0 for all 𝑖, 𝑗;• 𝑓𝑖 𝑀 𝑓𝑗 𝑡 = 0 for all 𝑖, 𝑗;• 𝑒𝑖 𝑀 𝑓𝑖 𝑡 = 𝑑𝑖 for all 𝑖, where d_i are positive integers such that 𝑑𝑖 |𝑑𝑖+1 for all 𝑖;• 𝑒𝑖 𝑀 𝑓𝑗 𝑡 = 0 for all 𝑖 not equal 𝑗.
The ordering for the factors 𝑑𝑖 |𝑑𝑖+1 and for the placement of zeroes was chosen to agree with the output ofsmith_form.
See the examples for a pictorial description of such a basis.
EXAMPLES:
sage: from sage.matrix.symplectic_basis import symplectic_basis_over_ZZ>>> from sage.all import *>>> from sage.matrix.symplectic_basis import symplectic_basis_over_ZZ

An example which does not have full rank:
sage: E = matrix(ZZ, 4, 4, [0, 16, 0, 2, -16, 0, 0, -4, 0, 0, 0, 0, -2, 4, 0, 0]);˓→ E
[ 0 16
0
2]
[-16
0
0 -4]
[ 0
0
0
0]
[ -2
4
0
0]
sage: F, C = symplectic_basis_over_ZZ(E)sage: F[ 0 2 0 0][-2 0 0 0]
[ 0 0 0 0]
[ 0 0 0 0]
sage: C * E * C.transpose() == F
True>>> from sage.all import *>>> E = matrix(ZZ, Integer(4), Integer(4), [Integer(0), Integer(16), Integer(0),␣
˓→Integer(2), -Integer(16), Integer(0), Integer(0), -Integer(4), Integer(0),␣
˓→Integer(0), Integer(0), Integer(0), -Integer(2), Integer(4), Integer(0),␣
˓→Integer(0)]); E[ 0 16
0
2]
[-16
0
0 -4]
[ 0
0
0
0]
[ -2
4
0
0]
>>> F, C = symplectic_basis_over_ZZ(E)>>> F[ 0 2 0 0][-2 0 0 0](continues on next page)1040

Chapter 44. Calculate symplectic bases for matrices over fields and the integers.

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 0 0 0 0]
[ 0 0 0 0]>>> C * E * C.transpose() == FTrue

A larger example:
sage: E = matrix(ZZ, 8, 8, [0, 25, 0, 0, -37, -3, 2, -5, -25, 0, 1, -5, -54, -3,␣
˓→3, 3, 0, -1, 0, 7, 0, -4, -20, 0, 0, 5, -7, 0, 0, 14, 0, -3, 37, 54, 0, 0, 0, 2,
˓→ 3, -12, 3, 3, 4, -14, -2, 0, -3, 2, -2, -3, 20, 0, -3, 3, 0, -2, 5, -3, 0, 3,␣
˓→12, -2, 2, 0]); E[ 0 2500 -37 -3
2 -5]
[-25
0
1 -5 -54 -3
33][ 0 -10
7
0 -4 -20
0]
[ 0
5 -7
0
0 14
0 -3]
[ 37 54000
2
3 -12][ 3
3
4 -14 -2
0 -3
2]
[ -2 -3 20
0 -3
3
0 -2]
[ 5 -30
3 12 -2
20]
sage: F, C = symplectic_basis_over_ZZ(E)sage: F
[
0
0
0
0
1
0
0
0]
[
0
0
0
0
0
1
0
0]
[
0
0
0
0
0
0
1
0]
[
0
0
0
0
0
0
0 20191]
[
-1
0
0
0
0
0
0
0]
[
0
-1
0
0
0
0
0
0]
[
0
0
-1
0
0
0
0
0]
[
0
0
0 -201910000]
sage: F == C * E * C.transpose()True
sage: E.smith_form()[0]
[
1
0
0
0
0
0
0
0]
[
0
1
0
0
0
0
0
0]
[
0
0
1
0
0
0
0
0]
[
0
0
0
1
0
0
0
0]
[
0
0
0
0
1
0
0
0]
[
0
0
0
0
0
1
0
0]
[
0
0
0
0
0
0 20191
0]
[
0
0
0
0
0
0
0 20191]>>> from sage.all import *>>> E = matrix(ZZ, Integer(8), Integer(8), [Integer(0), Integer(25), Integer(0),␣
˓→Integer(0), -Integer(37), -Integer(3), Integer(2), -Integer(5), -Integer(25),␣
˓→Integer(0), Integer(1), -Integer(5), -Integer(54), -Integer(3), Integer(3),␣
˓→Integer(3), Integer(0), -Integer(1), Integer(0), Integer(7), Integer(0), ˓→Integer(4), -Integer(20), Integer(0), Integer(0), Integer(5), -Integer(7),␣
˓→Integer(0), Integer(0), Integer(14), Integer(0), -Integer(3), Integer(37),␣
˓→Integer(54), Integer(0), Integer(0), Integer(0), Integer(2), Integer(3), ˓→Integer(12), Integer(3), Integer(3), Integer(4), -Integer(14), -Integer(2),␣
˓→Integer(0), -Integer(3), Integer(2), -Integer(2), -Integer(3), Integer(20),␣
˓→Integer(0), -Integer(3), Integer(3), Integer(0), -Integer(2), Integer(5), ˓→Integer(3), Integer(0), Integer(3), Integer(12), -Integer(2), Integer(2),␣
˓→Integer(0)]); E[ 0 2500 -37 -3
2 -5]
[-25
0
1 -5 -54 -3
3
3](continues on next page)1041

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ 0 -10
7
0 -4 -20
0]
[ 0
5 -7
0
0 14
0 -3]
[ 37 54000
2
3 -12][ 3
3
4 -14 -2
0 -3
2]
[ -2 -3 20
0 -3
3
0 -2]
[ 5 -30
3 12 -2
20]>>> F, C = symplectic_basis_over_ZZ(E)
>>> F
[
0
0
0
0
1
0
0
[
0
0
0
0
0
1
0
[
0
0
0
0
0
0
1
[
0
0
0
0
0
0
0
[
-1
0
0
0
0
0
0
[
0
-1
0
0
0
0
0
[
0
0
-1
0
0
0
0
[
0
0
0 -20191
00
0>>> F == C * E * C.transpose()
True>>> E.smith_form()[Integer(0)]
[
1
0
0
0
0
0
0
0]
[
0
1
0
0
0
0
0
0]
[
0
0
1
0
0
0
0
0]
[
0
0
0
1
0
0
0
0]
[
0
0
0
0
1
0
0
0]
[
0
0
0
0
0
1
0
0]
[
0
0
0
0
0
0 20191
0]
[
0
0
0
0
0
0
0 20191]0]0]0]20191]
0]0]
0]
0]

An odd dimensional example:
sage: E = matrix(ZZ, 5, 5, [0, 14, 0, -8, -2, -14, 0, -3, -11, 4, 0, 3, 0, 0, 0,␣
˓→8, 11, 0, 0, 8, 2, -4, 0, -8, 0]); E[ 0 140 -8 -2][-14
0 -3 -11
4]
[ 0
3
0
0
0]
[ 8 110
0
8][ 2 -40 -8
0]sage: F, C = symplectic_basis_over_ZZ(E)sage: F[ 0 0 1 0 0]
[ 0 0 0 2 0][-1 0 0 0 0]
[ 0 -2 0 0 0]
[ 0 0 0 0 0]
sage: F == C * E * C.transpose()True
sage: E.smith_form()[0][1 0 0 0 0]
[0 1 0 0 0]
[0 0 2 0 0]
[0 0 0 2 0]
[0 0 0 0 0]
sage: F.parent()
Full MatrixSpace of 5 by 5 dense matrices over Integer Ringsage: C.parent()
Full MatrixSpace of 5 by 5 dense matrices over Integer Ring

1042

Chapter 44. Calculate symplectic bases for matrices over fields and the integers.

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> E = matrix(ZZ, Integer(5), Integer(5), [Integer(0), Integer(14), Integer(0), ˓→Integer(8), -Integer(2), -Integer(14), Integer(0), -Integer(3), -Integer(11),␣
˓→Integer(4), Integer(0), Integer(3), Integer(0), Integer(0), Integer(0),␣
˓→Integer(8), Integer(11), Integer(0), Integer(0), Integer(8), Integer(2), ˓→Integer(4), Integer(0), -Integer(8), Integer(0)]); E[ 0 140 -8 -2][-14
0 -3 -11
4]
[ 0
3
0
0
0]
[ 8 110
0
8][ 2 -40 -8
0]>>> F, C = symplectic_basis_over_ZZ(E)>>> F[ 0 0 1 0 0]
[ 0 0 0 2 0][-1 0 0 0 0]
[ 0 -2 0 0 0]
[ 0 0 0 0 0]>>> F == C * E * C.transpose()
True>>> E.smith_form()[Integer(0)][1 0 0 0 0]
[0 1 0 0 0]
[0 0 2 0 0]
[0 0 0 2 0]
[0 0 0 0 0]>>> F.parent()
Full MatrixSpace of 5 by 5 dense matrices over Integer Ring>>> C.parent()
Full MatrixSpace of 5 by 5 dense matrices over Integer Ring

sage.matrix.symplectic_basis.symplectic_basis_over_field(M)Find a symplectic basis for an anti-symmetric, alternating matrix M defined over a field.
Returns a pair (F, C) such that the rows of C form a symplectic basis for M and F = C * M * C.transpose().
Anti-symmetric means that 𝑀 = −𝑀 𝑡 . Alternating means that the diagonal of 𝑀 is identically zero.
A symplectic basis is a basis of the form 𝑒1 , . . . , 𝑒𝑗 , 𝑓1 , . . . 𝑓𝑗 , 𝑧1 , . . . , 𝑧𝑘 such that• 𝑧𝑖 𝑀 𝑣 𝑡 = 0 for all vectors 𝑣;• 𝑒𝑖 𝑀 𝑒𝑗 𝑡 = 0 for all 𝑖, 𝑗;• 𝑓𝑖 𝑀 𝑓𝑗 𝑡 = 0 for all 𝑖, 𝑗;• 𝑒𝑖 𝑀 𝑓𝑖 𝑡 = 1 for all 𝑖;• 𝑒𝑖 𝑀 𝑓𝑗 𝑡 = 0 for all 𝑖 not equal 𝑗.
See the examples for a pictorial description of such a basis.
EXAMPLES:
sage: from sage.matrix.symplectic_basis import symplectic_basis_over_field>>> from sage.all import *>>> from sage.matrix.symplectic_basis import symplectic_basis_over_field

A full rank exact example:
1043

Matrices and Spaces of Matrices, Release 10.4

sage: E = matrix(QQ, 8, 8, [0, -1/2, -2, 1/2, 2, 0, -2, 1, 1/2, 0, -1, -3, 0, 2,␣
˓→5/2, -3, 2, 1, 0, 3/2, -1, 0, -1, -2, -1/2, 3, -3/2, 0, 1, 3/2, -1/2, -1/2, -2,␣
˓→0, 1, -1, 0, 0, 1, -1, 0, -2, 0, -3/2, 0, 0, 1/2, -2, 2, -5/2, 1, 1/2, -1, -1/2,
˓→ 0, -1, -1, 3, 2, 1/2, 1, 2, 1, 0]); E[
0 -1/2-2 1/2
2
0
-2
1]
[ 1/2
0
-1
-3
0
2 5/2
-3]
[
2
1
0 3/2
-1
0
-1
-2]
[-1/2
3 -3/20
1 3/2 -1/2 -1/2]
[ -2
0
1
-1
0
0
1
-1]
[
0
-2
0 -3/2
0
0 1/2
-2]
[
2 -5/2
1 1/2-1 -1/2
0
-1]
[ -1
3
2 1/2
1
2
1
0]
sage: F, C = symplectic_basis_over_field(E); F[ 0 0 0 0 1 0 0 0]
[ 0 0 0 0 0 1 0 0]
[ 0 0 0 0 0 0 1 0]
[ 0 0 0 0 0 0 0 1][-1 0 0 0 0 0 0 0]
[ 0 -1 0 0 0 0 0 0]
[ 0 0 -1 0 0 0 0 0]
[ 0 0 0 -1 0 0 0 0]
sage: F == C * E * C.transpose()True>>> from sage.all import *>>> E = matrix(QQ, Integer(8), Integer(8), [Integer(0), -Integer(1)/Integer(2), ˓→Integer(2), Integer(1)/Integer(2), Integer(2), Integer(0), -Integer(2),␣
˓→Integer(1), Integer(1)/Integer(2), Integer(0), -Integer(1), -Integer(3),␣
˓→Integer(0), Integer(2), Integer(5)/Integer(2), -Integer(3), Integer(2),␣
˓→Integer(1), Integer(0), Integer(3)/Integer(2), -Integer(1), Integer(0), ˓→Integer(1), -Integer(2), -Integer(1)/Integer(2), Integer(3), -Integer(3)/˓→Integer(2), Integer(0), Integer(1), Integer(3)/Integer(2), -Integer(1)/˓→Integer(2), -Integer(1)/Integer(2), -Integer(2), Integer(0), Integer(1), ˓→Integer(1), Integer(0), Integer(0), Integer(1), -Integer(1), Integer(0), ˓→Integer(2), Integer(0), -Integer(3)/Integer(2), Integer(0), Integer(0),␣
˓→Integer(1)/Integer(2), -Integer(2), Integer(2), -Integer(5)/Integer(2),␣
˓→Integer(1), Integer(1)/Integer(2), -Integer(1), -Integer(1)/Integer(2),␣
˓→Integer(0), -Integer(1), -Integer(1), Integer(3), Integer(2), Integer(1)/˓→Integer(2), Integer(1), Integer(2), Integer(1), Integer(0)]); E[
0 -1/2-2 1/2
2
0
-2
1]
[ 1/2
0
-1
-3
0
2 5/2
-3]
[
2
1
0 3/2
-1
0
-1
-2]
[-1/2
3 -3/20
1 3/2 -1/2 -1/2]
[ -2
0
1
-1
0
0
1
-1]
[
0
-2
0 -3/2
0
0 1/2
-2]
[
2 -5/2
1 1/2-1 -1/2
0
-1]
[ -1
3
2 1/2
1
2
1
0]
>>> F, C = symplectic_basis_over_field(E); F[ 0 0 0 0 1 0 0 0]
[ 0 0 0 0 0 1 0 0]
[ 0 0 0 0 0 0 1 0]
[ 0 0 0 0 0 0 0 1][-1 0 0 0 0 0 0 0]
[ 0 -1 0 0 0 0 0 0]
[ 0 0 -1 0 0 0 0 0]
[ 0 0 0 -1 0 0 0 0]>>> F == C * E * C.transpose()(continues on next page)1044

Chapter 44. Calculate symplectic bases for matrices over fields and the integers.

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)True

An example over a finite field:
sage: E = matrix(GF(7), 8, 8,....:[0, -1/2, -2, 1/2, 2, 0, -2, 1, 1/2, 0, -1, -3, 0, 2, 5/2,....:
-3, 2, 1, 0, 3/2, -1, 0, -1, -2, -1/2, 3, -3/2, 0, 1, 3/2,....:
-1/2, -1/2, -2, 0, 1, -1, 0, 0, 1, -1, 0, -2, 0, -3/2, 0,....:
0, 1/2, -2, 2, -5/2, 1, 1/2, -1, -1/2, 0, -1, -1, 3, 2,....:
1/2, 1, 2, 1, 0]); E[0 3 5 4 2 0 5 1]
[4 0 6 4 0 2 6 4]
[2 1 0 5 6 0 6 5]
[3 3 2 0 1 5 3 3]
[5 0 1 6 0 0 1 6]
[0 5 0 2 0 0 4 5]
[2 1 1 4 6 3 0 6]
[6 3 2 4 1 2 1 0]
sage: F, C = symplectic_basis_over_field(E); F[0 0 0 0 1 0 0 0]
[0 0 0 0 0 1 0 0]
[0 0 0 0 0 0 1 0]
[0 0 0 0 0 0 0 1]
[6 0 0 0 0 0 0 0]
[0 6 0 0 0 0 0 0]
[0 0 6 0 0 0 0 0]
[0 0 0 6 0 0 0 0]
sage: F == C * E * C.transpose()True>>> from sage.all import *>>> E = matrix(GF(Integer(7)), Integer(8), Integer(8),...
[Integer(0), -Integer(1)/Integer(2), -Integer(2), Integer(1)/˓→Integer(2), Integer(2), Integer(0), -Integer(2), Integer(1), Integer(1)/˓→Integer(2), Integer(0), -Integer(1), -Integer(3), Integer(0), Integer(2),␣
˓→Integer(5)/Integer(2),...
-Integer(3), Integer(2), Integer(1), Integer(0), Integer(3)/˓→Integer(2), -Integer(1), Integer(0), -Integer(1), -Integer(2), -Integer(1)/˓→Integer(2), Integer(3), -Integer(3)/Integer(2), Integer(0), Integer(1),␣
˓→Integer(3)/Integer(2),...
-Integer(1)/Integer(2), -Integer(1)/Integer(2), -Integer(2),␣
˓→Integer(0), Integer(1), -Integer(1), Integer(0), Integer(0), Integer(1), ˓→Integer(1), Integer(0), -Integer(2), Integer(0), -Integer(3)/Integer(2),␣
˓→Integer(0),...
Integer(0), Integer(1)/Integer(2), -Integer(2), Integer(2), ˓→Integer(5)/Integer(2), Integer(1), Integer(1)/Integer(2), -Integer(1), ˓→Integer(1)/Integer(2), Integer(0), -Integer(1), -Integer(1), Integer(3),␣
˓→Integer(2),...
Integer(1)/Integer(2), Integer(1), Integer(2), Integer(1),␣
˓→Integer(0)]); E[0 3 5 4 2 0 5 1]
[4 0 6 4 0 2 6 4]
[2 1 0 5 6 0 6 5]
[3 3 2 0 1 5 3 3]
[5 0 1 6 0 0 1 6]
[0 5 0 2 0 0 4 5]
(continues on next page)1045

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[2 1 1 4 6 3 0 6]
[6 3 2 4 1 2 1 0]>>> F, C = symplectic_basis_over_field(E); F[0 0 0 0 1 0 0 0]
[0 0 0 0 0 1 0 0]
[0 0 0 0 0 0 1 0]
[0 0 0 0 0 0 0 1]
[6 0 0 0 0 0 0 0]
[0 6 0 0 0 0 0 0]
[0 0 6 0 0 0 0 0]
[0 0 0 6 0 0 0 0]>>> F == C * E * C.transpose()
True

The tricky case of characteristic 2:
sage: E = matrix(GF(2), 8, 8,....:[0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,....:
0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0,....:
1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1,....:
0, 1, 0, 0]); E[0 0 1 1 0 1 0 1]
[0 0 0 0 0 0 0 0]
[1 0 0 0 0 0 1 1]
[1 0 0 0 0 0 0 1]
[0 0 0 0 0 1 1 0]
[1 0 0 0 1 0 1 1]
[0 0 1 0 1 1 0 0]
[1 0 1 1 0 1 0 0]
sage: F, C = symplectic_basis_over_field(E); F[0 0 0 1 0 0 0 0]
[0 0 0 0 1 0 0 0]
[0 0 0 0 0 1 0 0]
[1 0 0 0 0 0 0 0]
[0 1 0 0 0 0 0 0]
[0 0 1 0 0 0 0 0]
[0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0]
sage: F == C * E * C.transpose()True>>> from sage.all import *>>> E = matrix(GF(Integer(2)), Integer(8), Integer(8),...
[Integer(0), Integer(0), Integer(1), Integer(1), Integer(0),␣
˓→Integer(1), Integer(0), Integer(1), Integer(0), Integer(0), Integer(0),␣
˓→Integer(0), Integer(0), Integer(0), Integer(0), Integer(0), Integer(1),␣
˓→Integer(0), Integer(0), Integer(0),...
Integer(0), Integer(0), Integer(1), Integer(1), Integer(1),␣
˓→Integer(0), Integer(0), Integer(0), Integer(0), Integer(0), Integer(0),␣
˓→Integer(1), Integer(0), Integer(0), Integer(0), Integer(0), Integer(0),␣
˓→Integer(1), Integer(1), Integer(0),...
Integer(1), Integer(0), Integer(0), Integer(0), Integer(1),␣
˓→Integer(0), Integer(1), Integer(1), Integer(0), Integer(0), Integer(1),␣
˓→Integer(0), Integer(1), Integer(1), Integer(0), Integer(0), Integer(1),␣
˓→Integer(0), Integer(1), Integer(1),...
Integer(0), Integer(1), Integer(0), Integer(0)]); E(continues on next page)1046

Chapter 44. Calculate symplectic bases for matrices over fields and the integers.

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[0 0 1 1 0 1 0 1]
[0 0 0 0 0 0 0 0]
[1 0 0 0 0 0 1 1]
[1 0 0 0 0 0 0 1]
[0 0 0 0 0 1 1 0]
[1 0 0 0 1 0 1 1]
[0 0 1 0 1 1 0 0]
[1 0 1 1 0 1 0 0]>>> F, C = symplectic_basis_over_field(E); F[0 0 0 1 0 0 0 0]
[0 0 0 0 1 0 0 0]
[0 0 0 0 0 1 0 0]
[1 0 0 0 0 0 0 0]
[0 1 0 0 0 0 0 0]
[0 0 1 0 0 0 0 0]
[0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0]>>> F == C * E * C.transpose()
True

An inexact example:
sage: E = matrix(RR, 8, 8, [0.000000000000000, 0.420674846479344, -0.
˓→839702420666807, 0.658715385244413, 1.69467394825853, -1.14718543053828, 1.
˓→03076138152950, -0.227739521708484, -0.420674846479344, 0.000000000000000, 0.
˓→514381455379082, 0.282194064028260, -1.38977093018412, 0.278305070958958, -0.
˓→0781320488361574, -0.496003664217833, 0.839702420666807, -0.514381455379082, 0.
˓→000000000000000, -0.00618222322875384, -0.318386939149028, -0.0840205427053993,␣
˓→1.28202592892333, -0.512563654267693, -0.658715385244413, -0.282194064028260, 0.
˓→00618222322875384, 0.000000000000000, 0.852525732369211, -0.356957405431611, -0.
˓→699960114607661, 0.0260496330859998, -1.69467394825853, 1.38977093018412, 0.
˓→318386939149028, -0.852525732369211, 0.000000000000000, -0.836072521423577, 0.
˓→450137632758469, -0.696145287292091, 1.14718543053828, -0.278305070958958, 0.
˓→0840205427053993, 0.356957405431611, 0.836072521423577, 0.000000000000000, 0.
˓→214878541347751, -1.20221688928379, -1.03076138152950, 0.0781320488361574, -1.
˓→28202592892333, 0.699960114607661, -0.450137632758469, -0.214878541347751, 0.
˓→000000000000000, 0.785074452163036, 0.227739521708484, 0.496003664217833, 0.
˓→512563654267693, -0.0260496330859998, 0.696145287292091, 1.20221688928379, -0.
˓→785074452163036, 0.000000000000000]); E[
0.000000000000000
0.420674846479344-0.839702420666807
0.
˓→658715385244413
1.69467394825853-1.14718543053828
1.03076138152950 ␣
˓→ -0.227739521708484][ -0.420674846479344
0.000000000000000
0.514381455379082
0.
˓→282194064028260-1.38977093018412
0.278305070958958 -0.0781320488361574 ␣
˓→ -0.496003664217833][
0.839702420666807-0.514381455379082
0.000000000000000 -0.
˓→00618222322875384-0.318386939149028 -0.0840205427053993
1.
˓→28202592892333-0.512563654267693][ -0.658715385244413-0.282194064028260 0.00618222322875384
0.
˓→000000000000000
0.852525732369211-0.356957405431611-0.699960114607661 ␣
˓→ 0.0260496330859998][-1.69467394825853
1.38977093018412
0.318386939149028-0.
˓→852525732369211
0.000000000000000-0.836072521423577
0.450137632758469 ␣
˓→ -0.696145287292091][
1.14718543053828-0.278305070958958
0.0840205427053993
0.
˓→356957405431611
0.836072521423577
0.000000000000000
0.214878541347751 ␣˓→-1.20221688928379](continues on next page)1047

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[-1.03076138152950
0.0781320488361574-1.28202592892333
0.
˓→699960114607661-0.450137632758469-0.214878541347751
0.000000000000000 ␣˓→
0.785074452163036][
0.227739521708484
0.496003664217833
0.512563654267693 -0.
˓→0260496330859998
0.696145287292091
1.20221688928379-0.785074452163036␣
˓→
0.000000000000000]
sage: F, C = symplectic_basis_over_field(E); F # random[
0.000000000000000
0.000000000000000 2.22044604925031e-16 -2.
˓→22044604925031e-16
1.00000000000000
0.000000000000000
0.
˓→000000000000000 -3.33066907387547e-16][
0.000000000000000 8.14814392305203e-17 -1.66533453693773e-16 -1.
˓→11022302462516e-16
0.000000000000000
1.00000000000000 -1.
˓→11022302462516e-16
0.000000000000000][-5.27829526256056e-16 -2.40004077757759e-16 1.28373418199470e-16 -1.
˓→11022302462516e-16
0.000000000000000 -3.15483812822081e-16
1.
˓→00000000000000 -4.44089209850063e-16][ 1.31957381564014e-16 1.41622049084608e-16 -6.68515202578511e-17 -3.
˓→95597468756028e-17 -4.85722573273506e-17 -5.32388011580111e-17 -1.
˓→31328455615552e-16
1.00000000000000][-1.00000000000000
0.000000000000000
0.000000000000000 4.
˓→85722573273506e-17
0.000000000000000 -5.55111512312578e-17 -1.
˓→11022302462516e-16
2.22044604925031e-16][
0.000000000000000-1.00000000000000
0.000000000000000 -2.
˓→77555756156289e-17
5.55111512312578e-17 -8.69223574327834e-170.
˓→000000000000000 -4.44089209850063e-16][
0.000000000000000 -1.05042437087238e-17-1.00000000000000 3.
˓→33066907387547e-16
1.11022302462516e-16 -1.18333563634309e-16 4.
˓→40064433050777e-17
2.22044604925031e-16][ 5.27829526256056e-16 1.99901485752317e-16 1.65710718121313e-17-1.
˓→00000000000000 -2.22044604925031e-16
5.52150940090699e-16 -3.93560383111738e˓→16
1.01155762925061e-16]
sage: F == C * E * C.transpose()True
sage: abs(F[0, 4] - 1) < 1e-10
True
sage: abs(F[4, 0] + 1) < 1e-10
True
sage: F.parent()
Full MatrixSpace of 8 by 8 dense matrices over Real Field with 53 bits of␣˓→precision
sage: C.parent()
Full MatrixSpace of 8 by 8 dense matrices over Real Field with 53 bits of␣˓→precision>>> from sage.all import *>>> E = matrix(RR, Integer(8), Integer(8), [RealNumber( 0.000000000000000 ),␣
˓→RealNumber( 0.420674846479344 ), -RealNumber( 0.839702420666807 ), RealNumber(
˓→ 0.658715385244413 ), RealNumber( 1.69467394825853 ), -RealNumber( 1.
˓→14718543053828 ), RealNumber( 1.03076138152950 ), -RealNumber( 0.227739521708484
˓→ ), -RealNumber( 0.420674846479344 ), RealNumber( 0.000000000000000 ),␣
˓→RealNumber( 0.514381455379082 ), RealNumber( 0.282194064028260 ), -RealNumber(
˓→ 1.38977093018412 ), RealNumber( 0.278305070958958 ), -RealNumber( 0.
˓→0781320488361574 ), -RealNumber( 0.496003664217833 ), RealNumber( 0.
˓→839702420666807 ), -RealNumber( 0.514381455379082 ), RealNumber( 0.
˓→000000000000000 ), -RealNumber( 0.00618222322875384 ), -RealNumber( 0.
(continues on next page)

1048

Chapter 44. Calculate symplectic bases for matrices over fields and the integers.

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)318386939149028 ), -RealNumber( 0.0840205427053993 ), RealNumber( 1.
˓→28202592892333 ), -RealNumber( 0.512563654267693 ), -RealNumber( 0.
˓→658715385244413 ), -RealNumber( 0.282194064028260 ), RealNumber( 0.
˓→00618222322875384 ), RealNumber( 0.000000000000000 ), RealNumber( 0.
˓→852525732369211 ), -RealNumber( 0.356957405431611 ), -RealNumber( 0.
˓→699960114607661 ), RealNumber( 0.0260496330859998 ), -RealNumber( 1.
˓→69467394825853 ), RealNumber( 1.38977093018412 ), RealNumber( 0.318386939149028
˓→ ), -RealNumber( 0.852525732369211 ), RealNumber( 0.000000000000000 ), ˓→RealNumber( 0.836072521423577 ), RealNumber( 0.450137632758469 ), -RealNumber(
˓→ 0.696145287292091 ), RealNumber( 1.14718543053828 ), -RealNumber( 0.
˓→278305070958958 ), RealNumber( 0.0840205427053993 ), RealNumber( 0.
˓→356957405431611 ), RealNumber( 0.836072521423577 ), RealNumber( 0.
˓→000000000000000 ), RealNumber( 0.214878541347751 ), -RealNumber( 1.
˓→20221688928379 ), -RealNumber( 1.03076138152950 ), RealNumber( 0.
˓→0781320488361574 ), -RealNumber( 1.28202592892333 ), RealNumber( 0.
˓→699960114607661 ), -RealNumber( 0.450137632758469 ), -RealNumber( 0.
˓→214878541347751 ), RealNumber( 0.000000000000000 ), RealNumber( 0.
˓→785074452163036 ), RealNumber( 0.227739521708484 ), RealNumber( 0.
˓→496003664217833 ), RealNumber( 0.512563654267693 ), -RealNumber( 0.
˓→0260496330859998 ), RealNumber( 0.696145287292091 ), RealNumber( 1.
˓→20221688928379 ), -RealNumber( 0.785074452163036 ), RealNumber( 0.
˓→000000000000000 )]); E[
0.000000000000000
0.420674846479344-0.839702420666807
0.
˓→658715385244413
1.69467394825853-1.14718543053828
1.03076138152950 ␣
˓→ -0.227739521708484][ -0.420674846479344
0.000000000000000
0.514381455379082
0.
˓→282194064028260-1.38977093018412
0.278305070958958 -0.0781320488361574 ␣
˓→ -0.496003664217833][
0.839702420666807-0.514381455379082
0.000000000000000 -0.
˓→00618222322875384-0.318386939149028 -0.0840205427053993
1.
˓→28202592892333-0.512563654267693][ -0.658715385244413-0.282194064028260 0.00618222322875384
0.
˓→000000000000000
0.852525732369211-0.356957405431611-0.699960114607661 ␣
˓→ 0.0260496330859998][-1.69467394825853
1.38977093018412
0.318386939149028-0.
˓→852525732369211
0.000000000000000-0.836072521423577
0.450137632758469 ␣
˓→ -0.696145287292091][
1.14718543053828-0.278305070958958
0.0840205427053993
0.
˓→356957405431611
0.836072521423577
0.000000000000000
0.214878541347751 ␣˓→-1.20221688928379][-1.03076138152950
0.0781320488361574-1.28202592892333
0.
˓→699960114607661-0.450137632758469-0.214878541347751
0.000000000000000 ␣˓→
0.785074452163036][
0.227739521708484
0.496003664217833
0.512563654267693 -0.
˓→0260496330859998
0.696145287292091
1.20221688928379-0.785074452163036␣
˓→
0.000000000000000]>>> F, C = symplectic_basis_over_field(E); F # random[
0.000000000000000
0.000000000000000 2.22044604925031e-16 -2.
˓→22044604925031e-16
1.00000000000000
0.000000000000000
0.
˓→000000000000000 -3.33066907387547e-16][
0.000000000000000 8.14814392305203e-17 -1.66533453693773e-16 -1.
˓→11022302462516e-16
0.000000000000000
1.00000000000000 -1.
˓→11022302462516e-16
0.000000000000000][-5.27829526256056e-16 -2.40004077757759e-16 1.28373418199470e-16 -1.
˓→11022302462516e-16
0.000000000000000 -3.15483812822081e-16
1.
˓→00000000000000 -4.44089209850063e-16][ 1.31957381564014e-16 1.41622049084608e-16 -6.68515202578511e-17 -3.
˓→(continues on next page)1049

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)95597468756028e-17 -4.85722573273506e-17 -5.32388011580111e-17 -1.
˓→31328455615552e-16
1.00000000000000][-1.00000000000000
0.000000000000000
0.000000000000000 4.
˓→85722573273506e-17
0.000000000000000 -5.55111512312578e-17 -1.
˓→11022302462516e-16
2.22044604925031e-16][
0.000000000000000-1.00000000000000
0.000000000000000 -2.
˓→77555756156289e-17
5.55111512312578e-17 -8.69223574327834e-170.
˓→000000000000000 -4.44089209850063e-16][
0.000000000000000 -1.05042437087238e-17-1.00000000000000 3.
˓→33066907387547e-16
1.11022302462516e-16 -1.18333563634309e-16 4.
˓→40064433050777e-17
2.22044604925031e-16][ 5.27829526256056e-16 1.99901485752317e-16 1.65710718121313e-17-1.
˓→00000000000000 -2.22044604925031e-16
5.52150940090699e-16 -3.93560383111738e˓→16
1.01155762925061e-16]>>> F == C * E * C.transpose()True>>> abs(F[Integer(0), Integer(4)] - Integer(1)) < RealNumber( 1e-10 )True>>> abs(F[Integer(4), Integer(0)] + Integer(1)) < RealNumber( 1e-10 )True˓→>>> F.parent()
Full MatrixSpace of 8 by 8 dense matrices over Real Field with 53 bits of␣˓→precision>>> C.parent()
Full MatrixSpace of 8 by 8 dense matrices over Real Field with 53 bits of␣˓→precision

1050

Chapter 44. Calculate symplectic bases for matrices over fields and the integers.

CHAPTERFORTYFIVE

𝐽-IDEALS OF MATRICESLet 𝐵 be an 𝑛 × 𝑛-matrix over a principal ideal domain 𝐷.
For an ideal 𝐽, the 𝐽-ideal of 𝐵 is defined to be 𝑁𝐽 (𝐵) = {𝑓 ∈ 𝐷[𝑋] | 𝑓 (𝐵) ∈ 𝑀𝑛 (𝐽)}.
For a prime element 𝑝 of 𝐷 and 𝑡 ≥ 0, a (𝑝𝑡 )-minimal polynomial of 𝐵 is a monic polynomial 𝑓 ∈ 𝑁(𝑝𝑡 ) (𝐵) of minimal
degree.
This module computes these minimal polynomials.
Let 𝑝 be a prime element of 𝐷. Then there is a finite set 𝒮𝑝 of positive integers and monic polynomials 𝜈𝑝𝑠 for 𝑠 ∈ 𝒮𝑝
such that for 𝑡 ≥ 1,∑︁𝑁(𝑝𝑡 ) (𝐵) = 𝜇𝐵 𝐷[𝑋] + 𝑝𝑡 𝐷[𝑋] +𝑝max{0,𝑡−𝑠} 𝜈𝑝𝑠 𝐷[𝑋]𝑠∈𝒮𝑝𝑠≤𝑏(𝑡)

holds where 𝑏(𝑡) = min{𝑟 ∈ 𝒮𝑝 | 𝑟 ≥ 𝑠}. The degree of 𝜈𝑝𝑠 is strictly increasing in 𝑠 ∈ 𝒮𝑝 and 𝜈𝑝𝑠 is a (𝑝𝑠 )-minimal
polynomial. If 𝑡 ≤ max 𝒮𝑝 , then the summand 𝜇𝐵 𝐷[𝑋] can be omitted.
All computations are done by the class ComputeMinimalPolynomials where various intermediate results arecached. It provides the following methods:• p_minimal_polynomials() computes 𝒮𝑝 and the monic polynomials 𝜈𝑝𝑠 .
• null_ideal() determines 𝑁(𝑝𝑡 ) (𝐵).
• prime_candidates() determines all primes 𝑝 where 𝒮𝑝 might be non-empty.
• integer_valued_polynomials_generators() determines the generators of the ring {𝑓 ∈ 𝐾[𝑋] |𝑓 (𝐵) ∈ 𝑀𝑛 (𝐷)} of integer valued polynomials on 𝐵.
EXAMPLES:
sage: from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials
sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]])sage: C = ComputeMinimalPolynomials(B)sage: C.prime_candidates()[2, 3, 5]
sage: for t in range(4):....:print(C.null_ideal(2^t))
Principal ideal (1) ofUnivariate Polynomial Ring in x over Integer Ring
Ideal (2, x^2 + x) of
Univariate Polynomial Ring in x over Integer Ring
Ideal (4, x^2 + 3*x + 2) ofUnivariate Polynomial Ring in x over Integer Ring
Ideal (8, x^3 + x^2 - 12*x - 20, 2*x^2 + 6*x + 4) of(continues on next page)1051

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Univariate Polynomial Ring in x over Integer Ringsage: C.p_minimal_polynomials(2){2: x^2 + 3*x + 2}
sage: C.integer_valued_polynomials_generators()(x^3 + x^2 - 12*x - 20, [1, 1/4*x^2 + 3/4*x + 1/2])>>> from sage.all import *>>> from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials>>> B = matrix(ZZ, [[Integer(1), Integer(0), Integer(1)], [Integer(1), -Integer(2), ˓→Integer(1)], [Integer(10), Integer(0), Integer(0)]])>>> C = ComputeMinimalPolynomials(B)>>> C.prime_candidates()[2, 3, 5]>>> for t in range(Integer(4)):...
print(C.null_ideal(Integer(2)**t))Principal ideal (1) ofUnivariate Polynomial Ring in x over Integer Ring
Ideal (2, x^2 + x) of
Univariate Polynomial Ring in x over Integer Ring
Ideal (4, x^2 + 3*x + 2) ofUnivariate Polynomial Ring in x over Integer Ring
Ideal (8, x^3 + x^2 - 12*x - 20, 2*x^2 + 6*x + 4) ofUnivariate Polynomial Ring in x over Integer Ring>>> C.p_minimal_polynomials(Integer(2)){2: x^2 + 3*x + 2}>>> C.integer_valued_polynomials_generators()(x^3 + x^2 - 12*x - 20, [1, 1/4*x^2 + 3/4*x + 1/2])

The last output means that{𝑓 ∈1[𝑋] | 𝑓 (𝐵) ∈ 𝑀3 (Z)} = (𝑥3 + 𝑥2 − 12𝑥 − 20) [𝑋] + Z[𝑋] + (𝑥2 + 3𝑥 + 2)Z[𝑋].
4

Todo: Test code over PIDs other than ZZ.
This requires implementation of frobenius() over more general domains than ZZ.
Additionally, lifting() requires modification or a bug needs fixing, see AskSage Question 35555.
REFERENCES:[Ris2016], [HR2016]
AUTHORS:• Clemens Heuberger (2016)• Roswitha Rissner (2016)
ACKNOWLEDGEMENT:• Clemens Heuberger is supported by the Austrian Science Fund (FWF): P 24644-N26.
• Roswitha Rissner is supported by the Austrian Science Fund (FWF): P 27816-N26.

1052

Chapter 45. 𝐽-ideals of matrices

Matrices and Spaces of Matrices, Release 10.4

45.1 Classes and Methods
class sage.matrix.compute_J_ideal.ComputeMinimalPolynomials(B)Bases: SageObject
Create an object for computing (𝑝𝑡 )-minimal polynomials and 𝐽-ideals.
For an ideal 𝐽 and a square matrix 𝐵 over a principal ideal domain 𝐷, the 𝐽-ideal of 𝐵 is defined to be 𝑁𝐽 (𝐵) ={𝑓 ∈ 𝐷[𝑋] | 𝑓 (𝐵) ∈ 𝑀𝑛 (𝐽)}.
For a prime element 𝑝 of 𝐷 and 𝑡 ≥ 0, a (𝑝𝑡 )-minimal polynomial of 𝐵 is a monic polynomial 𝑓 ∈ 𝑁(𝑝𝑡 ) (𝐵) of
minimal degree.
The characteristic polynomial of 𝐵 is denoted by 𝜒𝐵 ; 𝑛 is the size of 𝐵.
INPUT:• B – a square matrix over a principal ideal domain 𝐷
OUTPUT:An object which allows to call p_minimal_polynomials(), null_ideal() and integer_valued_polynomials_generators().
EXAMPLES:
sage: from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials
sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]])sage: C = ComputeMinimalPolynomials(B)sage: C.prime_candidates()[2, 3, 5]
sage: for t in range(4):....:print(C.null_ideal(2^t))
Principal ideal (1) ofUnivariate Polynomial Ring in x over Integer Ring
Ideal (2, x^2 + x) of
Univariate Polynomial Ring in x over Integer Ring
Ideal (4, x^2 + 3*x + 2) ofUnivariate Polynomial Ring in x over Integer Ring
Ideal (8, x^3 + x^2 - 12*x - 20, 2*x^2 + 6*x + 4) ofUnivariate Polynomial Ring in x over Integer Ringsage: C.p_minimal_polynomials(2){2: x^2 + 3*x + 2}
sage: C.integer_valued_polynomials_generators()(x^3 + x^2 - 12*x - 20, [1, 1/4*x^2 + 3/4*x + 1/2])>>> from sage.all import *>>> from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials>>> B = matrix(ZZ, [[Integer(1), Integer(0), Integer(1)], [Integer(1), ˓→Integer(2), -Integer(1)], [Integer(10), Integer(0), Integer(0)]])>>> C = ComputeMinimalPolynomials(B)>>> C.prime_candidates()[2, 3, 5]>>> for t in range(Integer(4)):...
print(C.null_ideal(Integer(2)**t))Principal ideal (1) ofUnivariate Polynomial Ring in x over Integer Ring
Ideal (2, x^2 + x) of
Univariate Polynomial Ring in x over Integer Ring
(continues on next page)45.1. Classes and Methods

1053

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

Ideal (4, x^2 + 3*x + 2) ofUnivariate Polynomial Ring in x over Integer Ring
Ideal (8, x^3 + x^2 - 12*x - 20, 2*x^2 + 6*x + 4) ofUnivariate Polynomial Ring in x over Integer Ring>>> C.p_minimal_polynomials(Integer(2)){2: x^2 + 3*x + 2}>>> C.integer_valued_polynomials_generators()(x^3 + x^2 - 12*x - 20, [1, 1/4*x^2 + 3/4*x + 1/2])

current_nu(p, t, pt_generators, prev_nu)
Compute (𝑝𝑡 )-minimal polynomial of 𝐵.
INPUT:• p – a prime element of 𝐷
• t – a positive integer• pt_generators – a list (𝑔1 , . . . , 𝑔𝑠 ) of polynomials in 𝐷[𝑋] such that 𝑁(𝑝𝑡 ) (𝐵) = (𝑔1 , . . . , 𝑔𝑠 ) +𝑝𝑁(𝑝𝑡−1 ) (𝐵)• prev_nu – a (𝑝𝑡−1 )-minimal polynomial of 𝐵
OUTPUT:
A (𝑝𝑡 )-minimal polynomial of 𝐵.
EXAMPLES:
sage: from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials
sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]])sage: C = ComputeMinimalPolynomials(B)sage: x = polygen(ZZ, x )sage: nu_1 = x^2 + x
sage: generators_4 = [2*x^2 + 2*x, x^2 + 3*x + 2]
sage: C.current_nu(2, 2, generators_4, nu_1)x^2 + 3*x + 2>>> from sage.all import *>>> from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials>>> B = matrix(ZZ, [[Integer(1), Integer(0), Integer(1)], [Integer(1), ˓→Integer(2), -Integer(1)], [Integer(10), Integer(0), Integer(0)]])>>> C = ComputeMinimalPolynomials(B)>>> x = polygen(ZZ, x )>>> nu_1 = x**Integer(2) + x>>> generators_4 = [Integer(2)*x**Integer(2) + Integer(2)*x, x**Integer(2) +␣˓→Integer(3)*x + Integer(2)]>>> C.current_nu(Integer(2), Integer(2), generators_4, nu_1)x^2 + 3*x + 2

ALGORITHM:[HR2016], Algorithm 4.
find_monic_replacements(p, t, pt_generators, prev_nu)
Replace possibly non-monic generators of 𝑁(𝑝𝑡 ) (𝐵) by monic generators.
INPUT:• p – a prime element of 𝐷

1054

Chapter 45. 𝐽-ideals of matrices

Matrices and Spaces of Matrices, Release 10.4

• t – a non-negative integer• pt_generators – a list (𝑔1 , . . . , 𝑔𝑠 ) of polynomials in 𝐷[𝑋] such that 𝑁(𝑝𝑡 ) (𝐵) = (𝑔1 , . . . , 𝑔𝑠 ) +𝑝𝑁(𝑝𝑡−1 ) (𝐵)• prev_nu – a (𝑝𝑡−1 )-minimal polynomial of 𝐵
OUTPUT:
A list (ℎ1 , . . . , ℎ𝑟 ) of monic polynomials such that 𝑁(𝑝𝑡 ) (𝐵) = (ℎ1 , . . . , ℎ𝑟 ) + 𝑝𝑁(𝑝𝑡−1 ) (𝐵).
EXAMPLES:
sage: from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials
sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]])sage: C = ComputeMinimalPolynomials(B)sage: x = polygen(ZZ, x )sage: nu_1 = x^2 + x
sage: generators_4 = [2*x^2 + 2*x, x^2 + 3*x + 2]
sage: C.find_monic_replacements(2, 2, generators_4, nu_1)[x^2 + 3*x + 2]>>> from sage.all import *>>> from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials>>> B = matrix(ZZ, [[Integer(1), Integer(0), Integer(1)], [Integer(1), ˓→Integer(2), -Integer(1)], [Integer(10), Integer(0), Integer(0)]])>>> C = ComputeMinimalPolynomials(B)>>> x = polygen(ZZ, x )>>> nu_1 = x**Integer(2) + x>>> generators_4 = [Integer(2)*x**Integer(2) + Integer(2)*x, x**Integer(2) +␣˓→Integer(3)*x + Integer(2)]>>> C.find_monic_replacements(Integer(2), Integer(2), generators_4, nu_1)[x^2 + 3*x + 2]

ALGORITHM:[HR2016], Algorithms 2 and 3.
integer_valued_polynomials_generators()
Determine the generators of the ring of integer valued polynomials on 𝐵.
OUTPUT:
A pair (mu_B, P) where P is a list of polynomials in 𝐾[𝑋] such that{𝑓 ∈ 𝐾[𝑋] | 𝑓 (𝐵) ∈ 𝑀𝑛 (𝐷)} = 𝜇𝐵 𝐾[𝑋] +

∑︁

𝑔𝐷[𝑋]

𝑔∈𝑃

where 𝐾 denotes the fraction field of 𝐷.
EXAMPLES:
sage: from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials
sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]])sage: C = ComputeMinimalPolynomials(B)sage: C.integer_valued_polynomials_generators()(x^3 + x^2 - 12*x - 20, [1, 1/4*x^2 + 3/4*x + 1/2])>>> from sage.all import *>>> from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials(continues on next page)45.1. Classes and Methods

1055

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)>>> B = matrix(ZZ, [[Integer(1), Integer(0), Integer(1)], [Integer(1), ˓→Integer(2), -Integer(1)], [Integer(10), Integer(0), Integer(0)]])>>> C = ComputeMinimalPolynomials(B)>>> C.integer_valued_polynomials_generators()(x^3 + x^2 - 12*x - 20, [1, 1/4*x^2 + 3/4*x + 1/2])

mccoy_column(p, t, nu)
Compute matrix for McCoy’s criterion.
INPUT:• p – a prime element in 𝐷
• t – a positive integer• nu – a (𝑝𝑡 )-minimal polynomial of 𝐵
OUTPUT:(︀)︀
An (𝑛2 + 1) × 1 matrix 𝑔 with first entry nu such that 𝑏 −𝜒𝐵 𝐼 𝑔 ≡ 0 (mod 𝑝𝑡 ) where 𝑏 consists of theentries of adj(𝑋 − 𝐵).
EXAMPLES:
sage: from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials
sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]])sage: C = ComputeMinimalPolynomials(B)sage: x = polygen(ZZ, x )sage: nu_4 = x^2 + 3*x + 2
sage: g = C.mccoy_column(2, 2, nu_4)
sage: b = matrix(9, 1, (x - B).adjugate().list())
sage: M = matrix.block([[b, -B.charpoly(x)*matrix.identity(9)]])sage: (M*g % 4).is_zero()True>>> from sage.all import *>>> from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials>>> B = matrix(ZZ, [[Integer(1), Integer(0), Integer(1)], [Integer(1), ˓→Integer(2), -Integer(1)], [Integer(10), Integer(0), Integer(0)]])>>> C = ComputeMinimalPolynomials(B)>>> x = polygen(ZZ, x )>>> nu_4 = x**Integer(2) + Integer(3)*x + Integer(2)>>> g = C.mccoy_column(Integer(2), Integer(2), nu_4)>>> b = matrix(Integer(9), Integer(1), (x - B).adjugate().list())>>> M = matrix.block([[b, -B.charpoly(x)*matrix.identity(Integer(9))]])>>> (M*g % Integer(4)).is_zero()
True

ALGORITHM:[HR2016], Algorithm 5.
null_ideal(b=0)
Return the (𝑏)-ideal 𝑁(𝑏) (𝐵) = {𝑓 ∈ 𝐷[𝑋] | 𝑓 (𝐵) ∈ 𝑀𝑛 (𝑏𝐷)}.
INPUT:• b – an element of 𝐷 (default: 0)
OUTPUT:

1056

Chapter 45. 𝐽-ideals of matrices

Matrices and Spaces of Matrices, Release 10.4

An ideal in 𝐷[𝑋].
EXAMPLES:
sage: from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials
sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]])sage: C = ComputeMinimalPolynomials(B)sage: C.null_ideal()
Principal ideal (x^3 + x^2 - 12*x - 20) of
Univariate Polynomial Ring in x over Integer Ringsage: C.null_ideal(2)Ideal (2, x^2 + x) of
Univariate Polynomial Ring in x over Integer Ringsage: C.null_ideal(4)Ideal (4, x^2 + 3*x + 2) ofUnivariate Polynomial Ring in x over Integer Ringsage: C.null_ideal(8)Ideal (8, x^3 + x^2 - 12*x - 20, 2*x^2 + 6*x + 4) ofUnivariate Polynomial Ring in x over Integer Ringsage: C.null_ideal(3)Ideal (3, x^3 + x^2 - 12*x - 20) of
Univariate Polynomial Ring in x over Integer Ringsage: C.null_ideal(6)Ideal (6, 2*x^3 + 2*x^2 - 24*x - 40, 3*x^2 + 3*x) of
Univariate Polynomial Ring in x over Integer Ring>>> from sage.all import *>>> from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials>>> B = matrix(ZZ, [[Integer(1), Integer(0), Integer(1)], [Integer(1), ˓→Integer(2), -Integer(1)], [Integer(10), Integer(0), Integer(0)]])>>> C = ComputeMinimalPolynomials(B)>>> C.null_ideal()
Principal ideal (x^3 + x^2 - 12*x - 20) of
Univariate Polynomial Ring in x over Integer Ring>>> C.null_ideal(Integer(2))
Ideal (2, x^2 + x) of
Univariate Polynomial Ring in x over Integer Ring>>> C.null_ideal(Integer(4))
Ideal (4, x^2 + 3*x + 2) ofUnivariate Polynomial Ring in x over Integer Ring>>> C.null_ideal(Integer(8))
Ideal (8, x^3 + x^2 - 12*x - 20, 2*x^2 + 6*x + 4) ofUnivariate Polynomial Ring in x over Integer Ring>>> C.null_ideal(Integer(3))
Ideal (3, x^3 + x^2 - 12*x - 20) of
Univariate Polynomial Ring in x over Integer Ring>>> C.null_ideal(Integer(6))
Ideal (6, 2*x^3 + 2*x^2 - 24*x - 40, 3*x^2 + 3*x) of
Univariate Polynomial Ring in x over Integer Ring

p_minimal_polynomials(p, s_max=None)
Compute (𝑝𝑠 )-minimal polynomials 𝜈𝑠 of 𝐵.
Compute a finite subset 𝒮 of the positive integers and (𝑝𝑠 )-minimal polynomials 𝜈𝑠 for 𝑠 ∈ 𝒮.
For 0 < 𝑡 ≤ max 𝒮, a (𝑝𝑡 )-minimal polynomial is given by 𝜈𝑠 where 𝑠 = min{𝑟 ∈ 𝒮 | 𝑟 ≥ 𝑡}. For
𝑡 > max 𝒮, the minimal polynomial of 𝐵 is also a (𝑝𝑡 )-minimal polynomial.
INPUT:

45.1. Classes and Methods

1057

Matrices and Spaces of Matrices, Release 10.4

• p – a prime in 𝐷
• s_max – a positive integer (default: None); if set, only (𝑝𝑠 )-minimal polynomials for s <= s_max
are computed (see below for details)
OUTPUT:
A dictionary. Keys are the finite set 𝒮, the values are the associated (𝑝𝑠 )-minimal polynomials 𝜈𝑠 , 𝑠 ∈ 𝒮.
Setting s_max only affects the output if s_max is at most max 𝒮 where 𝒮 denotes the full set. In that case,only those 𝜈𝑠 with s <= s_max are returned where s_max is always included even if it is not included in
the full set 𝒮.
EXAMPLES:
sage: from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials
sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]])sage: C = ComputeMinimalPolynomials(B)sage: C.p_minimal_polynomials(2){2: x^2 + 3*x + 2}
sage: set_verbose(1)sage: C = ComputeMinimalPolynomials(B)sage: C.p_minimal_polynomials(2)verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)-----------------------------------------verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
p = 2, t = 1:verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
Result of lifting:verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
F =verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)[x^2 + x]
[
x]
[
0]
[
1]
[
1]
[ x + 1]
[
1]
[
0]
[
0]
[ x + 1]verbose 1 (...: compute_J_ideal.py, current_nu)-----------------------------------------verbose 1 (...: compute_J_ideal.py, current_nu)(x^2 + x)
verbose 1 (...: compute_J_ideal.py, current_nu)
Generators with (p^t)-generating property:
verbose 1 (...: compute_J_ideal.py, current_nu)[x^2 + x]
verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
nu = x^2 + xverbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
corresponding columns for G
verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)[x^2 + x][ x + 2]
[
0]
[
1]
[
1]
(continues on next page)

1058

Chapter 45. 𝐽-ideals of matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[ x - 1]
[
-1]
[
10]
[
0]
[ x + 1]verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)-----------------------------------------verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
p = 2, t = 2:verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
Result of lifting:verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
F =verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)[ 2*x^2 + 2*x x^2 + 3*x + 2][
2*xx + 4]
[
0
0]
[
2
1]
[
2
1]
[
2*x + 2x + 1]
[
2
-1]
[
0
10]
[
0
0]
[
2*x + 2x + 3]
verbose 1 (...: compute_J_ideal.py, current_nu)-----------------------------------------verbose 1 (...: compute_J_ideal.py, current_nu)(2*x^2 + 2*x, x^2 + 3*x + 2)
verbose 1 (...: compute_J_ideal.py, current_nu)
Generators with (p^t)-generating property:
verbose 1 (...: compute_J_ideal.py, current_nu)[x^2 + 3*x + 2]
verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
nu = x^2 + 3*x + 2verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
corresponding columns for G
verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)[x^2 + 3*x + 2][
x + 4]
[
0]
[
1]
[
1]
[
x + 1]
[
-1]
[
10]
[
0]
[
x + 3]
verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)-----------------------------------------verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
p = 2, t = 3:verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
Result of lifting:verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
F =verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)[x^3 + 7*x^2 + 6*x x^3 + 3*x^2 + 2*x]
(continues on next page)45.1. Classes and Methods

1059

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)[x^2 + 8*xx^2 + 4*x]
[
0
0]
[
x
x + 4][x + 4
x][x^2 + 5*x + 4
x^2 + x][-x + 4
-x]
[
10*x
10*x]
[
0
0]
[
x^2 + 7*xx^2 + 3*x + 4]
verbose 1 (...: compute_J_ideal.py, current_nu)-----------------------------------------verbose 1 (...: compute_J_ideal.py, current_nu)(x^3 + 7*x^2 + 6*x, x^3 + 3*x^2 + 2*x)
verbose 1 (...: compute_J_ideal.py, current_nu)
Generators with (p^t)-generating property:
verbose 1 (...: compute_J_ideal.py, current_nu)...
verbose 1 (...: compute_J_ideal.py, current_nu)[x^3 + 3*x^2 + 2*x]
verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
nu = x^3 + 3*x^2 + 2*x{2: x^2 + 3*x + 2}
sage: set_verbose(0)sage: C.p_minimal_polynomials(2, s_max=1){1: x^2 + x}
sage: C.p_minimal_polynomials(2, s_max=2){2: x^2 + 3*x + 2}
sage: C.p_minimal_polynomials(2, s_max=3){2: x^2 + 3*x + 2}>>> from sage.all import *>>> from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials>>> B = matrix(ZZ, [[Integer(1), Integer(0), Integer(1)], [Integer(1), ˓→Integer(2), -Integer(1)], [Integer(10), Integer(0), Integer(0)]])>>> C = ComputeMinimalPolynomials(B)>>> C.p_minimal_polynomials(Integer(2)){2: x^2 + 3*x + 2}>>> set_verbose(Integer(1))>>> C = ComputeMinimalPolynomials(B)>>> C.p_minimal_polynomials(Integer(2))
verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)-----------------------------------------verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
p = 2, t = 1:verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
Result of lifting:verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
F =verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)[x^2 + x]
[
x]
[
0]
[
1]
[
1]
[ x + 1][
1](continues on next page)1060

Chapter 45. 𝐽-ideals of matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

[
0]
[
0]
[ x + 1]verbose 1 (...: compute_J_ideal.py, current_nu)-----------------------------------------verbose 1 (...: compute_J_ideal.py, current_nu)(x^2 + x)
verbose 1 (...: compute_J_ideal.py, current_nu)
Generators with (p^t)-generating property:
verbose 1 (...: compute_J_ideal.py, current_nu)[x^2 + x]
verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
nu = x^2 + xverbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
corresponding columns for G
verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)[x^2 + x][ x + 2]
[
0]
[
1]
[
1]
[ x - 1]
[
-1]
[
10]
[
0]
[ x + 1]verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)-----------------------------------------verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
p = 2, t = 2:verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
Result of lifting:verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
F =verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)[ 2*x^2 + 2*x x^2 + 3*x + 2][
2*xx + 4]
[
0
0]
[
2
1]
[
2
1]
[
2*x + 2x + 1]
[
2
-1]
[
0
10]
[
0
0]
[
2*x + 2x + 3]
verbose 1 (...: compute_J_ideal.py, current_nu)-----------------------------------------verbose 1 (...: compute_J_ideal.py, current_nu)(2*x^2 + 2*x, x^2 + 3*x + 2)
verbose 1 (...: compute_J_ideal.py, current_nu)
Generators with (p^t)-generating property:
verbose 1 (...: compute_J_ideal.py, current_nu)[x^2 + 3*x + 2]
verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
nu = x^2 + 3*x + 2verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
corresponding columns for G(continues on next page)45.1. Classes and Methods

1061

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)[x^2 + 3*x + 2][
x + 4]
[
0]
[
1]
[
1]
[
x + 1]
[
-1]
[
10]
[
0]
[
x + 3]
verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)-----------------------------------------verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
p = 2, t = 3:verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
Result of lifting:verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
F =verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)[x^3 + 7*x^2 + 6*x x^3 + 3*x^2 + 2*x][x^2 + 8*xx^2 + 4*x]
[
0
0]
[
x
x + 4][x + 4
x][x^2 + 5*x + 4
x^2 + x][-x + 4
-x]
[
10*x
10*x]
[
0
0]
[
x^2 + 7*xx^2 + 3*x + 4]
verbose 1 (...: compute_J_ideal.py, current_nu)-----------------------------------------verbose 1 (...: compute_J_ideal.py, current_nu)(x^3 + 7*x^2 + 6*x, x^3 + 3*x^2 + 2*x)
verbose 1 (...: compute_J_ideal.py, current_nu)
Generators with (p^t)-generating property:
verbose 1 (...: compute_J_ideal.py, current_nu)...
verbose 1 (...: compute_J_ideal.py, current_nu)[x^3 + 3*x^2 + 2*x]
verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials)
nu = x^3 + 3*x^2 + 2*x{2: x^2 + 3*x + 2}>>> set_verbose(Integer(0))>>> C.p_minimal_polynomials(Integer(2), s_max=Integer(1)){1: x^2 + x}>>> C.p_minimal_polynomials(Integer(2), s_max=Integer(2)){2: x^2 + 3*x + 2}>>> C.p_minimal_polynomials(Integer(2), s_max=Integer(3)){2: x^2 + 3*x + 2}

ALGORITHM:[HR2016], Algorithm 5.
prime_candidates()
Determine those primes 𝑝 where 𝜇𝐵 might not be a (𝑝)-minimal polynomial.

1062

Chapter 45. 𝐽-ideals of matrices

Matrices and Spaces of Matrices, Release 10.4

OUTPUT:
A list of primes.
EXAMPLES:
sage: from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials
sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]])sage: C = ComputeMinimalPolynomials(B)sage: C.prime_candidates()[2, 3, 5]
sage: C.p_minimal_polynomials(2){2: x^2 + 3*x + 2}
sage: C.p_minimal_polynomials(3){}sage: C.p_minimal_polynomials(5){}>>> from sage.all import *>>> from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials>>> B = matrix(ZZ, [[Integer(1), Integer(0), Integer(1)], [Integer(1), ˓→Integer(2), -Integer(1)], [Integer(10), Integer(0), Integer(0)]])>>> C = ComputeMinimalPolynomials(B)>>> C.prime_candidates()[2, 3, 5]>>> C.p_minimal_polynomials(Integer(2)){2: x^2 + 3*x + 2}>>> C.p_minimal_polynomials(Integer(3)){}>>> C.p_minimal_polynomials(Integer(5)){}

This means that 3 and 5 were candidates, but actually, 𝜇𝐵 turns out to be a (3)-minimal polynomial and a(5)-minimal polynomial.
sage.matrix.compute_J_ideal.lifting(p, t, A, G)
Compute generators of {𝑓 ∈ 𝐷[𝑋]𝑑 | 𝐴𝑓 ≡ 0 (mod 𝑝𝑡 )} given generators of {𝑓 ∈ 𝐷[𝑋]𝑑 | 𝐴𝑓 ≡ 0(mod 𝑝𝑡−1 )}.
INPUT:• p – a prime element of some principal ideal domain 𝐷• t – a non-negative integer• A – a 𝑐 × 𝑑 matrix over 𝐷[𝑋](︀
• G – a matrix over 𝐷[𝑋]. The columns of 𝑝𝑡−1 𝐼(mod 𝑝𝑡−1 )}; can be set to None if t is zero)︀𝐺 are generators of {𝑓 ∈ 𝐷[𝑋]𝑑 | 𝐴𝑓 ≡ 0

OUTPUT:(︀
A matrix 𝐹 over 𝐷[𝑋] such that the columns of 𝑝𝑡 𝐼
(mod 𝑝𝑡 )}.

𝐹)︀
𝑝𝐺 are generators of {𝑓 ∈ 𝐷[𝑋]𝑑 | 𝐴𝑓 ≡ 0

EXAMPLES:
sage: from sage.matrix.compute_J_ideal import lifting
sage: X = polygen(ZZ, X )sage: A = matrix([[1, X], [2*X, X^2]])sage: G0 = lifting(5, 0, A, None)(continues on next page)45.1. Classes and Methods

1063

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)

sage: G1 = lifting(5, 1, A, G0); G1[]
sage: (A*G1 % 5).is_zero()Truesage: A = matrix([[1, X, X^2], [2*X, X^2, 3*X^3]])sage: G0 = lifting(5, 0, A, None)sage: G1 = lifting(5, 1, A, G0); G1[3*X^2][X][
1]
sage: (A*G1 % 5).is_zero()Truesage: G2 = lifting(5, 2, A, G1); G2[15*X^2 23*X^2]
[
5*X
X]
[
5
1]
sage: (A*G2 % 25).is_zero()Truesage: lifting(5, 10, A, G1)
Traceback (most recent call last):...
ValueError: A*G not zero mod 5^9>>> from sage.all import *>>> from sage.matrix.compute_J_ideal import lifting>>> X = polygen(ZZ, X )>>> A = matrix([[Integer(1), X], [Integer(2)*X, X**Integer(2)]])>>> G0 = lifting(Integer(5), Integer(0), A, None)>>> G1 = lifting(Integer(5), Integer(1), A, G0); G1[]>>> (A*G1 % Integer(5)).is_zero()
True>>> A = matrix([[Integer(1), X, X**Integer(2)], [Integer(2)*X, X**Integer(2),␣
˓→Integer(3)*X**Integer(3)]])>>> G0 = lifting(Integer(5), Integer(0), A, None)>>> G1 = lifting(Integer(5), Integer(1), A, G0); G1[3*X^2][X][
1]>>> (A*G1 % Integer(5)).is_zero()
True>>> G2 = lifting(Integer(5), Integer(2), A, G1); G2[15*X^2 23*X^2]
[
5*X
X]
[
5
1]
>>> (A*G2 % Integer(25)).is_zero()True>>> lifting(Integer(5), Integer(10), A, G1)
Traceback (most recent call last):...
ValueError: A*G not zero mod 5^9

ALGORITHM:[HR2016], Algorithm 1.
sage.matrix.compute_J_ideal.p_part(f, p)

1064

Chapter 45. 𝐽-ideals of matrices

Matrices and Spaces of Matrices, Release 10.4

Compute the 𝑝-part of a polynomial.
INPUT:• f – a polynomial over 𝐷• p – a prime in 𝐷
OUTPUT:
A polynomial 𝑔 such that deg 𝑔 ≤ deg 𝑓 and all non-zero coefficients of 𝑓 − 𝑝𝑔 are not divisible by 𝑝.
EXAMPLES:
sage: from sage.matrix.compute_J_ideal import p_part
sage: X = polygen(ZZ, X )sage: f = X^3 + 5*X + 25
sage: g = p_part(f, 5); gX + 5sage: f - 5*g
X^3>>> from sage.all import *>>> from sage.matrix.compute_J_ideal import p_part>>> X = polygen(ZZ, X )>>> f = X**Integer(3) + Integer(5)*X + Integer(25)>>> g = p_part(f, Integer(5)); g
X + 5>>> f - Integer(5)*gX^3

45.1. Classes and Methods

1065

Matrices and Spaces of Matrices, Release 10.4

1066

Chapter 45. 𝐽-ideals of matrices

CHAPTERFORTYSIX

BENCHMARKS FOR MATRICESThis file has many functions for computing timing benchmarks of various methods for random matrices with given bounds
for the entries. The systems supported are Sage and Magma.
The basic command syntax is as follows:
sage: import sage.matrix.benchmark as b
sage: print("starting"); import sys; sys.stdout.flush(); b.report([b.det_ZZ],
˓→systems=[ sage ])starting...
======================================================================
Test======================================================================...
======================================================================>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> print("starting"); import sys; sys.stdout.flush(); b.report([b.det_ZZ],
˓→systems=[ sage ])starting...
======================================================================
Test======================================================================...
======================================================================

Test ,␣

Test ,␣

sage.matrix.benchmark.MatrixVector_QQ(n=1000, h=100, system='sage', times=1)
Compute product of square n matrix by random vector with num and denom bounded by h the given number oftimes.
INPUT:• n – matrix dimension (default: 300)
• h – numerator and denominator bound (default: bnd)
• system – either ‘sage’ or ‘magma’ (default: ‘sage’)• times – number of experiments (default: 1)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.MatrixVector_QQ(500)
sage: tm = b.MatrixVector_QQ(500, system= magma )# optional - magma

1067

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.MatrixVector_QQ(Integer(500))>>> tm = b.MatrixVector_QQ(Integer(500), system= magma )# optional - magma

sage.matrix.benchmark.charpoly_GF(n=100, p=16411, system='sage')
Given a n x n matrix over GF with random entries, compute the charpoly.
INPUT:• n – matrix dimension (default: 100)
• p – prime number (default: 16411)• system – either ‘magma’ or ‘sage’ (default: ‘sage’)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.charpoly_GF(100)sage: tm = b.charpoly_GF(100, system= magma )# optional - magma>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.charpoly_GF(Integer(100))>>> tm = b.charpoly_GF(Integer(100), system= magma )# optional - magma

sage.matrix.benchmark.charpoly_ZZ(n=100, min=0, max=9, system='sage')
Characteristic polynomial over ZZ: Given a n x n matrix over ZZ with random entries between min and max,
compute the charpoly.
INPUT:• n – matrix dimension (default: 100)• min – minimal value for entries of matrix (default: 0)• max – maximal value for entries of matrix (default: 9)• system – either ‘sage’ or ‘magma’ (default: ‘sage’)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.charpoly_ZZ(100)sage: tm = b.charpoly_ZZ(100, system= magma )# optional - magma>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.charpoly_ZZ(Integer(100))>>> tm = b.charpoly_ZZ(Integer(100), system= magma )# optional - magma

sage.matrix.benchmark.det_GF(n=400, p=16411, system='sage')
Dense determinant over GF(p). Given an n x n matrix A over GF with random entries compute det(A).
INPUT:• n – matrix dimension (default: 300)
• p – prime number (default: 16411)• system – either ‘magma’ or ‘sage’ (default: ‘sage’)1068

Chapter 46. Benchmarks for matrices

Matrices and Spaces of Matrices, Release 10.4

EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.det_GF(1000)
sage: tm = b.det_GF(1000, system= magma )# optional - magma>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.det_GF(Integer(1000))>>> tm = b.det_GF(Integer(1000), system= magma )# optional - magma

sage.matrix.benchmark.det_QQ(n=300, num_bound=10, den_bound=10, system='sage')
Dense rational determinant over QQ. Given an n x n matrix A over QQ with random entries with numerator boundand denominator bound, compute det(A).
INPUT:• n – matrix dimension (default: 200)
• num_bound – numerator bound, inclusive (default: 10)• den_bound – denominator bound, inclusive (default: 10)• system – either ‘sage’ or ‘magma’ (default: ‘sage’)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.det_QQ(200)sage: ts = b.det_QQ(10, num_bound=100000, den_bound=10000)
sage: tm = b.det_QQ(200, system= magma ) # optional - magma>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.det_QQ(Integer(200))>>> ts = b.det_QQ(Integer(10), num_bound=Integer(100000), den_
˓→bound=Integer(10000))>>> tm = b.det_QQ(Integer(200), system= magma ) # optional - magma

sage.matrix.benchmark.det_ZZ(n=200, min=1, max=100, system='sage')
Dense integer determinant over ZZ. Given an n x n matrix A over ZZ with random entries between min and max,
inclusive, compute det(A).
INPUT:• n – matrix dimension (default: 200)
• min – minimal value for entries of matrix (default: 1)• max – maximal value for entries of matrix (default: 100)• system – either ‘sage’ or ‘magma’ (default: ‘sage’)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.det_ZZ(200)sage: tm = b.det_ZZ(200, system= magma )# optional - magma1069

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.det_ZZ(Integer(200))>>> tm = b.det_ZZ(Integer(200), system= magma )# optional - magma

sage.matrix.benchmark.det_hilbert_QQ(n=80, system='sage')
Runs the benchmark for calculating the determinant of the hilbert matrix over rationals of dimension n.
INPUT:• n – matrix dimension (default: 300)
• system – either ‘sage’ or ‘magma’ (default: ‘sage’)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.det_hilbert_QQ(50)sage: tm = b.det_hilbert_QQ(50, system= magma )# optional - magma>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.det_hilbert_QQ(Integer(50))>>> tm = b.det_hilbert_QQ(Integer(50), system= magma )# optional - magma

sage.matrix.benchmark.echelon_QQ(n=100, min=0, max=9, system='sage')
Given a n x (2*n) matrix over QQ with random integer entries between min and max, compute the reduced row
echelon form.
INPUT:• n – matrix dimension (default: 300)
• min – minimal value for entries of matrix (default: -9)• max – maximal value for entries of matrix (default: 9)• system – either ‘sage’ or ‘magma’ (default: ‘sage’)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.echelon_QQ(100)sage: tm = b.echelon_QQ(100, system= magma )# optional - magma>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.echelon_QQ(Integer(100))>>> tm = b.echelon_QQ(Integer(100), system= magma )# optional - magma

sage.matrix.benchmark.hilbert_matrix(n)Returns the Hilbert matrix of size n over rationals.
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: b.hilbert_matrix(3)[ 1 1/2 1/3]
[1/2 1/3 1/4]
[1/3 1/4 1/5]

1070

Chapter 46. Benchmarks for matrices

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> b.hilbert_matrix(Integer(3))[ 1 1/2 1/3]
[1/2 1/3 1/4]
[1/3 1/4 1/5]

sage.matrix.benchmark.inverse_QQ(n=100, min=0, max=9, system='sage')
Given a n x n matrix over QQ with random integer entries between min and max, compute the reduced row echelon
form.
INPUT:• n – matrix dimension (default: 300)
• min – minimal value for entries of matrix (default: -9)• max – maximal value for entries of matrix (default: 9)• system – either ‘sage’ or ‘magma’ (default: ‘sage’)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.inverse_QQ(100)sage: tm = b.inverse_QQ(100, system= magma )# optional - magma>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.inverse_QQ(Integer(100))>>> tm = b.inverse_QQ(Integer(100), system= magma )# optional - magma

sage.matrix.benchmark.invert_hilbert_QQ(n=40, system='sage')
Runs the benchmark for calculating the inverse of the hilbert matrix over rationals of dimension n.
INPUT:• n – matrix dimension (default: 300)
• system – either ‘sage’ or ‘magma’ (default: ‘sage’)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.invert_hilbert_QQ(30)sage: tm = b.invert_hilbert_QQ(30, system= magma )# optional - magma>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.invert_hilbert_QQ(Integer(30))>>> tm = b.invert_hilbert_QQ(Integer(30), system= magma )# optional - magma

sage.matrix.benchmark.matrix_add_GF(n=1000, p=16411, system='sage', times=100)
Given two n x n matrix over GF(p) with random entries, add them.
INPUT:• n – matrix dimension (default: 300)
• p – prime number (default: 16411)

1071

Matrices and Spaces of Matrices, Release 10.4

• system – either ‘magma’ or ‘sage’ (default: ‘sage’)• times – number of experiments (default: 100)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.matrix_add_GF(500, p=19)
sage: tm = b.matrix_add_GF(500, p=19, system= magma )# optional - magma>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.matrix_add_GF(Integer(500), p=Integer(19))>>> tm = b.matrix_add_GF(Integer(500), p=Integer(19), system= magma )˓→- magma# optional␣

sage.matrix.benchmark.matrix_add_ZZ(n=200, min=-9, max=9, system='sage', times=50)
Matrix addition over ZZ Given an n x n matrix A and B over ZZ with random entries between min and max,
inclusive, compute A + B times times.
INPUT:• n – matrix dimension (default: 200)
• min – minimal value for entries of matrix (default: -9)• max – maximal value for entries of matrix (default: 9)• system – either ‘sage’ or ‘magma’ (default: ‘sage’)• times – number of experiments (default: 50)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.matrix_add_ZZ(200)sage: tm = b.matrix_add_ZZ(200, system= magma )# optional - magma>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.matrix_add_ZZ(Integer(200))>>> tm = b.matrix_add_ZZ(Integer(200), system= magma )# optional - magma

sage.matrix.benchmark.matrix_add_ZZ_2(n=200, bits=16, system='sage', times=50)
Matrix addition over ZZ. Given an n x n matrix A and B over ZZ with random bits-bit entries, compute A + B.
INPUT:• n – matrix dimension (default: 200)
• bits – bitsize of entries• system – either ‘sage’ or ‘magma’ (default: ‘sage’)• times – number of experiments (default: 50)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.matrix_add_ZZ_2(200)sage: tm = b.matrix_add_ZZ_2(200, system= magma )1072# optional - magma

Chapter 46. Benchmarks for matrices

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.matrix_add_ZZ_2(Integer(200))>>> tm = b.matrix_add_ZZ_2(Integer(200), system= magma )# optional - magma

sage.matrix.benchmark.matrix_multiply_GF(n=100, p=16411, system='sage', times=3)
Given an n x n matrix A over GF(p) with random entries, compute A * (A+1).
INPUT:• n – matrix dimension (default: 100)
• p – prime number (default: 16411)• system – either ‘magma’ or ‘sage’ (default: ‘sage’)• times – number of experiments (default: 3)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.matrix_multiply_GF(100, p=19)
sage: tm = b.matrix_multiply_GF(100, p=19, system= magma )# optional - magma>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.matrix_multiply_GF(Integer(100), p=Integer(19))>>> tm = b.matrix_multiply_GF(Integer(100), p=Integer(19), system= magma )˓→optional - magma#␣sage.matrix.benchmark.matrix_multiply_QQ(n=100, bnd=2, system='sage', times=1)
Given an n x n matrix A over QQ with random entries whose numerators and denominators are bounded by bnd,
compute A * (A+1).
INPUT:• n – matrix dimension (default: 300)
• bnd – numerator and denominator bound (default: bnd)
• system – either ‘sage’ or ‘magma’ (default: ‘sage’)• times – number of experiments (default: 1)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.matrix_multiply_QQ(100)sage: tm = b.matrix_multiply_QQ(100, system= magma )# optional - magma>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.matrix_multiply_QQ(Integer(100))>>> tm = b.matrix_multiply_QQ(Integer(100), system= magma )# optional - magma

sage.matrix.benchmark.matrix_multiply_ZZ(n=300, min=-9, max=9, system='sage', times=1)
Matrix multiplication over ZZ Given an n x n matrix A over ZZ with random entries between min and max,
inclusive, compute A * (A+1).
INPUT:

1073

Matrices and Spaces of Matrices, Release 10.4

• n – matrix dimension (default: 300)
• min – minimal value for entries of matrix (default: -9)• max – maximal value for entries of matrix (default: 9)• system – either ‘sage’ or ‘magma’ (default: ‘sage’)• times – number of experiments (default: 1)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.matrix_multiply_ZZ(200)sage: tm = b.matrix_multiply_ZZ(200, system= magma )# optional - magma>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.matrix_multiply_ZZ(Integer(200))>>> tm = b.matrix_multiply_ZZ(Integer(200), system= magma )# optional - magma

sage.matrix.benchmark.nullspace_GF(n=300, p=16411, system='sage')
Given a n+1 x n matrix over GF(p) with random entries, compute the nullspace.
INPUT:• n – matrix dimension (default: 300)
• p – prime number (default: 16411)• system – either ‘magma’ or ‘sage’ (default: ‘sage’)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.nullspace_GF(300)sage: tm = b.nullspace_GF(300, system= magma )# optional - magma>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.nullspace_GF(Integer(300))>>> tm = b.nullspace_GF(Integer(300), system= magma )# optional - magma

sage.matrix.benchmark.nullspace_RDF(n=300, min=0, max=10, system='sage')
Nullspace over RDF: Given a n+1 x n matrix over RDF with random entries between min and max, compute thenullspace.
INPUT:• n – matrix dimension (default: 300)
• min – minimal value for entries of matrix (default: 0)• max – maximal value for entries of matrix (default: 10`)• system – either ‘sage’ or ‘magma’ (default: ‘sage’)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.nullspace_RDF(100) # long time
sage: tm = b.nullspace_RDF(100, system= magma )1074# optional - magma

Chapter 46. Benchmarks for matrices

Matrices and Spaces of Matrices, Release 10.4>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.nullspace_RDF(Integer(100)) # long time>>> tm = b.nullspace_RDF(Integer(100), system= magma )# optional - magma

sage.matrix.benchmark.nullspace_RR(n=300, min=0, max=10, system='sage')
Nullspace over RR: Given a n+1 x n matrix over RR with random entries between min and max, compute thenullspace.
INPUT:• n – matrix dimension (default: 300)
• min – minimal value for entries of matrix (default: 0)• max – maximal value for entries of matrix (default: 10)• system – either ‘sage’ or ‘magma’ (default: ‘sage’)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.nullspace_RR(100)sage: tm = b.nullspace_RR(100, system= magma )# optional - magma>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.nullspace_RR(Integer(100))>>> tm = b.nullspace_RR(Integer(100), system= magma )# optional - magma

sage.matrix.benchmark.nullspace_ZZ(n=200, min=0, max=4294967296, system='sage')
Nullspace over ZZ: Given a n+1 x n matrix over ZZ with random entries between min and max, compute thenullspace.
INPUT:• n – matrix dimension (default: 200)
• min – minimal value for entries of matrix (default: 0)• max – maximal value for entries of matrix (default: 2**32)• system – either ‘sage’ or ‘magma’ (default: ‘sage’)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.nullspace_ZZ(200)sage: tm = b.nullspace_ZZ(200, system= magma )# optional - magma>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.nullspace_ZZ(Integer(200))>>> tm = b.nullspace_ZZ(Integer(200), system= magma )# optional - magma

sage.matrix.benchmark.rank2_GF(n=500, p=16411, system='sage')
Rank over GF(p): Given a (n + 10) x n matrix over GF(p) with random entries, compute the rank.
INPUT:• n – matrix dimension (default: 300)
1075

Matrices and Spaces of Matrices, Release 10.4

• p – prime number (default: 16411)• system – either ‘magma’ or ‘sage’ (default: ‘sage’)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.rank2_GF(500)
sage: tm = b.rank2_GF(500, system= magma )# optional - magma>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.rank2_GF(Integer(500))>>> tm = b.rank2_GF(Integer(500), system= magma )# optional - magma

sage.matrix.benchmark.rank2_ZZ(n=400, min=0, max=18446744073709551616, system='sage')
Rank 2 over ZZ: Given a (n + 10) x n matrix over ZZ with random entries between min and max, compute therank.
INPUT:• n – matrix dimension (default: 400)
• min – minimal value for entries of matrix (default: 0)• max – maximal value for entries of matrix (default: 2**64)• system – either ‘sage’ or ‘magma’ (default: ‘sage’)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.rank2_ZZ(300)sage: tm = b.rank2_ZZ(300, system= magma )# optional - magma>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.rank2_ZZ(Integer(300))>>> tm = b.rank2_ZZ(Integer(300), system= magma )# optional - magma

sage.matrix.benchmark.rank_GF(n=500, p=16411, system='sage')
Rank over GF(p): Given a n x (n+10) matrix over GF(p) with random entries, compute the rank.
INPUT:• n – matrix dimension (default: 300)
• p – prime number (default: 16411)• system – either ‘magma’ or ‘sage’ (default: ‘sage’)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.rank_GF(1000)
sage: tm = b.rank_GF(1000, system= magma )# optional - magma>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.rank_GF(Integer(1000))>>> tm = b.rank_GF(Integer(1000), system= magma )1076# optional - magma

Chapter 46. Benchmarks for matrices

Matrices and Spaces of Matrices, Release 10.4

sage.matrix.benchmark.rank_ZZ(n=700, min=0, max=9, system='sage')
Rank over ZZ: Given a n x (n+10) matrix over ZZ with random entries between min and max, compute the rank.
INPUT:• n – matrix dimension (default: 700)
• min – minimal value for entries of matrix (default: 0)• max – maximal value for entries of matrix (default: 9)• system – either ‘sage’ or ‘magma’ (default: ‘sage’)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.rank_ZZ(300)sage: tm = b.rank_ZZ(300, system= magma )# optional - magma>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.rank_ZZ(Integer(300))>>> tm = b.rank_ZZ(Integer(300), system= magma )# optional - magma

sage.matrix.benchmark.report(F, title, systems=['sage', 'magma'], **kwds)
Run benchmarks with default arguments for each function in the list F.
INPUT:• F – a list of callables used for benchmarking• title – a string describing this report• systems – a list of systems (supported entries are ‘sage’ and ‘magma’)• **kwds – keyword arguments passed to all functions in F
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: print("starting"); import sys; sys.stdout.flush(); b.report([b.det_ZZ],
˓→ Test , systems=[ sage ])starting...
======================================================================
Test======================================================================...
======================================================================>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> print("starting"); import sys; sys.stdout.flush(); b.report([b.det_ZZ],
˓→ , systems=[ sage ])starting...
======================================================================
Test======================================================================...
======================================================================

Test

1077

Matrices and Spaces of Matrices, Release 10.4

sage.matrix.benchmark.report_GF(p=16411, **kwds)
Runs all the reports for finite field matrix operations, for prime p=16411.
INPUT:• p – ignored• **kwds – passed through to report()
Note: right now, even though p is an input, it is being ignored! If you need to check the performance for otherprimes, you can call individual benchmark functions.
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: print("starting"); import sys; sys.stdout.flush(); b.report_GF(systems=[
˓→ sage ])starting...
======================================================================
Dense benchmarks over GF with prime 16411======================================================================...
======================================================================>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> print("starting"); import sys; sys.stdout.flush(); b.report_GF(systems=[ sage
˓→ ])starting...
======================================================================
Dense benchmarks over GF with prime 16411======================================================================...
======================================================================

sage.matrix.benchmark.report_ZZ(**kwds)
Reports all the benchmarks for integer matrices and few rational matrices.
INPUT:• **kwds – passed through to report()
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: print("starting"); import sys; sys.stdout.flush(); b.report_ZZ(systems=[
˓→ sage ])# long time (15s on sage.math, 2012)
starting...
======================================================================
Dense benchmarks over ZZ======================================================================...
======================================================================>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> print("starting"); import sys; sys.stdout.flush(); b.report_ZZ(systems=[ sage
(continues on next page)

1078

Chapter 46. Benchmarks for matrices

Matrices and Spaces of Matrices, Release 10.4

(continued from previous page)]) # long time (15s on sage.math, 2012)
starting...
======================================================================
Dense benchmarks over ZZ======================================================================...
======================================================================
˓→sage.matrix.benchmark.smithform_ZZ(n=128, min=0, max=9, system='sage')
Smith Form over ZZ: Given a n x n matrix over ZZ with random entries between min and max, compute the Smith
normal form.
INPUT:• n – matrix dimension (default: 128)
• min – minimal value for entries of matrix (default: 0)• max – maximal value for entries of matrix (default: 9)• system – either ‘sage’ or ‘magma’ (default: ‘sage’)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.smithform_ZZ(100)sage: tm = b.smithform_ZZ(100, system= magma )# optional - magma>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.smithform_ZZ(Integer(100))>>> tm = b.smithform_ZZ(Integer(100), system= magma )# optional - magma

sage.matrix.benchmark.vecmat_ZZ(n=300, min=-9, max=9, system='sage', times=200)
Vector matrix multiplication over ZZ.
Given an n x n matrix A over ZZ with random entries between min and max, inclusive, and v the first row of A,
compute the product v * A.
INPUT:• n – matrix dimension (default: 300)
• min – minimal value for entries of matrix (default: -9)• max – maximal value for entries of matrix (default: 9)• system – either ‘sage’ or ‘magma’ (default: ‘sage’)• times – number of runs (default: 200)
EXAMPLES:
sage: import sage.matrix.benchmark as b
sage: ts = b.vecmat_ZZ(300) # long time
sage: tm = b.vecmat_ZZ(300, system= magma )# optional - magma>>> from sage.all import *>>> import sage.matrix.benchmark as b>>> ts = b.vecmat_ZZ(Integer(300)) # long time>>> tm = b.vecmat_ZZ(Integer(300), system= magma )# optional - magma

1079

Matrices and Spaces of Matrices, Release 10.4

1080

Chapter 46. Benchmarks for matrices

CHAPTERFORTYSEVEN

INDICES AND TABLES• Index• Module Index• Search Page

1081

Matrices and Spaces of Matrices, Release 10.4

1082

Chapter 47. Indices and Tables

PYTHON MODULE INDEX

msage.matrix.action, 1017
sage.matrix.args, 109
sage.matrix.benchmark, 1067
sage.matrix.berlekamp_massey, 589
sage.matrix.change_ring, 1021
sage.matrix.compute_J_ideal, 1051
sage.matrix.constructor, 31
sage.matrix.docs, 129
sage.matrix.echelon_matrix, 1023
sage.matrix.matrix0, 141
sage.matrix.matrix1, 211
sage.matrix.matrix2, 251
sage.matrix.matrix_complex_ball_dense,907
sage.matrix.matrix_complex_double_dense, 905
sage.matrix.matrix_cyclo_dense, 993
sage.matrix.matrix_dense, 591
sage.matrix.matrix_double_dense, 717
sage.matrix.matrix_generic_dense, 603
sage.matrix.matrix_generic_sparse, 605
sage.matrix.matrix_gf2e_dense, 801
sage.matrix.matrix_integer_dense, 609
sage.matrix.matrix_integer_dense_hnf,
661
sage.matrix.matrix_integer_dense_saturation, 681
sage.matrix.matrix_integer_sparse, 653
sage.matrix.matrix_misc, 1025
sage.matrix.matrix_mod2_dense, 785
sage.matrix.matrix_modn_dense_double,813
sage.matrix.matrix_modn_dense_float, 833
sage.matrix.matrix_modn_sparse, 853
sage.matrix.matrix_mpolynomial_dense,987
sage.matrix.matrix_polynomial_dense, 917
sage.matrix.matrix_rational_dense, 687
sage.matrix.matrix_rational_sparse, 711
sage.matrix.matrix_real_double_dense,783

sage.matrix.matrix_space, 3
sage.matrix.matrix_sparse, 593
sage.matrix.matrix_symbolic_dense, 861
sage.matrix.matrix_symbolic_sparse, 883
sage.matrix.matrix_window, 1029
sage.matrix.misc, 1031
sage.matrix.misc_flint, 1037
sage.matrix.misc_mpfr, 1035
sage.matrix.operation_table, 1001
sage.matrix.special, 47
sage.matrix.strassen, 583
sage.matrix.symplectic_basis, 1039

1083

Matrices and Spaces of Matrices, Release 10.4

1084

Python Module Index

INDEXA
act_on_polynomial() (sage.matrix.matrix0.Matrix
method), 142
add()(sage.matrix.matrix_window.MatrixWindow
method), 1029
add_column() (in module sage.matrix.matrix_integer_dense_hnf), 661
add_column_fallback() (in module sage.matrix.matrix_integer_dense_hnf), 662
add_multiple_of_column()(sage.matrix.matrix0.Matrix method), 143
add_multiple_of_row() (sage.matrix.matrix0.Matrix method), 144
add_prod() (sage.matrix.matrix_window.MatrixWindow method), 1029
add_row() (in module sage.matrix.matrix_integer_dense_hnf), 663
add_to_entry()(sage.matrix.matrix0.Matrix
method), 145
add_to_entry()(sage.matrix.matrix_rational_dense.Matrix_rational_dense
method),689
add_to_entry()(sage.matrix.matrix_rational_sparse.Matrix_rational_sparse
method),711
adjoint() (sage.matrix.matrix2.Matrix method), 273
adjoint_classical() (sage.matrix.matrix2.Matrix
method), 273
adjugate() (sage.matrix.matrix2.Matrix method), 274
anticommutator()(sage.matrix.matrix0.Matrix
method), 145
antitranspose()(sage.matrix.matrix_dense.Matrix_dense method), 591
antitranspose()(sage.matrix.matrix_integer_dense.Matrix_integer_dense
method),615
antitranspose()(sage.matrix.matrix_rational_dense.Matrix_rational_dense
method),689
antitranspose()(sage.matrix.matrix_sparse.Matrix_sparse method), 593
apply_map() (sage.matrix.matrix2.Matrix method), 276

apply_map() (sage.matrix.matrix_sparse.Matrix_sparse
method), 593
apply_morphism()(sage.matrix.matrix2.Matrix
method), 278
apply_morphism() (sage.matrix.matrix_sparse.Matrix_sparse method), 595
arguments() (sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense method), 866
arguments() (sage.matrix.matrix_symbolic_sparse.Matrix_symbolic_sparse method), 888
as_bipartite_graph() (sage.matrix.matrix2.Matrix
method), 279
as_sum_of_permutations()(sage.matrix.matrix2.Matrix method), 280
augment() (sage.matrix.matrix1.Matrix method), 211
augment()(sage.matrix.matrix_gf2e_dense.Matrix_gf2e_dense method), 802
augment()(sage.matrix.matrix_integer_dense.Matrix_integer_dense method), 616
augment()(sage.matrix.matrix_mod2_dense.Matrix_mod2_dense method), 787
augment() (sage.matrix.matrix_sparse.Matrix_sparse
method), 596
automorphisms_of_rows_and_columns()(sage.matrix.matrix2.Matrix method), 281

Bbase (sage.matrix.args.MatrixArgs attribute), 115
base_extend() (sage.matrix.matrix_space.MatrixSpace method), 7
base_ring() (sage.matrix.matrix0.Matrix method), 145
basis()(sage.matrix.matrix_space.MatrixSpace
method), 7
basis_completion() (sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method),918
benchmark_hnf() (in module sage.matrix.matrix_integer_dense_hnf), 663
benchmark_magma_hnf() (in module sage.matrix.matrix_integer_dense_hnf), 664
berlekamp_massey()(inmodulesage.matrix.berlekamp_massey), 589
1085

Matrices and Spaces of Matrices, Release 10.4

(sage.matrix.matrix_integer_dense.Matrix_integer_dense method), 610
BKZ() (sage.matrix.matrix_rational_dense.Matrix_rational_dense method), 688
block_diagonal_matrix() (in module sage.matrix.special), 48
block_ldlt() (sage.matrix.matrix2.Matrix method),283
block_matrix() (in module sage.matrix.special), 49
block_sum() (sage.matrix.matrix1.Matrix method), 215
BKZ()

C
C (sage.matrix.matrix2.Matrix attribute), 252cached_method() (sage.matrix.matrix_space.MatrixSpace method), 8
canonicalize_radical()(sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense
method), 866
canonicalize_radical()(sage.matrix.matrix_symbolic_sparse.Matrix_symbolic_sparse
method), 888
cardinality() (sage.matrix.matrix_space.MatrixSpace method), 10
change_names() (sage.matrix.operation_table.OperationTable method), 1009
change_ring() (sage.matrix.matrix0.Matrix method),146
change_ring()(sage.matrix.matrix_rational_dense.Matrix_rational_dense
method),690
change_ring() (sage.matrix.matrix_space.MatrixSpace method), 11
change_ring()(sage.matrix.matrix_sparse.Matrix_sparse method), 597
characteristic() (sage.matrix.matrix_space.MatrixSpace method), 11
characteristic_polynomial() (sage.matrix.matrix2.Matrix method), 289
charpoly() (sage.matrix.matrix2.Matrix method), 289
charpoly()(sage.matrix.matrix_complex_ball_dense.Matrix_complex_ball_dense
method), 907
charpoly()(sage.matrix.matrix_cyclo_dense.Matrix_cyclo_dense method), 994
charpoly()(sage.matrix.matrix_integer_dense.Matrix_integer_dense method), 618
charpoly()(sage.matrix.matrix_integer_sparse.Matrix_integer_sparse method), 653
charpoly()(sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_template
method),814
charpoly()(sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_template method), 834
1086

charpoly() (sage.matrix.matrix_rational_dense.Matrix_rational_dense method), 691
charpoly() (sage.matrix.matrix_sparse.Matrix_sparse
method), 598
charpoly() (sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense method), 867
charpoly() (sage.matrix.matrix_symbolic_sparse.Matrix_symbolic_sparse method), 889
charpoly_GF() (in module sage.matrix.benchmark),1068
charpoly_ZZ() (in module sage.matrix.benchmark),1068
cholesky() (sage.matrix.matrix2.Matrix method), 292
cholesky()(sage.matrix.matrix_double_dense.Matrix_double_dense method), 729
circulant() (in module sage.matrix.special), 53
cling()(sage.matrix.matrix_gf2e_dense.Matrix_gf2e_dense method), 803
cmp_pivots() (in module sage.matrix.misc), 1031
codomain()(sage.matrix.action.MatrixMulAction
method), 1020
coefficient_bound()(sage.matrix.matrix_cyclo_dense.Matrix_cyclo_dense method), 995
coefficient_matrix() (sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense
method), 922
color_table() (sage.matrix.operation_table.OperationTable method), 1011
column() (sage.matrix.matrix1.Matrix method), 216
column() (sage.matrix.matrix_integer_dense.Matrix_integer_dense method), 619
column()(sage.matrix.matrix_rational_dense.Matrix_rational_dense method), 692
column_ambient_module()(sage.matrix.matrix1.Matrix method), 216
column_degrees()(sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method),924
column_keys (sage.matrix.args.MatrixArgs attribute),
115
column_keys() (sage.matrix.operation_table.OperationTable method), 1012
column_matrix() (in module sage.matrix.special), 54
column_module()(sage.matrix.matrix2.Matrix
method), 299
column_space()(sage.matrix.matrix2.Matrix
method), 300
column_space() (sage.matrix.matrix_space.MatrixSpace method), 11
columns() (sage.matrix.matrix1.Matrix method), 217
columns()(sage.matrix.matrix_mod2_dense.Matrix_mod2_dense method), 788
commutator() (sage.matrix.matrix0.Matrix method),
147
Index

Matrices and Spaces of Matrices, Release 10.4

companion_matrix() (in module sage.matrix.special), 56
ComputeMinimalPolynomials (class in sage.matrix.compute_J_ideal), 1053
condition() (sage.matrix.matrix_double_dense.Matrix_double_dense method), 732
conjugate() (sage.matrix.matrix2.Matrix method), 300
conjugate() (sage.matrix.matrix_double_dense.Matrix_double_dense method), 737
conjugate_transpose() (sage.matrix.matrix2.Matrix method), 302
constant_matrix()(sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method),925
construction() (sage.matrix.matrix_space.MatrixSpace method), 12
contains()(sage.matrix.matrix_complex_ball_dense.Matrix_complex_ball_dense
method), 908
current_nu()(sage.matrix.compute_J_ideal.ComputeMinimalPolynomials method), 1054
cyclic_subspace()(sage.matrix.matrix2.Matrix
method), 305

Ddecomp_seq() (in module sage.matrix.matrix2), 581
decomposition()(sage.matrix.matrix2.Matrix
method), 308
decomposition()(sage.matrix.matrix_integer_dense.Matrix_integer_dense
method),620
decomposition()(sage.matrix.matrix_rational_dense.Matrix_rational_dense
method),693
decomposition_of_subspace() (sage.matrix.matrix2.Matrix method), 309
degree() (sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method), 926
degree_matrix()(sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method),927
delete_columns()(sage.matrix.matrix1.Matrix
method), 218delete_rows() (sage.matrix.matrix1.Matrix method),219
denominator() (sage.matrix.matrix2.Matrix method),311
denominator() (sage.matrix.matrix_cyclo_dense.Matrix_cyclo_dense method), 996
denominator()(sage.matrix.matrix_rational_dense.Matrix_rational_dense
method),694
denominator()(sage.matrix.matrix_rational_sparse.Matrix_rational_sparse
method),Index712
dense_coefficient_list()(sage.matrix.matrix0.Matrix method), 147
dense_columns()(sage.matrix.matrix1.Matrix
method), 220
dense_matrix()(sage.matrix.matrix1.Matrix
method), 221
dense_matrix()(sage.matrix.matrix_rational_sparse.Matrix_rational_sparse
method),712
dense_rows() (sage.matrix.matrix1.Matrix method),223
density() (sage.matrix.matrix2.Matrix method), 313
density()(sage.matrix.matrix_mod2_dense.Matrix_mod2_dense method), 789
density()(sage.matrix.matrix_modn_sparse.Matrix_modn_sparse method), 855
density() (sage.matrix.matrix_sparse.Matrix_sparse
method), 599
derivative() (sage.matrix.matrix2.Matrix method),314
det() (sage.matrix.matrix2.Matrix method), 314
det_from_modp_and_divisor() (in module
sage.matrix.matrix_integer_dense_hnf), 664
det_GF() (in module sage.matrix.benchmark), 1068
det_given_divisor() (in module sage.matrix.matrix_integer_dense_hnf), 665
det_hilbert_QQ() (in module sage.matrix.benchmark), 1070
det_padic() (in module sage.matrix.matrix_integer_dense_hnf), 666
det_QQ() (in module sage.matrix.benchmark), 1069
det_ZZ() (in module sage.matrix.benchmark), 1069
determinant() (sage.matrix.matrix2.Matrix method),315
determinant()(sage.matrix.matrix_complex_ball_dense.Matrix_complex_ball_dense
method), 908
determinant()(sage.matrix.matrix_double_dense.Matrix_double_dense
method),737
determinant()(sage.matrix.matrix_integer_dense.Matrix_integer_dense
method),621
determinant() (sage.matrix.matrix_mod2_dense.Matrix_mod2_dense method), 789
determinant()(sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_template method), 815
determinant()(sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_template method), 835
determinant() (sage.matrix.matrix_modn_sparse.Matrix_modn_sparse method), 856
1087

Matrices and Spaces of Matrices, Release 10.4

determinant()(sage.matrix.matrix_mpolynomial_dense.Matrix_mpolynomial_dense
method), 987
determinant()(sage.matrix.matrix_rational_dense.Matrix_rational_dense
method),694
determinant()(sage.matrix.matrix_sparse.Matrix_sparse method), 599
diagonal() (sage.matrix.matrix2.Matrix method), 316
diagonal_matrix() (in module sage.matrix.special),
60
diagonal_matrix() (sage.matrix.matrix_space.MatrixSpace method), 12
diagonalization()(sage.matrix.matrix2.Matrix
method), 317
dict() (sage.matrix.args.MatrixArgs method), 115
dict() (sage.matrix.matrix0.Matrix method), 148
dict_to_list() (in module sage.matrix.matrix_space), 25
dimension() (sage.matrix.matrix_space.MatrixSpace
method), 13
dimensions() (sage.matrix.matrix0.Matrix method),148
dims() (sage.matrix.matrix_space.MatrixSpace method),
14
double_det() (in module sage.matrix.matrix_integer_dense_hnf), 667

Eechelon_form()(sage.matrix.matrix2.Matrix
method), 321
echelon_form()(sage.matrix.matrix_cyclo_dense.Matrix_cyclo_dense method), 996
echelon_form()(sage.matrix.matrix_integer_dense.Matrix_integer_dense
method),623
echelon_form()(sage.matrix.matrix_mpolynomial_dense.Matrix_mpolynomial_dense
method), 988
echelon_form()(sage.matrix.matrix_rational_dense.Matrix_rational_dense
method),696
echelon_form()(sage.matrix.matrix_rational_sparse.Matrix_rational_sparse
method),713
echelon_in_place()(sage.matrix.matrix_window.MatrixWindow method), 1029
echelon_QQ() (in module sage.matrix.benchmark),
1070
echelonize() (sage.matrix.matrix2.Matrix method),322
echelonize() (sage.matrix.matrix_gf2e_dense.Matrix_gf2e_dense method), 8041088

echelonize() (sage.matrix.matrix_mod2_dense.Matrix_mod2_dense method), 790
echelonize() (sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_template method), 817
echelonize()(sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_template method), 836
echelonize()(sage.matrix.matrix_mpolynomial_dense.Matrix_mpolynomial_dense
method), 990
echelonize() (sage.matrix.matrix_rational_dense.Matrix_rational_dense method), 697
echelonize()(sage.matrix.matrix_rational_sparse.Matrix_rational_sparse
method),713
echelonize()(sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense
method),867
echelonize()(sage.matrix.matrix_symbolic_sparse.Matrix_symbolic_sparse method),889
eigenmatrix_left() (sage.matrix.matrix2.Matrix
method), 326
eigenmatrix_right() (sage.matrix.matrix2.Matrix
method), 329
eigenspaces_left() (sage.matrix.matrix2.Matrix
method), 332
eigenspaces_right() (sage.matrix.matrix2.Matrix
method), 341
eigenvalue_multiplicity() (sage.matrix.matrix2.Matrix method), 345
eigenvalues() (sage.matrix.matrix2.Matrix method),346
eigenvalues()(sage.matrix.matrix_complex_ball_dense.Matrix_complex_ball_dense
method), 908
eigenvalues()(sage.matrix.matrix_double_dense.Matrix_double_dense
method),738
eigenvalues()(sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense
method),867
eigenvalues()(sage.matrix.matrix_symbolic_sparse.Matrix_symbolic_sparse method),889
eigenvectors_left() (sage.matrix.matrix2.Matrix
method), 349
eigenvectors_left()(sage.matrix.matrix_complex_ball_dense.Matrix_complex_ball_dense
method), 910
eigenvectors_left()(sage.matrix.matrix_double_dense.Matrix_double_dense method), 741
eigenvectors_left()(sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense
method),Index

Matrices and Spaces of Matrices, Release 10.4

867
eigenvectors_left()(sage.matrix.matrix_symbolic_sparse.Matrix_symbolic_sparse method),889
eigenvectors_left_approx()(sage.matrix.matrix_complex_ball_dense.Matrix_complex_ball_dense method), 911eigenvectors_right() (sage.matrix.matrix2.Matrix
method), 350
eigenvectors_right() (sage.matrix.matrix_complex_ball_dense.Matrix_complex_ball_dense
method), 911eigenvectors_right() (sage.matrix.matrix_double_dense.Matrix_double_dense method), 744
eigenvectors_right() (sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense
method),870
eigenvectors_right() (sage.matrix.matrix_symbolic_sparse.Matrix_symbolic_sparse method),892
eigenvectors_right_approx()(sage.matrix.matrix_complex_ball_dense.Matrix_complex_ball_dense method), 912
element() (sage.matrix.args.MatrixArgs method), 115
element_is_zero()(sage.matrix.matrix_window.MatrixWindow method), 1029
elementary_divisors() (sage.matrix.matrix2.Matrix method), 351
elementary_divisors() (sage.matrix.matrix_integer_dense.Matrix_integer_dense method), 626
elementary_divisors() (sage.matrix.matrix_integer_sparse.Matrix_integer_sparse method), 654
elementary_matrix() (in module sage.matrix.special), 65
elementwise_product() (sage.matrix.matrix2.Matrix method), 352
entries (sage.matrix.args.MatrixArgs attribute), 117
entry (sage.matrix.args.SparseEntry attribute), 127
exp() (sage.matrix.matrix2.Matrix method), 356
exp()(sage.matrix.matrix_complex_ball_dense.Matrix_complex_ball_dense method), 913
exp()(sage.matrix.matrix_double_dense.Matrix_double_dense method), 746
exp() (sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense method), 871
exp() (sage.matrix.matrix_symbolic_sparse.Matrix_symbolic_sparse method), 893
expand()(sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense method), 873
expand()(sage.matrix.matrix_symbolic_sparse.Matrix_symbolic_sparse method), 895
extended_echelon_form()(sage.matrix.matrix2.Matrix method), 357
extract_ones_data() (in module sage.matrix.maIndex

trix_integer_dense_hnf), 668

Ffactor()(sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense method), 874
factor()(sage.matrix.matrix_symbolic_sparse.Matrix_symbolic_sparse method), 896
fcp() (sage.matrix.matrix2.Matrix method), 362
fcp() (sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense method), 874
fcp() (sage.matrix.matrix_symbolic_sparse.Matrix_symbolic_sparse method), 896
finalized() (sage.matrix.args.MatrixArgs method),117
find() (sage.matrix.matrix2.Matrix method), 363
find_monic_replacements() (sage.matrix.compute_J_ideal.ComputeMinimalPolynomials
method), 1054
fitting_ideal()(sage.matrix.matrix2.Matrix
method), 364
frobenius() (sage.matrix.matrix_integer_dense.Matrix_integer_dense method), 628
frobenius_form()(sage.matrix.matrix_integer_dense.Matrix_integer_dense
method),628
from_png()(inmodulesage.matrix.matrix_mod2_dense), 796
from_vector() (sage.matrix.matrix_space.MatrixSpace method), 14
function() (sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense method), 875
function() (sage.matrix.matrix_symbolic_sparse.Matrix_symbolic_sparse method), 897

G(sage.matrix.matrix_integer_dense.Matrix_integer_dense method), 630
gen() (sage.matrix.matrix_space.MatrixSpace method),15
get_matrix_class() (in module sage.matrix.matrix_space), 25
get_subdivisions() (sage.matrix.matrix2.Matrix
method), 367
get_unsafe()(sage.matrix.matrix_window.MatrixWindow method), 1029
gram_schmidt()(sage.matrix.matrix2.Matrix
method), 368
gray_table()(sage.matrix.operation_table.OperationTable method), 1013
gcd()

H
H (sage.matrix.matrix2.Matrix attribute), 252
hadamard_bound()(sage.matrix.matrix2.Matrix
method), 379
1089

Matrices and Spaces of Matrices, Release 10.4

hadamard_row_bound_mpfr() (in module sage.matrix.misc_mpfr), 1035
hankel() (in module sage.matrix.special), 71
height() (sage.matrix.matrix_cyclo_dense.Matrix_cyclo_dense method), 997
height() (sage.matrix.matrix_integer_dense.Matrix_integer_dense method), 630
height()(sage.matrix.matrix_rational_dense.Matrix_rational_dense method), 698
height()(sage.matrix.matrix_rational_sparse.Matrix_rational_sparse method), 714
hermite_form()(sage.matrix.matrix2.Matrix
method), 380
hermite_form()(sage.matrix.matrix_integer_dense.Matrix_integer_dense
method),630
hermite_form()(sage.matrix.matrix_integer_sparse.Matrix_integer_sparse
method),655
hermite_form()(sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method),928
hessenberg_form()(sage.matrix.matrix2.Matrix
method), 381
hessenbergize()(sage.matrix.matrix2.Matrix
method), 382
hessenbergize()(sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_template method), 819
hessenbergize()(sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_template method), 839
hilbert() (in module sage.matrix.special), 73
hilbert_matrix() (in module sage.matrix.benchmark), 1070
hnf() (in module sage.matrix.matrix_integer_dense_hnf),669
hnf_square() (in module sage.matrix.matrix_integer_dense_hnf), 670
hnf_with_transformation() (in module sage.matrix.matrix_integer_dense_hnf), 670
hnf_with_transformation_tests() (in module
sage.matrix.matrix_integer_dense_hnf), 671

identity_matrix() (sage.matrix.matrix_space.MatrixSpace method), 15
image() (sage.matrix.matrix2.Matrix method), 383
indefinite_factorization() (sage.matrix.matrix2.Matrix method), 384
index_in_saturation() (in module sage.matrix.matrix_integer_dense_saturation), 681
index_in_saturation() (sage.matrix.matrix_integer_dense.Matrix_integer_dense method), 634
insert_row() (sage.matrix.matrix_integer_dense.Matrix_integer_dense method), 634
int_range (class in sage.matrix.strassen), 583
integer_kernel()(sage.matrix.matrix2.Matrix
method), 388
integer_to_real_double_dense() (in module
sage.matrix.change_ring), 1021
integer_valued_polynomials_generators() (sage.matrix.compute_J_ideal.ComputeMinimalPolynomials method), 1055
integer_valued_polynomials_generators() (sage.matrix.matrix_integer_dense.Matrix_integer_dense method), 635
interleave_matrices() (in module sage.matrix.matrix_integer_dense_hnf), 671
intervals() (sage.matrix.strassen.int_range method),584
inverse() (sage.matrix.matrix2.Matrix method), 389
inverse()(sage.matrix.matrix_rational_dense.Matrix_rational_dense method), 699
inverse_of_unit()(sage.matrix.matrix0.Matrix
method), 149
inverse_of_unit()(sage.matrix.matrix_integer_dense.Matrix_integer_dense method), 636
inverse_positive_definite() (sage.matrix.matrix2.Matrix method), 390
inverse_QQ() (in module sage.matrix.benchmark),
1071
inverse_series_trunc()(sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method), 929
invert_hilbert_QQ() (in module sage.matrix.benchmark), 1071
is_alternating()(sage.matrix.matrix0.Matrix
method), 151
I
is_bistochastic()(sage.matrix.matrix2.Matrix
method),394
i (sage.matrix.args.SparseEntry attribute), 127(sage.matrix.matrix_polynoideal_or_fractional() (in module sage.ma- is_constant()
mial_dense.Matrix_polynomial_dense
method),trix.matrix2), 581
931
identical()(sage.matrix.matrix_comis_cross_positive_on()(sage.matrix.maplex_ball_dense.Matrix_complex_ball_dense
trix2.Matrix
method),395
method), 914
identity_matrix() (in module sage.matrix.special), is_dense() (sage.matrix.matrix0.Matrix method), 151
is_dense()(sage.matrix.matrix_space.MatrixSpace73
method), 16
1090

Index

Matrices and Spaces of Matrices, Release 10.4

is_diagonal() (sage.matrix.matrix2.Matrix method),396
is_diagonalizable() (sage.matrix.matrix2.Matrix
method), 397
is_finite() (sage.matrix.matrix_space.MatrixSpace
method), 16
is_hermite()(sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method),932
is_hermitian()(sage.matrix.matrix0.Matrix
method), 152
is_hermitian()(sage.matrix.matrix_double_dense.Matrix_double_dense
method),746
is_immutable()(sage.matrix.matrix0.Matrix
method), 154
is_in_hnf_form() (in module sage.matrix.matrix_integer_dense_hnf), 672
is_invertible()(sage.matrix.matrix0.Matrix
method), 154
is_LLL_reduced()(sage.matrix.matrix_integer_dense.Matrix_integer_dense
method),636
is_LLL_reduced()(sage.matrix.matrix_rational_dense.Matrix_rational_dense
method),701
is_lyapunov_like_on() (sage.matrix.matrix2.Matrix method), 402
is_MatrixSpace() (in module sage.matrix.matrix_space), 29
is_minimal_approximant_basis() (sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method), 934
is_minimal_kernel_basis()(sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method), 937
is_mutable() (sage.matrix.matrix0.Matrix method),155
is_nilpotent()(sage.matrix.matrix2.Matrix
method), 403
is_normal() (sage.matrix.matrix2.Matrix method), 404
is_normal() (sage.matrix.matrix_double_dense.Matrix_double_dense method), 749
is_one() (sage.matrix.matrix2.Matrix method), 407
is_one() (sage.matrix.matrix_integer_dense.Matrix_integer_dense method), 637
is_permutation_of() (sage.matrix.matrix2.Matrix
method), 408
is_popov() (sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method), 938
is_positive_definite()(sage.matrix.matrix2.Matrix method), 410
is_positive_definite()(sage.matrix.matrix_double_dense.Matrix_double_dense
Indexmethod), 753
is_positive_operator_on() (sage.matrix.matrix2.Matrix method), 413
is_positive_semidefinite() (sage.matrix.matrix2.Matrix method), 415
is_primitive()(sage.matrix.matrix_integer_dense.Matrix_integer_dense
method),637
is_reduced()(sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method),941
is_scalar() (sage.matrix.matrix2.Matrix method), 417
is_semisimple()(sage.matrix.matrix2.Matrix
method), 418
is_similar() (sage.matrix.matrix2.Matrix method),419
is_singular() (sage.matrix.matrix0.Matrix method),156
is_skew_hermitian() (sage.matrix.matrix0.Matrix
method), 157
is_skew_hermitian()(sage.matrix.matrix_double_dense.Matrix_double_dense method), 756
is_skew_symmetric() (sage.matrix.matrix0.Matrix
method), 159
is_skew_symmetrizable()(sage.matrix.matrix0.Matrix method), 160
is_sparse() (sage.matrix.matrix0.Matrix method), 161
is_sparse() (sage.matrix.matrix_space.MatrixSpace
method), 16
is_square() (sage.matrix.matrix0.Matrix method), 162
is_symmetric()(sage.matrix.matrix0.Matrix
method), 162
is_symmetrizable() (sage.matrix.matrix0.Matrix
method), 162
is_triangular()(sage.matrix.matrix2.Matrix
method), 426
is_unit() (sage.matrix.matrix0.Matrix method), 163
is_unitary() (sage.matrix.matrix2.Matrix method),427
is_unitary() (sage.matrix.matrix_double_dense.Matrix_double_dense method), 758
is_weak_popov()(sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method),942
is_Z_operator_on() (sage.matrix.matrix2.Matrix
method), 392
items() (sage.matrix.matrix0.Matrix method), 165
iter() (sage.matrix.args.MatrixArgs method), 118
iterates() (sage.matrix.matrix0.Matrix method), 165
ith_to_zero_rotation_matrix() (in module
sage.matrix.special), 74

Jj (sage.matrix.args.SparseEntry attribute), 128
1091

Matrices and Spaces of Matrices, Release 10.4

jordan_block() (in module sage.matrix.special), 77
jordan_decomposition()(sage.matrix.matrix2.Matrix method), 428
jordan_form() (sage.matrix.matrix2.Matrix method),430
jordan_form()(sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense
method),875
jordan_form()(sage.matrix.matrix_symbolic_sparse.Matrix_symbolic_sparse method),897

linear_combination_of_rows()(sage.matrix.matrix0.Matrix method), 168list() (sage.matrix.args.MatrixArgs method), 120list() (sage.matrix.matrix0.Matrix method), 170
LLL()(sage.matrix.matrix_integer_dense.Matrix_integer_dense method), 612
LLL() (sage.matrix.matrix_rational_dense.Matrix_rational_dense method), 689
LLL_gram() (sage.matrix.matrix2.Matrix method), 253
log_determinant()(sage.matrix.matrix_double_dense.Matrix_double_dense method), 763
LU() (sage.matrix.matrix2.Matrix method), 255
K
LU()(sage.matrix.matrix_double_dense.Matrix_double_dense method), 718
kernel() (sage.matrix.matrix2.Matrix method), 433(sage.matrix.matrix_double_dense.Makernel_on() (sage.matrix.matrix2.Matrix method), 437 LU_valid()
trix_double_dense method), 721
kwds (sage.matrix.args.MatrixArgs attribute), 120LM

leading_matrix()(sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method),945
leading_positions() (sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method),946
left_eigenmatrix() (sage.matrix.matrix2.Matrix
method), 439
left_eigenspaces() (sage.matrix.matrix2.Matrix
method), 442
left_eigenvectors() (sage.matrix.matrix2.Matrix
method), 451
left_eigenvectors()(sage.matrix.matrix_double_dense.Matrix_double_dense method), 761
left_kernel() (sage.matrix.matrix2.Matrix method),452
left_kernel_matrix() (sage.matrix.matrix2.Matrix
method), 456
left_nullity()(sage.matrix.matrix2.Matrix
method), 456
left_quo_rem()(sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method),948
lehmer() (in module sage.matrix.special), 77
lift() (sage.matrix.matrix1.Matrix method), 223
lift()(sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_template method), 819
lift()(sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_template method), 839
lift_centered()(sage.matrix.matrix1.Matrix
method), 224
lifting() (in module sage.matrix.compute_J_ideal),1063
linear_combination_of_columns() (sage.matrix.matrix0.Matrix method), 166

M4RIE_finite_field (class in sage.matrix.matrix_gf2e_dense), 802
Matrix (class in sage.matrix.matrix0), 141
Matrix (class in sage.matrix.matrix1), 211
Matrix (class in sage.matrix.matrix2), 252
Matrix() (in module sage.matrix.constructor), 31
matrix() (in module sage.matrix.constructor), 38
matrix() (sage.matrix.args.MatrixArgs method), 121
matrix()(sage.matrix.matrix_space.MatrixSpace
method), 17
matrix() (sage.matrix.matrix_window.MatrixWindow
method), 1029
matrix_add_GF() (in module sage.matrix.benchmark), 1071
matrix_add_ZZ() (in module sage.matrix.benchmark), 1072
matrix_add_ZZ_2() (in module sage.matrix.benchmark), 1072
Matrix_complex_ball_dense (class in sage.matrix.matrix_complex_ball_dense), 907
Matrix_complex_double_dense(classin
sage.matrix.matrix_complex_double_dense),
905
Matrix_cyclo_dense (class in sage.matrix.matrix_cyclo_dense), 993
Matrix_dense (class in sage.matrix.matrix_dense), 591
Matrix_double_dense (class in sage.matrix.matrix_double_dense), 717
matrix_from_columns() (sage.matrix.matrix1.Matrix method), 225
matrix_from_columns()(sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_template method), 820
matrix_from_columns()(sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_template method), 840

1092

Index

Matrices and Spaces of Matrices, Release 10.4

matrix_from_columns()(sage.matrix.matrix_modn_sparse.Matrix_modn_sparse method),857
matrix_from_columns() (sage.matrix.matrix_rational_dense.Matrix_rational_dense method), 701
matrix_from_rows() (sage.matrix.matrix1.Matrix
method), 226
matrix_from_rows()(sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_template method), 821
matrix_from_rows()(sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_template method), 841
matrix_from_rows()(sage.matrix.matrix_modn_sparse.Matrix_modn_sparse method),857
matrix_from_rows_and_columns() (sage.matrix.matrix1.Matrix method), 226
matrix_from_rows_and_columns() (sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_template method), 821
matrix_from_rows_and_columns()(sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_template method), 841
matrix_from_rows_and_columns() (sage.matrix.matrix_sparse.Matrix_sparse
method),599
Matrix_generic_dense (class in sage.matrix.matrix_generic_dense), 603
Matrix_generic_sparse (class in sage.matrix.matrix_generic_sparse), 607
Matrix_gf2e_dense (class in sage.matrix.matrix_gf2e_dense), 802
Matrix_integer_dense (class in sage.matrix.matrix_integer_dense), 610
matrix_integer_dense_rational_reconstruction() (in module sage.matrix.misc_flint), 1037
Matrix_integer_sparse (class in sage.matrix.matrix_integer_sparse), 653
matrix_integer_sparse_rational_reconstruction() (in module sage.matrix.misc),1031
matrix_method() (in module sage.matrix.special), 77
Matrix_mod2_dense (class in sage.matrix.matrix_mod2_dense), 787
Matrix_modn_dense_double (class in sage.matrix.matrix_modn_dense_double), 813
Matrix_modn_dense_float (class in sage.matrix.matrix_modn_dense_float), 833
Matrix_modn_dense_template (class in sage.matrix.matrix_modn_dense_double), 813
Matrix_modn_dense_template (class in sage.matrix.matrix_modn_dense_float), 833
Index

Matrix_modn_sparse (class in sage.matrix.matrix_modn_sparse), 855
Matrix_mpolynomial_dense (class in sage.matrix.matrix_mpolynomial_dense), 987
matrix_multiply_GF() (in module sage.matrix.benchmark), 1073
matrix_multiply_QQ() (in module sage.matrix.benchmark), 1073
matrix_multiply_ZZ() (in module sage.matrix.benchmark), 1073
matrix_of_variables() (sage.matrix.operation_table.OperationTable method), 1013
matrix_over_field() (sage.matrix.matrix1.Matrix
method), 227
Matrix_polynomial_dense (class in sage.matrix.matrix_polynomial_dense), 917
Matrix_rational_dense (class in sage.matrix.matrix_rational_dense), 688
matrix_rational_echelon_form_multimodular() (in module sage.matrix.misc),
1032
Matrix_rational_sparse (class in sage.matrix.matrix_rational_sparse), 711
Matrix_real_double_dense (class in sage.matrix.matrix_real_double_dense), 783
matrix_space()(sage.matrix.matrix1.Matrix
method), 228
matrix_space() (sage.matrix.matrix_space.MatrixSpace method), 18
Matrix_sparse (class in sage.matrix.matrix_sparse),
593
Matrix_sparse_from_rows() (in module sage.matrix.matrix_generic_sparse), 608
Matrix_symbolic_dense (class in sage.matrix.matrix_symbolic_dense), 866
Matrix_symbolic_sparse (class in sage.matrix.matrix_symbolic_sparse), 888
matrix_window()(sage.matrix.matrix2.Matrix
method), 457
matrix_window() (sage.matrix.matrix_window.MatrixWindow method), 1029
MatrixArgs (class in sage.matrix.args), 109
MatrixArgs_init() (in module sage.matrix.args),
126
MatrixMatrixAction (class in sage.matrix.action),
1018
MatrixMulAction (class in sage.matrix.action), 1019
MatrixPolymapAction (class in sage.matrix.action),
1020
MatrixSchemePointAction (class in sage.matrix.action), 1020
MatrixSpace (class in sage.matrix.matrix_space), 3
MatrixVector_QQ() (in module sage.matrix.benchmark), 1067
1093

Matrices and Spaces of Matrices, Release 10.4

MatrixVectorAction (class in sage.matrix.action),sage.matrix.matrix_cyclo_dense, 993
1020
sage.matrix.matrix_dense, 591
MatrixWindow (class in sage.matrix.matrix_ratiosage.matrix.matrix_double_dense, 717
nal_dense), 688
sage.matrix.matrix_generic_dense,
MatrixWindow (class in sage.matrix.matrix_window),
603
1029
sage.matrix.matrix_generic_sparse,
max_det_prime() (in module sage.matrix.matrix_inte605
ger_dense_hnf), 673
sage.matrix.matrix_gf2e_dense, 801
maxspin() (sage.matrix.matrix2.Matrix method), 458
sage.matrix.matrix_integer_dense,
mccoy_column() (sage.matrix.compute_J_ideal.Com609
puteMinimalPolynomials method), 1056
sage.matrix.matrix_inteminimal_approximant_basis()(sage.mager_dense_hnf, 661
trix.matrix_polynomial_dense.Matrix_polynosage.matrix.matrix_intemial_dense method), 950
ger_dense_saturation, 681
minimal_kernel_basis()(sage.matrix.masage.matrix.matrix_integer_sparse,
trix_polynomial_dense.Matrix_polyno653
mial_dense method), 953
sage.matrix.matrix_misc, 1025
minimal_polynomial() (sage.matrix.matrix2.Matrix
sage.matrix.matrix_mod2_dense, 785
method), 459
sage.matrix.matrix_modn_dense_douminors() (sage.matrix.matrix2.Matrix method), 459
ble, 813
minpoly() (sage.matrix.matrix2.Matrix method), 460
sage.matrix.maminpoly()(sage.matrix.matrix_integer_dense.Matrix_modn_dense_float, 833
trix_integer_dense method), 639
sage.matrix.matrix_modn_sparse, 853
minpoly()(sage.matrix.matrix_integer_sparse.Masage.matrix.matrix_mpolynotrix_integer_sparse method), 656
mial_dense, 987
minpoly()(sage.matrix.matrix_modn_dense_dousage.matrix.matrix_polynoble.Matrix_modn_dense_template
method),mial_dense, 917
822
sage.matrix.matrix_rational_dense,
minpoly() (sage.matrix.matrix_modn_dense_float.Ma687
trix_modn_dense_template method), 842
sage.matrix.matrix_rational_sparse,
minpoly()(sage.matrix.matrix_rational_dense.Ma711
trix_rational_dense method), 702
sage.matrix.matrix_real_douminpoly()(sage.matrix.matrix_symbolic_dense.Mable_dense, 783
trix_symbolic_dense method), 878
sage.matrix.matrix_space, 3
minpoly() (sage.matrix.matrix_symbolic_sparse.Masage.matrix.matrix_sparse, 593
trix_symbolic_sparse method), 900
sage.matrix.matrix_symbolic_dense,
mod() (sage.matrix.matrix0.Matrix method), 171
861
modulesage.matrix.matrix_symbolic_sparse,
sage.matrix.action, 1017
883
sage.matrix.args, 109
sage.matrix.matrix_window, 1029
sage.matrix.benchmark, 1067
sage.matrix.misc, 1031
sage.matrix.berlekamp_massey, 589
sage.matrix.misc_flint, 1037
sage.matrix.change_ring, 1021
sage.matrix.misc_mpfr, 1035
sage.matrix.compute_J_ideal, 1051
sage.matrix.operation_table, 1001
sage.matrix.constructor, 31
sage.matrix.special, 47
sage.matrix.docs, 129
sage.matrix.strassen, 583
sage.matrix.echelon_matrix, 1023
sage.matrix.symplectic_basis, 1039
sage.matrix.matrix0, 141
monomial_coefficients()(sage.matrix.masage.matrix.matrix1, 211
trix0.Matrix method), 171
sage.matrix.matrix2, 251
multiplicative_order()(sage.matrix.masage.matrix.matrix_comtrix0.Matrix method), 172
plex_ball_dense, 907
mutate() (sage.matrix.matrix0.Matrix method), 175
sage.matrix.matrix_complex_double_dense, 905
1094

Index

Matrices and Spaces of Matrices, Release 10.4

NO

ncols (sage.matrix.args.MatrixArgs attribute), 123
ncols() (sage.matrix.matrix0.Matrix method), 176
ncols()(sage.matrix.matrix_space.MatrixSpace
method), 18
ncols()(sage.matrix.matrix_window.MatrixWindow
method), 1029
new_empty_window()(sage.matrix.matrix_window.MatrixWindow method), 1029
new_matrix() (sage.matrix.matrix1.Matrix method),229
new_matrix_window()(sage.matrix.matrix_window.MatrixWindow method), 1029
ngens()(sage.matrix.matrix_space.MatrixSpace
method), 19
nonpivots() (sage.matrix.matrix0.Matrix method), 177
nonzero_positions() (sage.matrix.matrix0.Matrix
method), 177
nonzero_positions_in_column()(sage.matrix.matrix0.Matrix method), 178
nonzero_positions_in_row() (sage.matrix.matrix0.Matrix method), 179
norm() (sage.matrix.matrix2.Matrix method), 461
norm() (sage.matrix.matrix_double_dense.Matrix_double_dense method), 764
NotFullRankError, 580
nrows (sage.matrix.args.MatrixArgs attribute), 123
nrows() (sage.matrix.matrix0.Matrix method), 180
nrows()(sage.matrix.matrix_space.MatrixSpace
method), 19
nrows()(sage.matrix.matrix_window.MatrixWindow
method), 1029
null_ideal()(sage.matrix.compute_J_ideal.ComputeMinimalPolynomials method), 1056
null_ideal() (sage.matrix.matrix_integer_dense.Matrix_integer_dense method), 640
nullity() (sage.matrix.matrix2.Matrix method), 463
nullspace_GF() (in module sage.matrix.benchmark),1074
nullspace_RDF() (in module sage.matrix.benchmark), 1074
nullspace_RR() (in module sage.matrix.benchmark),
1075
nullspace_ZZ() (in module sage.matrix.benchmark),
1075
number_of_arguments() (sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense
method),878
number_of_arguments() (sage.matrix.matrix_symbolic_sparse.Matrix_symbolic_sparse method),
900
numerical_approx() (sage.matrix.matrix2.Matrix
method), 464
numpy() (sage.matrix.matrix1.Matrix method), 230

one() (sage.matrix.matrix_space.MatrixSpace method),19
ones()(inmodulesage.matrix.matrix_integer_dense_hnf), 673
ones_matrix() (in module sage.matrix.special), 78
OperationTable (class in sage.matrix.operation_table), 1001
options() (in module sage.matrix.constructor), 45
overlaps()(sage.matrix.matrix_complex_ball_dense.Matrix_complex_ball_dense
method), 914

Index

P
p (sage.matrix.matrix_modn_sparse.Matrix_modn_sparse
attribute), 857
p_minimal_polynomials()(sage.matrix.compute_J_ideal.ComputeMinimalPolynomials
method), 1057
p_minimal_polynomials()(sage.matrix.matrix_integer_dense.Matrix_integer_dense
method), 641
p_part() (in module sage.matrix.compute_J_ideal),1064
p_saturation() (in module sage.matrix.matrix_integer_dense_saturation), 682
pad_zeros() (in module sage.matrix.matrix_integer_dense_hnf), 674
parity() (in module sage.matrix.matrix_mod2_dense),797
permanent() (sage.matrix.matrix2.Matrix method), 466
permanental_minor() (sage.matrix.matrix2.Matrix
method), 468
permanental_minor_polynomial() (in module
sage.matrix.matrix_misc), 1025
permutation_normal_form() (sage.matrix.matrix2.Matrix method), 470
permute_columns()(sage.matrix.matrix0.Matrix
method), 180
permute_rows()(sage.matrix.matrix0.Matrix
method), 181
permute_rows_and_columns() (sage.matrix.matrix0.Matrix method), 183
pfaffian() (sage.matrix.matrix2.Matrix method), 471
pivot_rows() (sage.matrix.matrix2.Matrix method),475
pivots() (sage.matrix.matrix0.Matrix method), 184
pivots() (sage.matrix.matrix_integer_dense.Matrix_integer_dense method), 641
pivots() (sage.matrix.matrix_mpolynomial_dense.Matrix_mpolynomial_dense method), 991
pivots_of_hnf_matrix() (in module sage.matrix.matrix_integer_dense_hnf), 674
ple() (in module sage.matrix.matrix_mod2_dense), 797
1095

Matrices and Spaces of Matrices, Release 10.4

plot() (sage.matrix.matrix2.Matrix method), 475
pluq() (in module sage.matrix.matrix_mod2_dense), 798
PolymapMatrixAction (class in sage.matrix.action),
1020
popov_form()(sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method),955
prime_candidates()(sage.matrix.compute_J_ideal.ComputeMinimalPolynomials
method), 1062
principal_square_root()(sage.matrix.matrix2.Matrix method), 476
prm_mul() (in module sage.matrix.matrix_misc), 1028
probable_hnf() (in module sage.matrix.matrix_integer_dense_hnf), 675
probable_pivot_columns() (in module sage.matrix.matrix_integer_dense_hnf), 676
probable_pivot_rows() (in module sage.matrix.matrix_integer_dense_hnf), 677
prod_of_row_sums() (sage.matrix.matrix2.Matrix
method), 476
prod_of_row_sums()(sage.matrix.matrix_integer_dense.Matrix_integer_dense method), 642
prod_of_row_sums()(sage.matrix.matrix_rational_dense.Matrix_rational_dense
method),703
pseudoinverse()(sage.matrix.matrix2.Matrix
method), 477Q
qdet() (sage.matrix.matrix2.Matrix method), 480
QR() (sage.matrix.matrix2.Matrix method), 265
QR()(sage.matrix.matrix_double_dense.Matrix_double_dense method), 722
quantum_determinant() (sage.matrix.matrix2.Matrix method), 482

R
random_diagonalizable_matrix() (in module
sage.matrix.special), 80
random_echelonizable_matrix() (in module
sage.matrix.special), 82
random_element() (sage.matrix.matrix_space.MatrixSpace method), 20
random_matrix() (in module sage.matrix.special), 85
random_rref_matrix() (in module sage.matrix.special), 97
random_sublist_of_size() (in module sage.matrix.matrix_integer_dense_saturation), 683
random_subspaces_matrix() (in module sage.matrix.special), 98
random_unimodular_matrix()(inmodulesage.matrix.special), 101
randomize() (sage.matrix.matrix2.Matrix method), 483
1096

randomize()(sage.matrix.matrix_cyclo_dense.Matrix_cyclo_dense method), 998
randomize()(sage.matrix.matrix_gf2e_dense.Matrix_gf2e_dense method), 805
randomize() (sage.matrix.matrix_integer_dense.Matrix_integer_dense method), 642
randomize()(sage.matrix.matrix_mod2_dense.Matrix_mod2_dense method), 790
randomize() (sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_template
method),824
randomize()(sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_template method), 844
randomize() (sage.matrix.matrix_rational_dense.Matrix_rational_dense method), 703
rank() (sage.matrix.matrix0.Matrix method), 184rank()(sage.matrix.matrix_gf2e_dense.Matrix_gf2e_dense method), 808
rank() (sage.matrix.matrix_integer_dense.Matrix_integer_dense method), 643
rank() (sage.matrix.matrix_integer_sparse.Matrix_integer_sparse method), 657
rank()(sage.matrix.matrix_mod2_dense.Matrix_mod2_dense method), 791
rank()(sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_template method), 826
rank()(sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_template method), 846
rank()(sage.matrix.matrix_modn_sparse.Matrix_modn_sparse method), 858
rank() (sage.matrix.matrix_rational_dense.Matrix_rational_dense method), 707
rank2_GF() (in module sage.matrix.benchmark), 1075
rank2_ZZ() (in module sage.matrix.benchmark), 1076
rank_GF() (in module sage.matrix.benchmark), 1076
rank_ZZ() (in module sage.matrix.benchmark), 1076
rational_form()(sage.matrix.matrix2.Matrix
method), 485
rational_reconstruction() (sage.matrix.matrix_integer_dense.Matrix_integer_dense
method), 644
rational_reconstruction() (sage.matrix.matrix_integer_sparse.Matrix_integer_sparse
method), 657
reduce() (sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method), 958
reduced_echelon_matrix_iterator()(inmodule sage.matrix.echelon_matrix), 1023
reduced_form()(sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method),961
report() (in module sage.matrix.benchmark), 1077
report_GF() (in module sage.matrix.benchmark), 1077
Index

Matrices and Spaces of Matrices, Release 10.4

report_ZZ() (in module sage.matrix.benchmark), 1078
rescale_col() (sage.matrix.matrix0.Matrix method),
185
rescale_row() (sage.matrix.matrix0.Matrix method),
186
restrict() (sage.matrix.matrix2.Matrix method), 498
restrict_codomain() (sage.matrix.matrix2.Matrix
method), 499
restrict_domain()(sage.matrix.matrix2.Matrix
method), 500
reverse() (sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method), 964
reverse_rows_and_columns() (sage.matrix.matrix0.Matrix method), 188
right_eigenmatrix() (sage.matrix.matrix2.Matrix
method), 501
right_eigenspaces() (sage.matrix.matrix2.Matrix
method), 504
right_eigenvectors() (sage.matrix.matrix2.Matrix
method), 508
right_eigenvectors() (sage.matrix.matrix_double_dense.Matrix_double_dense method), 767
right_kernel()(sage.matrix.matrix2.Matrix
method), 509
right_kernel_matrix() (sage.matrix.matrix2.Matrix method), 519
right_kernel_matrix()(sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_template method), 828
right_kernel_matrix()(sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_template method), 848
right_nullity()(sage.matrix.matrix2.Matrix
method), 535
right_quo_rem()(sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method),967
rook_vector() (sage.matrix.matrix2.Matrix method),535
round() (sage.matrix.matrix_double_dense.Matrix_double_dense method), 769
row() (sage.matrix.matrix1.Matrix method), 232row()(sage.matrix.matrix_integer_dense.Matrix_integer_dense method), 645
row()(sage.matrix.matrix_mod2_dense.Matrix_mod2_dense method), 792
row() (sage.matrix.matrix_rational_dense.Matrix_rational_dense method), 708
row_ambient_module() (sage.matrix.matrix1.Matrix
method), 233
row_degrees()(sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method),971
row_iterator() (in module sage.matrix.matrix_misc),
Index

1028
row_keys (sage.matrix.args.MatrixArgs attribute), 123
row_keys()(sage.matrix.operation_table.OperationTable method), 1014
row_module() (sage.matrix.matrix2.Matrix method),538
row_space() (sage.matrix.matrix2.Matrix method), 539
row_space() (sage.matrix.matrix_space.MatrixSpace
method), 21
rows() (sage.matrix.matrix1.Matrix method), 233
rref() (sage.matrix.matrix2.Matrix method), 539

S
sage.matrix.action
module, 1017
sage.matrix.args
module, 109
sage.matrix.benchmark
module, 1067
sage.matrix.berlekamp_massey
module, 589
sage.matrix.change_ring
module, 1021
sage.matrix.compute_J_ideal
module, 1051
sage.matrix.constructor
module, 31
sage.matrix.docs
module, 129
sage.matrix.echelon_matrix
module, 1023
sage.matrix.matrix0
module, 141
sage.matrix.matrix1
module, 211
sage.matrix.matrix2
module, 251
sage.matrix.matrix_complex_ball_dense
module, 907
sage.matrix.matrix_complex_double_dense
module, 905
sage.matrix.matrix_cyclo_dense
module, 993
sage.matrix.matrix_dense
module, 591
sage.matrix.matrix_double_dense
module, 717
sage.matrix.matrix_generic_dense
module, 603
sage.matrix.matrix_generic_sparse
module, 605
sage.matrix.matrix_gf2e_dense
module, 801
1097

Matrices and Spaces of Matrices, Release 10.4

sage.matrix.matrix_integer_dense
module, 609
sage.matrix.matrix_integer_dense_hnf
module, 661
sage.matrix.matrix_integer_dense_saturation
module, 681
sage.matrix.matrix_integer_sparse
module, 653
sage.matrix.matrix_misc
module, 1025
sage.matrix.matrix_mod2_dense
module, 785
sage.matrix.matrix_modn_dense_double
module, 813
sage.matrix.matrix_modn_dense_float
module, 833
sage.matrix.matrix_modn_sparse
module, 853
sage.matrix.matrix_mpolynomial_dense
module, 987
sage.matrix.matrix_polynomial_dense
module, 917
sage.matrix.matrix_rational_dense
module, 687
sage.matrix.matrix_rational_sparse
module, 711
sage.matrix.matrix_real_double_dense
module, 783
sage.matrix.matrix_spacemodule, 3
sage.matrix.matrix_sparse
module, 593
sage.matrix.matrix_symbolic_dense
module, 861
sage.matrix.matrix_symbolic_sparse
module, 883
sage.matrix.matrix_window
module, 1029
sage.matrix.misc
module, 1031
sage.matrix.misc_flint
module, 1037
sage.matrix.misc_mpfr
module, 1035
sage.matrix.operation_table
module, 1001
sage.matrix.special
module, 47
sage.matrix.strassen
module, 583
sage.matrix.symplectic_basis
module, 1039

1098

sanity_checks() (in module sage.matrix.matrix_integer_dense_hnf), 677
saturation() (in module sage.matrix.matrix_integer_dense_saturation), 684
saturation() (sage.matrix.matrix_integer_dense.Matrix_integer_dense method), 646
schur() (sage.matrix.matrix_double_dense.Matrix_double_dense method), 770
set()(sage.matrix.matrix_window.MatrixWindow
method), 1029
set_block() (sage.matrix.matrix2.Matrix method), 542
set_col_to_multiple_of_col()(sage.matrix.matrix0.Matrix method), 190
set_column() (sage.matrix.matrix1.Matrix method),234
set_column_keys()(sage.matrix.args.MatrixArgs
method), 123
set_immutable()(sage.matrix.matrix0.Matrix
method), 190
set_immutable()(sage.matrix.matrix_cyclo_dense.Matrix_cyclo_dense method), 998
set_max_cols() (in module sage.matrix.matrix0), 208
set_max_rows() (in module sage.matrix.matrix0), 208
set_print_symbols() (sage.matrix.operation_table.OperationTable method), 1015
set_row() (sage.matrix.matrix1.Matrix method), 235
set_row_keys()(sage.matrix.args.MatrixArgs
method), 124
set_row_to_multiple_of_row()(sage.matrix.matrix0.Matrix method), 192
set_row_to_multiple_of_row()(sage.matrix.matrix_rational_dense.Matrix_rational_dense method), 709
set_row_to_multiple_of_row()(sage.matrix.matrix_rational_sparse.Matrix_rational_sparse method), 715
set_space() (sage.matrix.args.MatrixArgs method),125
set_to() (sage.matrix.matrix_window.MatrixWindow
method), 1029
set_to_diff()(sage.matrix.matrix_window.MatrixWindow method), 1029
set_to_prod()(sage.matrix.matrix_window.MatrixWindow method), 1029
set_to_sum()(sage.matrix.matrix_window.MatrixWindow method), 1029
set_to_zero()(sage.matrix.matrix_window.MatrixWindow method), 1029
set_unsafe()(sage.matrix.matrix_window.MatrixWindow method), 1029
shift()(sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method), 973
simplify() (sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense method), 879
IndexMatrices and Spaces of Matrices, Release 10.4

simplify() (sage.matrix.matrix_symbolic_sparse.Matrix_symbolic_sparse method), 901
simplify_full()(sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense
method),879
simplify_full()(sage.matrix.matrix_symbolic_sparse.Matrix_symbolic_sparse method),901
simplify_rational()(sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense
method),880
simplify_rational()(sage.matrix.matrix_symbolic_sparse.Matrix_symbolic_sparse method),902
simplify_trig()(sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense
method),880
simplify_trig()(sage.matrix.matrix_symbolic_sparse.Matrix_symbolic_sparse method),902
singular_values()(sage.matrix.matrix_double_dense.Matrix_double_dense method), 777
slice()(sage.matrix.matrix_gf2e_dense.Matrix_gf2e_dense method), 808
smith_form() (sage.matrix.matrix2.Matrix method),543
smith_form() (sage.matrix.matrix_integer_dense.Matrix_integer_dense method), 648
smith_form() (sage.matrix.matrix_integer_sparse.Matrix_integer_sparse method), 658
smithform_ZZ() (in module sage.matrix.benchmark),1079
solve_left() (sage.matrix.matrix2.Matrix method),547
solve_left_series_trunc()(sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method), 975
solve_right() (sage.matrix.matrix2.Matrix method),551
solve_right_series_trunc()(sage.matrix.matrix_polynomial_dense.Matrix_polynomial_dense method), 977
solve_system_with_difficult_last_row()(inmodulesage.matrix.matrix_integer_dense_hnf), 678
solve_system_with_difficult_last_row()(inmodulesage.matrix.matrix_integer_dense_saturation), 685
some_elements() (sage.matrix.matrix_space.MatrixSpace method), 21
space (sage.matrix.args.MatrixArgs attribute), 126
sparse (sage.matrix.args.MatrixArgs attribute), 126
sparse_columns()(sage.matrix.matrix1.Matrix
method), 236
Index

sparse_matrix()(sage.matrix.matrix1.Matrix
method), 237
sparse_rows() (sage.matrix.matrix1.Matrix method),238
SparseEntry (class in sage.matrix.args), 127
stack() (sage.matrix.matrix1.Matrix method), 239
str() (sage.matrix.matrix0.Matrix method), 192
str()(sage.matrix.matrix_mod2_dense.Matrix_mod2_dense method), 792
strassen_echelon()(inmodulesage.matrix.strassen), 585
strassen_window_multiply()(inmodulesage.matrix.strassen), 587
subdivide() (sage.matrix.matrix2.Matrix method), 561
subdivision() (sage.matrix.matrix2.Matrix method),563
subdivision_entry() (sage.matrix.matrix2.Matrix
method), 565
subdivisions()(sage.matrix.matrix2.Matrix
method), 566
submatrix() (sage.matrix.matrix1.Matrix method), 245
submatrix()(sage.matrix.matrix_gf2e_dense.Matrix_gf2e_dense method), 809
submatrix()(sage.matrix.matrix_mod2_dense.Matrix_mod2_dense method), 794
submatrix() (sage.matrix.matrix_modn_dense_double.Matrix_modn_dense_template
method),829
submatrix()(sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_template method), 849
submodule() (sage.matrix.matrix_space.MatrixSpace
method), 22
subs() (sage.matrix.matrix2.Matrix method), 566
subtract() (sage.matrix.matrix_window.MatrixWindow method), 1029
subtract_prod() (sage.matrix.matrix_window.MatrixWindow method), 1030
SVD()
(sage.matrix.matrix_double_dense.Matrix_double_dense method), 727
swap_columns()(sage.matrix.matrix0.Matrix
method), 196
swap_rows() (sage.matrix.matrix0.Matrix method), 197
swap_rows() (sage.matrix.matrix_modn_sparse.Matrix_modn_sparse method), 858
swap_rows() (sage.matrix.matrix_window.MatrixWindow method), 1030
swapped_columns()(sage.matrix.matrix_mpolynomial_dense.Matrix_mpolynomial_dense
method), 992
symplectic_basis_over_field() (in module
sage.matrix.symplectic_basis), 1043
symplectic_basis_over_ZZ()(inmodulesage.matrix.symplectic_basis), 1039
1099

Matrices and Spaces of Matrices, Release 10.4
symplectic_form()(sage.matrix.matrix2.Matrix U
method), 568
unpickle() (in module sage.matrix.matrix0), 209
symplectic_form()(sage.matrix.matrix_inte- unpickle_matrix_gf2e_dense_v0() (in module
ger_dense.Matrix_integer_dense method), 650
sage.matrix.matrix_gf2e_dense), 810
unpickle_matrix_mod2_dense_v2() (in moduleTsage.matrix.matrix_mod2_dense), 800
T (sage.matrix.matrix2.Matrix attribute), 272
table()(sage.matrix.operation_table.OperationTable V
method), 1015
vandermonde() (in module sage.matrix.special), 104
tensor_product()(sage.matrix.matrix2.Matrix variables() (sage.matrix.matrix_symbolic_dense.Mamethod), 569
trix_symbolic_dense method), 881
tensor_product()(sage.matrix.matrix_cy- variables() (sage.matrix.matrix_symbolic_sparse.Maclo_dense.Matrix_cyclo_dense method), 999
trix_symbolic_sparse method), 903
test() (in module sage.matrix.strassen), 587
vecmat_ZZ() (in module sage.matrix.benchmark), 1079
to_list() (sage.matrix.strassen.int_range method), 585 vector_on_axis_rotation_matrix() (in modto_matrix() (sage.matrix.matrix_window.MatrixWinule sage.matrix.special), 104
dow method), 1030
VectorMatrixAction (class in sage.matrix.action),
to_png() (in module sage.matrix.matrix_mod2_dense),
1020
799
visualize_structure() (sage.matrix.matrix2.Matoeplitz() (in module sage.matrix.special), 103
trix method), 572
trace() (sage.matrix.matrix2.Matrix method), 571
trace() (sage.matrix.matrix_complex_ball_dense.Ma- W
trix_complex_ball_dense method), 915
weak_popov_form()(sage.matrix.matrix_polynotrace_of_product() (sage.matrix.matrix2.Matrix
mial_dense.Matrix_polynomial_dense method),
method), 572
982
translation() (sage.matrix.operation_table.Opera- wiedemann() (sage.matrix.matrix2.Matrix method), 573
tionTable method), 1016
with_added_multiple_of_column() (sage.matranspose()(sage.matrix.matrix_comtrix.matrix0.Matrix method), 197
plex_ball_dense.Matrix_complex_ball_dense
with_added_multiple_of_row()(sage.mamethod), 915
trix.matrix0.Matrix method), 198transpose() (sage.matrix.matrix_dense.Matrix_dense with_col_set_to_multiple_of_col()method), 592(sage.matrix.matrix0.Matrix method), 199transpose() (sage.matrix.matrix_integer_dense.Ma- with_permuted_columns()(sage.matrix.matrix_integer_dense method), 651
trix0.Matrix method), 200transpose()(sage.matrix.matrix_mod2_dense.Ma- with_permuted_rows() (sage.matrix.matrix0.Matrix
trix_mod2_dense method), 795
method), 201
transpose() (sage.matrix.matrix_modn_dense_dou- with_permuted_rows_and_columns()
ble.Matrix_modn_dense_template
method),(sage.matrix.matrix0.Matrix method), 202830
with_rescaled_col() (sage.matrix.matrix0.Matrix
transpose()(sage.matrix.mamethod), 203
trix_modn_dense_float.Mawith_rescaled_row() (sage.matrix.matrix0.Matrix
trix_modn_dense_template method), 850
method), 204transpose() (sage.matrix.matrix_modn_sparse.Ma- with_row_set_to_multiple_of_row()
trix_modn_sparse method), 858(sage.matrix.matrix0.Matrix method), 205
transpose() (sage.matrix.matrix_rational_dense.Ma- with_swapped_columns()(sage.matrix.matrix_rational_dense method), 709
trix0.Matrix method), 206transpose() (sage.matrix.matrix_sparse.Matrix_sparse with_swapped_rows() (sage.matrix.matrix0.Matrix
method), 601
method), 207transposed() (sage.matrix.matrix_space.MatrixSpaceZ
method), 24
truncate() (sage.matrix.matrix_polynomial_dense.Ma- zero() (sage.matrix.matrix_space.MatrixSpace method),
trix_polynomial_dense method), 980
24
zero_at()(sage.matrix.matrix_double_dense.Matrix_double_dense method), 781
1100

Index

Matrices and Spaces of Matrices, Release 10.4

zero_matrix() (in module sage.matrix.special), 106
zero_matrix() (sage.matrix.matrix_space.MatrixSpace method), 25
zero_pattern_matrix() (sage.matrix.matrix1.Matrix method), 246
zigzag_form() (sage.matrix.matrix2.Matrix method),
573

Index

1101