Symbolic sparse matrices¶
EXAMPLES:
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]
>>> 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]
>>> 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) pi]
[ -1 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]
[ pi e]
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]
[ pi e]
>>> TestSuite(m).run()
Comparison:
sage: m = matrix(SR, 2, [sqrt(2), 3, pi, e], sparse=True)
sage: m == m
True
sage: m != 3
True
sage: m = matrix(SR,2,[1..4], sparse=True); n = m^2
sage: (exp(m+n) - exp(m)*exp(n)).simplify_rational() == 0 # indirect test
True
>>> 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 - 6
sage: 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 + 6
>>> from sage.all import *
>>> M = matrix(SR, Integer(2), Integer(2), [x,Integer(2),Integer(3),Integer(4)], sparse=True)
>>> M.permanent()
4*x + 6
Rank:
sage: M = matrix(SR, 5, 5, range(25), sparse=True)
sage: M.rank()
2
sage: 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 a
matrix 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 a
matrix 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]
[ pi e]
sage: n
[sin(1) 3]
[ pi e]
>>> 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]
[ pi e]
Conversion to Maxima:
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[source]¶
Bases:
Matrix_generic_sparse
- arguments()[source]¶
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()[source]¶
Choose a canonical branch of each entry of
self
by callingExpression.canonicalize_radical()
componentwise.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)] >>> 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)[source]¶
Compute the characteristic polynomial of
self
, using maxima.Note
The characteristic polynomial is defined as \(\det(xI-A)\).
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^3
- eigenvalues(extend=True)[source]¶
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]
- eigenvectors_left(other=None)[source]¶
Compute the left eigenvectors of a matrix.
INPUT:
other
– a square matrix \(B\) (default:None
) in a generalized eigenvalue problem; ifNone
, an ordinary eigenvalue problem is solved (currently supported only if the base ring ofself
isRDF
orCDF
)
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') True
sage: 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)] 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\times 3\) matrix with three variables. However, if the entries are integers or rationals it can produce exact values in a 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 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)[source]¶
Compute the right eigenvectors of a matrix.
INPUT:
other
– a square matrix \(B\) (default:None
) in a generalized eigenvalue problem; ifNone
, an ordinary eigenvalue problem is solved (currently supported only if the base ring ofself
isRDF
orCDF
)
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 the eigenvalue.
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] >>> 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()[source]¶
Return the matrix exponential of this matrix \(X\), which is the matrix
\[e^X = \sum_{k=0}^{\infty} \frac{X^k}{k!}.\]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:
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 \(m, n\) have the property that \(e^{m+n} = e^m e^n\) (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,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()[source]¶
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]
>>> 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()[source]¶
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')[source]¶
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)]
>>> 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)[source]¶
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)[source]¶
Return a Jordan normal form of
self
.INPUT:
self
– a square matrixsubdivide
– boolean (default:True
)transformation
– boolean (default:False
)
OUTPUT:
If
transformation
isFalse
, only a Jordan normal form (unique up to the ordering of the Jordan blocks) is returned. Otherwise, a pair(J, P)
is returned, whereJ
is a Jordan normal form andP
is an invertible matrix such thatself
equalsP * J * P^(-1)
.If
subdivide
isTrue
, the Jordan blocks in the returned matrixJ
are indicated by a subdivision in the sense ofsubdivide()
.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() [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 to be 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*c 1] [0 x], [-c^2 0] ) 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*d c 0] [0 a 1] [ 0 d 0] [0 0 a], [ 0 0 1] ) 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*c 1] [0 x], [-c^2 0] ) >>> 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 ( [a 1 0] [b*d c 0] [0 a 1] [ 0 d 0] [0 0 a], [ 0 0 1] ) >>> (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')[source]¶
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()[source]¶
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 [ a 1] [ 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 [ a 1] [ x^2 y^2 + 2] >>> m.number_of_arguments() 3
- simplify()[source]¶
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()[source]¶
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 simplifiedEXAMPLES:
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() [ 1 sin(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() [ 1 sin(1/(x + 1))] [ factorial(n) x^(-a + 1)*sin(2)]
- simplify_rational()[source]¶
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]
- simplify_trig()[source]¶
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()[source]¶
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 [ x x + 2] [ x^2 x^2 + 2] sage: m.variables() (x,) sage: m = matrix([[a, b+c], [x^2, y^2+2]], sparse=True); m [ a b + 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 [ x x + 2] [ x^2 x^2 + 2] >>> m.variables() (x,) >>> m = matrix([[a, b+c], [x**Integer(2), y**Integer(2)+Integer(2)]], sparse=True); m [ a b + c] [ x^2 y^2 + 2] >>> m.variables() (a, b, c, x, y)