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 < b
False
sage: b < a
True
sage: a > b
True
sage: 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]
[ 2325/2303 1779/2303 -513/2303]
[-1710/2303 950/2303 95/2303]
>>> b.det()
285/2303
>>> a == b
False
>>> a < b
False
>>> b < a
True
>>> a > b
True
>>> a*b
[1 0 0]
[0 1 0]
[0 0 1]
- class sage.matrix.matrix_rational_dense.MatrixWindow¶
Bases:
object
- class sage.matrix.matrix_rational_dense.Matrix_rational_dense[source]¶
Bases:
Matrix_denseINPUT:
parent– a matrix space overQQentries– seematrix()copy– ignored (for backwards compatibility)coerce– ifFalse, assume without checking that the entries are of typeRational
- BKZ(*args, **kwargs)[source]¶
Return the result of running Block Korkin-Zolotarev reduction on
selfinterpreted as a lattice.The arguments
*argsand**kwargsare passed ontosage.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] [-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() / d True
- LLL(*args, **kwargs)[source]¶
Return an LLL reduced or approximated LLL reduced lattice for
selfinterpreted as a lattice.The arguments
*argsand**kwargsare passed ontosage.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/40 0] sage: L, U = A.LLL(transformation=True) sage: U * A == L True 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/40 0] >>> L, U = A.LLL(transformation=True) >>> U * A == L True >>> 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() / d True
- add_to_entry(i, j, elt)[source]¶
Add
eltto 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]
- antitranspose()[source]¶
Return the antitranspose of
self, without changingself.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)[source]¶
Create the matrix over R with entries the entries of
selfcoerced 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) 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)[source]¶
Return the characteristic polynomial of this matrix.
Note
The characteristic polynomial is defined as \(\det(xI-A)\).
INPUT:
var– (optional) name of the variable as a stringalgorithm– 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(); f x^3 - 7/12*x^2 - 149/40*x + 97/30 sage: f(a) [0 0 0] [0 0 0] [0 0 0]
>>> 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(); f x^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)[source]¶
Return the \(i\)-th column of this matrix as a dense vector.
INPUT:
i– integerfrom_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 >>> 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)[source]¶
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 be sorted 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 the subspace \(W_i = ker(g_(A)^n)\), 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 that ker(g(A)) = \(ker(g(A)^n)\).
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– ignoreddual– whether to also return decompositions for the dualalgorithm– an optional specification of an algorithmNone– (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 algorithmproof– boolean orNone(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 on height, 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)]
>>> 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()[source]¶
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)[source]¶
Return the determinant of this matrix.
INPUT:
algorithm– an optional specification of an algorithm. It can be one ofNone: (default) uses flint'flint': uses flint library'pari': uses PARI library'integer': removes denominator and call determinant on the correspondinginteger matrix
'generic': calls the generic Sage implementation
proof– boolean orNone; ifNoneuse proof.linear_algebra(); only relevant for the padic algorithm
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/15 sage: 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/288 sage: 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 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)[source]¶
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] [ 0 1 0 -5/157] [ 0 0 1 238/157] [ 0 0 0 0] sage: a.echelon_form(algorithm='multimodular') [ 1 0 0 -76/157] [ 0 1 0 -5/157] [ 0 0 1 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.echelon_form() [ 1 0 0 -76/157] [ 0 1 0 -5/157] [ 0 0 1 238/157] [ 0 0 0 0] >>> a.echelon_form(algorithm='multimodular') [ 1 0 0 -76/157] [ 0 1 0 -5/157] [ 0 0 1 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)[source]¶
Transform the matrix
selfinto reduced row echelon form in place.INPUT:
algorithm– an optional specification of an algorithm. One ofNone: (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 be faster when coefficients are huge),'classical': just clear each column using Gauss elimination.
height_guess,**kwds– all passed to the multimodular algorithm; ignored by other algorithmsproof– boolean orNone(default: None, see proof.linear_algebra or sage.structure.proof). Passed to the multimodular algorithm. Note that the Sage global default isproof=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] [ 0 1 0 -5/157] [ 0 0 1 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] [ 0 1 0 -5/157] [ 0 0 1 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] [ 0 1 0 -5/157] [ 0 0 1 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] [ 0 1 0 -5/157] [ 0 0 1 238/157] [ 0 0 0 0]
- height()[source]¶
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: integer
EXAMPLES:
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)[source]¶
Return the inverse of this matrix.
INPUT:
algorithm– an optional specification of an algorithm. It can be one ofNone: (default) uses flint'flint': uses flint library'pari': uses PARI library'iml': uses IML library
check_invertible– only used whenalgorithm=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] [ -5/11 -2/55 3/10 -3/22] [ -13/22 307/440 -1/10 -9/88] [ 15/22 -37/88 0 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 nonsingular sage: a.inverse(algorithm='iml') Traceback (most recent call last): ... ZeroDivisionError: input matrix must be nonsingular sage: 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') 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)[source]¶
Return
Trueif this lattice is \((\delta, \eta)\)-LLL reduced. For a definition of LLL reduction, seesage.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() True
- matrix_from_columns(columns)[source]¶
Return the matrix constructed from
selfusing 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] [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)[source]¶
Return the minimal polynomial of this matrix.
INPUT:
var– (optional) the variable name as a string (default:'x')algorithm– an optional specification of an algorithm. It can be one ofNone: (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(); f x^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(); f x^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) True
sage: 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) 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
- randomize(density=1, num_bound=2, den_bound=2, distribution=None, nonzero=False)[source]¶
Randomize
densityproportion of the entries of this matrix, leaving the rest unchanged.If
xandyare given, randomized entries of this matrix have numerators and denominators bounded byxandyand have density 1.INPUT:
density– number between 0 and 1 (default: 1)num_bound– numerator bound (default: 2)den_bound– denominator bound (default: 2)distribution–Noneor ‘1/n’ (default:None); if ‘1/n’ thennum_bound,den_boundare ignored and numbers are chosen using the GMP functionmpq_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':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)) ... 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') >>> 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) 100
- rank(algorithm=None)[source]¶
Return the rank of this matrix.
INPUT:
algorithm– an optional specification of an algorithm. One ofNone– (default) will use flint'flint'– uses the flint library'pari'– uses the PARI library'integer'– eliminate denominators and calls the rank function on the corresponding integer matrix
EXAMPLES:
sage: matrix(QQ,3,[1..9]).rank() 2 sage: 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)[source]¶
Return the \(i\)-th row of this matrix as a dense vector.
INPUT:
i– integerfrom_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) >>> 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)[source]¶
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()[source]¶
Return the transpose of
self, without changingself.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]
>>> 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]
.Tis 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]