Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/matrix/matrix2.pyx
8815 views
1
r"""
2
Base class for matrices, part 2
3
4
For design documentation see matrix/docs.py.
5
6
AUTHORS:
7
8
- William Stein: initial version
9
10
- Miguel Marco (2010-06-19): modified eigenvalues and eigenvectors functions to
11
allow the option extend=False
12
13
- Rob Beezer (2011-02-05): refactored all of the matrix kernel routines
14
15
TESTS::
16
17
sage: m = matrix(ZZ['x'], 2, 3, [1..6])
18
sage: TestSuite(m).run()
19
"""
20
21
#*****************************************************************************
22
# Copyright (C) 2005, 2006 William Stein <[email protected]>
23
#
24
# Distributed under the terms of the GNU General Public License (GPL)
25
# as published by the Free Software Foundation; either version 2 of
26
# the License, or (at your option) any later version.
27
# http://www.gnu.org/licenses/
28
#*****************************************************************************
29
30
include "sage/ext/stdsage.pxi"
31
include "sage/ext/python.pxi"
32
include "sage/ext/interrupt.pxi"
33
34
from sage.misc.randstate cimport randstate, current_randstate
35
from sage.structure.sequence import Sequence
36
from sage.structure.element import is_Vector
37
from sage.misc.misc import verbose, get_verbose
38
from sage.misc.temporary_file import graphics_filename
39
from sage.rings.number_field.all import is_NumberField
40
from sage.rings.integer_ring import ZZ, is_IntegerRing
41
from sage.rings.integer import Integer
42
from sage.rings.rational_field import QQ, is_RationalField
43
from sage.rings.real_double import RDF
44
from sage.rings.complex_double import CDF
45
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
46
from sage.misc.derivative import multi_derivative
47
48
import sage.modules.free_module
49
import matrix_space
50
import berlekamp_massey
51
from sage.modules.free_module_element import is_FreeModuleElement
52
53
cdef class Matrix(matrix1.Matrix):
54
def _backslash_(self, B):
55
r"""
56
Used to compute `A \backslash B`, i.e., the backslash solver
57
operator.
58
59
EXAMPLES::
60
61
sage: A = matrix(QQ, 3, [1,2,4,2,3,1,0,1,2])
62
sage: B = matrix(QQ, 3, 2, [1,7,5, 2,1,3])
63
sage: C = A._backslash_(B); C
64
[ -1 1]
65
[13/5 -3/5]
66
[-4/5 9/5]
67
sage: A*C == B
68
True
69
sage: A._backslash_(B) == A \ B
70
True
71
sage: A._backslash_(B) == A.solve_right(B)
72
True
73
"""
74
return self.solve_right(B)
75
76
def subs(self, in_dict=None, **kwds):
77
"""
78
EXAMPLES::
79
80
sage: var('a,b,d,e')
81
(a, b, d, e)
82
sage: m = matrix([[a,b], [d,e]])
83
sage: m.substitute(a=1)
84
[1 b]
85
[d e]
86
sage: m.subs(a=b, b=d)
87
[b d]
88
[d e]
89
"""
90
v = [a.subs(in_dict, **kwds) for a in self.list()]
91
return self.new_matrix(self.nrows(), self.ncols(), v)
92
93
def solve_left(self, B, check=True):
94
"""
95
If self is a matrix `A`, then this function returns a
96
vector or matrix `X` such that `X A = B`. If
97
`B` is a vector then `X` is a vector and if
98
`B` is a matrix, then `X` is a matrix.
99
100
INPUT:
101
102
103
- ``B`` - a matrix
104
105
- ``check`` - bool (default: True) - if False and self
106
is nonsquare, may not raise an error message even if there is no
107
solution. This is faster but more dangerous.
108
109
110
EXAMPLES::
111
112
sage: A = matrix(QQ,4,2, [0, -1, 1, 0, -2, 2, 1, 0])
113
sage: B = matrix(QQ,2,2, [1, 0, 1, -1])
114
sage: X = A.solve_left(B)
115
sage: X*A == B
116
True
117
118
TESTS::
119
120
sage: A = matrix(QQ,4,2, [0, -1, 1, 0, -2, 2, 1, 0])
121
sage: B = vector(QQ,2, [2,1])
122
sage: X = A.solve_left(B)
123
sage: X*A == B
124
True
125
sage: X
126
(-1, 2, 0, 0)
127
sage: A = Matrix(Zmod(128), 2, 3, [5, 29, 33, 64, 0, 7])
128
sage: B = vector(Zmod(128), [31,39,56])
129
sage: X = A.solve_left(B); X
130
(19, 83)
131
sage: X * A == B
132
True
133
134
"""
135
if is_Vector(B):
136
return self.transpose().solve_right(B, check=check)
137
else:
138
return self.transpose().solve_right(B.transpose(), check=check).transpose()
139
140
def solve_right(self, B, check=True):
141
r"""
142
If self is a matrix `A`, then this function returns a
143
vector or matrix `X` such that `A X = B`. If
144
`B` is a vector then `X` is a vector and if
145
`B` is a matrix, then `X` is a matrix.
146
147
.. note::
148
149
In Sage one can also write ``A \backslash B`` for
150
``A.solve_right(B)``, i.e., Sage implements the "the
151
MATLAB/Octave backslash operator".
152
153
INPUT:
154
155
156
- ``B`` - a matrix or vector
157
158
- ``check`` - bool (default: True) - if False and self
159
is nonsquare, may not raise an error message even if there is no
160
solution. This is faster but more dangerous.
161
162
163
OUTPUT: a matrix or vector
164
165
.. seealso::
166
167
:meth:`solve_left`
168
169
EXAMPLES::
170
171
sage: A = matrix(QQ, 3, [1,2,3,-1,2,5,2,3,1])
172
sage: b = vector(QQ,[1,2,3])
173
sage: x = A \ b; x
174
(-13/12, 23/12, -7/12)
175
sage: A * x
176
(1, 2, 3)
177
178
We solve with A nonsquare::
179
180
sage: A = matrix(QQ,2,4, [0, -1, 1, 0, -2, 2, 1, 0]); B = matrix(QQ,2,2, [1, 0, 1, -1])
181
sage: X = A.solve_right(B); X
182
[-3/2 1/2]
183
[ -1 0]
184
[ 0 0]
185
[ 0 0]
186
sage: A*X == B
187
True
188
189
Another nonsingular example::
190
191
sage: A = matrix(QQ,2,3, [1,2,3,2,4,6]); v = vector([-1/2,-1])
192
sage: x = A \ v; x
193
(-1/2, 0, 0)
194
sage: A*x == v
195
True
196
197
Same example but over `\ZZ`::
198
199
sage: A = matrix(ZZ,2,3, [1,2,3,2,4,6]); v = vector([-1,-2])
200
sage: A \ v
201
(-1, 0, 0)
202
203
An example in which there is no solution::
204
205
sage: A = matrix(QQ,2,3, [1,2,3,2,4,6]); v = vector([1,1])
206
sage: A \ v
207
Traceback (most recent call last):
208
...
209
ValueError: matrix equation has no solutions
210
211
A ValueError is raised if the input is invalid::
212
213
sage: A = matrix(QQ,4,2, [0, -1, 1, 0, -2, 2, 1, 0])
214
sage: B = matrix(QQ,2,2, [1, 0, 1, -1])
215
sage: X = A.solve_right(B)
216
Traceback (most recent call last):
217
...
218
ValueError: number of rows of self must equal number of rows of B
219
220
We solve with A singular::
221
222
sage: A = matrix(QQ,2,3, [1,2,3,2,4,6]); B = matrix(QQ,2,2, [6, -6, 12, -12])
223
sage: X = A.solve_right(B); X
224
[ 6 -6]
225
[ 0 0]
226
[ 0 0]
227
sage: A*X == B
228
True
229
230
We illustrate left associativity, etc., of the backslash operator.
231
232
::
233
234
sage: A = matrix(QQ, 2, [1,2,3,4])
235
sage: A \ A
236
[1 0]
237
[0 1]
238
sage: A \ A \ A
239
[1 2]
240
[3 4]
241
sage: A.parent()(1) \ A
242
[1 2]
243
[3 4]
244
sage: A \ (A \ A)
245
[ -2 1]
246
[ 3/2 -1/2]
247
sage: X = A \ (A - 2); X
248
[ 5 -2]
249
[-3 2]
250
sage: A * X
251
[-1 2]
252
[ 3 2]
253
254
Solving over a polynomial ring::
255
256
sage: x = polygen(QQ, 'x')
257
sage: A = matrix(2, [x,2*x,-5*x^2+1,3])
258
sage: v = vector([3,4*x - 2])
259
sage: X = A \ v
260
sage: X
261
((-8*x^2 + 4*x + 9)/(10*x^3 + x), (19*x^2 - 2*x - 3)/(10*x^3 + x))
262
sage: A * X == v
263
True
264
265
Solving some systems over `\ZZ/n\ZZ`::
266
267
sage: A = Matrix(Zmod(6), 3, 2, [1,2,3,4,5,6])
268
sage: B = vector(Zmod(6), [1,1,1])
269
sage: A.solve_right(B)
270
(5, 1)
271
sage: B = vector(Zmod(6), [5,1,1])
272
sage: A.solve_right(B)
273
Traceback (most recent call last):
274
...
275
ValueError: matrix equation has no solutions
276
sage: A = Matrix(Zmod(128), 2, 3, [23,11,22,4,1,0])
277
sage: B = Matrix(Zmod(128), 2, 1, [1,0])
278
sage: A.solve_right(B)
279
[ 1]
280
[124]
281
[ 1]
282
283
Solving a system over the p-adics::
284
285
sage: k = Qp(5,4)
286
sage: a = matrix(k, 3, [1,7,3,2,5,4,1,1,2]); a
287
[ 1 + O(5^4) 2 + 5 + O(5^4) 3 + O(5^4)]
288
[ 2 + O(5^4) 5 + O(5^5) 4 + O(5^4)]
289
[ 1 + O(5^4) 1 + O(5^4) 2 + O(5^4)]
290
sage: v = vector(k, 3, [1,2,3])
291
sage: x = a \ v; x
292
(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))
293
sage: a * x == v
294
True
295
296
Solving a system of linear equation symbolically using symbolic matrices::
297
298
sage: var('a,b,c,d,x,y')
299
(a, b, c, d, x, y)
300
sage: A=matrix(SR,2,[a,b,c,d]); A
301
[a b]
302
[c d]
303
sage: result=vector(SR,[3,5]); result
304
(3, 5)
305
sage: soln=A.solve_right(result)
306
sage: soln
307
(-b*(3*c/a - 5)/(a*(b*c/a - d)) + 3/a, (3*c/a - 5)/(b*c/a - d))
308
sage: (a*x+b*y).subs(x=soln[0],y=soln[1]).simplify_full()
309
3
310
sage: (c*x+d*y).subs(x=soln[0],y=soln[1]).simplify_full()
311
5
312
sage: (A*soln).apply_map(lambda x: x.simplify_full())
313
(3, 5)
314
"""
315
316
if is_Vector(B):
317
if self.nrows() != B.degree():
318
raise ValueError, "number of rows of self must equal degree of B"
319
else:
320
if self.nrows() != B.nrows():
321
raise ValueError, "number of rows of self must equal number of rows of B"
322
323
K = self.base_ring()
324
if not K.is_integral_domain():
325
from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing
326
if is_IntegerModRing(K):
327
from sage.libs.pari.all import pari
328
A = pari(self.lift())
329
b = pari([c.lift() for c in B]).Col()
330
ret = A.matsolvemod(pari(K.cardinality()), b)
331
if ret.type() == 't_INT':
332
raise ValueError("matrix equation has no solutions")
333
ret = ret.Vec().sage()
334
if is_Vector(B):
335
return (K ** self.ncols())(ret)
336
return self.matrix_space(self.ncols(), 1)(ret)
337
raise TypeError, "base ring must be an integral domain or a ring of integers mod n"
338
if not K.is_field():
339
K = K.fraction_field()
340
self = self.change_ring(K)
341
342
matrix = True
343
if is_Vector(B):
344
matrix = False
345
C = self.matrix_space(self.nrows(), 1)(B.list())
346
else:
347
C = B
348
349
if not self.is_square():
350
X = self._solve_right_general(C, check=check)
351
if not matrix:
352
# Convert back to a vector
353
return (X.base_ring() ** X.nrows())(X.list())
354
else:
355
return X
356
357
if self.rank() != self.nrows():
358
X = self._solve_right_general(C, check=check)
359
else:
360
X = self._solve_right_nonsingular_square(C, check_rank=False)
361
362
if not matrix:
363
# Convert back to a vector
364
return X.column(0)
365
else:
366
return X
367
368
def _solve_right_nonsingular_square(self, B, check_rank=True):
369
r"""
370
If self is a matrix `A` of full rank, then this function
371
returns a matrix `X` such that `A X = B`.
372
373
.. seealso::
374
375
:meth:`solve_right` and :meth:`solve_left`
376
377
INPUT:
378
379
380
- ``B`` - a matrix
381
382
- ``check_rank`` - bool (default: True)
383
384
385
OUTPUT: matrix
386
387
EXAMPLES::
388
389
sage: A = matrix(QQ,3,[1,2,4,5,3,1,1,2,-1])
390
sage: B = matrix(QQ,3,2,[1,5,1,2,1,5])
391
sage: A._solve_right_nonsingular_square(B)
392
[ -1/7 -11/7]
393
[ 4/7 23/7]
394
[ 0 0]
395
sage: A._solve_right_nonsingular_square(B, check_rank=False)
396
[ -1/7 -11/7]
397
[ 4/7 23/7]
398
[ 0 0]
399
sage: X = A._solve_right_nonsingular_square(B, check_rank=False)
400
sage: A*X == B
401
True
402
"""
403
D = self.augment(B).echelon_form()
404
return D.matrix_from_columns(range(self.ncols(),D.ncols()))
405
406
407
def pivot_rows(self):
408
"""
409
Return the pivot row positions for this matrix, which are a topmost
410
subset of the rows that span the row space and are linearly
411
independent.
412
413
OUTPUT: a tuple of integers
414
415
EXAMPLES::
416
417
sage: A = matrix(QQ,3,3, [0,0,0,1,2,3,2,4,6]); A
418
[0 0 0]
419
[1 2 3]
420
[2 4 6]
421
sage: A.pivot_rows()
422
(1,)
423
sage: A.pivot_rows() # testing cached value
424
(1,)
425
"""
426
v = self.fetch('pivot_rows')
427
if v is not None:
428
return tuple(v)
429
v = self.transpose().pivots()
430
self.cache('pivot_rows', v)
431
return v
432
433
def _solve_right_general(self, B, check=True):
434
r"""
435
This is used internally by the ``solve_right`` command
436
to solve for self\*X = B when self is not square or not of full
437
rank. It does some linear algebra, then solves a full-rank square
438
system.
439
440
INPUT:
441
442
443
- ``B`` - a matrix
444
445
- ``check`` - bool (default: True); if False, if there
446
is no solution this function will not detect that fact.
447
448
449
OUTPUT: matrix
450
451
EXAMPLES::
452
453
sage: A = matrix(QQ,2,3, [1,2,3,2,4,6]); B = matrix(QQ,2,2, [6, -6, 12, -12])
454
sage: A._solve_right_general(B)
455
[ 6 -6]
456
[ 0 0]
457
[ 0 0]
458
"""
459
pivot_cols = self.pivots()
460
A = self.matrix_from_columns(pivot_cols)
461
pivot_rows = A.pivot_rows()
462
A = A.matrix_from_rows(pivot_rows)
463
X = A.solve_right(B.matrix_from_rows(pivot_rows), check=False)
464
if len(pivot_cols) < self.ncols():
465
# Now we have to put in zeros for the non-pivot ROWS, i.e.,
466
# make a matrix from X with the ROWS of X interspersed with
467
# 0 ROWS.
468
Y = X.new_matrix(self.ncols(), X.ncols())
469
# Put the columns of X into the matrix Y at the pivot_cols positions
470
for i, c in enumerate(pivot_cols):
471
Y.set_row(c, X.row(i))
472
X = Y
473
if check:
474
# Have to check that we actually solved the equation.
475
if self*X != B:
476
raise ValueError, "matrix equation has no solutions"
477
return X
478
479
def prod_of_row_sums(self, cols):
480
r"""
481
Calculate the product of all row sums of a submatrix of `A`
482
for a list of selected columns ``cols``.
483
484
EXAMPLES::
485
486
sage: a = matrix(QQ, 2,2, [1,2,3,2]); a
487
[1 2]
488
[3 2]
489
sage: a.prod_of_row_sums([0,1])
490
15
491
492
Another example::
493
494
sage: a = matrix(QQ, 2,3, [1,2,3,2,5,6]); a
495
[1 2 3]
496
[2 5 6]
497
sage: a.prod_of_row_sums([1,2])
498
55
499
500
AUTHORS:
501
502
- Jaap Spies (2006-02-18)
503
"""
504
cdef Py_ssize_t c, row
505
pr = 1
506
for row from 0 <= row < self._nrows:
507
tmp = []
508
for c in cols:
509
# if c<0 or c >= self._ncols:
510
# raise IndexError, "matrix column index out of range"
511
tmp.append(self.get_unsafe(row, c))
512
pr = pr * sum(tmp)
513
return pr
514
515
def elementwise_product(self, right):
516
r"""
517
Returns the elementwise product of two matrices
518
of the same size (also known as the Hadamard product).
519
520
INPUT:
521
522
- ``right`` - the right operand of the product. A matrix
523
of the same size as ``self`` such that multiplication
524
of elements of the base rings of ``self`` and ``right``
525
is defined, once Sage's coercion model is applied. If
526
the matrices have different sizes, or if multiplication
527
of individual entries cannot be achieved, a ``TypeError``
528
will result.
529
530
OUTPUT:
531
532
A matrix of the same size as ``self`` and ``right``. The
533
entry in location `(i,j)` of the output is the product of
534
the two entries in location `(i,j)` of ``self`` and
535
``right`` (in that order).
536
537
The parent of the result is determined by Sage's coercion
538
model. If the base rings are identical, then the result
539
is dense or sparse according to this property for
540
the left operand. If the base rings must be adjusted
541
for one, or both, matrices then the result will be sparse
542
only if both operands are sparse. No subdivisions are
543
present in the result.
544
545
If the type of the result is not to your liking, or
546
the ring could be "tighter," adjust the operands with
547
:meth:`~sage.matrix.matrix0.Matrix.change_ring`.
548
Adjust sparse versus dense inputs with the methods
549
:meth:`~sage.matrix.matrix1.Matrix.sparse_matrix` and
550
:meth:`~sage.matrix.matrix1.Matrix.dense_matrix`.
551
552
EXAMPLES::
553
554
sage: A = matrix(ZZ, 2, range(6))
555
sage: B = matrix(QQ, 2, [5, 1/3, 2/7, 11/2, -3/2, 8])
556
sage: C = A.elementwise_product(B)
557
sage: C
558
[ 0 1/3 4/7]
559
[33/2 -6 40]
560
sage: C.parent()
561
Full MatrixSpace of 2 by 3 dense matrices over Rational Field
562
563
564
Notice the base ring of the results in the next two examples. ::
565
566
sage: D = matrix(ZZ[x],2,[1+x^2,2,3,4-x])
567
sage: E = matrix(QQ,2,[1,2,3,4])
568
sage: F = D.elementwise_product(E)
569
sage: F
570
[ x^2 + 1 4]
571
[ 9 -4*x + 16]
572
sage: F.parent()
573
Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Rational Field
574
575
::
576
577
sage: G = matrix(GF(3),2,[0,1,2,2])
578
sage: H = matrix(ZZ,2,[1,2,3,4])
579
sage: J = G.elementwise_product(H)
580
sage: J
581
[0 2]
582
[0 2]
583
sage: J.parent()
584
Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 3
585
586
Non-commutative rings behave as expected. These are the usual quaternions. ::
587
588
sage: R.<i,j,k> = QuaternionAlgebra(-1, -1)
589
sage: A = matrix(R, 2, [1,i,j,k])
590
sage: B = matrix(R, 2, [i,i,i,i])
591
sage: A.elementwise_product(B)
592
[ i -1]
593
[-k j]
594
sage: B.elementwise_product(A)
595
[ i -1]
596
[ k -j]
597
598
Input that is not a matrix will raise an error. ::
599
600
sage: A = random_matrix(ZZ,5,10,x=20)
601
sage: A.elementwise_product(vector(ZZ, [1,2,3,4]))
602
Traceback (most recent call last):
603
...
604
TypeError: operand must be a matrix, not an element of Ambient free module of rank 4 over the principal ideal domain Integer Ring
605
606
Matrices of different sizes for operands will raise an error. ::
607
608
sage: A = random_matrix(ZZ,5,10,x=20)
609
sage: B = random_matrix(ZZ,10,5,x=40)
610
sage: A.elementwise_product(B)
611
Traceback (most recent call last):
612
...
613
TypeError: incompatible sizes for matrices from: Full MatrixSpace of 5 by 10 dense matrices over Integer Ring and Full MatrixSpace of 10 by 5 dense matrices over Integer Ring
614
615
Some pairs of rings do not have a common parent where
616
multiplication makes sense. This will raise an error. ::
617
618
sage: A = matrix(QQ, 3, range(6))
619
sage: B = matrix(GF(3), 3, [2]*6)
620
sage: A.elementwise_product(B)
621
Traceback (most recent call last):
622
...
623
TypeError: no common canonical parent for objects with parents: 'Full MatrixSpace of 3 by 2 dense matrices over Rational Field' and 'Full MatrixSpace of 3 by 2 dense matrices over Finite Field of size 3'
624
625
We illustrate various combinations of sparse and dense matrices.
626
Notice how if base rings are unequal, both operands must be sparse
627
to get a sparse result. ::
628
629
sage: A = matrix(ZZ, 5, range(30), sparse=False)
630
sage: B = matrix(ZZ, 5, range(30), sparse=True)
631
sage: C = matrix(QQ, 5, range(30), sparse=True)
632
sage: A.elementwise_product(C).is_dense()
633
True
634
sage: B.elementwise_product(C).is_sparse()
635
True
636
sage: A.elementwise_product(B).is_dense()
637
True
638
sage: B.elementwise_product(A).is_dense()
639
True
640
641
TESTS:
642
643
Implementation for dense and sparse matrices are
644
different, this will provide a trivial test that
645
they are working identically. ::
646
647
sage: A = random_matrix(ZZ, 10, x=1000, sparse=False)
648
sage: B = random_matrix(ZZ, 10, x=1000, sparse=False)
649
sage: C = A.sparse_matrix()
650
sage: D = B.sparse_matrix()
651
sage: E = A.elementwise_product(B)
652
sage: F = C.elementwise_product(D)
653
sage: E.is_dense() and F.is_sparse() and (E == F)
654
True
655
656
If the ring has zero divisors, the routines for setting
657
entries of a sparse matrix should intercept zero results
658
and not create an entry. ::
659
660
sage: R = Integers(6)
661
sage: A = matrix(R, 2, [3, 2, 0, 0], sparse=True)
662
sage: B = matrix(R, 2, [2, 3, 1, 0], sparse=True)
663
sage: C = A.elementwise_product(B)
664
sage: len(C.nonzero_positions()) == 0
665
True
666
667
AUTHOR:
668
669
- Rob Beezer (2009-07-13)
670
"""
671
# Optimized routines for specialized classes would likely be faster
672
# See the "pairwise_product" of vectors for some guidance on doing this
673
from sage.structure.element import canonical_coercion
674
if not PY_TYPE_CHECK(right, Matrix):
675
raise TypeError('operand must be a matrix, not an element of %s' % right.parent())
676
if (self.nrows() != right.nrows()) or (self.ncols() != right.ncols()):
677
raise TypeError('incompatible sizes for matrices from: %s and %s'%(self.parent(), right.parent()))
678
if self._parent is not (<Matrix>right)._parent:
679
self, right = canonical_coercion(self, right)
680
return self._elementwise_product(right)
681
682
def permanent(self):
683
r"""
684
Calculate and return the permanent of the `m \times n`
685
matrix ``self`` using Ryser's algorithm.
686
687
Let `A = (a_{i,j})` be an `m \times n` matrix over
688
any commutative ring, with `m \le n`. The permanent of
689
`A` is
690
691
.. MATH::
692
693
\mathrm{per}(A)
694
= \sum_\pi a_{1,\pi(1)} a_{2,\pi(2)} \cdots a_{m,\pi(m)}
695
696
where the summation extends over all one-to-one functions
697
`\pi` from `\{1, \ldots, m\}` to
698
`\{1, \ldots, n\}`.
699
700
The product
701
`a_{1,\pi(1)} a_{2,\pi(2)} \cdots a_{m,\pi(m)}` is
702
called diagonal product. So the permanent of an
703
`m \times n` matrix `A` is the sum of all the
704
diagonal products of `A`.
705
706
INPUT:
707
708
- ``A`` -- matrix of size `m \times n` with `m \leq n`
709
710
OUTPUT:
711
712
permanent of the matrix `A`
713
714
ALGORITHM:
715
716
Modification of theorem 7.1.1. from Brualdi and Ryser:
717
Combinatorial Matrix Theory. Instead of deleting columns from
718
`A`, we choose columns from `A` and calculate the
719
product of the row sums of the selected submatrix.
720
721
EXAMPLES::
722
723
sage: M = MatrixSpace(ZZ,4,4)
724
sage: A = M([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1])
725
sage: A.permanent()
726
24
727
728
::
729
730
sage: M = MatrixSpace(QQ,3,6)
731
sage: A = M([1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1])
732
sage: A.permanent()
733
36
734
735
::
736
737
sage: M = MatrixSpace(RR,3,6)
738
sage: A = M([1.0,1.0,1.0,1.0,0,0,0,1.0,1.0,1.0,1.0,0,0,0,1.0,1.0,1.0,1.0])
739
sage: A.permanent()
740
36.0000000000000
741
742
See Sloane's sequence OEIS A079908(3) = 36, "The Dancing School
743
Problems"
744
745
::
746
747
sage: oeis(79908) # optional -- internet
748
A079908: Solution to the Dancing School Problem with 3 girls and n+3 boys: f(3,n).
749
sage: _(3) # optional -- internet
750
36
751
752
::
753
754
sage: M = MatrixSpace(ZZ,4,5)
755
sage: A = M([1,1,0,1,1,0,1,1,1,1,1,0,1,0,1,1,1,0,1,0])
756
sage: A.permanent()
757
32
758
759
See Minc: Permanents, Example 2.1, p. 5.
760
761
::
762
763
sage: M = MatrixSpace(QQ,2,2)
764
sage: A = M([1/5,2/7,3/2,4/5])
765
sage: A.permanent()
766
103/175
767
768
::
769
770
sage: R.<a> = PolynomialRing(ZZ)
771
sage: A = MatrixSpace(R,2)([[a,1], [a,a+1]])
772
sage: A.permanent()
773
a^2 + 2*a
774
775
::
776
777
sage: R.<x,y> = PolynomialRing(ZZ,2)
778
sage: A = MatrixSpace(R,2)([x, y, x^2, y^2])
779
sage: A.permanent()
780
x^2*y + x*y^2
781
782
AUTHORS:
783
784
- Jaap Spies (2006-02-16)
785
786
- Jaap Spies (2006-02-21): added definition of permanent
787
"""
788
cdef Py_ssize_t m, n, r
789
cdef int sn
790
791
perm = 0
792
m = self._nrows
793
n = self._ncols
794
if not m <= n:
795
raise ValueError, "must have m <= n, but m (=%s) and n (=%s)"%(m,n)
796
797
for r from 1 <= r < m+1:
798
lst = _choose(n, r)
799
tmp = []
800
for cols in lst:
801
tmp.append(self.prod_of_row_sums(cols))
802
s = sum(tmp)
803
# sn = (-1)^(m-r)
804
if (m - r) % 2 == 0:
805
sn = 1
806
else:
807
sn = -1
808
perm = perm + sn * _binomial(n-r, m-r) * s
809
return perm
810
811
812
def permanental_minor(self, Py_ssize_t k):
813
r"""
814
Return the permanental `k`-minor of an `m \times n` matrix.
815
816
This is the sum of the permanents of all possible `k` by
817
`k` submatrices of `A`.
818
819
See Brualdi and Ryser: Combinatorial Matrix Theory, p. 203. Note
820
the typo `p_0(A) = 0` in that reference! For applications
821
see Theorem 7.2.1 and Theorem 7.2.4.
822
823
Note that the permanental `m`-minor equals
824
`\mathrm{per}(A)` if `m = n`.
825
826
For a (0,1)-matrix `A` the permanental `k`-minor
827
counts the number of different selections of `k` 1's of
828
`A` with no two of the 1's on the same row and no two of the
829
1's on the same column.
830
831
INPUT:
832
833
- ``self`` -- matrix of size `m \times n` with `m \leq n`
834
835
OUTPUT:
836
837
The permanental `k`-minor of the matrix ``self``.
838
839
EXAMPLES::
840
841
sage: M = MatrixSpace(ZZ,4,4)
842
sage: A = M([1,0,1,0,1,0,1,0,1,0,10,10,1,0,1,1])
843
sage: A.permanental_minor(2)
844
114
845
846
::
847
848
sage: M = MatrixSpace(ZZ,3,6)
849
sage: A = M([1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1])
850
sage: A.permanental_minor(0)
851
1
852
sage: A.permanental_minor(1)
853
12
854
sage: A.permanental_minor(2)
855
40
856
sage: A.permanental_minor(3)
857
36
858
859
Note that if `k = m = n`, the permanental `k`-minor equals
860
`\mathrm{per}(A)`::
861
862
sage: A.permanent()
863
36
864
865
::
866
867
sage: A.permanental_minor(5)
868
0
869
870
For `C` the "complement" of `A`::
871
872
sage: M = MatrixSpace(ZZ,3,6)
873
sage: C = M([0,0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0])
874
sage: m, n = 3, 6
875
sage: sum([(-1)^k * C.permanental_minor(k)*factorial(n-k)/factorial(n-m) for k in range(m+1)])
876
36
877
878
See Theorem 7.2.1 of Brualdi and Ryser: Combinatorial Matrix
879
Theory: per(A)
880
881
AUTHORS:
882
883
- Jaap Spies (2006-02-19)
884
"""
885
m = self._nrows
886
n = self._ncols
887
if not m <= n:
888
raise ValueError("must have m <= n, but m (=%s) and n (=%s)"%(m,n))
889
890
R = self._base_ring
891
if k == 0:
892
return R.one()
893
if k > m:
894
return R.zero()
895
896
pm = 0
897
for cols in _choose(n,k):
898
for rows in _choose(m,k):
899
pm = pm + self.matrix_from_rows_and_columns(rows, cols).permanent()
900
return pm
901
902
903
def rook_vector(self, check = False):
904
r"""
905
Return the rook vector of the matrix ``self``.
906
907
Let `A` be an `m` by `n` (0,1)-matrix with `m \le n`. We identify
908
`A` with a chessboard where rooks can be placed on the fields
909
`(i, j)` with `a_{i,j} = 1`. The number
910
`r_k = p_k(A)` (the permanental `k`-minor) counts the number of
911
ways to place `k` rooks on this board so that no rook can attack
912
another.
913
914
The rook vector of the matrix `A` is the list consisting of
915
`r_0, r_1, \ldots, r_m`.
916
917
The rook polynomial is defined by
918
`r(x) = \sum_{k=0}^m r_k x^k`.
919
920
INPUT:
921
922
- ``self`` -- an `m` by `n` (0,1)-matrix with `m \le n`
923
924
- ``check`` -- Boolean (default: ``False``) determining whether
925
to check that ``self`` is a (0,1)-matrix.
926
927
OUTPUT:
928
929
The rook vector of the matrix ``self``.
930
931
EXAMPLES::
932
933
sage: M = MatrixSpace(ZZ,3,6)
934
sage: A = M([1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1])
935
sage: A.rook_vector()
936
[1, 12, 40, 36]
937
938
::
939
940
sage: R.<x> = PolynomialRing(ZZ)
941
sage: rv = A.rook_vector()
942
sage: rook_polynomial = sum([rv[k] * x^k for k in range(len(rv))])
943
sage: rook_polynomial
944
36*x^3 + 40*x^2 + 12*x + 1
945
946
AUTHORS:
947
948
- Jaap Spies (2006-02-24)
949
"""
950
m = self._nrows
951
n = self._ncols
952
if not m <= n:
953
raise ValueError, "must have m <= n, but m (=%s) and n (=%s)"%(m,n)
954
955
if check:
956
# verify that self[i, j] in {0, 1}
957
for i in range(m):
958
for j in range(n):
959
x = self.get_unsafe(i, j)
960
if not (x == 0 or x == 1):
961
raise ValueError, "must have zero or one, but we have (=%s)"%x
962
963
tmp = []
964
for k in range(m+1):
965
tmp.append(self.permanental_minor(k))
966
return tmp
967
968
def minors(self,k):
969
r"""
970
Return the list of all `k \times k` minors of self.
971
972
Let `A` be an `m \times n` matrix and `k` an integer with
973
`0 \leq k`, `k \leq m` and `k \leq n`.
974
A `k \times k` minor of `A` is the determinant of a
975
`k \times k` matrix obtained from `A` by deleting `m - k`
976
rows and `n - k` columns.
977
There are no `k \times k` minors of `A` if `k` is larger
978
than either `m` or `n`.
979
980
The returned list is sorted in lexicographical row major ordering,
981
e.g., if A is a `3 \times 3` matrix then the minors returned are
982
with these rows/columns: [ [0, 1]x[0, 1], [0, 1]x[0, 2], [0, 1]x[1, 2],
983
[0, 2]x[0, 1], [0, 2]x[0, 2], [0, 2]x[1, 2], [1, 2]x[0, 1], [1,
984
2]x[0, 2], [1, 2]x[1, 2] ].
985
986
INPUT:
987
988
- ``k`` -- integer
989
990
EXAMPLES::
991
992
sage: A = Matrix(ZZ,2,3,[1,2,3,4,5,6]); A
993
[1 2 3]
994
[4 5 6]
995
sage: A.minors(2)
996
[-3, -6, -3]
997
sage: A.minors(1)
998
[1, 2, 3, 4, 5, 6]
999
sage: A.minors(0)
1000
[1]
1001
sage: A.minors(5)
1002
[]
1003
1004
::
1005
1006
sage: k = GF(37)
1007
sage: P.<x0,x1,x2> = PolynomialRing(k)
1008
sage: A = Matrix(P,2,3,[x0*x1, x0, x1, x2, x2 + 16, x2 + 5*x1 ])
1009
sage: A.minors(2)
1010
[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]
1011
"""
1012
from sage.combinat.combination import Combinations
1013
all_rows = range(self.nrows())
1014
all_cols = range(self.ncols())
1015
m = []
1016
for rows in Combinations(all_rows,k):
1017
for cols in Combinations(all_cols,k):
1018
m.append(self.matrix_from_rows_and_columns(rows,cols).determinant())
1019
return m
1020
1021
def determinant(self, algorithm=None):
1022
r"""
1023
Returns the determinant of self.
1024
1025
ALGORITHM:
1026
1027
For small matrices (n less than 4), this is computed using the naive
1028
formula. In the specific case of matrices over the integers modulo a
1029
non-prime, the determinant of a lift is computed over the integers.
1030
In general, the characteristic polynomial is computed either using
1031
the Hessenberg form (specified by ``"hessenberg"``) or the generic
1032
division-free algorithm (specified by ``"df"``). When the base ring
1033
is an exact field, the default choice is ``"hessenberg"``, otherwise
1034
it is ``"df"``. Note that for matrices over most rings, more
1035
sophisticated algorithms can be used. (Type ``A.determinant?`` to
1036
see what is done for a specific matrix ``A``.)
1037
1038
INPUT:
1039
1040
- ``algorithm`` - string:
1041
- ``"df"`` - Generic O(n^4) division-free algorithm
1042
- ``"hessenberg"`` - Use the Hessenberg form of the matrix
1043
1044
EXAMPLES::
1045
1046
sage: A = MatrixSpace(Integers(8),3)([1,7,3, 1,1,1, 3,4,5])
1047
sage: A.determinant()
1048
6
1049
sage: A.determinant() is A.determinant()
1050
True
1051
sage: A[0,0] = 10
1052
sage: A.determinant()
1053
7
1054
1055
We compute the determinant of the arbitrary 3x3 matrix::
1056
1057
sage: R = PolynomialRing(QQ,9,'x')
1058
sage: A = matrix(R,3,R.gens())
1059
sage: A
1060
[x0 x1 x2]
1061
[x3 x4 x5]
1062
[x6 x7 x8]
1063
sage: A.determinant()
1064
-x2*x4*x6 + x1*x5*x6 + x2*x3*x7 - x0*x5*x7 - x1*x3*x8 + x0*x4*x8
1065
1066
We create a matrix over `\ZZ[x,y]` and compute its
1067
determinant.
1068
1069
::
1070
1071
sage: R.<x,y> = PolynomialRing(IntegerRing(),2)
1072
sage: A = MatrixSpace(R,2)([x, y, x**2, y**2])
1073
sage: A.determinant()
1074
-x^2*y + x*y^2
1075
1076
TESTS::
1077
1078
sage: A = matrix(5, 5, [next_prime(i^2) for i in range(25)])
1079
sage: B = MatrixSpace(ZZ['x'], 5, 5)(A)
1080
sage: A.det() - B.det()
1081
0
1082
1083
We verify that :trac:`5569` is resolved (otherwise the following
1084
would hang for hours)::
1085
1086
sage: d = random_matrix(GF(next_prime(10^20)),50).det()
1087
sage: d = random_matrix(Integers(10^50),50).det()
1088
1089
We verify that trac 7704 is resolved::
1090
1091
sage: matrix(ZZ, {(0,0):1,(1,1):2,(2,2):3,(3,3):4}).det()
1092
24
1093
sage: matrix(QQ, {(0,0):1,(1,1):2,(2,2):3,(3,3):4}).det()
1094
24
1095
1096
We verify that trac 10063 is resolved::
1097
1098
sage: A = GF(2)['x,y,z']
1099
sage: A.inject_variables()
1100
Defining x, y, z
1101
sage: R = A.quotient(x^2 + 1).quotient(y^2 + 1).quotient(z^2 + 1)
1102
sage: R.inject_variables()
1103
Defining xbarbarbar, ybarbarbar, zbarbarbar
1104
sage: M = matrix([[1,1,1,1],[xbarbarbar,ybarbarbar,1,1],[0,1,zbarbarbar,1],[xbarbarbar,zbarbarbar,1,1]])
1105
sage: M.determinant()
1106
xbarbarbar*ybarbarbar*zbarbarbar + xbarbarbar*ybarbarbar + xbarbarbar*zbarbarbar + ybarbarbar*zbarbarbar + xbarbarbar + ybarbarbar + zbarbarbar + 1
1107
1108
Check that the determinant is computed from a cached charpoly
1109
properly::
1110
1111
sage: A = matrix(RR, [ [1, 0, 1/2],
1112
... [0, 1, 0 ],
1113
... [0, 0, -2 ] ])
1114
sage: B = copy(A)
1115
sage: _ = A.charpoly()
1116
sage: A.determinant() == B.determinant()
1117
True
1118
1119
AUTHORS:
1120
1121
- Unknown: No author specified in the file from 2009-06-25
1122
- Sebastian Pancratz (2009-06-25): Use the division-free
1123
algorithm for charpoly
1124
- Thierry Monteil (2010-10-05): Bugfix for trac ticket #10063,
1125
so that the determinant is computed even for rings for which
1126
the is_field method is not implemented.
1127
"""
1128
1129
from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing
1130
1131
if self._nrows != self._ncols:
1132
raise ValueError, "self must be a square matrix"
1133
1134
d = self.fetch('det')
1135
if not d is None:
1136
return d
1137
1138
# If charpoly known, then det is easy.
1139
f = self.fetch('charpoly')
1140
if f is not None:
1141
c = f[0]
1142
if self._nrows % 2 != 0:
1143
c = -c
1144
d = self._coerce_element(c)
1145
self.cache('det', d)
1146
return d
1147
1148
cdef Py_ssize_t n
1149
n = self._ncols
1150
R = self._base_ring
1151
1152
# For small matrices, you can't beat the naive formula.
1153
if n <= 3:
1154
if n == 0:
1155
d = R(1)
1156
elif n == 1:
1157
d = self.get_unsafe(0,0)
1158
elif n == 2:
1159
d = self.get_unsafe(0,0)*self.get_unsafe(1,1) - self.get_unsafe(1,0)*self.get_unsafe(0,1)
1160
elif n == 3:
1161
d = self.get_unsafe(0,0) * (self.get_unsafe(1,1)*self.get_unsafe(2,2) - self.get_unsafe(1,2)*self.get_unsafe(2,1)) \
1162
- self.get_unsafe(1,0) * (self.get_unsafe(0,1)*self.get_unsafe(2,2) - self.get_unsafe(0,2)*self.get_unsafe(2,1)) \
1163
+ self.get_unsafe(2,0) * (self.get_unsafe(0,1)*self.get_unsafe(1,2) - self.get_unsafe(0,2)*self.get_unsafe(1,1))
1164
self.cache('det', d)
1165
return d
1166
1167
# Special case for Z/nZ or GF(p):
1168
if is_IntegerModRing(R) and self.is_dense():
1169
import sys
1170
# If the characteristic is prime and smaller than a machine
1171
# word, use PARI.
1172
ch = R.characteristic()
1173
if ch.is_prime() and ch < (2*sys.maxint):
1174
d = R(self._pari_().matdet())
1175
else:
1176
# Lift to ZZ and compute there.
1177
d = R(self.apply_map(lambda x : x.centerlift()).det())
1178
self.cache('det', d)
1179
return d
1180
1181
# N.B. The following comment should be obsolete now that the generic
1182
# code to compute the determinant has been replaced by generic
1183
# division-free code to compute the characteristic polynomial and read
1184
# off the determinant from this.
1185
#
1186
# If R is an exact integral domain, we could get the det by computing
1187
# charpoly. The generic fraction field implementation is so slow that
1188
# the naive algorithm is much faster in practice despite
1189
# asymptotics.
1190
# TODO: Find a reasonable cutoff point. (This is field specific, but
1191
# seems to be quite large for Q[x].)
1192
if algorithm is None:
1193
try:
1194
R_is_field_attempt = R.is_field()
1195
except NotImplementedError:
1196
R_is_field_attempt = False
1197
if (algorithm is None and R_is_field_attempt and R.is_exact()) or (algorithm == "hessenberg"):
1198
try:
1199
c = self.charpoly('x', algorithm="hessenberg")[0]
1200
except ValueError:
1201
# Hessenberg algorithm not supported, so we use whatever the default algorithm is.
1202
c = self.charpoly('x')[0]
1203
if self._nrows % 2:
1204
c = -c
1205
d = self._coerce_element(c)
1206
self.cache('det', d)
1207
return d
1208
1209
# Generic division-free algorithm to compute the characteristic
1210
# polynomial.
1211
#
1212
# N.B. The case of symbolic rings is quite specific. It would be
1213
# nice to avoid hardcoding a reserved variable name as below, as this
1214
# is then assumed to not be a variable in the symbolic ring. But this
1215
# resulted in further exceptions/ errors.
1216
from sage.symbolic.ring import is_SymbolicExpressionRing
1217
1218
var = R('A0123456789') if is_SymbolicExpressionRing(R) else 'x'
1219
try:
1220
c = self.charpoly(var, algorithm="df")[0]
1221
except ValueError:
1222
# Division free algorithm not supported, so we use whatever the default algorithm is.
1223
c = self.charpoly(var)[0]
1224
1225
if self._nrows % 2:
1226
c = -c
1227
d = self._coerce_element(c)
1228
self.cache('det', d)
1229
return d
1230
1231
cdef _det_by_minors(self, Py_ssize_t level):
1232
"""
1233
Compute the determinant of the upper-left level x level submatrix
1234
of self. Does not handle degenerate cases, level MUST be >= 2
1235
"""
1236
cdef Py_ssize_t n, i
1237
if level == 2:
1238
return self.get_unsafe(0,0) * self.get_unsafe(1,1) - self.get_unsafe(0,1) * self.get_unsafe(1,0)
1239
else:
1240
level -= 1
1241
d = self.get_unsafe(level,level) * self._det_by_minors(level)
1242
# on each iteration, row i will be missing in the first (level) rows
1243
# swapping is much faster than taking submatrices
1244
for i from level > i >= 0:
1245
self.swap_rows(level, i)
1246
if (level - i) % 2:
1247
d -= self.get_unsafe(level,level) * self._det_by_minors(level)
1248
else:
1249
d += self.get_unsafe(level,level) * self._det_by_minors(level)
1250
# undo all our permutations to get us back to where we started
1251
for i from 0 <= i < level:
1252
self.swap_rows(level, i)
1253
return d
1254
1255
def pfaffian(self, algorithm=None, check=True):
1256
r"""
1257
Return the Pfaffian of ``self``, assuming that ``self`` is an
1258
alternating matrix.
1259
1260
INPUT:
1261
1262
- ``algorithm`` -- string, the algorithm to use; currently the
1263
following algorithms have been implemented:
1264
1265
* ``'definition'`` - using the definition given by perfect
1266
matchings
1267
1268
- ``check`` (default: ``True``) -- Boolean determining whether to
1269
check ``self`` for alternatingness and squareness. This has to
1270
be set to ``False`` if ``self`` is defined over a non-discrete
1271
ring.
1272
1273
The Pfaffian of an alternating matrix is defined as follows:
1274
1275
Let `A` be an alternating `k \times k` matrix over a commutative
1276
ring. (Here, "alternating" means that `A^T = -A` and that the
1277
diagonal entries of `A` are zero.)
1278
If `k` is odd, then the Pfaffian of the matrix `A` is
1279
defined to be `0`. Let us now define it when `k` is even. In this
1280
case, set `n = k/2` (this is an integer). For every `i` and `j`,
1281
we denote the `(i, j)`-th entry of `A` by `a_{i, j}`. Let `M`
1282
denote the set of all perfect matchings of the set
1283
`\{ 1, 2, \ldots, 2n \}` (see
1284
:class:`sage.combinat.perfect_matching.PerfectMatchings` ).
1285
For every matching `m \in M`, define the sign `\mathrm{sign}(m)`
1286
of `m` by writing `m` as `\{ \{ i_1, j_1 \}, \{ i_2, j_2 \},
1287
\ldots, \{ i_n, j_n \} \}` with `i_k < j_k` for all `k`, and
1288
setting `\mathrm{sign}(m)` to be the sign of the permutation
1289
`( i_1, j_1, i_2, j_2, \ldots, i_n, j_n )` (written here in
1290
one-line notation). For every matching `m \in M`, define the
1291
weight `w(m)` of `m` by writing `m` as
1292
`\{ \{ i_1, j_1 \}, \{ i_2, j_2 \}, \ldots, \{ i_n, j_n \} \}`
1293
with `i_k < j_k` for all `k`, and setting
1294
`w(m) = a_{i_1, j_1} a_{i_2, j_2} \cdots a_{i_n, j_n}`. Now, the
1295
Pfaffian of the matrix `A` is defined to be the sum
1296
1297
.. MATH::
1298
1299
\sum_{m \in M} \mathrm{sign}(m) w(m).
1300
1301
The Pfaffian of `A` is commonly denoted by `\mathrm{Pf}(A)`. It
1302
is well-known that `(\mathrm{Pf}(A))^2 = \det A` for every
1303
alternating matrix `A`, and that
1304
`\mathrm{Pf} (U^T A U) = \det U \cdot \mathrm{Pf}(A)` for any
1305
`n \times n` matrix `U` and any alternating `n \times n`
1306
matrix `A`.
1307
1308
See [Kn95]_, [DW95]_ and [Rote2001]_, just to name three
1309
sources, for further properties of Pfaffians.
1310
1311
ALGORITHM:
1312
1313
The current implementation uses the definition given above.
1314
It checks alternatingness of the matrix ``self`` only if
1315
``check`` is ``True`` (this is important because even if ``self``
1316
is alternating, a non-discrete base ring might prevent Sage
1317
from being able to check this).
1318
1319
REFERENCES:
1320
1321
.. [Kn95] Donald E. Knuth, *Overlapping Pfaffians*,
1322
:arxiv:`math/9503234v1`.
1323
1324
.. [Rote2001] Gunter Rote,
1325
*Division-Free Algorithms for the Determinant and the
1326
Pfaffian: Algebraic and Combinatorial Approaches*,
1327
H. Alt (Ed.): Computational Discrete Mathematics, LNCS
1328
2122, pp. 119–135, 2001.
1329
http://page.mi.fu-berlin.de/rote/Papers/pdf/Division-free+algorithms.pdf
1330
1331
.. [DW95] Andreas W.M. Dress, Walter Wenzel,
1332
*A Simple Proof of an Identity Concerning Pfaffians of
1333
Skew Symmetric Matrices*,
1334
Advances in Mathematics, volume 112, Issue 1, April
1335
1995, pp. 120-134.
1336
http://www.sciencedirect.com/science/article/pii/S0001870885710298
1337
1338
.. TODO::
1339
1340
Implement faster algorithms, including a division-free one.
1341
Does [Rote2001]_, section 3.3 give one?
1342
1343
Check the implementation of the matchings used here for
1344
performance?
1345
1346
EXAMPLES:
1347
1348
A `3 \times 3` alternating matrix has Pfaffian 0 independently
1349
of its entries::
1350
1351
sage: MSp = MatrixSpace(Integers(27), 3)
1352
sage: A = MSp([0, 2, -3, -2, 0, 8, 3, -8, 0])
1353
sage: A.pfaffian()
1354
0
1355
sage: parent(A.pfaffian())
1356
Ring of integers modulo 27
1357
1358
The Pfaffian of a `2 \times 2` alternating matrix is just its
1359
northeast entry::
1360
1361
sage: MSp = MatrixSpace(QQ, 2)
1362
sage: A = MSp([0, 4, -4, 0])
1363
sage: A.pfaffian()
1364
4
1365
sage: parent(A.pfaffian())
1366
Rational Field
1367
1368
The Pfaffian of a `0 \times 0` alternating matrix is `1`::
1369
1370
sage: MSp = MatrixSpace(ZZ, 0)
1371
sage: A = MSp([])
1372
sage: A.pfaffian()
1373
1
1374
sage: parent(A.pfaffian())
1375
Integer Ring
1376
1377
Let us compute the Pfaffian of a generic `4 \times 4`
1378
alternating matrix::
1379
1380
sage: R = PolynomialRing(QQ, 'x12,x13,x14,x23,x24,x34')
1381
sage: x12, x13, x14, x23, x24, x34 = R.gens()
1382
sage: A = matrix(R, [[ 0, x12, x13, x14],
1383
....: [-x12, 0, x23, x24],
1384
....: [-x13, -x23, 0, x34],
1385
....: [-x14, -x24, -x34, 0]])
1386
sage: A.pfaffian()
1387
x14*x23 - x13*x24 + x12*x34
1388
sage: parent(A.pfaffian())
1389
Multivariate Polynomial Ring in x12, x13, x14, x23, x24, x34 over Rational Field
1390
1391
The Pfaffian of an alternating matrix squares to its
1392
determinant::
1393
1394
sage: A = [[0] * 6 for i in range(6)]
1395
sage: for i in range(6):
1396
....: for j in range(i):
1397
....: u = floor(random() * 10)
1398
....: A[i][j] = u
1399
....: A[j][i] = -u
1400
....: A[i][i] = 0
1401
sage: AA = Matrix(ZZ, A)
1402
sage: AA.pfaffian() ** 2 == AA.det()
1403
True
1404
1405
AUTHORS:
1406
1407
- Darij Grinberg (1 Oct 2013): first (slow)
1408
implementation.
1409
"""
1410
k = self._nrows
1411
1412
if check:
1413
if k != self._ncols:
1414
raise ValueError("self must be a square matrix")
1415
if not self.is_alternating():
1416
raise ValueError("self must be alternating, which includes the diagonal entries being 0")
1417
1418
R = self.base_ring()
1419
1420
if k % 2 == 1:
1421
return R.zero()
1422
1423
if k == 0:
1424
return R.one()
1425
1426
n = k // 2
1427
1428
res = R.zero()
1429
1430
from sage.combinat.perfect_matching import PerfectMatchings
1431
from sage.misc.flatten import flatten
1432
from sage.misc.misc_c import prod
1433
from sage.combinat.permutation import Permutation
1434
for m in PerfectMatchings(k):
1435
# We only need each edge of the matching to be sorted,
1436
# not the totality of edges.
1437
edges = [sorted(edge) for edge in list(m)]
1438
sgn = Permutation(flatten(edges)).sign()
1439
# Subtract 1 from everything for indexing purposes:
1440
edges2 = [[i-1 for i in edge] for edge in edges]
1441
# Product without base case since k == 0 case has
1442
# already been dealt with:
1443
res += sgn * prod([self.get_unsafe(edge[0], edge[1]) for edge in edges2])
1444
1445
return res
1446
1447
# shortcuts
1448
def det(self, *args, **kwds):
1449
"""
1450
Synonym for self.determinant(...).
1451
1452
EXAMPLES::
1453
1454
sage: A = MatrixSpace(Integers(8),3)([1,7,3, 1,1,1, 3,4,5])
1455
sage: A.det()
1456
6
1457
"""
1458
return self.determinant(*args, **kwds)
1459
1460
def __abs__(self):
1461
"""
1462
Synonym for self.determinant(...).
1463
1464
EXAMPLES::
1465
1466
sage: a = matrix(QQ, 2,2, [1,2,3,4]); a
1467
[1 2]
1468
[3 4]
1469
sage: abs(a)
1470
-2
1471
"""
1472
return self.determinant()
1473
1474
def characteristic_polynomial(self, *args, **kwds):
1475
"""
1476
Synonym for self.charpoly(...).
1477
1478
EXAMPLES::
1479
1480
sage: a = matrix(QQ, 2,2, [1,2,3,4]); a
1481
[1 2]
1482
[3 4]
1483
sage: a.characteristic_polynomial('T')
1484
T^2 - 5*T - 2
1485
"""
1486
return self.charpoly(*args, **kwds)
1487
1488
def minimal_polynomial(self, var='x', **kwds):
1489
r"""
1490
This is a synonym for ``self.minpoly``
1491
1492
EXAMPLES::
1493
1494
sage: a = matrix(QQ, 4, range(16))
1495
sage: a.minimal_polynomial('z')
1496
z^3 - 30*z^2 - 80*z
1497
sage: a.minpoly()
1498
x^3 - 30*x^2 - 80*x
1499
"""
1500
return self.minpoly(var, **kwds)
1501
1502
def minpoly(self, var='x', **kwds):
1503
r"""
1504
Return the minimal polynomial of self.
1505
1506
This uses a simplistic - and potentially very very slow - algorithm
1507
that involves computing kernels to determine the powers of the
1508
factors of the charpoly that divide the minpoly.
1509
1510
EXAMPLES::
1511
1512
sage: A = matrix(GF(9,'c'), 4, [1, 1, 0,0, 0,1,0,0, 0,0,5,0, 0,0,0,5])
1513
sage: factor(A.minpoly())
1514
(x + 1) * (x + 2)^2
1515
sage: A.minpoly()(A) == 0
1516
True
1517
sage: factor(A.charpoly())
1518
(x + 1)^2 * (x + 2)^2
1519
1520
The default variable name is `x`, but you can specify
1521
another name::
1522
1523
sage: factor(A.minpoly('y'))
1524
(y + 1) * (y + 2)^2
1525
1526
We can take the minimal polynomial of symbolic matrices::
1527
1528
sage: t = var('t')
1529
sage: m = matrix(2,[1,2,4,t])
1530
sage: m.minimal_polynomial()
1531
x^2 + (-t - 1)*x + t - 8
1532
"""
1533
f = self.fetch('minpoly')
1534
if not f is None:
1535
return f.change_variable_name(var)
1536
f = self.charpoly(var=var, **kwds)
1537
if f.is_squarefree(): # is_squarefree for polys much faster than factor.
1538
# Then f must be the minpoly
1539
self.cache('minpoly', f)
1540
return f
1541
1542
# Now we have to work harder. We find the power of each
1543
# irreducible factor that divides the minpoly.
1544
mp = f.radical()
1545
for h, e in f.factor():
1546
if e > 1:
1547
# Find the power of B so that the dimension
1548
# of the kernel equals e*deg(h)
1549
B = h(self) # this is the killer.
1550
C = B
1551
n = 1
1552
while C.kernel().dimension() < e*h.degree():
1553
if n == e - 1:
1554
n += 1
1555
break
1556
C *= B
1557
n += 1
1558
mp *= h**(n-1)
1559
self.cache('minpoly', mp)
1560
return mp
1561
1562
def charpoly(self, var = 'x', algorithm = None):
1563
r"""
1564
Returns the characteristic polynomial of self, as a polynomial over
1565
the base ring.
1566
1567
ALGORITHM:
1568
1569
In the generic case of matrices over a ring (commutative and with
1570
unity), there is a division-free algorithm, which can be accessed
1571
using ``"df"``, with complexity `O(n^4)`. Alternatively, by
1572
specifying ``"hessenberg"``, this method computes the Hessenberg
1573
form of the matrix and then reads off the characteristic polynomial.
1574
Moreover, for matrices over number fields, this method can use
1575
PARI's charpoly implementation instead.
1576
1577
The method's logic is as follows: If no algorithm is specified,
1578
first check if the base ring is a number field (and then use PARI),
1579
otherwise check if the base ring is the ring of integers modulo n (in
1580
which case compute the characteristic polynomial of a lift of the
1581
matrix to the integers, and then coerce back to the base), next check
1582
if the base ring is an exact field (and then use the Hessenberg form),
1583
or otherwise, use the generic division-free algorithm.
1584
If an algorithm is specified explicitly, if
1585
``algorithm == "hessenberg"``, use the Hessenberg form, or otherwise
1586
use the generic division-free algorithm.
1587
1588
The result is cached.
1589
1590
INPUT:
1591
1592
- ``var`` - a variable name (default: 'x')
1593
- ``algorithm`` - string:
1594
- ``"df"`` - Generic `O(n^4)` division-free algorithm
1595
- ``"hessenberg"`` - Use the Hessenberg form of the matrix
1596
1597
EXAMPLES:
1598
1599
First a matrix over `\ZZ`::
1600
1601
sage: A = MatrixSpace(ZZ,2)( [1,2, 3,4] )
1602
sage: f = A.charpoly('x')
1603
sage: f
1604
x^2 - 5*x - 2
1605
sage: f.parent()
1606
Univariate Polynomial Ring in x over Integer Ring
1607
sage: f(A)
1608
[0 0]
1609
[0 0]
1610
1611
An example over `\QQ`::
1612
1613
sage: A = MatrixSpace(QQ,3)(range(9))
1614
sage: A.charpoly('x')
1615
x^3 - 12*x^2 - 18*x
1616
sage: A.trace()
1617
12
1618
sage: A.determinant()
1619
0
1620
1621
We compute the characteristic polynomial of a matrix over the
1622
polynomial ring `\ZZ[a]`::
1623
1624
sage: R.<a> = PolynomialRing(ZZ)
1625
sage: M = MatrixSpace(R,2)([a,1, a,a+1]); M
1626
[ a 1]
1627
[ a a + 1]
1628
sage: f = M.charpoly('x'); f
1629
x^2 + (-2*a - 1)*x + a^2
1630
sage: f.parent()
1631
Univariate Polynomial Ring in x over Univariate Polynomial Ring in a over Integer Ring
1632
sage: M.trace()
1633
2*a + 1
1634
sage: M.determinant()
1635
a^2
1636
1637
We compute the characteristic polynomial of a matrix over the
1638
multi-variate polynomial ring `\ZZ[x,y]`::
1639
1640
sage: R.<x,y> = PolynomialRing(ZZ,2)
1641
sage: A = MatrixSpace(R,2)([x, y, x^2, y^2])
1642
sage: f = A.charpoly('x'); f
1643
x^2 + (-y^2 - x)*x - x^2*y + x*y^2
1644
1645
It's a little difficult to distinguish the variables. To fix this,
1646
we temporarily view the indeterminate as `Z`::
1647
1648
sage: with localvars(f.parent(), 'Z'): print f
1649
Z^2 + (-y^2 - x)*Z - x^2*y + x*y^2
1650
1651
We could also compute f in terms of Z from the start::
1652
1653
sage: A.charpoly('Z')
1654
Z^2 + (-y^2 - x)*Z - x^2*y + x*y^2
1655
1656
Here is an example over a number field::
1657
1658
sage: x = QQ['x'].gen()
1659
sage: K.<a> = NumberField(x^2 - 2)
1660
sage: m = matrix(K, [[a-1, 2], [a, a+1]])
1661
sage: m.charpoly('Z')
1662
Z^2 - 2*a*Z - 2*a + 1
1663
sage: m.charpoly('a')(m) == 0
1664
True
1665
1666
Here is an example over a general commutative ring, that is to say,
1667
as of version 4.0.2, SAGE does not even positively determine that
1668
``S`` in the following example is an integral domain. But the
1669
computation of the characteristic polynomial succeeds as follows::
1670
1671
sage: R.<a,b> = QQ[]
1672
sage: S.<x,y> = R.quo((b^3))
1673
sage: A = matrix(S, [[x*y^2,2*x],[2,x^10*y]])
1674
sage: A
1675
[ x*y^2 2*x]
1676
[ 2 x^10*y]
1677
sage: A.charpoly('T')
1678
T^2 + (-x^10*y - x*y^2)*T - 4*x
1679
1680
TESTS::
1681
1682
sage: P.<a,b,c> = PolynomialRing(Rationals())
1683
sage: u = MatrixSpace(P,3)([[0,0,a],[1,0,b],[0,1,c]])
1684
sage: Q.<x> = PolynomialRing(P)
1685
sage: u.charpoly('x')
1686
x^3 - c*x^2 - b*x - a
1687
1688
A test case from :trac:`6442`. Prior to :trac:`12292`, the
1689
call to ``A.det()`` would attempt to use the cached charpoly,
1690
and crash if an empty dictionary was cached. We don't cache
1691
dictionaries anymore, but this test should still pass::
1692
1693
sage: z = Zp(p=5)
1694
sage: A = matrix(z, [ [3 + O(5^1), 4 + O(5^1), 4 + O(5^1)],
1695
... [2*5^2 + O(5^3), 2 + O(5^1), 1 + O(5^1)],
1696
... [5 + O(5^2), 1 + O(5^1), 1 + O(5^1)] ])
1697
sage: A.charpoly(algorithm='hessenberg')
1698
Traceback (most recent call last):
1699
...
1700
ValueError: negative valuation
1701
sage: A.det()
1702
3 + O(5)
1703
1704
The cached polynomial should be independent of the ``var``
1705
argument (:trac:`12292`). We check (indirectly) that the
1706
second call uses the cached value by noting that its result is
1707
not cached::
1708
1709
sage: M = MatrixSpace(RR, 2)
1710
sage: A = M(range(0, 2^2))
1711
sage: type(A)
1712
<type 'sage.matrix.matrix_generic_dense.Matrix_generic_dense'>
1713
sage: A.charpoly('x')
1714
x^2 - 3.00000000000000*x - 2.00000000000000
1715
sage: A.charpoly('y')
1716
y^2 - 3.00000000000000*y - 2.00000000000000
1717
sage: A._cache['charpoly']
1718
x^2 - 3.00000000000000*x - 2.00000000000000
1719
1720
AUTHORS:
1721
1722
- Unknown: No author specified in the file from 2009-06-25
1723
- Sebastian Pancratz (2009-06-25): Include the division-free algorithm
1724
"""
1725
1726
f = self.fetch('charpoly')
1727
if f is not None:
1728
return f.change_variable_name(var)
1729
1730
from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing
1731
1732
if algorithm is None:
1733
R = self._base_ring
1734
if is_NumberField(R):
1735
f = self._charpoly_over_number_field(var)
1736
elif is_IntegerModRing(R):
1737
f = self.lift().charpoly(var).change_ring(R)
1738
elif R.is_field(proof = False) and R.is_exact():
1739
f = self._charpoly_hessenberg(var)
1740
else:
1741
f = self._charpoly_df(var)
1742
else:
1743
if algorithm == "hessenberg":
1744
f = self._charpoly_hessenberg(var)
1745
else:
1746
f = self._charpoly_df(var)
1747
1748
# Cache the result, and return it.
1749
self.cache('charpoly', f)
1750
return f
1751
1752
def _charpoly_df(self, var = 'x'):
1753
r"""
1754
Computes the characteristic polynomial of ``self`` without divisions.
1755
1756
INPUT:
1757
1758
- ``var`` - a variable name (default: ``'x'``)
1759
1760
OUTPUT:
1761
1762
- polynomial - the characteristic polynomial of ``self``
1763
1764
EXAMPLES:
1765
1766
Here is one easy example over the integers to illustrate this::
1767
1768
sage: A = matrix(ZZ, [[1,24],[3,5]])
1769
sage: A
1770
[ 1 24]
1771
[ 3 5]
1772
sage: A._charpoly_df()
1773
x^2 - 6*x - 67
1774
1775
The second example is a matrix over a univariate polynomial ring over the
1776
rationals::
1777
1778
sage: R.<t> = QQ[]
1779
sage: A = matrix(R, [[7*t^2 - t - 9, -1/4*t - 1, -17*t^2 - t + 1], \
1780
[-t^2 + 1/4*t, t^2 + 5/7*t + 3, 1/5*t^2 + \
1781
1662], \
1782
[-2*t - 3, 2*t^2 + 6*t - 1/2, -1/6*t^2]])
1783
sage: A
1784
[ 7*t^2 - t - 9 -1/4*t - 1 -17*t^2 - t + 1]
1785
[ -t^2 + 1/4*t t^2 + 5/7*t + 3 1/5*t^2 + 1662]
1786
[ -2*t - 3 2*t^2 + 6*t - 1/2 -1/6*t^2]
1787
sage: A._charpoly_df()
1788
x^3 + (-47/6*t^2 + 2/7*t + 6)*x^2 + (79/15*t^4 - 13189/420*t^3 -
1789
1884709/560*t^2 - 279501/28*t + 807)*x - 901/30*t^6 - 423/8*t^5 +
1790
11218517/480*t^4 + 2797765/42*t^3 - 12987971/280*t^2 - 5235245/56*t + 2484
1791
1792
Thirdly, an example over a ring which is not an integral domain::
1793
1794
sage: A = matrix(ZZ.quo(12), 3, [5,8,0,10,2,1,8,7,9])
1795
sage: A
1796
[ 5 8 0]
1797
[10 2 1]
1798
[ 8 7 9]
1799
sage: A._charpoly_df()
1800
x^3 + 8*x^2 + 10*x + 1
1801
1802
TESTS::
1803
1804
sage: A = matrix(ZZ, 0, 0)
1805
sage: A
1806
[]
1807
sage: A._charpoly_df()
1808
1
1809
1810
sage: A = matrix(ZZ, 1, 1, [[23]])
1811
sage: A._charpoly_df()
1812
x - 23
1813
1814
NOTES:
1815
1816
The key feature of this implementation is that it is division-free.
1817
This means that it can be used as a generic implementation for any
1818
ring (commutative and with multiplicative identity). The algorithm
1819
is described in full detail as Algorithm 3.1 in [Se02].
1820
1821
Note that there is a missing minus sign in front of the last term in
1822
the penultimate line of Algorithm 3.1.
1823
1824
REFERENCES:
1825
1826
- [Se02] T. R. Seifullin, "Computation of determinants, adjoint
1827
matrices, and characteristic polynomials without division"
1828
1829
AUTHORS:
1830
1831
- Sebastian Pancratz (2009-06-12)
1832
"""
1833
1834
# Validate assertions
1835
#
1836
if not self.is_square():
1837
raise ValueError("self must be a square matrix")
1838
1839
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
1840
1841
# Extract parameters
1842
#
1843
cdef Matrix M = <Matrix> self
1844
n = M._ncols
1845
R = M._base_ring
1846
S = PolynomialRing(R, var)
1847
1848
# Corner cases
1849
# N.B. We already tested for M to be square, hence we do not need to
1850
# test for 0 x n or m x 0 matrices.
1851
#
1852
if n == 0:
1853
return S(1)
1854
1855
# In the notation of Algorithm 3.1,
1856
#
1857
# F Matrix over R such that F[p, t] is the coefficient of X^{t-p}
1858
# in the polynomial $F_t$;
1859
# a List of lists such that a[p, t] is a vector of length t;
1860
# A Matrix over R.
1861
#
1862
# But by looking at the algorithm, we see that in F, a and A we can
1863
# drop the second index t, reducing storage requirements.
1864
#
1865
# N.B. The documentation is still 1-based, although the code, after
1866
# having been ported from Magma to SAGE, is 0-based.
1867
#
1868
from sage.matrix.constructor import matrix
1869
1870
F = [R(0) for i in xrange(n)]
1871
cdef Matrix a = <Matrix> matrix(R, n-1, n)
1872
A = [R(0) for i in xrange(n)]
1873
1874
F[0] = - M.get_unsafe(0, 0)
1875
for t in xrange(1,n):
1876
1877
# Set a(1, t) to be M(<=t, t)
1878
#
1879
for i in xrange(t+1):
1880
a.set_unsafe(0, i, M.get_unsafe(i, t))
1881
1882
# Set A[1, t] to be the (t)th entry in a[1, t]
1883
#
1884
A[0] = M.get_unsafe(t, t)
1885
1886
for p in xrange(1, t):
1887
1888
# Set a(p, t) to the product of M[<=t, <=t] * a(p-1, t)
1889
#
1890
for i in xrange(t+1):
1891
s = R(0)
1892
for j in xrange(t+1):
1893
s = s + M.get_unsafe(i, j) * a.get_unsafe(p-1, j)
1894
a.set_unsafe(p, i, s)
1895
1896
# Set A[p, t] to be the (t)th entry in a[p, t]
1897
#
1898
A[p] = a.get_unsafe(p, t)
1899
1900
# Set A[t, t] to be M[t, <=t] * a(p-1, t)
1901
#
1902
s = R(0)
1903
for j in xrange(t+1):
1904
s = s + M.get_unsafe(t, j) * a.get_unsafe(t-1, j)
1905
A[t] = s
1906
1907
for p in xrange(t+1):
1908
s = F[p]
1909
for k in xrange(p):
1910
s = s - A[k] * F[p-k-1]
1911
F[p] = s - A[p]
1912
1913
X = S.gen(0)
1914
f = X ** n
1915
for p in xrange(n):
1916
f = f + F[p] * X ** (n-1-p)
1917
1918
return f
1919
1920
def _charpoly_over_number_field(self, var='x'):
1921
r"""
1922
Use PARI to compute the characteristic polynomial of self as a
1923
polynomial over the base ring.
1924
1925
EXAMPLES::
1926
1927
sage: x = QQ['x'].gen()
1928
sage: K.<a> = NumberField(x^2 - 2)
1929
sage: m = matrix(K, [[a-1, 2], [a, a+1]])
1930
sage: m._charpoly_over_number_field('Z')
1931
Z^2 - 2*a*Z - 2*a + 1
1932
sage: m._charpoly_over_number_field('a')(m) == 0
1933
True
1934
sage: m = matrix(K, [[0, a, 0], [-a, 0, 0], [0, 0, 0]])
1935
sage: m._charpoly_over_number_field('Z')
1936
Z^3 + 2*Z
1937
1938
The remaining tests are indirect::
1939
1940
sage: L.<b> = K.extension(x^3 - a)
1941
sage: m = matrix(L, [[b+a, 1], [a, b^2-2]])
1942
sage: m.charpoly('Z')
1943
Z^2 + (-b^2 - b - a + 2)*Z + a*b^2 - 2*b - 2*a
1944
sage: m.charpoly('a')
1945
a^2 + (-b^2 - b - a + 2)*a + a*b^2 - 2*b - 2*a
1946
sage: m.charpoly('a')(m) == 0
1947
True
1948
1949
::
1950
1951
sage: M.<c> = L.extension(x^2 - a*x + b)
1952
sage: m = matrix(M, [[a+b+c, 0, b], [0, c, 1], [a-1, b^2+1, 2]])
1953
sage: f = m.charpoly('Z'); f
1954
Z^3 + (-2*c - b - a - 2)*Z^2 + ((b + 2*a + 4)*c - b^2 + (-a + 2)*b + 2*a - 1)*Z + (b^2 + (a - 3)*b - 4*a + 1)*c + a*b^2 + 3*b + 2*a
1955
sage: f(m) == 0
1956
True
1957
sage: f.base_ring() is M
1958
True
1959
"""
1960
K = self.base_ring()
1961
if not is_NumberField(K):
1962
raise ValueError, "_charpoly_over_number_field called with base ring (%s) not a number field" % K
1963
1964
paripoly = self._pari_().charpoly()
1965
return K[var](paripoly)
1966
1967
def fcp(self, var='x'):
1968
"""
1969
Return the factorization of the characteristic polynomial of self.
1970
1971
INPUT:
1972
1973
- ``var`` - (default: 'x') name of variable of charpoly
1974
1975
EXAMPLES::
1976
1977
sage: M = MatrixSpace(QQ,3,3)
1978
sage: A = M([1,9,-7,4/5,4,3,6,4,3])
1979
sage: A.fcp()
1980
x^3 - 8*x^2 + 209/5*x - 286
1981
sage: A = M([3, 0, -2, 0, -2, 0, 0, 0, 0])
1982
sage: A.fcp('T')
1983
(T - 3) * T * (T + 2)
1984
"""
1985
return self.charpoly(var).factor()
1986
1987
## def minimal_polynomial(self, var, algorithm=''):
1988
## """
1989
## Synonym for self.charpoly(...).
1990
1991
## EXAMPLES:
1992
## sage: ???
1993
## """
1994
## return self.minpoly(*args, **kwds)
1995
1996
## def minpoly(self, *args, **kwds):
1997
## """
1998
## EXAMPLES:
1999
## sage: ???
2000
## """
2001
## raise NotImplementedError
2002
2003
def denominator(self):
2004
r"""
2005
Return the least common multiple of the denominators of the
2006
elements of self.
2007
2008
If there is no denominator function for the base field, or no LCM
2009
function for the denominators, raise a TypeError.
2010
2011
EXAMPLES::
2012
2013
sage: A = MatrixSpace(QQ,2)(['1/2', '1/3', '1/5', '1/7'])
2014
sage: A.denominator()
2015
210
2016
2017
A trivial example::
2018
2019
sage: A = matrix(QQ, 0,2)
2020
sage: A.denominator()
2021
1
2022
2023
Denominators are not defined for real numbers::
2024
2025
sage: A = MatrixSpace(RealField(),2)([1,2,3,4])
2026
sage: A.denominator()
2027
Traceback (most recent call last):
2028
...
2029
TypeError: denominator not defined for elements of the base ring
2030
2031
We can even compute the denominator of matrix over the fraction
2032
field of `\ZZ[x]`.
2033
2034
::
2035
2036
sage: K.<x> = Frac(ZZ['x'])
2037
sage: A = MatrixSpace(K,2)([1/x, 2/(x+1), 1, 5/(x^3)])
2038
sage: A.denominator()
2039
x^4 + x^3
2040
2041
Here's an example involving a cyclotomic field::
2042
2043
sage: K.<z> = CyclotomicField(3)
2044
sage: M = MatrixSpace(K,3,sparse=True)
2045
sage: A = M([(1+z)/3,(2+z)/3,z/3,1,1+z,-2,1,5,-1+z])
2046
sage: print A
2047
[1/3*z + 1/3 1/3*z + 2/3 1/3*z]
2048
[ 1 z + 1 -2]
2049
[ 1 5 z - 1]
2050
sage: print A.denominator()
2051
3
2052
"""
2053
if self.nrows() == 0 or self.ncols() == 0:
2054
return ZZ(1)
2055
R = self.base_ring()
2056
x = self.list()
2057
try:
2058
d = x[0].denominator()
2059
except AttributeError:
2060
raise TypeError, "denominator not defined for elements of the base ring"
2061
try:
2062
for y in x:
2063
d = d.lcm(y.denominator())
2064
except AttributeError:
2065
raise TypeError, "lcm function not defined for elements of the base ring"
2066
return d
2067
2068
def diagonal(self):
2069
r"""
2070
Return the diagonal entries of ``self``.
2071
2072
OUTPUT:
2073
2074
A list containing the entries of the matrix that
2075
have equal row and column indices, in order of the
2076
indices. Behavior is not limited to square matrices.
2077
2078
EXAMPLES::
2079
2080
sage: A = matrix([[2,5],[3,7]]); A
2081
[2 5]
2082
[3 7]
2083
sage: A.diagonal()
2084
[2, 7]
2085
2086
Two rectangular matrices. ::
2087
2088
sage: B = matrix(3, 7, range(21)); B
2089
[ 0 1 2 3 4 5 6]
2090
[ 7 8 9 10 11 12 13]
2091
[14 15 16 17 18 19 20]
2092
sage: B.diagonal()
2093
[0, 8, 16]
2094
2095
sage: C = matrix(3, 2, range(6)); C
2096
[0 1]
2097
[2 3]
2098
[4 5]
2099
sage: C.diagonal()
2100
[0, 3]
2101
2102
Empty matrices behave properly. ::
2103
2104
sage: E = matrix(0, 5, []); E
2105
[]
2106
sage: E.diagonal()
2107
[]
2108
"""
2109
n = min(self.nrows(), self.ncols())
2110
return [self[i,i] for i in range(n)]
2111
2112
def trace(self):
2113
"""
2114
Return the trace of self, which is the sum of the diagonal entries
2115
of self.
2116
2117
INPUT:
2118
2119
2120
- ``self`` - a square matrix
2121
2122
2123
OUTPUT: element of the base ring of self
2124
2125
EXAMPLES::
2126
2127
sage: a = matrix(3,range(9)); a
2128
[0 1 2]
2129
[3 4 5]
2130
[6 7 8]
2131
sage: a.trace()
2132
12
2133
sage: a = matrix({(1,1):10, (2,1):-3, (2,2):4/3}); a
2134
[ 0 0 0]
2135
[ 0 10 0]
2136
[ 0 -3 4/3]
2137
sage: a.trace()
2138
34/3
2139
"""
2140
if self._nrows != self._ncols:
2141
raise ValueError, "self must be a square matrix"
2142
R = self._base_ring
2143
cdef Py_ssize_t i
2144
cdef object s
2145
s = R(0)
2146
for i from 0 <= i < self._nrows:
2147
s = s + self.get_unsafe(i,i)
2148
return s
2149
2150
def trace_of_product(self, Matrix other):
2151
"""
2152
Returns the trace of self * other without computing the entire product.
2153
2154
EXAMPLES::
2155
2156
sage: M = random_matrix(ZZ, 10, 20)
2157
sage: N = random_matrix(ZZ, 20, 10)
2158
sage: M.trace_of_product(N)
2159
-1629
2160
sage: (M*N).trace()
2161
-1629
2162
"""
2163
if self._nrows != other._ncols or other._nrows != self._ncols:
2164
raise ArithmeticError, "incompatible dimensions"
2165
s = self._base_ring(0)
2166
for i from 0 <= i < self._nrows:
2167
for j from 0 <= j < self._ncols:
2168
s += self.get_unsafe(i, j) * other.get_unsafe(j, i)
2169
return s
2170
2171
#####################################################################################
2172
# Generic Hessenberg Form and charpoly algorithm
2173
#####################################################################################
2174
def hessenberg_form(self):
2175
"""
2176
Return Hessenberg form of self.
2177
2178
If the base ring is merely an integral domain (and not a field),
2179
the Hessenberg form will (in general) only be defined over the
2180
fraction field of the base ring.
2181
2182
EXAMPLES::
2183
2184
sage: A = matrix(ZZ,4,[2, 1, 1, -2, 2, 2, -1, -1, -1,1,2,3,4,5,6,7])
2185
sage: h = A.hessenberg_form(); h
2186
[ 2 -7/2 -19/5 -2]
2187
[ 2 1/2 -17/5 -1]
2188
[ 0 25/4 15/2 5/2]
2189
[ 0 0 58/5 3]
2190
sage: parent(h)
2191
Full MatrixSpace of 4 by 4 dense matrices over Rational Field
2192
sage: A.hessenbergize()
2193
Traceback (most recent call last):
2194
...
2195
TypeError: Hessenbergize only possible for matrices over a field
2196
"""
2197
X = self.fetch('hessenberg_form')
2198
if not X is None:
2199
return X
2200
R = self._base_ring
2201
if not R.is_field():
2202
try:
2203
K = self._base_ring.fraction_field()
2204
H = self.change_ring(K)
2205
H.hessenbergize()
2206
except TypeError, msg:
2207
raise TypeError, "%s\nHessenberg form only possible for matrices over a field"%msg
2208
else:
2209
H = self.__copy__()
2210
H.hessenbergize()
2211
#end if
2212
self.cache('hessenberg_form', H)
2213
return H
2214
2215
def hessenbergize(self):
2216
"""
2217
Transform self to Hessenberg form.
2218
2219
The hessenberg form of a matrix `A` is a matrix that is
2220
similar to `A`, so has the same characteristic polynomial
2221
as `A`, and is upper triangular except possible for entries
2222
right below the diagonal.
2223
2224
ALGORITHM: See Henri Cohen's first book.
2225
2226
EXAMPLES::
2227
2228
sage: A = matrix(QQ,3, [2, 1, 1, -2, 2, 2, -1, -1, -1])
2229
sage: A.hessenbergize(); A
2230
[ 2 3/2 1]
2231
[ -2 3 2]
2232
[ 0 -3 -2]
2233
2234
::
2235
2236
sage: A = matrix(QQ,4, [2, 1, 1, -2, 2, 2, -1, -1, -1,1,2,3,4,5,6,7])
2237
sage: A.hessenbergize(); A
2238
[ 2 -7/2 -19/5 -2]
2239
[ 2 1/2 -17/5 -1]
2240
[ 0 25/4 15/2 5/2]
2241
[ 0 0 58/5 3]
2242
2243
You can't Hessenbergize an immutable matrix::
2244
2245
sage: A = matrix(QQ, 3, [1..9])
2246
sage: A.set_immutable()
2247
sage: A.hessenbergize()
2248
Traceback (most recent call last):
2249
...
2250
ValueError: matrix is immutable; please change a copy instead (i.e., use copy(M) to change a copy of M).
2251
"""
2252
cdef Py_ssize_t i, j, m, n, r
2253
n = self._nrows
2254
2255
tm = verbose("Computing Hessenberg Normal Form of %sx%s matrix"%(n,n))
2256
2257
if not self.is_square():
2258
raise TypeError, "self must be square"
2259
2260
if not self._base_ring.is_field():
2261
raise TypeError, "Hessenbergize only possible for matrices over a field"
2262
2263
self.check_mutability()
2264
2265
zero = self._base_ring(0)
2266
one = self._base_ring(1)
2267
for m from 1 <= m < n-1:
2268
# Search for a non-zero entry in column m-1
2269
i = -1
2270
for r from m+1 <= r < n:
2271
if self.get_unsafe(r, m-1) != zero:
2272
i = r
2273
break
2274
if i != -1:
2275
# Found a nonzero entry in column m-1 that is strictly below row m
2276
# Now set i to be the first nonzero position >= m in column m-1
2277
if self.get_unsafe(m,m-1) != zero:
2278
i = m
2279
t = self.get_unsafe(i,m-1)
2280
t_inv = None
2281
if i > m:
2282
self.swap_rows_c(i,m)
2283
# We must do the corresponding column swap to
2284
# maintain the characteristic polynomial (which is
2285
# an invariant of Hessenberg form)
2286
self.swap_columns_c(i,m)
2287
# Now the nonzero entry in position (m,m-1) is t.
2288
# Use t to clear the entries in column m-1 below m.
2289
for j from m+1 <= j < n:
2290
x = self.get_unsafe(j, m-1)
2291
if x != zero:
2292
if t_inv is None:
2293
t_inv = one / t
2294
u = x * t_inv
2295
self.add_multiple_of_row_c(j, m, -u, 0)
2296
# To maintain charpoly, do the corresponding column operation,
2297
# which doesn't mess up the matrix, since it only changes
2298
# column m, and we're only worried about column m-1 right now.
2299
# Add u*column_j to column_m.
2300
self.add_multiple_of_column_c(m, j, u, 0)
2301
verbose("Finished Hessenberg Normal Form of %sx%s matrix"%(n,n),tm)
2302
2303
2304
2305
def _charpoly_hessenberg(self, var):
2306
"""
2307
Transforms self in place to its Hessenberg form then computes and
2308
returns the coefficients of the characteristic polynomial of this
2309
matrix.
2310
2311
INPUT:
2312
2313
- ``var`` - name of the indeterminate of the charpoly
2314
2315
The characteristic polynomial is represented as a vector of ints,
2316
where the constant term of the characteristic polynomial is the 0th
2317
coefficient of the vector.
2318
2319
EXAMPLES::
2320
2321
sage: matrix(QQ,3,range(9))._charpoly_hessenberg('Z')
2322
Z^3 - 12*Z^2 - 18*Z
2323
sage: matrix(ZZ,3,range(9))._charpoly_hessenberg('Z')
2324
Z^3 - 12*Z^2 - 18*Z
2325
sage: matrix(GF(7),3,range(9))._charpoly_hessenberg('Z')
2326
Z^3 + 2*Z^2 + 3*Z
2327
sage: matrix(QQ['x'],3,range(9))._charpoly_hessenberg('Z')
2328
Z^3 - 12*Z^2 - 18*Z
2329
sage: matrix(ZZ['ZZ'],3,range(9))._charpoly_hessenberg('Z')
2330
Z^3 - 12*Z^2 - 18*Z
2331
"""
2332
if self._nrows != self._ncols:
2333
raise ArithmeticError, "charpoly not defined for non-square matrix."
2334
2335
# Replace self by its Hessenberg form
2336
# (note the entries might now live in the fraction field)
2337
cdef Matrix H
2338
H = self.hessenberg_form()
2339
2340
# We represent the intermediate polynomials that come up in
2341
# the calculations as rows of an (n+1)x(n+1) matrix, since
2342
# we've implemented basic arithmetic with such a matrix.
2343
# Please see the generic implementation of charpoly in
2344
# matrix.py to see more clearly how the following algorithm
2345
# actually works. (The implementation is clearer (but slower)
2346
# if one uses polynomials to represent polynomials instead of
2347
# using the rows of a matrix.) Also see Cohen's first GTM,
2348
# Algorithm 2.2.9.
2349
2350
cdef Py_ssize_t i, m, n,
2351
n = self._nrows
2352
2353
cdef Matrix c
2354
c = H.new_matrix(nrows=n+1,ncols=n+1) # the 0 matrix
2355
one = H._coerce_element(1)
2356
c.set_unsafe(0,0,one)
2357
2358
for m from 1 <= m <= n:
2359
# Set the m-th row of c to (x - H[m-1,m-1])*c[m-1] = x*c[m-1] - H[m-1,m-1]*c[m-1]
2360
# We do this by hand by setting the m-th row to c[m-1]
2361
# shifted to the right by one. We then add
2362
# -H[m-1,m-1]*c[m-1] to the resulting m-th row.
2363
for i from 1 <= i <= n:
2364
c.set_unsafe(m, i, c.get_unsafe(m-1,i-1))
2365
c.add_multiple_of_row_c(m, m-1, -H.get_unsafe(m-1, m-1), 0)
2366
t = one
2367
for i from 1 <= i < m:
2368
t = t * H.get_unsafe(m-i,m-i-1)
2369
# Set the m-th row of c to c[m] - t*H[m-i-1,m-1]*c[m-i-1]
2370
c.add_multiple_of_row_c(m, m-i-1, - t*H.get_unsafe(m-i-1,m-1), 0)
2371
2372
# The answer is now the n-th row of c.
2373
v = PyList_New(n+1) # this is really sort of v = []..."
2374
for i from 0 <= i <= n:
2375
# Finally, set v[i] = c[n,i]
2376
o = c.get_unsafe(n,i)
2377
Py_INCREF(o); PyList_SET_ITEM(v, i, o)
2378
2379
R = self._base_ring[var] # polynomial ring over the base ring
2380
return R(v)
2381
2382
#####################################################################################
2383
# Decomposition: kernel, image, decomposition
2384
#####################################################################################
2385
nullity = left_nullity
2386
2387
def left_nullity(self):
2388
"""
2389
Return the (left) nullity of this matrix, which is the dimension of
2390
the (left) kernel of this matrix acting from the right on row
2391
vectors.
2392
2393
EXAMPLES::
2394
2395
sage: M = Matrix(QQ,[[1,0,0,1],[0,1,1,0],[1,1,1,0]])
2396
sage: M.nullity()
2397
0
2398
sage: M.left_nullity()
2399
0
2400
2401
::
2402
2403
sage: A = M.transpose()
2404
sage: A.nullity()
2405
1
2406
sage: A.left_nullity()
2407
1
2408
2409
::
2410
2411
sage: M = M.change_ring(ZZ)
2412
sage: M.nullity()
2413
0
2414
sage: A = M.transpose()
2415
sage: A.nullity()
2416
1
2417
"""
2418
# Use that rank + nullity = number of rows, since matrices act
2419
# from the right on row vectors.
2420
return self.nrows() - self.rank()
2421
2422
def right_nullity(self):
2423
"""
2424
Return the right nullity of this matrix, which is the dimension of
2425
the right kernel.
2426
2427
EXAMPLES::
2428
2429
sage: A = MatrixSpace(QQ,3,2)(range(6))
2430
sage: A.right_nullity()
2431
0
2432
2433
::
2434
2435
sage: A = matrix(ZZ,3,range(9))
2436
sage: A.right_nullity()
2437
1
2438
"""
2439
return self.ncols() - self.rank()
2440
2441
######################################
2442
# Kernel Helper Functions
2443
######################################
2444
2445
def _right_kernel_matrix_over_number_field(self):
2446
r"""
2447
Returns a pair that includes a matrix of basis vectors
2448
for the right kernel of ``self``.
2449
2450
OUTPUT:
2451
2452
Returns a pair. First item is the string 'pivot-pari-numberfield'
2453
that identifies the nature of the basis vectors.
2454
2455
Second item is a matrix whose rows are a basis for the right kernel,
2456
over the number field, as computed by PARI.
2457
2458
EXAMPLES::
2459
2460
sage: Q = QuadraticField(-7)
2461
sage: a = Q.gen(0)
2462
sage: A = matrix(Q, [[ 2, 5-a, 15-a],
2463
... [2+a, a, -7 + 5*a]])
2464
sage: result = A._right_kernel_matrix_over_number_field()
2465
sage: result[0]
2466
'pivot-pari-numberfield'
2467
sage: P = result[1]; P
2468
[-a -3 1]
2469
sage: A*P.transpose() == zero_matrix(Q, 2, 1)
2470
True
2471
2472
TESTS:
2473
2474
We test some trivial cases. ::
2475
2476
sage: Q = QuadraticField(-7)
2477
sage: A = matrix(Q, 0, 2)
2478
sage: A._right_kernel_matrix_over_number_field()[1]
2479
[1 0]
2480
[0 1]
2481
sage: A = matrix(Q, 2, 0)
2482
sage: A._right_kernel_matrix_over_number_field()[1].parent()
2483
Full MatrixSpace of 0 by 0 dense matrices over Number Field in a with defining polynomial x^2 + 7
2484
sage: A = zero_matrix(Q, 4, 3)
2485
sage: A._right_kernel_matrix_over_number_field()[1]
2486
[1 0 0]
2487
[0 1 0]
2488
[0 0 1]
2489
"""
2490
tm = verbose("computing right kernel matrix over a number field for %sx%s matrix" % (self.nrows(), self.ncols()),level=1)
2491
basis = self._pari_().matker()
2492
# Coerce PARI representations into the number field
2493
R = self.base_ring()
2494
basis = [[R(x) for x in row] for row in basis]
2495
verbose("done computing right kernel matrix over a number field for %sx%s matrix" % (self.nrows(), self.ncols()),level=1,t=tm)
2496
return 'pivot-pari-numberfield', matrix_space.MatrixSpace(R, len(basis), ncols=self._ncols)(basis)
2497
2498
def _right_kernel_matrix_over_field(self, *args, **kwds):
2499
r"""
2500
Returns a pair that includes a matrix of basis vectors
2501
for the right kernel of ``self``.
2502
2503
OUTPUT:
2504
2505
Returns a pair. First item is the string 'pivot-generic'
2506
that identifies the nature of the basis vectors.
2507
2508
Second item is a matrix whose rows are a basis for the right kernel,
2509
over the field, as computed by general Python code.
2510
2511
EXAMPLES::
2512
2513
sage: C = CyclotomicField(14)
2514
sage: a = C.gen(0)
2515
sage: A = matrix(C, 3, 4, [[ 1, a, 1+a, a^3+a^5],
2516
... [ a, a^4, a+a^4, a^4+a^8],
2517
... [a^2, a^6, a^2+a^6, a^5+a^10]])
2518
sage: result = A._right_kernel_matrix_over_field()
2519
sage: result[0]
2520
'pivot-generic'
2521
sage: P = result[1]; P
2522
[ -1 -1 1 0]
2523
[-zeta14^3 -zeta14^4 0 1]
2524
sage: A*P.transpose() == zero_matrix(C, 3, 2)
2525
True
2526
2527
TESTS:
2528
2529
We test some trivial cases. ::
2530
2531
sage: C = CyclotomicField(14)
2532
sage: A = matrix(C, 0, 2)
2533
sage: A._right_kernel_matrix_over_field()[1]
2534
[1 0]
2535
[0 1]
2536
sage: A = matrix(C, 2, 0)
2537
sage: A._right_kernel_matrix_over_field()[1].parent()
2538
Full MatrixSpace of 0 by 0 dense matrices over Cyclotomic Field of order 14 and degree 6
2539
sage: A = zero_matrix(C, 4, 3)
2540
sage: A._right_kernel_matrix_over_field()[1]
2541
[1 0 0]
2542
[0 1 0]
2543
[0 0 1]
2544
"""
2545
tm = verbose("computing right kernel matrix over an arbitrary field for %sx%s matrix" % (self.nrows(), self.ncols()),level=1)
2546
E = self.echelon_form(*args, **kwds)
2547
pivots = E.pivots()
2548
pivots_set = set(pivots)
2549
R = self.base_ring()
2550
zero = R(0)
2551
one = R(1)
2552
basis = []
2553
for i in xrange(self._ncols):
2554
if not (i in pivots_set):
2555
v = [zero]*self._ncols
2556
v[i] = one
2557
for r in range(len(pivots)):
2558
v[pivots[r]] = -E[r,i]
2559
basis.append(v)
2560
tm = verbose("done computing right kernel matrix over an arbitrary field for %sx%s matrix" % (self.nrows(), self.ncols()),level=1,t=tm)
2561
return 'pivot-generic', matrix_space.MatrixSpace(R, len(basis), self._ncols)(basis)
2562
2563
def _right_kernel_matrix_over_domain(self):
2564
r"""
2565
Returns a pair that includes a matrix of basis vectors
2566
for the right kernel of ``self``.
2567
2568
OUTPUT:
2569
2570
Returns a pair. First item is the string 'computed-smith-form'
2571
that identifies the nature of the basis vectors.
2572
2573
Second item is a matrix whose rows are a basis for the right kernel,
2574
over the field, as computed by general Python code.
2575
2576
.. warning::
2577
2578
This routine uses Smith normal form, which can fail
2579
if the domain is not a principal ideal domain. Since we do
2580
not have a good test for PIDs, this is just a risk we take.
2581
See an example failure in the documentation for
2582
:meth:`right_kernel_matrix`.
2583
2584
EXAMPLES:
2585
2586
Univariate polynomials over a field form a PID. ::
2587
2588
sage: R.<y> = QQ[]
2589
sage: A = matrix(R, [[ 1, y, 1+y^2],
2590
... [y^3, y^2, 2*y^3]])
2591
sage: result = A._right_kernel_matrix_over_domain()
2592
sage: result[0]
2593
'computed-smith-form'
2594
sage: P = result[1]; P
2595
[-1 -y 1]
2596
sage: A*P.transpose() == zero_matrix(R, 2, 1)
2597
True
2598
2599
TESTS:
2600
2601
We test some trivial cases. ::
2602
2603
sage: R.<y> = QQ[]
2604
sage: A = matrix(R, 0, 2)
2605
sage: A._right_kernel_matrix_over_domain()[1]
2606
[1 0]
2607
[0 1]
2608
sage: A = matrix(R, 2, 0)
2609
sage: A._right_kernel_matrix_over_domain()[1].parent()
2610
Full MatrixSpace of 0 by 0 dense matrices over Univariate Polynomial Ring in y over Rational Field
2611
sage: A = zero_matrix(R, 4, 3)
2612
sage: A._right_kernel_matrix_over_domain()[1]
2613
[1 0 0]
2614
[0 1 0]
2615
[0 0 1]
2616
"""
2617
tm = verbose("computing right kernel matrix over a domain for %sx%s matrix" % (self.nrows(), self.ncols()),level=1)
2618
d, u, v = self.smith_form()
2619
basis = []
2620
for i in xrange(self.ncols()):
2621
if (i >= self.nrows()) or d[i][i] == 0:
2622
basis.append( v.column(i).list() )
2623
verbose("done computing right kernel matrix over a domain for %sx%s matrix" % (self.nrows(), self.ncols()),level=1,t=tm)
2624
return 'computed-smith-form', self.new_matrix(nrows=len(basis), ncols=self._ncols, entries=basis)
2625
2626
def right_kernel_matrix(self, *args, **kwds):
2627
r"""
2628
Returns a matrix whose rows form a basis
2629
for the right kernel of ``self``.
2630
2631
INPUT:
2632
2633
- ``algorithm`` - default: 'default' - a keyword that selects the
2634
algorithm employed. Allowable values are:
2635
2636
- 'default' - allows the algorithm to be chosen automatically
2637
- 'generic' - naive algorithm usable for matrices over any field
2638
- 'pari' - PARI library code for matrices over number fields
2639
or the integers
2640
- 'padic' - padic algorithm from IML library for matrices
2641
over the rationals and integers
2642
- 'pluq' - PLUQ matrix factorization for matrices mod 2
2643
2644
- ``basis`` - default: 'echelon' - a keyword that describes
2645
the format of the basis returned. Allowable values are:
2646
2647
- 'echelon': the basis matrix is in echelon form
2648
- 'pivot' : each basis vector is computed from the reduced
2649
row-echelon form of ``self`` by placing a single one in a
2650
non-pivot column and zeros in the remaining non-pivot columns.
2651
Only available for matrices over fields.
2652
- 'LLL': an LLL-reduced basis. Only available for matrices
2653
over the integers.
2654
- 'computed': no work is done to transform the basis, it is
2655
returned exactly as provided by whichever routine actually
2656
computed the basis. Request this for the least possible
2657
computation possible, but with no guarantees about the format
2658
of the basis.
2659
2660
OUTPUT:
2661
2662
A matrix ``X`` whose rows are an independent set spanning the
2663
right kernel of ``self``. So ``self*X.transpose()`` is a zero matrix.
2664
2665
The output varies depending on the choice of ``algorithm`` and the
2666
format chosen by ``basis``.
2667
2668
The results of this routine are not cached, so you can call it again
2669
with different options to get possibly different output (like the basis
2670
format). Conversely, repeated calls on the same matrix will always
2671
start from scratch.
2672
2673
.. note::
2674
2675
If you want to get the most basic description of a kernel, with a
2676
minimum of overhead, then ask for the right kernel matrix with
2677
the basis format requested as 'computed'. You are then free to
2678
work with the output for whatever purpose. For a left kernel,
2679
call this method on the transpose of your matrix.
2680
2681
For greater convenience, plus cached results, request an actual
2682
vector space or free module with :meth:`right_kernel`
2683
or :meth:`left_kernel`.
2684
2685
EXAMPLES:
2686
2687
Over the Rational Numbers:
2688
2689
Kernels are computed by the IML library in
2690
:meth:`~sage.matrix.matrix_rational_dense.Matrix_rational_dense._right_kernel_matrix`.
2691
Setting the `algorithm` keyword to 'default', 'padic' or unspecified
2692
will yield the same result, as there is no optional behavior.
2693
The 'computed' format of the basis vectors are exactly the negatives
2694
of the vectors in the 'pivot' format. ::
2695
2696
sage: A = matrix(QQ, [[1, 0, 1, -3, 1],
2697
... [-5, 1, 0, 7, -3],
2698
... [0, -1, -4, 6, -2],
2699
... [4, -1, 0, -6, 2]])
2700
sage: C = A.right_kernel_matrix(algorithm='default', basis='computed'); C
2701
[-1 2 -2 -1 0]
2702
[ 1 2 0 0 -1]
2703
sage: A*C.transpose() == zero_matrix(QQ, 4, 2)
2704
True
2705
sage: P = A.right_kernel_matrix(algorithm='padic', basis='pivot'); P
2706
[ 1 -2 2 1 0]
2707
[-1 -2 0 0 1]
2708
sage: A*P.transpose() == zero_matrix(QQ, 4, 2)
2709
True
2710
sage: C == -P
2711
True
2712
sage: E = A.right_kernel_matrix(algorithm='default', basis='echelon'); E
2713
[ 1 0 1 1/2 -1/2]
2714
[ 0 1 -1/2 -1/4 -1/4]
2715
sage: A*E.transpose() == zero_matrix(QQ, 4, 2)
2716
True
2717
2718
Since the rationals are a field, we can call the general code
2719
available for any field by using the 'generic' keyword. ::
2720
2721
sage: A = matrix(QQ, [[1, 0, 1, -3, 1],
2722
... [-5, 1, 0, 7, -3],
2723
... [0, -1, -4, 6, -2],
2724
... [4, -1, 0, -6, 2]])
2725
sage: G = A.right_kernel_matrix(algorithm='generic', basis='echelon'); G
2726
[ 1 0 1 1/2 -1/2]
2727
[ 0 1 -1/2 -1/4 -1/4]
2728
sage: A*G.transpose() == zero_matrix(QQ, 4, 2)
2729
True
2730
2731
We verify that the rational matrix code is called for both
2732
dense and sparse rational matrices, with equal result. ::
2733
2734
sage: A = matrix(QQ, [[1, 0, 1, -3, 1],
2735
... [-5, 1, 0, 7, -3],
2736
... [0, -1, -4, 6, -2],
2737
... [4, -1, 0, -6, 2]],
2738
... sparse=False)
2739
sage: B = copy(A).sparse_matrix()
2740
sage: set_verbose(1)
2741
sage: D = A.right_kernel(); D
2742
verbose ...
2743
verbose 1 (<module>) computing right kernel matrix over the rationals for 4x5 matrix
2744
...
2745
verbose 1 (<module>) done computing right kernel matrix over the rationals for 4x5 matrix
2746
...
2747
Vector space of degree 5 and dimension 2 over Rational Field
2748
Basis matrix:
2749
[ 1 0 1 1/2 -1/2]
2750
[ 0 1 -1/2 -1/4 -1/4]
2751
sage: S = B.right_kernel(); S
2752
verbose ...
2753
verbose 1 (<module>) computing right kernel matrix over the rationals for 4x5 matrix
2754
...
2755
verbose 1 (<module>) done computing right kernel matrix over the rationals for 4x5 matrix
2756
...
2757
Vector space of degree 5 and dimension 2 over Rational Field
2758
Basis matrix:
2759
[ 1 0 1 1/2 -1/2]
2760
[ 0 1 -1/2 -1/4 -1/4]
2761
sage: set_verbose(0)
2762
sage: D == S
2763
True
2764
2765
Over Number Fields:
2766
2767
Kernels are by default computed by PARI, (except for exceptions like
2768
the rationals themselves). The raw results from PARI are a pivot
2769
basis, so the `basis` keywords 'computed' and 'pivot' will return
2770
the same results. ::
2771
2772
sage: Q = QuadraticField(-7)
2773
sage: a = Q.gen(0)
2774
sage: A = matrix(Q, [[2, 5-a, 15-a, 16+4*a],
2775
... [2+a, a, -7 + 5*a, -3+3*a]])
2776
sage: C = A.right_kernel_matrix(algorithm='default', basis='computed'); C
2777
[ -a -3 1 0]
2778
[ -2 -a - 1 0 1]
2779
sage: A*C.transpose() == zero_matrix(Q, 2, 2)
2780
True
2781
sage: P = A.right_kernel_matrix(algorithm='pari', basis='pivot'); P
2782
[ -a -3 1 0]
2783
[ -2 -a - 1 0 1]
2784
sage: A*P.transpose() == zero_matrix(Q, 2, 2)
2785
True
2786
sage: E = A.right_kernel_matrix(algorithm='default', basis='echelon'); E
2787
[ 1 0 7/88*a + 3/88 -3/176*a - 39/176]
2788
[ 0 1 -1/88*a - 13/88 13/176*a - 7/176]
2789
sage: A*E.transpose() == zero_matrix(Q, 2, 2)
2790
True
2791
2792
We can bypass using PARI for number fields and use Sage's general
2793
code for matrices over any field. The basis vectors as computed
2794
are in pivot format. ::
2795
2796
sage: Q = QuadraticField(-7)
2797
sage: a = Q.gen(0)
2798
sage: A = matrix(Q, [[2, 5-a, 15-a, 16+4*a],[2+a, a, -7 + 5*a, -3+3*a]])
2799
sage: G = A.right_kernel_matrix(algorithm='generic', basis='computed'); G
2800
[ -a -3 1 0]
2801
[ -2 -a - 1 0 1]
2802
sage: A*G.transpose() == zero_matrix(Q, 2, 2)
2803
True
2804
2805
We check that number fields are handled by the right routine as part of
2806
typical right kernel computation. ::
2807
2808
sage: Q = QuadraticField(-7)
2809
sage: a = Q.gen(0)
2810
sage: A = matrix(Q, [[2, 5-a, 15-a, 16+4*a],[2+a, a, -7 + 5*a, -3+3*a]])
2811
sage: set_verbose(1)
2812
sage: A.right_kernel(algorithm='default')
2813
verbose ...
2814
verbose 1 (<module>) computing right kernel matrix over a number field for 2x4 matrix
2815
verbose 1 (<module>) done computing right kernel matrix over a number field for 2x4 matrix
2816
...
2817
Vector space of degree 4 and dimension 2 over Number Field in a with defining polynomial x^2 + 7
2818
Basis matrix:
2819
[ 1 0 7/88*a + 3/88 -3/176*a - 39/176]
2820
[ 0 1 -1/88*a - 13/88 13/176*a - 7/176]
2821
sage: set_verbose(0)
2822
2823
Over the Finite Field of Order 2:
2824
2825
Kernels are computed by the M4RI library using PLUQ matrix
2826
decomposition in the
2827
:meth:`~sage.matrix.matrix_mod2_dense.Matrix_mod2_dense._right_kernel_matrix`
2828
method. There are no options for the algorithm used. ::
2829
2830
sage: A = matrix(GF(2),[[0, 1, 1, 0, 0, 0],
2831
... [1, 0, 0, 0, 1, 1,],
2832
... [1, 0, 0, 0, 1, 1]])
2833
sage: E = A.right_kernel_matrix(algorithm='default', format='echelon'); E
2834
[1 0 0 0 0 1]
2835
[0 1 1 0 0 0]
2836
[0 0 0 1 0 0]
2837
[0 0 0 0 1 1]
2838
sage: A*E.transpose() == zero_matrix(GF(2), 3, 4)
2839
True
2840
2841
Since GF(2) is a field we can route this computation to the generic
2842
code and obtain the 'pivot' form of the basis. The ``algorithm``
2843
keywords, 'pluq', 'default' and unspecified, all have the
2844
same effect as there is no optional behavior. ::
2845
2846
sage: A = matrix(GF(2),[[0, 1, 1, 0, 0, 0],
2847
... [1, 0, 0, 0, 1, 1,],
2848
... [1, 0, 0, 0, 1, 1]])
2849
sage: P = A.right_kernel_matrix(algorithm='generic', basis='pivot'); P
2850
[0 1 1 0 0 0]
2851
[0 0 0 1 0 0]
2852
[1 0 0 0 1 0]
2853
[1 0 0 0 0 1]
2854
sage: A*P.transpose() == zero_matrix(GF(2), 3, 4)
2855
True
2856
sage: DP = A.right_kernel_matrix(algorithm='default', basis='pivot'); DP
2857
[0 1 1 0 0 0]
2858
[0 0 0 1 0 0]
2859
[1 0 0 0 1 0]
2860
[1 0 0 0 0 1]
2861
sage: A*DP.transpose() == zero_matrix(GF(2), 3, 4)
2862
True
2863
sage: A.right_kernel_matrix(algorithm='pluq', basis='echelon')
2864
[1 0 0 0 0 1]
2865
[0 1 1 0 0 0]
2866
[0 0 0 1 0 0]
2867
[0 0 0 0 1 1]
2868
2869
We test that the mod 2 code is called for matrices over GF(2). ::
2870
2871
sage: A = matrix(GF(2),[[0, 1, 1, 0, 0, 0],
2872
... [1, 0, 0, 0, 1, 1,],
2873
... [1, 0, 0, 0, 1, 1]])
2874
sage: set_verbose(1)
2875
sage: A.right_kernel(algorithm='default')
2876
verbose ...
2877
verbose 1 (<module>) computing right kernel matrix over integers mod 2 for 3x6 matrix
2878
verbose 1 (<module>) done computing right kernel matrix over integers mod 2 for 3x6 matrix
2879
...
2880
Vector space of degree 6 and dimension 4 over Finite Field of size 2
2881
Basis matrix:
2882
[1 0 0 0 0 1]
2883
[0 1 1 0 0 0]
2884
[0 0 0 1 0 0]
2885
[0 0 0 0 1 1]
2886
sage: set_verbose(0)
2887
2888
Over Arbitrary Fields:
2889
2890
For kernels over fields not listed above, totally general code
2891
will compute a set of basis vectors in the pivot format.
2892
These could be returned as a basis in echelon form. ::
2893
2894
sage: F.<a> = FiniteField(5^2)
2895
sage: A = matrix(F, 3, 4, [[ 1, a, 1+a, a^3+a^5],
2896
... [ a, a^4, a+a^4, a^4+a^8],
2897
... [a^2, a^6, a^2+a^6, a^5+a^10]])
2898
sage: P = A.right_kernel_matrix(algorithm='default', basis='pivot'); P
2899
[ 4 4 1 0]
2900
[ a + 2 3*a + 3 0 1]
2901
sage: A*P.transpose() == zero_matrix(F, 3, 2)
2902
True
2903
sage: E = A.right_kernel_matrix(algorithm='default', basis='echelon'); E
2904
[ 1 0 3*a + 4 2*a + 2]
2905
[ 0 1 2*a 3*a + 3]
2906
sage: A*E.transpose() == zero_matrix(F, 3, 2)
2907
True
2908
2909
This general code can be requested for matrices over any field
2910
with the ``algorithm`` keyword 'generic'. Normally, matrices
2911
over the rationals would be handled by specific routines from
2912
the IML library. The default format is an echelon basis, but a
2913
pivot basis may be requested, which is identical to the computed
2914
basis. ::
2915
2916
sage: A = matrix(QQ, 3, 4, [[1,3,-2,4],
2917
... [2,0,2,2],
2918
... [-1,1,-2,0]])
2919
sage: G = A.right_kernel_matrix(algorithm='generic'); G
2920
[ 1 0 -1/2 -1/2]
2921
[ 0 1 1/2 -1/2]
2922
sage: A*G.transpose() == zero_matrix(QQ, 3, 2)
2923
True
2924
sage: C = A.right_kernel_matrix(algorithm='generic', basis='computed'); C
2925
[-1 1 1 0]
2926
[-1 -1 0 1]
2927
sage: A*C.transpose() == zero_matrix(QQ, 3, 2)
2928
True
2929
2930
We test that the generic code is called for matrices over fields,
2931
lacking any more specific routine. ::
2932
2933
sage: F.<a> = FiniteField(5^2)
2934
sage: A = matrix(F, 3, 4, [[ 1, a, 1+a, a^3+a^5],
2935
... [ a, a^4, a+a^4, a^4+a^8],
2936
... [a^2, a^6, a^2+a^6, a^5+a^10]])
2937
sage: set_verbose(1)
2938
sage: A.right_kernel(algorithm='default')
2939
verbose ...
2940
verbose 1 (<module>) computing right kernel matrix over an arbitrary field for 3x4 matrix
2941
...
2942
verbose 1 (<module>) done computing right kernel matrix over an arbitrary field for 3x4 matrix
2943
...
2944
Vector space of degree 4 and dimension 2 over Finite Field in a of size 5^2
2945
Basis matrix:
2946
[ 1 0 3*a + 4 2*a + 2]
2947
[ 0 1 2*a 3*a + 3]
2948
sage: set_verbose(0)
2949
2950
Over the Integers:
2951
2952
Either the IML or PARI libraries are used to provide a set of basis
2953
vectors. The ``algorithm`` keyword can be used to select either,
2954
or when set to 'default' a heuristic will choose between the two.
2955
Results can be returned in the 'compute' format, straight out of
2956
the libraries. Unique to the integers, the basis vectors can be
2957
returned as an LLL basis. Note the similarities and differences
2958
in the results. The 'pivot' format is not available, since the
2959
integers are not a field. ::
2960
2961
sage: A = matrix(ZZ, [[8, 0, 7, 1, 3, 4, 6],
2962
... [4, 0, 3, 4, 2, 7, 7],
2963
... [1, 4, 6, 1, 2, 8, 5],
2964
... [0, 3, 1, 2, 3, 6, 2]])
2965
2966
sage: X = A.right_kernel_matrix(algorithm='default', basis='echelon'); X
2967
[ 1 12 3 14 -3 -10 1]
2968
[ 0 35 0 25 -1 -31 17]
2969
[ 0 0 7 12 -3 -1 -8]
2970
sage: A*X.transpose() == zero_matrix(ZZ, 4, 3)
2971
True
2972
2973
sage: X = A.right_kernel_matrix(algorithm='padic', basis='LLL'); X
2974
[ -3 -1 5 7 2 -3 -2]
2975
[ 3 1 2 5 -5 2 -6]
2976
[ -4 -13 2 -7 5 7 -3]
2977
sage: A*X.transpose() == zero_matrix(ZZ, 4, 3)
2978
True
2979
2980
sage: X = A.right_kernel_matrix(algorithm='pari', basis='computed'); X
2981
[ 3 1 -5 -7 -2 3 2]
2982
[ 3 1 2 5 -5 2 -6]
2983
[ 4 13 -2 7 -5 -7 3]
2984
sage: A*X.transpose() == zero_matrix(ZZ, 4, 3)
2985
True
2986
2987
sage: X = A.right_kernel_matrix(algorithm='padic', basis='computed'); X
2988
[ 265 345 -178 17 -297 0 0]
2989
[-242 -314 163 -14 271 -1 0]
2990
[ -36 -47 25 -1 40 0 -1]
2991
sage: A*X.transpose() == zero_matrix(ZZ, 4, 3)
2992
True
2993
2994
We test that the code for integer matrices is called for matrices
2995
defined over the integers, both dense and sparse, with equal result. ::
2996
2997
sage: A = matrix(ZZ, [[8, 0, 7, 1, 3, 4, 6],
2998
... [4, 0, 3, 4, 2, 7, 7],
2999
... [1, 4, 6, 1, 2, 8, 5],
3000
... [0, 3, 1, 2, 3, 6, 2]],
3001
... sparse=False)
3002
sage: B = copy(A).sparse_matrix()
3003
sage: set_verbose(1)
3004
sage: D = A.right_kernel(); D
3005
verbose ...
3006
verbose 1 (<module>) computing right kernel matrix over the integers for 4x7 matrix
3007
verbose 1 (<module>) done computing right kernel matrix over the integers for 4x7 matrix
3008
...
3009
Free module of degree 7 and rank 3 over Integer Ring
3010
Echelon basis matrix:
3011
[ 1 12 3 14 -3 -10 1]
3012
[ 0 35 0 25 -1 -31 17]
3013
[ 0 0 7 12 -3 -1 -8]
3014
sage: S = B.right_kernel(); S
3015
verbose ...
3016
verbose 1 (<module>) computing right kernel matrix over the integers for 4x7 matrix
3017
verbose 1 (<module>) done computing right kernel matrix over the integers for 4x7 matrix
3018
...
3019
Free module of degree 7 and rank 3 over Integer Ring
3020
Echelon basis matrix:
3021
[ 1 12 3 14 -3 -10 1]
3022
[ 0 35 0 25 -1 -31 17]
3023
[ 0 0 7 12 -3 -1 -8]
3024
sage: set_verbose(0)
3025
sage: D == S
3026
True
3027
3028
Over Principal Ideal Domains:
3029
3030
Kernels can be computed using Smith normal form. Only the default
3031
algorithm is available, and the 'pivot' basis format is
3032
not available. ::
3033
3034
sage: R.<y> = QQ[]
3035
sage: A = matrix(R, [[ 1, y, 1+y^2],
3036
... [y^3, y^2, 2*y^3]])
3037
sage: E = A.right_kernel_matrix(algorithm='default', basis='echelon'); E
3038
[-1 -y 1]
3039
sage: A*E.transpose() == zero_matrix(ZZ, 2, 1)
3040
True
3041
3042
It can be computationally expensive to determine if an integral
3043
domain is a principal ideal domain. The Smith normal form routine
3044
can fail for non-PIDs, as in this example. ::
3045
3046
sage: D.<x> = ZZ[]
3047
sage: A = matrix(D, 2, 2, [[x^2 - x, -x + 5],
3048
... [x^2 - 8, -x + 2]])
3049
sage: A.right_kernel_matrix()
3050
Traceback (most recent call last):
3051
...
3052
ArithmeticError: Ideal Ideal (x^2 - x, x^2 - 8) of Univariate Polynomial Ring in x over Integer Ring not principal
3053
3054
We test that the domain code is called for domains that lack any
3055
extra structure. ::
3056
3057
sage: R.<y> = QQ[]
3058
sage: A = matrix(R, [[ 1, y, 1+y^2],
3059
... [y^3, y^2, 2*y^3]])
3060
sage: set_verbose(1)
3061
sage: A.right_kernel(algorithm='default', basis='echelon')
3062
verbose ...
3063
verbose 1 (<module>) computing right kernel matrix over a domain for 2x3 matrix
3064
verbose 1 (<module>) done computing right kernel matrix over a domain for 2x3 matrix
3065
...
3066
Free module of degree 3 and rank 1 over Univariate Polynomial Ring in y over Rational Field
3067
Echelon basis matrix:
3068
[-1 -y 1]
3069
sage: set_verbose(0)
3070
3071
Trivial Cases:
3072
3073
We test two trivial cases. Any possible values for the
3074
keywords (``algorithm``, ``basis``) will return identical results. ::
3075
3076
sage: A = matrix(ZZ, 0, 2)
3077
sage: A.right_kernel_matrix()
3078
[1 0]
3079
[0 1]
3080
sage: A = matrix(FiniteField(7), 2, 0)
3081
sage: A.right_kernel_matrix().parent()
3082
Full MatrixSpace of 0 by 0 dense matrices over Finite Field of size 7
3083
3084
TESTS:
3085
3086
The "usual" quaternions are a non-commutative ring and computations
3087
of kernels over these rings are not implemented. ::
3088
3089
sage: Q.<i,j,k> = QuaternionAlgebra(-1,-1)
3090
sage: A = matrix(Q, 2, [i,j,-1,k])
3091
sage: A.right_kernel_matrix()
3092
Traceback (most recent call last):
3093
...
3094
NotImplementedError: Cannot compute a matrix kernel over Quaternion Algebra (-1, -1) with base ring Rational Field
3095
3096
We test error messages for improper choices of the 'algorithm'
3097
keyword. ::
3098
3099
sage: matrix(ZZ, 2, 2).right_kernel_matrix(algorithm='junk')
3100
Traceback (most recent call last):
3101
...
3102
ValueError: matrix kernel algorithm 'junk' not recognized
3103
sage: matrix(GF(2), 2, 2).right_kernel_matrix(algorithm='padic')
3104
Traceback (most recent call last):
3105
...
3106
ValueError: 'padic' matrix kernel algorithm only available over the rationals and the integers, not over Finite Field of size 2
3107
sage: matrix(QQ, 2, 2).right_kernel_matrix(algorithm='pari')
3108
Traceback (most recent call last):
3109
...
3110
ValueError: 'pari' matrix kernel algorithm only available over non-trivial number fields and the integers, not over Rational Field
3111
sage: matrix(Integers(6), 2, 2).right_kernel_matrix(algorithm='generic')
3112
Traceback (most recent call last):
3113
...
3114
ValueError: 'generic' matrix kernel algorithm only available over a field, not over Ring of integers modulo 6
3115
sage: matrix(QQ, 2, 2).right_kernel_matrix(algorithm='pluq')
3116
Traceback (most recent call last):
3117
...
3118
ValueError: 'pluq' matrix kernel algorithm only available over integers mod 2, not over Rational Field
3119
3120
We test error messages for improper basis format requests. ::
3121
3122
sage: matrix(ZZ, 2, 2).right_kernel_matrix(basis='junk')
3123
Traceback (most recent call last):
3124
...
3125
ValueError: matrix kernel basis format 'junk' not recognized
3126
sage: matrix(ZZ, 2, 2).right_kernel_matrix(basis='pivot')
3127
Traceback (most recent call last):
3128
...
3129
ValueError: pivot basis only available over a field, not over Integer Ring
3130
sage: matrix(QQ, 2, 2).right_kernel_matrix(basis='LLL')
3131
Traceback (most recent call last):
3132
...
3133
ValueError: LLL-reduced basis only available over the integers, not over Rational Field
3134
3135
Finally, error messages for the 'proof' keyword. ::
3136
3137
sage: matrix(ZZ, 2, 2).right_kernel_matrix(proof='junk')
3138
Traceback (most recent call last):
3139
...
3140
ValueError: 'proof' must be one of True, False or None, not junk
3141
sage: matrix(QQ, 2, 2).right_kernel_matrix(proof=True)
3142
Traceback (most recent call last):
3143
...
3144
ValueError: 'proof' flag only valid for matrices over the integers
3145
3146
AUTHOR:
3147
3148
- Rob Beezer (2011-02-05)
3149
"""
3150
R = self.base_ring()
3151
3152
# First: massage keywords
3153
# Determine algorithm to use for computation of kernel matrix
3154
algorithm = kwds.pop('algorithm', None)
3155
if algorithm is None:
3156
algorithm = 'default'
3157
elif not algorithm in ['default', 'generic', 'pari', 'padic', 'pluq']:
3158
raise ValueError("matrix kernel algorithm '%s' not recognized" % algorithm )
3159
elif algorithm == 'padic' and not (is_IntegerRing(R) or is_RationalField(R)):
3160
raise ValueError("'padic' matrix kernel algorithm only available over the rationals and the integers, not over %s" % R)
3161
elif algorithm == 'pari' and not (is_IntegerRing(R) or (is_NumberField(R) and not is_RationalField(R))):
3162
raise ValueError("'pari' matrix kernel algorithm only available over non-trivial number fields and the integers, not over %s" % R)
3163
elif algorithm == 'generic' and not R.is_field():
3164
raise ValueError("'generic' matrix kernel algorithm only available over a field, not over %s" % R)
3165
elif algorithm == 'pluq' and not isinstance(self, sage.matrix.matrix_mod2_dense.Matrix_mod2_dense):
3166
raise ValueError("'pluq' matrix kernel algorithm only available over integers mod 2, not over %s" % R)
3167
3168
# Determine the basis format of independent spanning set to return
3169
basis = kwds.pop('basis', None)
3170
if basis is None:
3171
basis = 'echelon'
3172
elif not basis in ['computed', 'echelon', 'pivot', 'LLL']:
3173
raise ValueError("matrix kernel basis format '%s' not recognized" % basis )
3174
elif basis == 'pivot' and not R.is_field():
3175
raise ValueError('pivot basis only available over a field, not over %s' % R)
3176
elif basis == 'LLL' and not is_IntegerRing(R):
3177
raise ValueError('LLL-reduced basis only available over the integers, not over %s' % R)
3178
3179
# Determine proof keyword for integer matrices
3180
proof = kwds.pop('proof', None)
3181
if not (proof in [None, True, False]):
3182
raise ValueError("'proof' must be one of True, False or None, not %s" % proof)
3183
if not (proof is None or is_IntegerRing(R)):
3184
raise ValueError("'proof' flag only valid for matrices over the integers")
3185
3186
# We could sanitize/process remaining (un-popped) keywords here and
3187
# send them to the echelon form routine in the 'generic' algorithm case
3188
# Would need to handle 'algorithm' keyword properly
3189
3190
# Second: Trivial cases over any integral domain
3191
# With zero columns the domain has dimension 0,
3192
# so only an empty basis is possible
3193
# With zero rows the codomain is just the zero vector,
3194
# thus the kernel is the whole domain, so return an identity matrix
3195
# identity_matrix constructor will fail if ring does not have a one
3196
# For all keywords the results are identical
3197
if self._ncols == 0 and R.is_integral_domain():
3198
return self.new_matrix(nrows = 0, ncols = self._ncols)
3199
if self._nrows == 0 and R.is_integral_domain():
3200
import constructor
3201
return constructor.identity_matrix(R, self._ncols)
3202
3203
# Third: generic first, if requested explicitly
3204
# then try specialized class methods, and finally
3205
# delegate to ad-hoc methods in greater generality
3206
M = None; format = ''
3207
3208
if algorithm == 'generic':
3209
format, M = self._right_kernel_matrix_over_field()
3210
3211
if M is None:
3212
try:
3213
format, M = self._right_kernel_matrix(algorithm=algorithm, proof=proof)
3214
except AttributeError:
3215
pass
3216
3217
if M is None and is_NumberField(R):
3218
format, M = self._right_kernel_matrix_over_number_field()
3219
3220
if M is None and R.is_field():
3221
format, M = self._right_kernel_matrix_over_field()
3222
3223
if M is None and R.is_integral_domain():
3224
format, M = self._right_kernel_matrix_over_domain()
3225
3226
if M is None:
3227
raise NotImplementedError("Cannot compute a matrix kernel over %s" % R)
3228
3229
# Trivial kernels give empty matrices, which sometimes mistakenly have
3230
# zero columns as well. (eg PARI?) This could be fixed at the source
3231
# with a careful study of the phenomenon. Start by commenting out
3232
# the following and running doctests in sage/matrix
3233
if M.nrows()==0 and M.ncols()!=self.ncols():
3234
M = M.new_matrix(nrows=0, ncols=self.ncols())
3235
3236
# Convert basis to requested type and return the matrix
3237
# format string leads with 'echelon', 'pivot' or 'LLL' if known
3238
# to be of that format otherwise format string leads with
3239
# 'computed' if it needs work (ie raw results)
3240
if basis == 'computed':
3241
return M
3242
elif basis == 'echelon':
3243
if not format[:7] == 'echelon':
3244
return M.echelon_form()
3245
else:
3246
return M
3247
elif basis == 'pivot':
3248
# cannot get here unless over a field
3249
if not format[:5] == 'pivot':
3250
# convert non-pivot columns to identity matrix
3251
# this is the basis immediately obvious from echelon form
3252
# so C is always invertible (when working over a field)
3253
C = M.matrix_from_columns(self.nonpivots())
3254
return C.inverse()*M
3255
else:
3256
return M
3257
elif basis == 'LLL':
3258
# cannot get here unless over integers
3259
if not format[:3] == 'LLL':
3260
return M.LLL()
3261
else:
3262
return M
3263
3264
def right_kernel(self, *args, **kwds):
3265
r"""
3266
Returns the right kernel of this matrix, as a vector space or
3267
free module. This is the set of vectors ``x`` such that ``self*x = 0``.
3268
3269
.. note::
3270
3271
For the left kernel, use :meth:`left_kernel`. The method
3272
:meth:`kernel` is exactly equal to :meth:`left_kernel`.
3273
3274
INPUT:
3275
3276
- ``algorithm`` - default: 'default' - a keyword that selects the
3277
algorithm employed. Allowable values are:
3278
3279
- 'default' - allows the algorithm to be chosen automatically
3280
- 'generic' - naive algorithm usable for matrices over any field
3281
- 'pari' - PARI library code for matrices over number fields
3282
or the integers
3283
- 'padic' - padic algorithm from IML library for matrices
3284
over the rationals and integers
3285
- 'pluq' - PLUQ matrix factorization for matrices mod 2
3286
3287
- ``basis`` - default: 'echelon' - a keyword that describes the
3288
format of the basis used to construct the left kernel.
3289
Allowable values are:
3290
3291
- 'echelon': the basis matrix is in echelon form
3292
- 'pivot' : each basis vector is computed from the reduced
3293
row-echelon form of ``self`` by placing a single one in a
3294
non-pivot column and zeros in the remaining non-pivot columns.
3295
Only available for matrices over fields.
3296
- 'LLL': an LLL-reduced basis. Only available for matrices
3297
over the integers.
3298
3299
OUTPUT:
3300
3301
A vector space or free module whose degree equals the number
3302
of columns in ``self`` and contains all the vectors ``x`` such
3303
that ``self*x = 0``.
3304
3305
If ``self`` has 0 columns, the kernel has dimension 0, while if
3306
``self`` has 0 rows the kernel is the entire ambient vector space.
3307
3308
The result is cached. Requesting the right kernel a second time,
3309
but with a different basis format, will return the cached result
3310
with the format from the first computation.
3311
3312
.. note::
3313
3314
For more detailed documentation on the selection of algorithms
3315
used and a more flexible method for computing a basis matrix
3316
for a right kernel (rather than computing a vector space), see
3317
:meth:`right_kernel_matrix`, which powers the computations for
3318
this method.
3319
3320
EXAMPLES::
3321
3322
sage: A = matrix(QQ, [[0, 0, 1, 2, 2, -5, 3],
3323
... [-1, 5, 2, 2, 1, -7, 5],
3324
... [0, 0, -2, -3, -3, 8, -5],
3325
... [-1, 5, 0, -1, -2, 1, 0]])
3326
sage: K = A.right_kernel(); K
3327
Vector space of degree 7 and dimension 4 over Rational Field
3328
Basis matrix:
3329
[ 1 0 0 0 -1 -1 -1]
3330
[ 0 1 0 0 5 5 5]
3331
[ 0 0 1 0 -1 -2 -3]
3332
[ 0 0 0 1 0 1 1]
3333
sage: A*K.basis_matrix().transpose() == zero_matrix(QQ, 4, 4)
3334
True
3335
3336
The default is basis vectors that form a matrix in echelon form.
3337
A "pivot basis" instead has a basis matrix where the columns of
3338
an identity matrix are in the locations of the non-pivot columns
3339
of the original matrix. This alternate format is available whenever
3340
the base ring is a field. ::
3341
3342
sage: A = matrix(QQ, [[0, 0, 1, 2, 2, -5, 3],
3343
... [-1, 5, 2, 2, 1, -7, 5],
3344
... [0, 0, -2, -3, -3, 8, -5],
3345
... [-1, 5, 0, -1, -2, 1, 0]])
3346
sage: A.rref()
3347
[ 1 -5 0 0 1 1 -1]
3348
[ 0 0 1 0 0 -1 1]
3349
[ 0 0 0 1 1 -2 1]
3350
[ 0 0 0 0 0 0 0]
3351
sage: A.nonpivots()
3352
(1, 4, 5, 6)
3353
sage: K = A.right_kernel(basis='pivot'); K
3354
Vector space of degree 7 and dimension 4 over Rational Field
3355
User basis matrix:
3356
[ 5 1 0 0 0 0 0]
3357
[-1 0 0 -1 1 0 0]
3358
[-1 0 1 2 0 1 0]
3359
[ 1 0 -1 -1 0 0 1]
3360
sage: A*K.basis_matrix().transpose() == zero_matrix(QQ, 4, 4)
3361
True
3362
3363
Matrices may have any field as a base ring. Number fields are
3364
computed by PARI library code, matrices over `GF(2)` are computed
3365
by the M4RI library, and matrices over the rationals are computed by
3366
the IML library. For any of these specialized cases, general-purpose
3367
code can be called instead with the keyword setting
3368
``algorithm='generic'``.
3369
3370
Over an arbitrary field, with two basis formats. Same vector space,
3371
different bases. ::
3372
3373
sage: F.<a> = FiniteField(5^2)
3374
sage: A = matrix(F, 3, 4, [[ 1, a, 1+a, a^3+a^5],
3375
... [ a, a^4, a+a^4, a^4+a^8],
3376
... [a^2, a^6, a^2+a^6, a^5+a^10]])
3377
sage: K = A.right_kernel(); K
3378
Vector space of degree 4 and dimension 2 over Finite Field in a of size 5^2
3379
Basis matrix:
3380
[ 1 0 3*a + 4 2*a + 2]
3381
[ 0 1 2*a 3*a + 3]
3382
sage: A*K.basis_matrix().transpose() == zero_matrix(F, 3, 2)
3383
True
3384
sage: B = copy(A)
3385
sage: P = B.right_kernel(basis = 'pivot'); P
3386
Vector space of degree 4 and dimension 2 over Finite Field in a of size 5^2
3387
User basis matrix:
3388
[ 4 4 1 0]
3389
[ a + 2 3*a + 3 0 1]
3390
sage: B*P.basis_matrix().transpose() == zero_matrix(F, 3, 2)
3391
True
3392
sage: K == P
3393
True
3394
3395
Over number fields, PARI is used by default, but general-purpose code
3396
can be requested. Same vector space, same bases, different code.::
3397
3398
sage: Q = QuadraticField(-7)
3399
sage: a = Q.gen(0)
3400
sage: A = matrix(Q, [[ 2, 5-a, 15-a, 16+4*a],
3401
... [2+a, a, -7 + 5*a, -3+3*a]])
3402
sage: K = A.right_kernel(algorithm='default'); K
3403
Vector space of degree 4 and dimension 2 over Number Field in a with defining polynomial x^2 + 7
3404
Basis matrix:
3405
[ 1 0 7/88*a + 3/88 -3/176*a - 39/176]
3406
[ 0 1 -1/88*a - 13/88 13/176*a - 7/176]
3407
sage: A*K.basis_matrix().transpose() == zero_matrix(Q, 2, 2)
3408
True
3409
sage: B = copy(A)
3410
sage: G = A.right_kernel(algorithm='generic'); G
3411
Vector space of degree 4 and dimension 2 over Number Field in a with defining polynomial x^2 + 7
3412
Basis matrix:
3413
[ 1 0 7/88*a + 3/88 -3/176*a - 39/176]
3414
[ 0 1 -1/88*a - 13/88 13/176*a - 7/176]
3415
sage: B*G.basis_matrix().transpose() == zero_matrix(Q, 2, 2)
3416
True
3417
sage: K == G
3418
True
3419
3420
For matrices over the integers, several options are possible.
3421
The basis can be an LLL-reduced basis or an echelon basis.
3422
The pivot basis isnot available. A heuristic will decide whether
3423
to use a p-adic algorithm from the IML library or an algorithm
3424
from the PARI library. Note how specifying the algorithm can
3425
mildly influence the LLL basis. ::
3426
3427
sage: A = matrix(ZZ, [[0, -1, -1, 2, 9, 4, -4],
3428
... [-1, 1, 0, -2, -7, -1, 6],
3429
... [2, 0, 1, 0, 1, -5, -2],
3430
... [-1, -1, -1, 3, 10, 10, -9],
3431
... [-1, 2, 0, -3, -7, 1, 6]])
3432
sage: A.right_kernel(basis='echelon')
3433
Free module of degree 7 and rank 2 over Integer Ring
3434
Echelon basis matrix:
3435
[ 1 5 -8 3 -1 -1 -1]
3436
[ 0 11 -19 5 -2 -3 -3]
3437
sage: B = copy(A)
3438
sage: B.right_kernel(basis='LLL')
3439
Free module of degree 7 and rank 2 over Integer Ring
3440
User basis matrix:
3441
[ 2 -1 3 1 0 1 1]
3442
[-5 -3 2 -5 1 -1 -1]
3443
sage: C = copy(A)
3444
sage: C.right_kernel(basis='pivot')
3445
Traceback (most recent call last):
3446
...
3447
ValueError: pivot basis only available over a field, not over Integer Ring
3448
sage: D = copy(A)
3449
sage: D.right_kernel(algorithm='pari')
3450
Free module of degree 7 and rank 2 over Integer Ring
3451
Echelon basis matrix:
3452
[ 1 5 -8 3 -1 -1 -1]
3453
[ 0 11 -19 5 -2 -3 -3]
3454
sage: E = copy(A)
3455
sage: E.right_kernel(algorithm='padic', basis='LLL')
3456
Free module of degree 7 and rank 2 over Integer Ring
3457
User basis matrix:
3458
[-2 1 -3 -1 0 -1 -1]
3459
[ 5 3 -2 5 -1 1 1]
3460
3461
Besides the integers, rings may be as general as principal ideal
3462
domains. Results are then free modules. ::
3463
3464
sage: R.<y> = QQ[]
3465
sage: A = matrix(R, [[ 1, y, 1+y^2],
3466
... [y^3, y^2, 2*y^3]])
3467
sage: K = A.right_kernel(algorithm='default', basis='echelon'); K
3468
Free module of degree 3 and rank 1 over Univariate Polynomial Ring in y over Rational Field
3469
Echelon basis matrix:
3470
[-1 -y 1]
3471
sage: A*K.basis_matrix().transpose() == zero_matrix(ZZ, 2, 1)
3472
True
3473
3474
It is possible to compute a kernel for a matrix over an integral
3475
domain which is not a PID, but usually this will fail. ::
3476
3477
sage: D.<x> = ZZ[]
3478
sage: A = matrix(D, 2, 2, [[x^2 - x, -x + 5],
3479
... [x^2 - 8, -x + 2]])
3480
sage: A.right_kernel()
3481
Traceback (most recent call last):
3482
...
3483
ArithmeticError: Ideal Ideal (x^2 - x, x^2 - 8) of Univariate Polynomial Ring in x over Integer Ring not principal
3484
3485
Matrices over non-commutative rings are not a good idea either.
3486
These are the "usual" quaternions. ::
3487
3488
sage: Q.<i,j,k> = QuaternionAlgebra(-1,-1)
3489
sage: A = matrix(Q, 2, [i,j,-1,k])
3490
sage: A.right_kernel()
3491
Traceback (most recent call last):
3492
...
3493
NotImplementedError: Cannot compute a matrix kernel over Quaternion Algebra (-1, -1) with base ring Rational Field
3494
3495
Sparse matrices, over the rationals and the integers,
3496
use the same routines as the dense versions. ::
3497
3498
sage: A = matrix(ZZ, [[0, -1, 1, 1, 2],
3499
... [1, -2, 0, 1, 3],
3500
... [-1, 2, 0, -1, -3]],
3501
... sparse=True)
3502
sage: A.right_kernel()
3503
Free module of degree 5 and rank 3 over Integer Ring
3504
Echelon basis matrix:
3505
[ 1 0 0 2 -1]
3506
[ 0 1 0 -1 1]
3507
[ 0 0 1 -3 1]
3508
sage: B = A.change_ring(QQ)
3509
sage: B.is_sparse()
3510
True
3511
sage: B.right_kernel()
3512
Vector space of degree 5 and dimension 3 over Rational Field
3513
Basis matrix:
3514
[ 1 0 0 2 -1]
3515
[ 0 1 0 -1 1]
3516
[ 0 0 1 -3 1]
3517
3518
With no columns, the kernel can only have dimension zero.
3519
With no rows, every possible vector is in the kernel. ::
3520
3521
sage: A = matrix(QQ, 2, 0)
3522
sage: A.right_kernel()
3523
Vector space of degree 0 and dimension 0 over Rational Field
3524
Basis matrix:
3525
[]
3526
sage: A = matrix(QQ, 0, 2)
3527
sage: A.right_kernel()
3528
Vector space of degree 2 and dimension 2 over Rational Field
3529
Basis matrix:
3530
[1 0]
3531
[0 1]
3532
3533
Every vector is in the kernel of a zero matrix, the
3534
dimension is the number of columns. ::
3535
3536
sage: A = zero_matrix(QQ, 10, 20)
3537
sage: A.right_kernel()
3538
Vector space of degree 20 and dimension 20 over Rational Field
3539
Basis matrix:
3540
20 x 20 dense matrix over Rational Field
3541
3542
Results are cached as the right kernel of the matrix.
3543
Subsequent requests for the right kernel will return
3544
the cached result, without regard for new values of the
3545
algorithm or format keyword. Work with a copy if you
3546
need a new right kernel, or perhaps investigate the
3547
:meth:`right_kernel_matrix` method, which does not
3548
cache its results and is more flexible. ::
3549
3550
sage: A = matrix(QQ, 3, range(9))
3551
sage: K1 = A.right_kernel(basis='echelon')
3552
sage: K1
3553
Vector space of degree 3 and dimension 1 over Rational Field
3554
Basis matrix:
3555
[ 1 -2 1]
3556
sage: K2 = A.right_kernel(basis='pivot')
3557
sage: K2
3558
Vector space of degree 3 and dimension 1 over Rational Field
3559
Basis matrix:
3560
[ 1 -2 1]
3561
sage: K1 is K2
3562
True
3563
sage: B = copy(A)
3564
sage: K3 = B.kernel(basis='pivot')
3565
sage: K3
3566
Vector space of degree 3 and dimension 1 over Rational Field
3567
User basis matrix:
3568
[ 1 -2 1]
3569
sage: K3 is K1
3570
False
3571
sage: K3 == K1
3572
True
3573
"""
3574
K = self.fetch('right_kernel')
3575
if not K is None:
3576
verbose("retrieving cached right kernel for %sx%s matrix" % (self.nrows(), self.ncols()),level=1)
3577
return K
3578
3579
R = self.base_ring()
3580
tm = verbose("computing a right kernel for %sx%s matrix over %s" % (self.nrows(), self.ncols(), R),level=1)
3581
3582
# Sanitize basis format
3583
# 'computed' is OK in right_kernel_matrix(), but not here
3584
# 'echelon' is default here (and elsewhere)
3585
# everything else gets checked in right_kernel_matrix()
3586
basis = kwds.pop('basis', None)
3587
if basis == 'computed':
3588
raise ValueError("kernel basis format 'computed' not supported for kernels (just right kernel matrices)")
3589
if basis is None:
3590
basis = 'echelon'
3591
kwds['basis'] = basis
3592
3593
# Go get the kernel matrix, this is where it all happens
3594
M = self.right_kernel_matrix(*args, **kwds)
3595
3596
ambient = R**self.ncols()
3597
if basis == 'echelon':
3598
K = ambient.submodule(M.rows(), already_echelonized=True, check=False)
3599
else:
3600
K = ambient.submodule_with_basis(M.rows(), already_echelonized=False, check=False)
3601
3602
verbose("done computing a right kernel for %sx%s matrix over %s" % (self.nrows(), self.ncols(), R),level=1, t=tm)
3603
self.cache('right_kernel', K)
3604
return K
3605
3606
def left_kernel(self, *args, **kwds):
3607
r"""
3608
Returns the left kernel of this matrix, as a vector space or free module.
3609
This is the set of vectors ``x`` such that ``x*self = 0``.
3610
3611
.. note::
3612
3613
For the right kernel, use :meth:`right_kernel`. The method
3614
:meth:`kernel` is exactly equal to :meth:`left_kernel`.
3615
3616
INPUT:
3617
3618
- ``algorithm`` - default: 'default' - a keyword that selects the
3619
algorithm employed. Allowable values are:
3620
3621
- 'default' - allows the algorithm to be chosen automatically
3622
- 'generic' - naive algorithm usable for matrices over any field
3623
- 'pari' - PARI library code for matrices over number fields
3624
or the integers
3625
- 'padic' - padic algorithm from IML library for matrices
3626
over the rationals and integers
3627
- 'pluq' - PLUQ matrix factorization for matrices mod 2
3628
3629
- ``basis`` - default: 'echelon' - a keyword that describes
3630
the format of the basis used to construct the left kernel.
3631
Allowable values are:
3632
3633
- 'echelon': the basis matrix is in echelon form
3634
- 'pivot' : each basis vector is computed from the reduced
3635
row-echelon form of ``self`` by placing a single one in a
3636
non-pivot column and zeros in the remaining non-pivot columns.
3637
Only available for matrices over fields.
3638
- 'LLL': an LLL-reduced basis. Only available for matrices
3639
over the integers.
3640
3641
OUTPUT:
3642
3643
A vector space or free module whose degree equals the number
3644
of rows in ``self`` and contains all the vectors ``x`` such
3645
that ``x*self = 0``.
3646
3647
If ``self`` has 0 rows, the kernel has dimension 0, while if ``self``
3648
has 0 columns the kernel is the entire ambient vector space.
3649
3650
The result is cached. Requesting the left kernel a second time,
3651
but with a different basis format will return the cached result
3652
with the format from the first computation.
3653
3654
.. note::
3655
3656
For much more detailed documentation of the various options see
3657
:meth:`right_kernel`, since this method just computes
3658
the right kernel of the transpose of ``self``.
3659
3660
EXAMPLES:
3661
3662
Over the rationals with a basis matrix in echelon form. ::
3663
3664
sage: A = matrix(QQ, [[1, 2, 4, -7, 4],
3665
... [1, 1, 0, 2, -1],
3666
... [1, 0, 3, -3, 1],
3667
... [0, -1, -1, 3, -2],
3668
... [0, 0, -1, 2, -1]])
3669
sage: A.left_kernel()
3670
Vector space of degree 5 and dimension 2 over Rational Field
3671
Basis matrix:
3672
[ 1 0 -1 2 -1]
3673
[ 0 1 -1 1 -4]
3674
3675
Over a finite field, with a basis matrix in "pivot" format. ::
3676
3677
sage: A = matrix(FiniteField(7), [[5, 0, 5, 2, 4],
3678
... [1, 3, 2, 3, 6],
3679
... [1, 1, 6, 5, 3],
3680
... [2, 5, 6, 0, 0]])
3681
sage: A.kernel(basis='pivot')
3682
Vector space of degree 4 and dimension 2 over Finite Field of size 7
3683
User basis matrix:
3684
[5 2 1 0]
3685
[6 3 0 1]
3686
3687
The left kernel of a zero matrix is the entire ambient vector
3688
space whose degree equals the number of rows of ``self``
3689
(i.e. everything). ::
3690
3691
sage: A = MatrixSpace(QQ, 3, 4)(0)
3692
sage: A.kernel()
3693
Vector space of degree 3 and dimension 3 over Rational Field
3694
Basis matrix:
3695
[1 0 0]
3696
[0 1 0]
3697
[0 0 1]
3698
3699
We test matrices with no rows or columns. ::
3700
3701
sage: A = matrix(QQ, 2, 0)
3702
sage: A.left_kernel()
3703
Vector space of degree 2 and dimension 2 over Rational Field
3704
Basis matrix:
3705
[1 0]
3706
[0 1]
3707
sage: A = matrix(QQ, 0, 2)
3708
sage: A.left_kernel()
3709
Vector space of degree 0 and dimension 0 over Rational Field
3710
Basis matrix:
3711
[]
3712
3713
The results are cached. Note that requesting a new format
3714
for the basis is ignored and the cached copy is returned.
3715
Work with a copy if you need a new left kernel, or perhaps
3716
investigate the :meth:`right_kernel_matrix` method on the
3717
transpose, which does not cache its results and is more
3718
flexible. ::
3719
3720
sage: A = matrix(QQ, [[1,1],[2,2]])
3721
sage: K1 = A.left_kernel()
3722
sage: K1
3723
Vector space of degree 2 and dimension 1 over Rational Field
3724
Basis matrix:
3725
[ 1 -1/2]
3726
sage: K2 = A.left_kernel()
3727
sage: K1 is K2
3728
True
3729
sage: K3 = A.left_kernel(basis='pivot')
3730
sage: K3
3731
Vector space of degree 2 and dimension 1 over Rational Field
3732
Basis matrix:
3733
[ 1 -1/2]
3734
sage: B = copy(A)
3735
sage: K3 = B.left_kernel(basis='pivot')
3736
sage: K3
3737
Vector space of degree 2 and dimension 1 over Rational Field
3738
User basis matrix:
3739
[-2 1]
3740
sage: K3 is K1
3741
False
3742
sage: K3 == K1
3743
True
3744
"""
3745
K = self.fetch('left_kernel')
3746
if not K is None:
3747
verbose("retrieving cached left kernel for %sx%s matrix" % (self.nrows(), self.ncols()),level=1)
3748
return K
3749
3750
tm = verbose("computing left kernel for %sx%s matrix" % (self.nrows(), self.ncols()),level=1)
3751
K = self.transpose().right_kernel(*args, **kwds)
3752
self.cache('left_kernel', K)
3753
verbose("done computing left kernel for %sx%s matrix" % (self.nrows(), self.ncols()),level=1,t=tm)
3754
return K
3755
3756
# .kernel() is a an alias for .left_kernel()
3757
kernel = left_kernel
3758
3759
def kernel_on(self, V, poly=None, check=True):
3760
"""
3761
Return the kernel of self restricted to the invariant subspace V.
3762
The result is a vector subspace of V, which is also a subspace
3763
of the ambient space.
3764
3765
INPUT:
3766
3767
- ``V`` - vector subspace
3768
3769
- ``check`` - (optional) default: True; whether to check that
3770
V is invariant under the action of self.
3771
3772
- ``poly`` - (optional) default: None; if not None, compute instead
3773
the kernel of poly(self) on V.
3774
3775
OUTPUT:
3776
3777
- a subspace
3778
3779
.. warning::
3780
3781
This function does *not* check that V is in fact
3782
invariant under self if check is False. With check False this
3783
function is much faster.
3784
3785
EXAMPLES::
3786
3787
sage: t = matrix(QQ, 4, [39, -10, 0, -12, 0, 2, 0, -1, 0, 1, -2, 0, 0, 2, 0, -2]); t
3788
[ 39 -10 0 -12]
3789
[ 0 2 0 -1]
3790
[ 0 1 -2 0]
3791
[ 0 2 0 -2]
3792
sage: t.fcp()
3793
(x - 39) * (x + 2) * (x^2 - 2)
3794
sage: s = (t-39)*(t^2-2)
3795
sage: V = s.kernel(); V
3796
Vector space of degree 4 and dimension 3 over Rational Field
3797
Basis matrix:
3798
[1 0 0 0]
3799
[0 1 0 0]
3800
[0 0 0 1]
3801
sage: s.restrict(V)
3802
[0 0 0]
3803
[0 0 0]
3804
[0 0 0]
3805
sage: s.kernel_on(V)
3806
Vector space of degree 4 and dimension 3 over Rational Field
3807
Basis matrix:
3808
[1 0 0 0]
3809
[0 1 0 0]
3810
[0 0 0 1]
3811
sage: k = t-39
3812
sage: k.restrict(V)
3813
[ 0 -10 -12]
3814
[ 0 -37 -1]
3815
[ 0 2 -41]
3816
sage: ker = k.kernel_on(V); ker
3817
Vector space of degree 4 and dimension 1 over Rational Field
3818
Basis matrix:
3819
[ 1 -2/7 0 -2/7]
3820
sage: ker.0 * k
3821
(0, 0, 0, 0)
3822
3823
Test that trac ticket #9425 is fixed.
3824
3825
::
3826
3827
sage: V = span([[1/7,0,0] ,[0,1,0]], ZZ); V
3828
Free module of degree 3 and rank 2 over Integer Ring
3829
Echelon basis matrix:
3830
[1/7 0 0]
3831
[ 0 1 0]
3832
sage: T = matrix(ZZ,3,[1,0,0,0,0,0,0,0,0]); T
3833
[1 0 0]
3834
[0 0 0]
3835
[0 0 0]
3836
sage: W = T.kernel_on(V); W.basis()
3837
[
3838
(0, 1, 0)
3839
]
3840
sage: W.is_submodule(V)
3841
True
3842
"""
3843
A = self.restrict(V, check=check)
3844
if not poly is None:
3845
A = poly(A)
3846
W = A.kernel()
3847
if V.is_ambient():
3848
return W
3849
else:
3850
A = V.basis_matrix()
3851
B = W.basis_matrix()
3852
C = B*A
3853
return C.row_module(base_ring=V.base_ring())
3854
3855
3856
def integer_kernel(self, ring=ZZ):
3857
"""
3858
Return the kernel of this matrix over the given ring (which should be
3859
either the base ring, or a PID whose fraction field is the base ring).
3860
3861
Assume that the base field of this matrix has a numerator and
3862
denominator functions for its elements, e.g., it is the rational
3863
numbers or a fraction field. This function computes a basis over
3864
the integers for the kernel of self.
3865
3866
If the matrix is not coercible into QQ, then the PID itself should be
3867
given as a second argument, as in the third example below.
3868
3869
EXAMPLES::
3870
3871
sage: A = MatrixSpace(QQ, 4)(range(16))
3872
sage: A.integer_kernel()
3873
Free module of degree 4 and rank 2 over Integer Ring
3874
Echelon basis matrix:
3875
[ 1 0 -3 2]
3876
[ 0 1 -2 1]
3877
3878
The integer kernel even makes sense for matrices with fractional
3879
entries::
3880
3881
sage: A = MatrixSpace(QQ, 2)(['1/2',0, 0, 0])
3882
sage: A.integer_kernel()
3883
Free module of degree 2 and rank 1 over Integer Ring
3884
Echelon basis matrix:
3885
[0 1]
3886
3887
An example over a bigger ring::
3888
3889
sage: L.<w> = NumberField(x^2 - x + 2)
3890
sage: OL = L.ring_of_integers()
3891
sage: A = matrix(L, 2, [1, w/2])
3892
sage: A.integer_kernel(OL)
3893
Free module of degree 2 and rank 1 over Maximal Order in Number Field in w with defining polynomial x^2 - x + 2
3894
Echelon basis matrix:
3895
[ -1 -w + 1]
3896
3897
"""
3898
try:
3899
A, _ = self._clear_denom()
3900
return A.kernel()
3901
except AttributeError:
3902
d = self.denominator()
3903
A = self*d
3904
M = matrix_space.MatrixSpace(ring, self.nrows(), self.ncols())(A)
3905
return M.kernel()
3906
3907
def image(self):
3908
"""
3909
Return the image of the homomorphism on rows defined by this
3910
matrix.
3911
3912
EXAMPLES::
3913
3914
sage: MS1 = MatrixSpace(ZZ,4)
3915
sage: MS2 = MatrixSpace(QQ,6)
3916
sage: A = MS1.matrix([3,4,5,6,7,3,8,10,14,5,6,7,2,2,10,9])
3917
sage: B = MS2.random_element()
3918
3919
::
3920
3921
sage: image(A)
3922
Free module of degree 4 and rank 4 over Integer Ring
3923
Echelon basis matrix:
3924
[ 1 0 0 426]
3925
[ 0 1 0 518]
3926
[ 0 0 1 293]
3927
[ 0 0 0 687]
3928
3929
::
3930
3931
sage: image(B) == B.row_module()
3932
True
3933
"""
3934
return self.row_module()
3935
3936
def _row_ambient_module(self, base_ring=None):
3937
if base_ring is None:
3938
base_ring = self.base_ring()
3939
x = self.fetch('row_ambient_module_%s'%base_ring)
3940
if not x is None:
3941
return x
3942
x = sage.modules.free_module.FreeModule(base_ring, self.ncols(), sparse=self.is_sparse())
3943
self.cache('row_ambient_module',x)
3944
return x
3945
3946
def row_module(self, base_ring=None):
3947
"""
3948
Return the free module over the base ring spanned by the rows of
3949
self.
3950
3951
EXAMPLES::
3952
3953
sage: A = MatrixSpace(IntegerRing(), 2)([1,2,3,4])
3954
sage: A.row_module()
3955
Free module of degree 2 and rank 2 over Integer Ring
3956
Echelon basis matrix:
3957
[1 0]
3958
[0 2]
3959
"""
3960
M = self._row_ambient_module(base_ring = base_ring)
3961
if (base_ring is None or base_ring == self.base_ring()) and self.fetch('in_echelon_form'):
3962
if self.rank() != self.nrows():
3963
rows = self.matrix_from_rows(range(self.rank())).rows()
3964
else:
3965
rows = self.rows()
3966
return M.span(rows, already_echelonized=True)
3967
else:
3968
return M.span(self.rows(), already_echelonized=False)
3969
3970
def row_space(self, base_ring=None):
3971
"""
3972
Return the row space of this matrix. (Synonym for
3973
self.row_module().)
3974
3975
EXAMPLES::
3976
3977
sage: t = matrix(QQ, 3, range(9)); t
3978
[0 1 2]
3979
[3 4 5]
3980
[6 7 8]
3981
sage: t.row_space()
3982
Vector space of degree 3 and dimension 2 over Rational Field
3983
Basis matrix:
3984
[ 1 0 -1]
3985
[ 0 1 2]
3986
3987
::
3988
3989
sage: m = Matrix(Integers(5),2,2,[2,2,2,2]);
3990
sage: m.row_space()
3991
Vector space of degree 2 and dimension 1 over Ring of integers modulo 5
3992
Basis matrix:
3993
[1 1]
3994
"""
3995
return self.row_module(base_ring=base_ring)
3996
3997
3998
def _column_ambient_module(self):
3999
x = self.fetch('column_ambient_module')
4000
if not x is None:
4001
return x
4002
x = sage.modules.free_module.FreeModule(self.base_ring(), self.nrows(),
4003
sparse=self.is_sparse())
4004
self.cache('column_ambient_module',x)
4005
return x
4006
4007
def column_module(self):
4008
"""
4009
Return the free module over the base ring spanned by the columns of
4010
this matrix.
4011
4012
EXAMPLES::
4013
4014
sage: t = matrix(QQ, 3, range(9)); t
4015
[0 1 2]
4016
[3 4 5]
4017
[6 7 8]
4018
sage: t.column_module()
4019
Vector space of degree 3 and dimension 2 over Rational Field
4020
Basis matrix:
4021
[ 1 0 -1]
4022
[ 0 1 2]
4023
"""
4024
return self.transpose().row_module()
4025
4026
def column_space(self):
4027
"""
4028
Return the vector space over the base ring spanned by the columns
4029
of this matrix.
4030
4031
EXAMPLES::
4032
4033
sage: M = MatrixSpace(QQ,3,3)
4034
sage: A = M([1,9,-7,4/5,4,3,6,4,3])
4035
sage: A.column_space()
4036
Vector space of degree 3 and dimension 3 over Rational Field
4037
Basis matrix:
4038
[1 0 0]
4039
[0 1 0]
4040
[0 0 1]
4041
sage: W = MatrixSpace(CC,2,2)
4042
sage: B = W([1, 2+3*I,4+5*I,9]); B
4043
[ 1.00000000000000 2.00000000000000 + 3.00000000000000*I]
4044
[4.00000000000000 + 5.00000000000000*I 9.00000000000000]
4045
sage: B.column_space()
4046
Vector space of degree 2 and dimension 2 over Complex Field with 53 bits of precision
4047
Basis matrix:
4048
[ 1.00000000000000 0.000000000000000]
4049
[0.000000000000000 1.00000000000000]
4050
"""
4051
return self.column_module()
4052
4053
4054
4055
def decomposition(self, algorithm='spin',
4056
is_diagonalizable=False, dual=False):
4057
"""
4058
Returns the decomposition of the free module on which this matrix A
4059
acts from the right (i.e., the action is x goes to x A), along with
4060
whether this matrix acts irreducibly on each factor. The factors
4061
are guaranteed to be sorted in the same way as the corresponding
4062
factors of the characteristic polynomial.
4063
4064
Let A be the matrix acting from the on the vector space V of column
4065
vectors. Assume that A is square. This function computes maximal
4066
subspaces W_1, ..., W_n corresponding to Galois conjugacy classes
4067
of eigenvalues of A. More precisely, let `f(X)` be the characteristic
4068
polynomial of A. This function computes the subspace
4069
`W_i = ker(g_(A)^n)`, where `g_i(X)` is an irreducible
4070
factor of `f(X)` and `g_i(X)` exactly divides `f(X)`. If the optional
4071
parameter is_diagonalizable is True, then we let `W_i = ker(g(A))`,
4072
since then we know that `ker(g(A)) = ker(g(A)^n)`.
4073
4074
INPUT:
4075
4076
4077
- ``self`` - a matrix
4078
4079
- ``algorithm`` - 'spin' (default): algorithm involves
4080
iterating the action of self on a vector. 'kernel': naively just
4081
compute `ker(f_i(A))` for each factor `f_i`.
4082
4083
- ``dual`` - bool (default: False): If True, also
4084
returns the corresponding decomposition of V under the action of
4085
the transpose of A. The factors are guaranteed to correspond.
4086
4087
- ``is_diagonalizable`` - if the matrix is known to
4088
be diagonalizable, set this to True, which might speed up the
4089
algorithm in some cases.
4090
4091
.. note::
4092
4093
If the base ring is not a field, the kernel algorithm is
4094
used.
4095
4096
4097
OUTPUT:
4098
4099
4100
- ``Sequence`` - list of pairs (V,t), where V is a vector
4101
spaces and t is a bool, and t is True exactly when the
4102
charpoly of self on V is irreducible.
4103
4104
4105
- (optional) list - list of pairs (W,t), where W is a vector
4106
space and t is a bool, and t is True exactly when the
4107
charpoly of the transpose of self on W is irreducible.
4108
4109
EXAMPLES::
4110
4111
sage: A = matrix(ZZ, 4, [3,4,5,6,7,3,8,10,14,5,6,7,2,2,10,9])
4112
sage: B = matrix(QQ, 6, range(36))
4113
sage: B*11
4114
[ 0 11 22 33 44 55]
4115
[ 66 77 88 99 110 121]
4116
[132 143 154 165 176 187]
4117
[198 209 220 231 242 253]
4118
[264 275 286 297 308 319]
4119
[330 341 352 363 374 385]
4120
sage: A.decomposition()
4121
[
4122
(Ambient free module of rank 4 over the principal ideal domain Integer Ring, True)
4123
]
4124
sage: B.decomposition()
4125
[
4126
(Vector space of degree 6 and dimension 2 over Rational Field
4127
Basis matrix:
4128
[ 1 0 -1 -2 -3 -4]
4129
[ 0 1 2 3 4 5], True),
4130
(Vector space of degree 6 and dimension 4 over Rational Field
4131
Basis matrix:
4132
[ 1 0 0 0 -5 4]
4133
[ 0 1 0 0 -4 3]
4134
[ 0 0 1 0 -3 2]
4135
[ 0 0 0 1 -2 1], False)
4136
]
4137
"""
4138
if algorithm == 'kernel' or not self.base_ring().is_field():
4139
return self._decomposition_using_kernels(is_diagonalizable = is_diagonalizable, dual=dual)
4140
elif algorithm == 'spin':
4141
X = self._decomposition_spin_generic(is_diagonalizable = is_diagonalizable)
4142
if dual:
4143
Y = self.transpose()._decomposition_spin_generic(is_diagonalizable = is_diagonalizable)
4144
return X, Y
4145
return X
4146
else:
4147
raise ValueError, "no algorithm '%s'"%algorithm
4148
4149
def _decomposition_spin_generic(self, is_diagonalizable=False):
4150
r"""
4151
Compute the decomposition of this matrix using the spin algorithm.
4152
4153
INPUT:
4154
4155
- ``self`` - a matrix with field entries
4156
4157
OUTPUT: a list of reduced row echelon form basis
4158
4159
AUTHORS:
4160
4161
- William Stein
4162
"""
4163
if not self.is_square():
4164
raise ValueError, "self must be a square matrix"
4165
4166
if not self.base_ring().is_field():
4167
raise TypeError, "self must be over a field."
4168
4169
if self.nrows() == 0:
4170
return decomp_seq([])
4171
4172
f = self.charpoly('x')
4173
E = decomp_seq([])
4174
4175
t = verbose('factoring the characteristic polynomial', level=2, caller_name='generic spin decomp')
4176
F = f.factor()
4177
verbose('done factoring', t=t, level=2, caller_name='generic spin decomp')
4178
4179
if len(F) == 1:
4180
V = self.base_ring()**self.nrows()
4181
return decomp_seq([(V,F[0][1]==1)])
4182
4183
V = self.base_ring()**self.nrows()
4184
v = V.random_element()
4185
num_iterates = max([0] + [f.degree() - g.degree() for g, _ in F if g.degree() > 1]) + 1
4186
4187
S = [ ]
4188
4189
F.sort()
4190
for i in range(len(F)):
4191
g, m = F[i]
4192
4193
if g.degree() == 1:
4194
# Just use kernel -- much easier.
4195
B = self.__copy__()
4196
for k from 0 <= k < self.nrows():
4197
B[k,k] += g[0]
4198
if m > 1 and not is_diagonalizable:
4199
B = B**m
4200
W = B.kernel()
4201
E.append((W, m==1))
4202
continue
4203
4204
# General case, i.e., deg(g) > 1:
4205
W = None
4206
tries = m
4207
while True:
4208
4209
# Compute the complementary factor.
4210
h = f // (g**m)
4211
v = h.list()
4212
4213
while len(S) < tries:
4214
t = verbose('%s-spinning %s-th random vector'%(num_iterates, len(S)), level=2, caller_name='generic spin decomp')
4215
S.append(self.iterates(V.random_element(), num_iterates))
4216
verbose('done spinning', level=2, t=t, caller_name='generic spin decomp')
4217
4218
for j in range(0 if W is None else W.nrows() // g.degree(), len(S)):
4219
# Compute one element of the kernel of g(A)**m.
4220
t = verbose('compute element of kernel of g(A), for g of degree %s'%g.degree(),level=2,
4221
caller_name='generic spin decomp')
4222
w = S[j].linear_combination_of_rows(h.list())
4223
t = verbose('done computing element of kernel of g(A)', t=t,level=2, caller_name='generic spin decomp')
4224
4225
# Get the rest of the kernel.
4226
t = verbose('fill out rest of kernel',level=2, caller_name='generic spin decomp')
4227
if W is None:
4228
W = self.iterates(w, g.degree())
4229
else:
4230
W = W.stack(self.iterates(w, g.degree()))
4231
t = verbose('finished filling out more of kernel',level=2, t=t, caller_name='generic spin decomp')
4232
4233
if W.rank() == m * g.degree():
4234
t = verbose('now computing row space', level=2, caller_name='generic spin decomp')
4235
W.echelonize()
4236
E.append((W.row_space(), m==1))
4237
verbose('computed row space', level=2,t=t, caller_name='generic spin decomp')
4238
break
4239
else:
4240
verbose('we have not yet generated all the kernel (rank so far=%s, target rank=%s)'%(
4241
W.rank(), m*g.degree()), level=2, caller_name='generic spin decomp')
4242
tries += 1
4243
if tries > 1000*m: # avoid an insanely long infinite loop
4244
raise RuntimeError, "likely bug in decomposition"
4245
# end if
4246
#end while
4247
#end for
4248
return E
4249
4250
def _decomposition_using_kernels(self, is_diagonalizable=False, dual=False):
4251
if not self.is_square():
4252
raise ValueError, "self must be a square matrix"
4253
4254
if self.nrows() == 0:
4255
return decomp_seq([])
4256
4257
f = self.charpoly('x')
4258
E = decomp_seq([])
4259
4260
# Idea: For optimization, could compute powers of self
4261
# up to max degree of any factor. Then get g(self)
4262
# by taking a linear combination.
4263
4264
if dual:
4265
Edual = decomp_seq([])
4266
F = f.factor()
4267
if len(F) == 1:
4268
V = sage.modules.free_module.FreeModule(
4269
self.base_ring(), self.nrows(), sparse=self.is_sparse())
4270
m = F[0][1]
4271
if dual:
4272
return decomp_seq([(V, m==1)]), decomp_seq([(V, m==1)])
4273
else:
4274
return decomp_seq([(V, m==1)])
4275
F.sort()
4276
for g, m in f.factor():
4277
t = verbose('decomposition -- Computing g(self) for an irreducible factor g of degree %s'%g.degree(),level=2)
4278
if is_diagonalizable:
4279
B = g(self)
4280
else:
4281
B = g(self)
4282
t2 = verbose('decomposition -- raising g(self) to the power %s'%m,level=2)
4283
B = B ** m
4284
verbose('done powering',t2)
4285
t = verbose('decomposition -- done computing g(self)', level=2, t=t)
4286
E.append((B.kernel(), m==1))
4287
t = verbose('decomposition -- time to compute kernel', level=2, t=t)
4288
if dual:
4289
Edual.append((B.transpose().kernel(), m==1))
4290
verbose('decomposition -- time to compute dual kernel', level=2, t=t)
4291
if dual:
4292
return E, Edual
4293
return E
4294
4295
def decomposition_of_subspace(self, M, check_restrict = True, **kwds):
4296
"""
4297
Suppose the right action of self on M leaves M invariant. Return
4298
the decomposition of M as a list of pairs (W, is_irred) where
4299
is_irred is True if the charpoly of self acting on the factor W is
4300
irreducible.
4301
4302
Additional inputs besides M are passed onto the decomposition
4303
command.
4304
4305
INPUT:
4306
4307
- `M` -- A subspace of the free module ``self`` acts on.
4308
- ``check_restrict`` -- A boolean (default: ``True``); Call restrict
4309
with or without check.
4310
- ``kwds`` -- Keywords that will be forwarded to :meth:`~.decomposition`.
4311
4312
EXAMPLES::
4313
4314
sage: t = matrix(QQ, 3, [3, 0, -2, 0, -2, 0, 0, 0, 0]); t
4315
[ 3 0 -2]
4316
[ 0 -2 0]
4317
[ 0 0 0]
4318
sage: t.fcp('X') # factored charpoly
4319
(X - 3) * X * (X + 2)
4320
sage: v = kernel(t*(t+2)); v # an invariant subspace
4321
Vector space of degree 3 and dimension 2 over Rational Field
4322
Basis matrix:
4323
[0 1 0]
4324
[0 0 1]
4325
sage: D = t.decomposition_of_subspace(v); D
4326
[
4327
(Vector space of degree 3 and dimension 1 over Rational Field
4328
Basis matrix:
4329
[0 0 1], True),
4330
(Vector space of degree 3 and dimension 1 over Rational Field
4331
Basis matrix:
4332
[0 1 0], True)
4333
]
4334
sage: t.restrict(D[0][0])
4335
[0]
4336
sage: t.restrict(D[1][0])
4337
[-2]
4338
4339
We do a decomposition over ZZ::
4340
4341
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])
4342
sage: a.decomposition_of_subspace(ZZ^6)
4343
[
4344
(Free module of degree 6 and rank 2 over Integer Ring
4345
Echelon basis matrix:
4346
[ 1 0 1 -1 1 -1]
4347
[ 0 1 0 -1 2 -1], False),
4348
(Free module of degree 6 and rank 4 over Integer Ring
4349
Echelon basis matrix:
4350
[ 1 0 -1 0 1 0]
4351
[ 0 1 0 0 0 0]
4352
[ 0 0 0 1 0 0]
4353
[ 0 0 0 0 0 1], False)
4354
]
4355
4356
TESTS::
4357
4358
sage: t = matrix(QQ, 3, [3, 0, -2, 0, -2, 0, 0, 0, 0]);
4359
sage: t.decomposition_of_subspace(v, check_restrict = False) == t.decomposition_of_subspace(v)
4360
True
4361
"""
4362
if not sage.modules.free_module.is_FreeModule(M):
4363
raise TypeError, "M must be a free module."
4364
if not self.is_square():
4365
raise ArithmeticError, "self must be a square matrix"
4366
if M.base_ring() != self.base_ring():
4367
raise ArithmeticError, "base rings must be the same, but self is over %s and module is over %s"%(
4368
self.base_ring(), M.base_ring())
4369
if M.degree() != self.ncols():
4370
raise ArithmeticError, \
4371
"M must be a subspace of an %s-dimensional space"%self.ncols()
4372
4373
time = verbose(t=0)
4374
4375
# 1. Restrict
4376
B = self.restrict(M, check = check_restrict)
4377
time0 = verbose("decompose restriction -- ", time)
4378
4379
# 2. Decompose restriction
4380
D = B.decomposition(**kwds)
4381
4382
sum_dim = sum([A.dimension() for A,_ in D])
4383
assert sum_dim == M.dimension(), \
4384
"bug in decomposition; " + \
4385
"the sum of the dimensions (=%s) of the factors must equal the dimension (%s) of the acted on space:\nFactors found: %s\nSpace: %s"%(sum_dim, M.dimension(), D, M)
4386
4387
# 3. Lift decomposition to subspaces of ambient vector space.
4388
# Each basis vector for an element of D defines a linear
4389
# combination of the basis of W, and these linear combinations
4390
# define the corresponding subspaces of the ambient space M.
4391
4392
verbose("decomposition -- ", time0)
4393
C = M.basis_matrix()
4394
4395
D = [((W.basis_matrix() * C).row_module(self.base_ring()), is_irred) for W, is_irred in D]
4396
D = decomp_seq(D)
4397
4398
verbose(t=time)
4399
return D
4400
4401
def restrict(self, V, check=True):
4402
"""
4403
Returns the matrix that defines the action of self on the chosen
4404
basis for the invariant subspace V. If V is an ambient, returns
4405
self (not a copy of self).
4406
4407
INPUT:
4408
4409
4410
- ``V`` - vector subspace
4411
4412
- ``check`` - (optional) default: True; if False may
4413
not check that V is invariant (hence can be faster).
4414
4415
4416
OUTPUT: a matrix
4417
4418
.. warning::
4419
4420
This function returns an nxn matrix, where V has dimension
4421
n. It does *not* check that V is in fact invariant under
4422
self, unless check is True.
4423
4424
EXAMPLES::
4425
4426
sage: V = VectorSpace(QQ, 3)
4427
sage: M = MatrixSpace(QQ, 3)
4428
sage: A = M([1,2,0, 3,4,0, 0,0,0])
4429
sage: W = V.subspace([[1,0,0], [0,1,0]])
4430
sage: A.restrict(W)
4431
[1 2]
4432
[3 4]
4433
sage: A.restrict(W, check=True)
4434
[1 2]
4435
[3 4]
4436
4437
We illustrate the warning about invariance not being checked by
4438
default, by giving a non-invariant subspace. With the default
4439
check=False this function returns the 'restriction' matrix, which
4440
is meaningless as check=True reveals.
4441
4442
::
4443
4444
sage: W2 = V.subspace([[1,0,0], [0,1,1]])
4445
sage: A.restrict(W2, check=False)
4446
[1 2]
4447
[3 4]
4448
sage: A.restrict(W2, check=True)
4449
Traceback (most recent call last):
4450
...
4451
ArithmeticError: subspace is not invariant under matrix
4452
"""
4453
if not isinstance(V, sage.modules.free_module.FreeModule_generic):
4454
raise TypeError, "V must be a free module"
4455
#if V.base_ring() != self.base_ring():
4456
# raise ValueError, "matrix and module must have the same base ring, but matrix is over %s and module is over %s"%(self.base_ring(), V.base_ring())
4457
if V.degree() != self.nrows():
4458
raise IndexError, "degree of V (=%s) must equal number of rows of self (=%s)"%(\
4459
V.degree(), self.nrows())
4460
if V.rank() == 0 or V.degree() == 0:
4461
return self.new_matrix(nrows=0, ncols=0)
4462
4463
if not check and V.base_ring().is_field() and not V.has_user_basis():
4464
B = V.echelonized_basis_matrix()
4465
P = B.pivots()
4466
return B*self.matrix_from_columns(P)
4467
else:
4468
n = V.rank()
4469
try:
4470
# todo optimize so only involves matrix multiplies ?
4471
C = [V.coordinate_vector(b*self) for b in V.basis()]
4472
except ArithmeticError:
4473
raise ArithmeticError, "subspace is not invariant under matrix"
4474
return self.new_matrix(n, n, C, sparse=False)
4475
4476
def restrict_domain(self, V):
4477
"""
4478
Compute the matrix relative to the basis for V on the domain
4479
obtained by restricting self to V, but not changing the codomain of
4480
the matrix. This is the matrix whose rows are the images of the
4481
basis for V.
4482
4483
INPUT:
4484
4485
4486
- ``V`` - vector space (subspace of ambient space on
4487
which self acts)
4488
4489
4490
.. seealso::
4491
4492
:meth:`restrict`
4493
4494
EXAMPLES::
4495
4496
sage: V = QQ^3
4497
sage: A = matrix(QQ,3,[1,2,0, 3,4,0, 0,0,0])
4498
sage: W = V.subspace([[1,0,0], [1,2,3]])
4499
sage: A.restrict_domain(W)
4500
[1 2 0]
4501
[3 4 0]
4502
sage: W2 = V.subspace_with_basis([[1,0,0], [1,2,3]])
4503
sage: A.restrict_domain(W2)
4504
[ 1 2 0]
4505
[ 7 10 0]
4506
"""
4507
return V.basis_matrix() * self
4508
4509
def restrict_codomain(self, V):
4510
r"""
4511
Suppose that self defines a linear map from some domain to a
4512
codomain that contains `V` and that the image of self is
4513
contained in `V`. This function returns a new matrix
4514
`A` that represents this linear map but as a map to
4515
`V`, in the sense that if `x` is in the domain,
4516
then `xA` is the linear combination of the elements of the
4517
basis of `V` that equals v\*self.
4518
4519
INPUT:
4520
4521
4522
- ``V`` - vector space (space of degree
4523
``self.ncols()``) that contains the image of self.
4524
4525
4526
.. seealso::
4527
4528
:meth:`restrict`, :meth:`restrict_domain`
4529
4530
EXAMPLES::
4531
4532
sage: A = matrix(QQ,3,[1..9])
4533
sage: V = (QQ^3).span([[1,2,3], [7,8,9]]); V
4534
Vector space of degree 3 and dimension 2 over Rational Field
4535
Basis matrix:
4536
[ 1 0 -1]
4537
[ 0 1 2]
4538
sage: z = vector(QQ,[1,2,5])
4539
sage: B = A.restrict_codomain(V); B
4540
[1 2]
4541
[4 5]
4542
[7 8]
4543
sage: z*B
4544
(44, 52)
4545
sage: z*A
4546
(44, 52, 60)
4547
sage: 44*V.0 + 52*V.1
4548
(44, 52, 60)
4549
"""
4550
return V.basis_matrix().solve_left(self)
4551
4552
def maxspin(self, v):
4553
"""
4554
Computes the largest integer n such that the list of vectors
4555
`S=[v, v*A, ..., v * A^n]` are linearly independent, and
4556
returns that list.
4557
4558
INPUT:
4559
4560
4561
- ``self`` - Matrix
4562
4563
- ``v`` - Vector
4564
4565
4566
OUTPUT:
4567
4568
4569
- ``list`` - list of Vectors
4570
4571
4572
ALGORITHM: The current implementation just adds vectors to a vector
4573
space until the dimension doesn't grow. This could be optimized by
4574
directly using matrices and doing an efficient Echelon form. Also,
4575
when the base is Q, maybe we could simultaneously keep track of
4576
what is going on in the reduction modulo p, which might make things
4577
much faster.
4578
4579
EXAMPLES::
4580
4581
sage: t = matrix(QQ, 3, range(9)); t
4582
[0 1 2]
4583
[3 4 5]
4584
[6 7 8]
4585
sage: v = (QQ^3).0
4586
sage: t.maxspin(v)
4587
[(1, 0, 0), (0, 1, 2), (15, 18, 21)]
4588
sage: k = t.kernel(); k
4589
Vector space of degree 3 and dimension 1 over Rational Field
4590
Basis matrix:
4591
[ 1 -2 1]
4592
sage: t.maxspin(k.0)
4593
[(1, -2, 1)]
4594
"""
4595
if v == 0:
4596
return []
4597
if not is_FreeModuleElement(v):
4598
raise TypeError, "v must be a FreeModuleElement"
4599
VS = v.parent()
4600
V = VS.span([v])
4601
w = v
4602
S = [v]
4603
while True:
4604
w = w*self
4605
W = V + VS.span([w])
4606
if W.dimension() == V.dimension():
4607
return S
4608
V = W
4609
S.append(w)
4610
4611
4612
def wiedemann(self, i, t=0):
4613
"""
4614
Application of Wiedemann's algorithm to the i-th standard basis
4615
vector.
4616
4617
INPUT:
4618
4619
4620
- ``i`` - an integer
4621
4622
- ``t`` - an integer (default: 0) if t is nonzero, use
4623
only the first t linear recurrence relations.
4624
4625
4626
IMPLEMENTATION: This is a toy implementation.
4627
4628
EXAMPLES::
4629
4630
sage: t = matrix(QQ, 3, range(9)); t
4631
[0 1 2]
4632
[3 4 5]
4633
[6 7 8]
4634
sage: t.wiedemann(0)
4635
x^2 - 12*x - 18
4636
sage: t.charpoly()
4637
x^3 - 12*x^2 - 18*x
4638
"""
4639
i = int(i); t=int(t)
4640
if self.nrows() != self.ncols():
4641
raise ArithmeticError, "self must be a square matrix"
4642
n = self.nrows()
4643
v = sage.modules.free_module.VectorSpace(self.base_ring(), n).gen(i)
4644
tm = verbose('computing iterates...')
4645
cols = self.iterates(v, 2*n).columns()
4646
tm = verbose('computed iterates', tm)
4647
f = None
4648
# Compute the minimal polynomial of the linear recurrence
4649
# sequence corresponding to the 0-th entries of the iterates,
4650
# then the 1-th entries, etc.
4651
if t == 0:
4652
R = range(n)
4653
else:
4654
R = [t]
4655
for i in R:
4656
tm = verbose('applying berlekamp-massey')
4657
g = berlekamp_massey.berlekamp_massey(cols[i].list())
4658
verbose('berlekamp-massey done', tm)
4659
if f is None:
4660
f = g
4661
else:
4662
f = f.lcm(g)
4663
if f.degree() == n:
4664
break
4665
return f
4666
4667
# Deprecated Aug 2008 Trac #3794
4668
# Removed July 2011
4669
# def eigenspaces(self, var='a', even_if_inexact=None):
4670
4671
def _eigenspace_format(self, format):
4672
r"""
4673
Helper method to control output format for eigenspaces.
4674
4675
INPUT:
4676
4677
- ``format`` - ``None``, ``'all'`` or ``'galois'``
4678
4679
OUTPUT:
4680
4681
Any format except ``None`` is just passed through. When the
4682
format is ``None`` a choice is made about the style of the output.
4683
If there is an algebraically closed field that will contain the
4684
possible eigenvalues, then 'all" of the eigenspaces are given.
4685
4686
However if this is not the case, then only one eigenspace is output
4687
for each irreducible factor of the characteristic polynomial.
4688
4689
EXAMPLES:
4690
4691
Pass-through first. ::
4692
4693
sage: A = matrix(QQ, 2, range(4))
4694
sage: A._eigenspace_format('all') == 'all'
4695
True
4696
sage: A._eigenspace_format('galois') == 'galois'
4697
True
4698
4699
The algebraic closure of the rationals, the field of algebraic numbers,
4700
(aka ``QQbar``) is implemented, while in general the algebraic closure
4701
of a finite field is not implemented. ::
4702
4703
sage: A = matrix(QQ, 2, range(4))
4704
sage: A._eigenspace_format(None) == 'all'
4705
True
4706
sage: B = matrix(GF(13), 2, range(4))
4707
sage: B._eigenspace_format(None) == 'galois'
4708
True
4709
4710
Subrings are promoted to fraction fields and then checked for the
4711
existence of algebraic closures. ::
4712
4713
sage: A = matrix(ZZ, 2, range(4))
4714
sage: A._eigenspace_format(None) == 'all'
4715
True
4716
"""
4717
if not format in [None, 'all', 'galois']:
4718
msg = "format keyword must be None, 'all' or 'galois', not {0}"
4719
raise ValueError(msg.format(format))
4720
4721
# For subrings of implemented algebraically closed fields we
4722
# default to all eigenspaces in the absence of a format keyword
4723
# Add newly implemented algebraically closed fields to list below
4724
# and implement the determintion of the actual eigenvalues
4725
# in the eigenspace_left() routine
4726
if format is None:
4727
R = self.base_ring()
4728
from sage.rings.qqbar import QQbar
4729
try:
4730
if R.fraction_field().algebraic_closure() in [QQbar]:
4731
return 'all'
4732
else:
4733
return 'galois'
4734
except (NotImplementedError, AttributeError):
4735
return 'galois'
4736
else:
4737
return format
4738
4739
def eigenspaces_left(self, format='all', var='a', algebraic_multiplicity=False):
4740
r"""
4741
Compute the left eigenspaces of a matrix.
4742
4743
Note that ``eigenspaces_left()`` and ``left_eigenspaces()``
4744
are identical methods. Here "left" refers to the eigenvectors
4745
being placed to the left of the matrix.
4746
4747
INPUT:
4748
4749
- ``self`` - a square matrix over an exact field. For inexact
4750
matrices consult the numerical or symbolic matrix classes.
4751
4752
- ``format`` - default: ``None``
4753
4754
- ``'all'`` - attempts to create every eigenspace. This will
4755
always be possible for matrices with rational entries.
4756
- ``'galois'`` - for each irreducible factor of the characteristic
4757
polynomial, a single eigenspace will be output for a
4758
single root/eigenvalue for the irreducible factor.
4759
- ``None`` - Uses the 'all' format if the base ring is contained
4760
in an algebraically closed field which is implemented.
4761
Otherwise, uses the 'galois' format.
4762
4763
- ``var`` - default: 'a' - variable name used to
4764
represent elements of the root field of each
4765
irreducible factor of the characteristic polynomial.
4766
If var='a', then the root fields will be in terms of
4767
a0, a1, a2, ...., where the numbering runs across all
4768
the irreducible factors of the characteristic polynomial,
4769
even for linear factors.
4770
4771
- ``algebraic_multiplicity`` - default: False - whether or
4772
not to include the algebraic multiplicity of each eigenvalue
4773
in the output. See the discussion below.
4774
4775
OUTPUT:
4776
4777
If algebraic_multiplicity=False, return a list of pairs (e, V)
4778
where e is an eigenvalue of the matrix, and V is the corresponding
4779
left eigenspace. For Galois conjugates of eigenvalues, there
4780
may be just one representative eigenspace, depending on the
4781
``format`` keyword.
4782
4783
If algebraic_multiplicity=True, return a list of triples (e, V, n)
4784
where e and V are as above and n is the algebraic multiplicity of
4785
the eigenvalue.
4786
4787
.. warning::
4788
4789
Uses a somewhat naive algorithm (simply factors the
4790
characteristic polynomial and computes kernels directly
4791
over the extension field).
4792
4793
EXAMPLES:
4794
4795
We compute the left eigenspaces of a `3\times 3`
4796
rational matrix. First, we request `all` of the eigenvalues,
4797
so the results are in the field of algebraic numbers, `QQbar`.
4798
Then we request just one eigenspace per irreducible factor of
4799
the characteristic polynomial with the `galois` keyword. ::
4800
4801
sage: A = matrix(QQ,3,3,range(9)); A
4802
[0 1 2]
4803
[3 4 5]
4804
[6 7 8]
4805
sage: es = A.eigenspaces_left(format='all'); es
4806
[
4807
(0, Vector space of degree 3 and dimension 1 over Rational Field
4808
User basis matrix:
4809
[ 1 -2 1]),
4810
(-1.348469228349535?, Vector space of degree 3 and dimension 1 over Algebraic Field
4811
User basis matrix:
4812
[ 1 0.3101020514433644? -0.3797958971132713?]),
4813
(13.34846922834954?, Vector space of degree 3 and dimension 1 over Algebraic Field
4814
User basis matrix:
4815
[ 1 1.289897948556636? 1.579795897113272?])
4816
]
4817
4818
sage: es = A.eigenspaces_left(format='galois'); es
4819
[
4820
(0, Vector space of degree 3 and dimension 1 over Rational Field
4821
User basis matrix:
4822
[ 1 -2 1]),
4823
(a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18
4824
User basis matrix:
4825
[ 1 1/15*a1 + 2/5 2/15*a1 - 1/5])
4826
]
4827
sage: es = A.eigenspaces_left(format='galois', algebraic_multiplicity=True); es
4828
[
4829
(0, Vector space of degree 3 and dimension 1 over Rational Field
4830
User basis matrix:
4831
[ 1 -2 1], 1),
4832
(a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18
4833
User basis matrix:
4834
[ 1 1/15*a1 + 2/5 2/15*a1 - 1/5], 1)
4835
]
4836
sage: e, v, n = es[0]; v = v.basis()[0]
4837
sage: delta = e*v - v*A
4838
sage: abs(abs(delta)) < 1e-10
4839
True
4840
4841
The same computation, but with implicit base change to a field. ::
4842
4843
sage: A = matrix(ZZ,3,range(9)); A
4844
[0 1 2]
4845
[3 4 5]
4846
[6 7 8]
4847
sage: A.eigenspaces_left(format='galois')
4848
[
4849
(0, Vector space of degree 3 and dimension 1 over Rational Field
4850
User basis matrix:
4851
[ 1 -2 1]),
4852
(a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18
4853
User basis matrix:
4854
[ 1 1/15*a1 + 2/5 2/15*a1 - 1/5])
4855
]
4856
4857
We compute the left eigenspaces of the matrix of the Hecke operator
4858
`T_2` on level 43 modular symbols, both with all eigenvalues (the default)
4859
and with one subspace per factor. ::
4860
4861
sage: A = ModularSymbols(43).T(2).matrix(); A
4862
[ 3 0 0 0 0 0 -1]
4863
[ 0 -2 1 0 0 0 0]
4864
[ 0 -1 1 1 0 -1 0]
4865
[ 0 -1 0 -1 2 -1 1]
4866
[ 0 -1 0 1 1 -1 1]
4867
[ 0 0 -2 0 2 -2 1]
4868
[ 0 0 -1 0 1 0 -1]
4869
sage: A.base_ring()
4870
Rational Field
4871
sage: f = A.charpoly(); f
4872
x^7 + x^6 - 12*x^5 - 16*x^4 + 36*x^3 + 52*x^2 - 32*x - 48
4873
sage: factor(f)
4874
(x - 3) * (x + 2)^2 * (x^2 - 2)^2
4875
sage: A.eigenspaces_left(algebraic_multiplicity=True)
4876
[
4877
(3, Vector space of degree 7 and dimension 1 over Rational Field
4878
User basis matrix:
4879
[ 1 0 1/7 0 -1/7 0 -2/7], 1),
4880
(-2, Vector space of degree 7 and dimension 2 over Rational Field
4881
User basis matrix:
4882
[ 0 1 0 1 -1 1 -1]
4883
[ 0 0 1 0 -1 2 -1], 2),
4884
(-1.414213562373095?, Vector space of degree 7 and dimension 2 over Algebraic Field
4885
User basis matrix:
4886
[ 0 1 0 -1 0.4142135623730951? 1 -1]
4887
[ 0 0 1 0 -1 0 2.414213562373095?], 2),
4888
(1.414213562373095?, Vector space of degree 7 and dimension 2 over Algebraic Field
4889
User basis matrix:
4890
[ 0 1 0 -1 -2.414213562373095? 1 -1]
4891
[ 0 0 1 0 -1 0 -0.4142135623730951?], 2)
4892
]
4893
sage: A.eigenspaces_left(format='galois', algebraic_multiplicity=True)
4894
[
4895
(3, Vector space of degree 7 and dimension 1 over Rational Field
4896
User basis matrix:
4897
[ 1 0 1/7 0 -1/7 0 -2/7], 1),
4898
(-2, Vector space of degree 7 and dimension 2 over Rational Field
4899
User basis matrix:
4900
[ 0 1 0 1 -1 1 -1]
4901
[ 0 0 1 0 -1 2 -1], 2),
4902
(a2, Vector space of degree 7 and dimension 2 over Number Field in a2 with defining polynomial x^2 - 2
4903
User basis matrix:
4904
[ 0 1 0 -1 -a2 - 1 1 -1]
4905
[ 0 0 1 0 -1 0 -a2 + 1], 2)
4906
]
4907
4908
Next we compute the left eigenspaces over the finite field of order 11. ::
4909
4910
sage: A = ModularSymbols(43, base_ring=GF(11), sign=1).T(2).matrix(); A
4911
[ 3 9 0 0]
4912
[ 0 9 0 1]
4913
[ 0 10 9 2]
4914
[ 0 9 0 2]
4915
sage: A.base_ring()
4916
Finite Field of size 11
4917
sage: A.charpoly()
4918
x^4 + 10*x^3 + 3*x^2 + 2*x + 1
4919
sage: A.eigenspaces_left(format='galois', var = 'beta')
4920
[
4921
(9, Vector space of degree 4 and dimension 1 over Finite Field of size 11
4922
User basis matrix:
4923
[0 0 1 5]),
4924
(3, Vector space of degree 4 and dimension 1 over Finite Field of size 11
4925
User basis matrix:
4926
[1 6 0 6]),
4927
(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
4928
User basis matrix:
4929
[ 0 1 0 5*beta2 + 10])
4930
]
4931
4932
This method is only applicable to exact matrices.
4933
The "eigenmatrix" routines for matrices with double-precision
4934
floating-point entries (``RDF``, ``CDF``) are the best
4935
alternative. (Since some platforms return eigenvectors
4936
that are the negatives of those given here, this one example
4937
is not tested here.) There are also "eigenmatrix" routines for
4938
matrices with symbolic entries. ::
4939
4940
sage: A = matrix(QQ, 3, 3, range(9))
4941
sage: A.change_ring(RR).eigenspaces_left()
4942
Traceback (most recent call last):
4943
...
4944
NotImplementedError: eigenspaces cannot be computed reliably for inexact rings such as Real Field with 53 bits of precision,
4945
consult numerical or symbolic matrix classes for other options
4946
4947
sage: em = A.change_ring(RDF).eigenmatrix_left()
4948
sage: eigenvalues = em[0]; eigenvalues.dense_matrix().zero_at(2e-15)
4949
[ 13.3484692283 0.0 0.0]
4950
[ 0.0 -1.34846922835 0.0]
4951
[ 0.0 0.0 0.0]
4952
sage: eigenvectors = em[1]; eigenvectors # not tested
4953
[ 0.440242867... 0.567868371... 0.695493875...]
4954
[ 0.897878732... 0.278434036... -0.341010658...]
4955
[ 0.408248290... -0.816496580... 0.408248290...]
4956
4957
sage: x, y = var('x y')
4958
sage: S = matrix([[x, y], [y, 3*x^2]])
4959
sage: em = S.eigenmatrix_left()
4960
sage: eigenvalues = em[0]; eigenvalues
4961
[3/2*x^2 + 1/2*x - 1/2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2) 0]
4962
[ 0 3/2*x^2 + 1/2*x + 1/2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2)]
4963
sage: eigenvectors = em[1]; eigenvectors
4964
[ 1 1/2*(3*x^2 - x - sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y]
4965
[ 1 1/2*(3*x^2 - x + sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y]
4966
4967
4968
A request for ``'all'`` the eigenvalues, when it is not
4969
possible, will raise an error. Using the ``'galois'``
4970
format option is more likely to be successful. ::
4971
4972
sage: F.<b> = FiniteField(11^2)
4973
sage: A = matrix(F, [[b + 1, b + 1], [10*b + 4, 5*b + 4]])
4974
sage: A.eigenspaces_left(format='all')
4975
Traceback (most recent call last):
4976
...
4977
NotImplementedError: unable to construct eigenspaces for eigenvalues outside the base field,
4978
try the keyword option: format='galois'
4979
4980
sage: A.eigenspaces_left(format='galois')
4981
[
4982
(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
4983
User basis matrix:
4984
[ 1 6*b*a0 + 3*b + 1])
4985
]
4986
4987
TESTS:
4988
4989
We make sure that :trac:`13308` is fixed. ::
4990
4991
sage: M = ModularSymbols(Gamma1(23), sign=1)
4992
sage: m = M.cuspidal_subspace().hecke_matrix(2)
4993
sage: [j*m==i[0]*j for i in m.eigenspaces_left(format='all') for j in i[1].basis()] # long time (4s)
4994
[True, True, True, True, True, True, True, True, True, True, True, True]
4995
4996
sage: B = matrix(QQ, 2, 3, range(6))
4997
sage: B.eigenspaces_left()
4998
Traceback (most recent call last):
4999
...
5000
TypeError: matrix must be square, not 2 x 3
5001
5002
sage: B = matrix(QQ, 4, 4, range(16))
5003
sage: B.eigenspaces_left(format='junk')
5004
Traceback (most recent call last):
5005
...
5006
ValueError: format keyword must be None, 'all' or 'galois', not junk
5007
5008
sage: B.eigenspaces_left(algebraic_multiplicity='garbage')
5009
Traceback (most recent call last):
5010
...
5011
ValueError: algebraic_multiplicity keyword must be True or False
5012
"""
5013
if not algebraic_multiplicity in [True, False]:
5014
msg = 'algebraic_multiplicity keyword must be True or False'
5015
raise ValueError(msg.format(algebraic_multiplicity))
5016
if not self.is_square():
5017
msg = 'matrix must be square, not {0} x {1}'
5018
raise TypeError(msg.format(self.nrows(), self.ncols()))
5019
if not self.base_ring().is_exact():
5020
msg = ("eigenspaces cannot be computed reliably for inexact rings such as {0},\n",
5021
"consult numerical or symbolic matrix classes for other options")
5022
raise NotImplementedError(''.join(msg).format(self.base_ring()))
5023
5024
format = self._eigenspace_format(format)
5025
5026
key = 'eigenspaces_left_' + format + '{0}'.format(var)
5027
x = self.fetch(key)
5028
if not x is None:
5029
if algebraic_multiplicity:
5030
return x
5031
else:
5032
return Sequence([(e[0],e[1]) for e in x], cr=True, check=False)
5033
5034
# Possible improvements:
5035
# algorithm for dual_eigenvector in sage/modular/hecke/module.py
5036
# use minpoly when algebraic_multiplicity=False
5037
# as of 2007-03-25 minpoly is unreliable via linbox
5038
5039
import sage.categories.homset
5040
import sage.rings.qqbar
5041
5042
G = self.fcp() # factored characteristic polynomial
5043
V = []
5044
i = -1 # variable name index, increments for each eigenvalue
5045
for h, e in G:
5046
i = i + 1
5047
if h.degree() == 1:
5048
alpha = -h[0]/h[1]
5049
F = alpha.parent()
5050
if F != self.base_ring():
5051
self = self.change_ring(F)
5052
A = self - alpha
5053
W = A.kernel()
5054
V.append((alpha, W.ambient_module().span_of_basis(W.basis()), e))
5055
else:
5056
F = h.root_field('{0}{1}'.format(var,i))
5057
alpha = F.gen(0)
5058
A = self.change_ring(F) - alpha
5059
W = A.kernel()
5060
WB = W.basis()
5061
if format == 'galois':
5062
V.append((alpha, W.ambient_module().span_of_basis(WB), e))
5063
elif format == 'all':
5064
try:
5065
alpha_conj = alpha.galois_conjugates(sage.rings.qqbar.QQbar)
5066
except AttributeError:
5067
msg = ("unable to construct eigenspaces for eigenvalues outside the base field,\n"
5068
"try the keyword option: format='galois'")
5069
raise NotImplementedError(''.join(msg))
5070
for ev in alpha_conj:
5071
m = sage.categories.homset.hom(alpha.parent(), ev.parent(), ev)
5072
space = (ev.parent())**self.nrows()
5073
evec_list = [(space)([m(v_j) for v_j in v]) for v in WB]
5074
V.append((ev, space.span_of_basis(evec_list, already_echelonized=True), e))
5075
V = Sequence(V, cr=True, check=False)
5076
self.cache(key, V)
5077
if algebraic_multiplicity:
5078
return V
5079
else:
5080
return Sequence([(e[0],e[1]) for e in V], cr=True, check=False)
5081
5082
left_eigenspaces = eigenspaces_left
5083
5084
def eigenspaces_right(self, format='all', var='a', algebraic_multiplicity=False):
5085
r"""
5086
Compute the right eigenspaces of a matrix.
5087
5088
Note that ``eigenspaces_right()`` and ``right_eigenspaces()``
5089
are identical methods. Here "right" refers to the eigenvectors
5090
being placed to the right of the matrix.
5091
5092
INPUT:
5093
5094
- ``self`` - a square matrix over an exact field. For inexact
5095
matrices consult the numerical or symbolic matrix classes.
5096
5097
- ``format`` - default: ``None``
5098
5099
- ``'all'`` - attempts to create every eigenspace. This will
5100
always be possible for matrices with rational entries.
5101
- ``'galois'`` - for each irreducible factor of the characteristic
5102
polynomial, a single eigenspace will be output for a
5103
single root/eigenvalue for the irreducible factor.
5104
- ``None`` - Uses the 'all' format if the base ring is contained
5105
in an algebraically closed field which is implemented.
5106
Otherwise, uses the 'galois' format.
5107
5108
- ``var`` - default: 'a' - variable name used to
5109
represent elements of the root field of each
5110
irreducible factor of the characteristic polynomial.
5111
If var='a', then the root fields will be in terms of
5112
a0, a1, a2, ...., where the numbering runs across all
5113
the irreducible factors of the characteristic polynomial,
5114
even for linear factors.
5115
5116
- ``algebraic_multiplicity`` - default: False - whether or
5117
not to include the algebraic multiplicity of each eigenvalue
5118
in the output. See the discussion below.
5119
5120
OUTPUT:
5121
5122
If algebraic_multiplicity=False, return a list of pairs (e, V)
5123
where e is an eigenvalue of the matrix, and V is the corresponding
5124
left eigenspace. For Galois conjugates of eigenvalues, there
5125
may be just one representative eigenspace, depending on the
5126
``format`` keyword.
5127
5128
If algebraic_multiplicity=True, return a list of triples (e, V, n)
5129
where e and V are as above and n is the algebraic multiplicity of
5130
the eigenvalue.
5131
5132
.. warning::
5133
5134
Uses a somewhat naive algorithm (simply factors the
5135
characteristic polynomial and computes kernels directly
5136
over the extension field).
5137
5138
EXAMPLES:
5139
5140
Right eigenspaces are computed from the left eigenspaces of the
5141
transpose of the matrix. As such, there is a greater collection
5142
of illustrative examples at the :meth:`eigenspaces_left`.
5143
5144
We compute the right eigenspaces of a `3\times 3` rational matrix. ::
5145
5146
sage: A = matrix(QQ, 3 ,3, range(9)); A
5147
[0 1 2]
5148
[3 4 5]
5149
[6 7 8]
5150
sage: A.eigenspaces_right()
5151
[
5152
(0, Vector space of degree 3 and dimension 1 over Rational Field
5153
User basis matrix:
5154
[ 1 -2 1]),
5155
(-1.348469228349535?, Vector space of degree 3 and dimension 1 over Algebraic Field
5156
User basis matrix:
5157
[ 1 0.1303061543300932? -0.7393876913398137?]),
5158
(13.34846922834954?, Vector space of degree 3 and dimension 1 over Algebraic Field
5159
User basis matrix:
5160
[ 1 3.069693845669907? 5.139387691339814?])
5161
]
5162
sage: es = A.eigenspaces_right(format='galois'); es
5163
[
5164
(0, Vector space of degree 3 and dimension 1 over Rational Field
5165
User basis matrix:
5166
[ 1 -2 1]),
5167
(a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18
5168
User basis matrix:
5169
[ 1 1/5*a1 + 2/5 2/5*a1 - 1/5])
5170
]
5171
sage: es = A.eigenspaces_right(format='galois', algebraic_multiplicity=True); es
5172
[
5173
(0, Vector space of degree 3 and dimension 1 over Rational Field
5174
User basis matrix:
5175
[ 1 -2 1], 1),
5176
(a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18
5177
User basis matrix:
5178
[ 1 1/5*a1 + 2/5 2/5*a1 - 1/5], 1)
5179
]
5180
sage: e, v, n = es[0]; v = v.basis()[0]
5181
sage: delta = v*e - A*v
5182
sage: abs(abs(delta)) < 1e-10
5183
True
5184
5185
The same computation, but with implicit base change to a field::
5186
5187
sage: A = matrix(ZZ, 3, range(9)); A
5188
[0 1 2]
5189
[3 4 5]
5190
[6 7 8]
5191
sage: A.eigenspaces_right(format='galois')
5192
[
5193
(0, Vector space of degree 3 and dimension 1 over Rational Field
5194
User basis matrix:
5195
[ 1 -2 1]),
5196
(a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18
5197
User basis matrix:
5198
[ 1 1/5*a1 + 2/5 2/5*a1 - 1/5])
5199
]
5200
5201
This method is only applicable to exact matrices.
5202
The "eigenmatrix" routines for matrices with double-precision
5203
floating-point entries (``RDF``, ``CDF``) are the best
5204
alternative. (Since some platforms return eigenvectors
5205
that are the negatives of those given here, this one example
5206
is not tested here.) There are also "eigenmatrix" routines for
5207
matrices with symbolic entries. ::
5208
5209
sage: B = matrix(RR, 3, 3, range(9))
5210
sage: B.eigenspaces_right()
5211
Traceback (most recent call last):
5212
...
5213
NotImplementedError: eigenspaces cannot be computed reliably for inexact rings such as Real Field with 53 bits of precision,
5214
consult numerical or symbolic matrix classes for other options
5215
5216
sage: em = B.change_ring(RDF).eigenmatrix_right()
5217
sage: eigenvalues = em[0]; eigenvalues.dense_matrix().zero_at(1e-15)
5218
[ 13.3484692283 0.0 0.0]
5219
[ 0.0 -1.34846922835 0.0]
5220
[ 0.0 0.0 0.0]
5221
sage: eigenvectors = em[1]; eigenvectors # not tested
5222
[ 0.164763817... 0.799699663... 0.408248290...]
5223
[ 0.505774475... 0.104205787... -0.816496580...]
5224
[ 0.846785134... -0.591288087... 0.408248290...]
5225
5226
sage: x, y = var('x y')
5227
sage: S = matrix([[x, y], [y, 3*x^2]])
5228
sage: em = S.eigenmatrix_right()
5229
sage: eigenvalues = em[0]; eigenvalues
5230
[3/2*x^2 + 1/2*x - 1/2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2) 0]
5231
[ 0 3/2*x^2 + 1/2*x + 1/2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2)]
5232
5233
sage: eigenvectors = em[1]; eigenvectors
5234
[ 1 1]
5235
[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]
5236
5237
5238
TESTS::
5239
5240
sage: B = matrix(QQ, 2, 3, range(6))
5241
sage: B.eigenspaces_right()
5242
Traceback (most recent call last):
5243
...
5244
TypeError: matrix must be square, not 2 x 3
5245
5246
sage: B = matrix(QQ, 4, 4, range(16))
5247
sage: B.eigenspaces_right(format='junk')
5248
Traceback (most recent call last):
5249
...
5250
ValueError: format keyword must be None, 'all' or 'galois', not junk
5251
5252
sage: B.eigenspaces_right(algebraic_multiplicity='garbage')
5253
Traceback (most recent call last):
5254
...
5255
ValueError: algebraic_multiplicity keyword must be True or False
5256
"""
5257
if not algebraic_multiplicity in [True, False]:
5258
msg = 'algebraic_multiplicity keyword must be True or False'
5259
raise ValueError(msg.format(algebraic_multiplicity))
5260
if not self.is_square():
5261
msg = 'matrix must be square, not {0} x {1}'
5262
raise TypeError(msg.format(self.nrows(), self.ncols()))
5263
if not self.base_ring().is_exact():
5264
msg = ("eigenspaces cannot be computed reliably for inexact rings such as {0},\n",
5265
"consult numerical or symbolic matrix classes for other options")
5266
raise NotImplementedError(''.join(msg).format(self.base_ring()))
5267
5268
format = self._eigenspace_format(format)
5269
5270
key = 'eigenspaces_right_' + format + '{0}'.format(var)
5271
x = self.fetch(key)
5272
if not x is None:
5273
if algebraic_multiplicity:
5274
return x
5275
else:
5276
return Sequence([(e[0],e[1]) for e in x], cr=True, check=False)
5277
5278
V = self.transpose().eigenspaces_left(format=format, var=var, algebraic_multiplicity=True)
5279
5280
self.cache(key, V)
5281
if algebraic_multiplicity:
5282
return V
5283
else:
5284
return Sequence([(e[0],e[1]) for e in V], cr=True, check=False)
5285
5286
right_eigenspaces = eigenspaces_right
5287
5288
def eigenvalues(self,extend=True):
5289
r"""
5290
Return a sequence of the eigenvalues of a matrix, with
5291
multiplicity. If the eigenvalues are roots of polynomials in QQ,
5292
then QQbar elements are returned that represent each separate
5293
root.
5294
5295
If the option extend is set to False, only eigenvalues in the base
5296
ring are considered.
5297
5298
EXAMPLES::
5299
5300
sage: a = matrix(QQ, 4, range(16)); a
5301
[ 0 1 2 3]
5302
[ 4 5 6 7]
5303
[ 8 9 10 11]
5304
[12 13 14 15]
5305
sage: sorted(a.eigenvalues(), reverse=True)
5306
[32.46424919657298?, 0, 0, -2.464249196572981?]
5307
5308
::
5309
5310
sage: a=matrix([(1, 9, -1, -1), (-2, 0, -10, 2), (-1, 0, 15, -2), (0, 1, 0, -1)])
5311
sage: a.eigenvalues()
5312
[-0.9386318578049146?, 15.50655435353258?, 0.2160387521361705? - 4.713151979747493?*I, 0.2160387521361705? + 4.713151979747493?*I]
5313
5314
A symmetric matrix a+a.transpose() should have real eigenvalues
5315
5316
::
5317
5318
sage: b=a+a.transpose()
5319
sage: ev = b.eigenvalues(); ev
5320
[-8.35066086057957?, -1.107247901349379?, 5.718651326708515?, 33.73925743522043?]
5321
5322
The eigenvalues are elements of QQbar, so they really represent
5323
exact roots of polynomials, not just approximations.
5324
5325
::
5326
5327
sage: e = ev[0]; e
5328
-8.35066086057957?
5329
sage: p = e.minpoly(); p
5330
x^4 - 30*x^3 - 171*x^2 + 1460*x + 1784
5331
sage: p(e) == 0
5332
True
5333
5334
To perform computations on the eigenvalue as an element of a number
5335
field, you can always convert back to a number field element.
5336
5337
::
5338
5339
sage: e.as_number_field_element()
5340
(Number Field in a with defining polynomial y^4 - 2*y^3 - 507*y^2 - 3972*y - 4264,
5341
a + 7,
5342
Ring morphism:
5343
From: Number Field in a with defining polynomial y^4 - 2*y^3 - 507*y^2 - 3972*y - 4264
5344
To: Algebraic Real Field
5345
Defn: a |--> -15.35066086057957?)
5346
5347
Notice the effect of the extend option.
5348
5349
::
5350
5351
sage: M=matrix(QQ,[[0,-1,0],[1,0,0],[0,0,2]])
5352
sage: M.eigenvalues()
5353
[2, -1*I, 1*I]
5354
sage: M.eigenvalues(extend=False)
5355
[2]
5356
5357
"""
5358
x = self.fetch('eigenvalues')
5359
if not x is None:
5360
if not extend:
5361
x1=Sequence([])
5362
for i in x:
5363
if i in self.base_ring():
5364
x1.append(i)
5365
x=x1
5366
return x
5367
5368
if not self.base_ring().is_exact():
5369
from warnings import warn
5370
warn("Using generic algorithm for an inexact ring, which will probably give incorrect results due to numerical precision issues.")
5371
5372
from sage.rings.qqbar import QQbar
5373
G = self.fcp() # factored charpoly of self.
5374
V = []
5375
i=0
5376
for h, e in G:
5377
if h.degree() == 1:
5378
alpha = [-h[0]/h[1]]
5379
V.extend(alpha*e)
5380
else:
5381
if extend:
5382
F = h.root_field('%s%s'%('a',i))
5383
try:
5384
alpha = F.gen(0).galois_conjugates(QQbar)
5385
except AttributeError:
5386
raise NotImplementedError, "eigenvalues() is not implemented for matrices with eigenvalues that are not in the fraction field of the base ring or in QQbar"
5387
V.extend(alpha*e)
5388
i+=1
5389
V = Sequence(V)
5390
if extend:
5391
self.cache('eigenvalues', V)
5392
if not extend:
5393
V1=Sequence([])
5394
for i in V:
5395
if i in self.base_ring():
5396
V1.append(i)
5397
V=V1
5398
return V
5399
5400
5401
5402
def eigenvectors_left(self,extend=True):
5403
r"""
5404
Compute the left eigenvectors of a matrix.
5405
5406
For each distinct eigenvalue, returns a list of the form (e,V,n)
5407
where e is the eigenvalue, V is a list of eigenvectors forming a
5408
basis for the corresponding left eigenspace, and n is the algebraic
5409
multiplicity of the eigenvalue.
5410
5411
If the option extend is set to False, then only the eigenvalues that
5412
live in the base ring are considered.
5413
5414
EXAMPLES: We compute the left eigenvectors of a `3\times 3`
5415
rational matrix.
5416
5417
::
5418
5419
sage: A = matrix(QQ,3,3,range(9)); A
5420
[0 1 2]
5421
[3 4 5]
5422
[6 7 8]
5423
sage: es = A.eigenvectors_left(); es
5424
[(0, [
5425
(1, -2, 1)
5426
], 1),
5427
(-1.348469228349535?, [(1, 0.3101020514433644?, -0.3797958971132713?)], 1),
5428
(13.34846922834954?, [(1, 1.289897948556636?, 1.579795897113272?)], 1)]
5429
sage: eval, [evec], mult = es[0]
5430
sage: delta = eval*evec - evec*A
5431
sage: abs(abs(delta)) < 1e-10
5432
True
5433
5434
Notice the difference between considering ring extensions or not.
5435
5436
::
5437
5438
sage: M=matrix(QQ,[[0,-1,0],[1,0,0],[0,0,2]])
5439
sage: M.eigenvectors_left()
5440
[(2, [
5441
(0, 0, 1)
5442
], 1), (-1*I, [(1, -1*I, 0)], 1), (1*I, [(1, 1*I, 0)], 1)]
5443
sage: M.eigenvectors_left(extend=False)
5444
[(2, [
5445
(0, 0, 1)
5446
], 1)]
5447
5448
"""
5449
x = self.fetch('eigenvectors_left')
5450
if not x is None:
5451
return x
5452
5453
if not self.base_ring().is_exact():
5454
from warnings import warn
5455
warn("Using generic algorithm for an inexact ring, which may result in garbage from numerical precision issues.")
5456
5457
V = []
5458
from sage.rings.qqbar import QQbar
5459
from sage.categories.homset import hom
5460
eigenspaces = self.eigenspaces_left(format='galois', algebraic_multiplicity=True)
5461
evec_list=[]
5462
n = self._nrows
5463
evec_eval_list = []
5464
F = self.base_ring().fraction_field()
5465
for ev in eigenspaces:
5466
eigval = ev[0]
5467
eigbasis = ev[1].basis()
5468
eigmult = ev[2]
5469
if eigval in self.base_ring() or extend:
5470
if eigval.parent().fraction_field() == F:
5471
evec_eval_list.append((eigval, eigbasis, eigmult))
5472
else:
5473
try:
5474
eigval_conj = eigval.galois_conjugates(QQbar)
5475
except AttributeError:
5476
raise NotImplementedError, "eigenvectors are not implemented for matrices with eigenvalues that are not in the fraction field of the base ring or in QQbar"
5477
5478
for e in eigval_conj:
5479
m = hom(eigval.parent(), e.parent(), e)
5480
space = (e.parent())**n
5481
evec_list = [(space)([m(i) for i in v]) for v in eigbasis]
5482
evec_eval_list.append( (e, evec_list, eigmult))
5483
5484
return evec_eval_list
5485
5486
left_eigenvectors = eigenvectors_left
5487
5488
def eigenvectors_right(self, extend=True):
5489
r"""
5490
Compute the right eigenvectors of a matrix.
5491
5492
For each distinct eigenvalue, returns a list of the form (e,V,n)
5493
where e is the eigenvalue, V is a list of eigenvectors forming a
5494
basis for the corresponding right eigenspace, and n is the
5495
algebraic multiplicity of the eigenvalue. If ``extend = True``
5496
(the default), this will return eigenspaces over the algebraic
5497
closure of the base field where this is implemented; otherwise
5498
it will restrict to eigenvalues in the base field.
5499
5500
EXAMPLES: We compute the right eigenvectors of a
5501
`3\times 3` rational matrix.
5502
5503
::
5504
5505
sage: A = matrix(QQ,3,3,range(9)); A
5506
[0 1 2]
5507
[3 4 5]
5508
[6 7 8]
5509
sage: es = A.eigenvectors_right(); es
5510
[(0, [
5511
(1, -2, 1)
5512
], 1),
5513
(-1.348469228349535?, [(1, 0.1303061543300932?, -0.7393876913398137?)], 1),
5514
(13.34846922834954?, [(1, 3.069693845669907?, 5.139387691339814?)], 1)]
5515
sage: A.eigenvectors_right(extend=False)
5516
[(0, [
5517
(1, -2, 1)
5518
], 1)]
5519
sage: eval, [evec], mult = es[0]
5520
sage: delta = eval*evec - A*evec
5521
sage: abs(abs(delta)) < 1e-10
5522
True
5523
"""
5524
return self.transpose().eigenvectors_left(extend=extend)
5525
5526
right_eigenvectors = eigenvectors_right
5527
5528
def eigenmatrix_left(self):
5529
r"""
5530
Return matrices D and P, where D is a diagonal matrix of
5531
eigenvalues and P is the corresponding matrix where the rows are
5532
corresponding eigenvectors (or zero vectors) so that P\*self =
5533
D\*P.
5534
5535
EXAMPLES::
5536
5537
sage: A = matrix(QQ,3,3,range(9)); A
5538
[0 1 2]
5539
[3 4 5]
5540
[6 7 8]
5541
sage: D, P = A.eigenmatrix_left()
5542
sage: D
5543
[ 0 0 0]
5544
[ 0 -1.348469228349535? 0]
5545
[ 0 0 13.34846922834954?]
5546
sage: P
5547
[ 1 -2 1]
5548
[ 1 0.3101020514433644? -0.3797958971132713?]
5549
[ 1 1.289897948556636? 1.579795897113272?]
5550
sage: P*A == D*P
5551
True
5552
5553
Because P is invertible, A is diagonalizable.
5554
5555
::
5556
5557
sage: A == (~P)*D*P
5558
True
5559
5560
The matrix P may contain zero rows corresponding to eigenvalues for
5561
which the algebraic multiplicity is greater than the geometric
5562
multiplicity. In these cases, the matrix is not diagonalizable.
5563
5564
::
5565
5566
sage: A = jordan_block(2,3); A
5567
[2 1 0]
5568
[0 2 1]
5569
[0 0 2]
5570
sage: A = jordan_block(2,3)
5571
sage: D, P = A.eigenmatrix_left()
5572
sage: D
5573
[2 0 0]
5574
[0 2 0]
5575
[0 0 2]
5576
sage: P
5577
[0 0 1]
5578
[0 0 0]
5579
[0 0 0]
5580
sage: P*A == D*P
5581
True
5582
5583
TESTS:
5584
5585
For matrices with floating point entries, some platforms will
5586
return eigenvectors that are negatives of those returned by the
5587
majority of platforms. This test accounts for that possibility.
5588
Running this test independently, without adjusting the eigenvectors
5589
could indicate this situation on your hardware. ::
5590
5591
sage: A = matrix(QQ, 3, 3, range(9))
5592
sage: em = A.change_ring(RDF).eigenmatrix_left()
5593
sage: evalues = em[0]; evalues.dense_matrix().zero_at(2e-15)
5594
[ 13.3484692283 0.0 0.0]
5595
[ 0.0 -1.34846922835 0.0]
5596
[ 0.0 0.0 0.0]
5597
sage: evectors = em[1];
5598
sage: for i in range(3):
5599
... scale = evectors[i,0].sign()
5600
... evectors.rescale_row(i, scale)
5601
sage: evectors
5602
[ 0.440242867... 0.567868371... 0.695493875...]
5603
[ 0.897878732... 0.278434036... -0.341010658...]
5604
[ 0.408248290... -0.816496580... 0.408248290...]
5605
"""
5606
from sage.misc.flatten import flatten
5607
evecs = self.eigenvectors_left()
5608
D = sage.matrix.constructor.diagonal_matrix(flatten([[e[0]]*e[2] for e in evecs]))
5609
rows = []
5610
for e in evecs:
5611
rows.extend(e[1]+[e[1][0].parent().zero_vector()]*(e[2]-len(e[1])))
5612
P = sage.matrix.constructor.matrix(rows)
5613
return D,P
5614
5615
left_eigenmatrix = eigenmatrix_left
5616
5617
def eigenmatrix_right(self):
5618
r"""
5619
Return matrices D and P, where D is a diagonal matrix of
5620
eigenvalues and P is the corresponding matrix where the columns are
5621
corresponding eigenvectors (or zero vectors) so that self\*P =
5622
P\*D.
5623
5624
EXAMPLES::
5625
5626
sage: A = matrix(QQ,3,3,range(9)); A
5627
[0 1 2]
5628
[3 4 5]
5629
[6 7 8]
5630
sage: D, P = A.eigenmatrix_right()
5631
sage: D
5632
[ 0 0 0]
5633
[ 0 -1.348469228349535? 0]
5634
[ 0 0 13.34846922834954?]
5635
sage: P
5636
[ 1 1 1]
5637
[ -2 0.1303061543300932? 3.069693845669907?]
5638
[ 1 -0.7393876913398137? 5.139387691339814?]
5639
sage: A*P == P*D
5640
True
5641
5642
Because P is invertible, A is diagonalizable.
5643
5644
::
5645
5646
sage: A == P*D*(~P)
5647
True
5648
5649
The matrix P may contain zero columns corresponding to eigenvalues
5650
for which the algebraic multiplicity is greater than the geometric
5651
multiplicity. In these cases, the matrix is not diagonalizable.
5652
5653
::
5654
5655
sage: A = jordan_block(2,3); A
5656
[2 1 0]
5657
[0 2 1]
5658
[0 0 2]
5659
sage: A = jordan_block(2,3)
5660
sage: D, P = A.eigenmatrix_right()
5661
sage: D
5662
[2 0 0]
5663
[0 2 0]
5664
[0 0 2]
5665
sage: P
5666
[1 0 0]
5667
[0 0 0]
5668
[0 0 0]
5669
sage: A*P == P*D
5670
True
5671
5672
TESTS:
5673
5674
For matrices with floating point entries, some platforms will
5675
return eigenvectors that are negatives of those returned by the
5676
majority of platforms. This test accounts for that possibility.
5677
Running this test independently, without adjusting the eigenvectors
5678
could indicate this situation on your hardware. ::
5679
5680
sage: B = matrix(QQ, 3, 3, range(9))
5681
sage: em = B.change_ring(RDF).eigenmatrix_right()
5682
sage: evalues = em[0]; evalues.dense_matrix().zero_at(2e-15)
5683
[ 13.3484692283 0.0 0.0]
5684
[ 0.0 -1.34846922835 0.0]
5685
[ 0.0 0.0 0.0]
5686
sage: evectors = em[1];
5687
sage: for i in range(3):
5688
... scale = evectors[0,i].sign()
5689
... evectors.rescale_col(i, scale)
5690
sage: evectors
5691
[ 0.164763817... 0.799699663... 0.408248290...]
5692
[ 0.505774475... 0.104205787... -0.816496580...]
5693
[ 0.846785134... -0.591288087... 0.408248290...]
5694
"""
5695
D,P=self.transpose().eigenmatrix_left()
5696
return D,P.transpose()
5697
5698
right_eigenmatrix = eigenmatrix_right
5699
5700
5701
5702
#####################################################################################
5703
# Generic Echelon Form
5704
###################################################################################
5705
5706
5707
def rref(self, *args, **kwds):
5708
"""
5709
Return the reduced row echelon form of the matrix, considered
5710
as a matrix over a field.
5711
5712
If the matrix is over a ring, then an equivalent matrix is
5713
constructed over the fraction field, and then row reduced.
5714
5715
All arguments are passed on to :meth:``echelon_form``.
5716
5717
.. note::
5718
5719
Because the matrix is viewed as a matrix over a field,
5720
every leading coefficient of the returned matrix will be
5721
one and will be the only nonzero entry in its column.
5722
5723
EXAMPLES::
5724
5725
sage: A=matrix(3,range(9)); A
5726
[0 1 2]
5727
[3 4 5]
5728
[6 7 8]
5729
sage: A.rref()
5730
[ 1 0 -1]
5731
[ 0 1 2]
5732
[ 0 0 0]
5733
5734
5735
Note that there is a difference between :meth:`rref` and
5736
:meth:`echelon_form` when the matrix is not over a field (in
5737
this case, the integers instead of the rational numbers)::
5738
5739
sage: A.base_ring()
5740
Integer Ring
5741
sage: A.echelon_form()
5742
[ 3 0 -3]
5743
[ 0 1 2]
5744
[ 0 0 0]
5745
5746
sage: B=random_matrix(QQ,3,num_bound=10); B
5747
[ -4 -3 6]
5748
[ 5 -5 9/2]
5749
[3/2 -4 -7]
5750
sage: B.rref()
5751
[1 0 0]
5752
[0 1 0]
5753
[0 0 1]
5754
5755
In this case, since ``B`` is a matrix over a field (the
5756
rational numbers), :meth:`rref` and :meth:`echelon_form` are
5757
exactly the same::
5758
5759
sage: B.echelon_form()
5760
[1 0 0]
5761
[0 1 0]
5762
[0 0 1]
5763
sage: B.echelon_form() is B.rref()
5764
True
5765
5766
Since :meth:`echelon_form` is not implemented for every ring,
5767
sometimes behavior varies, as here::
5768
5769
sage: R.<x>=ZZ[]
5770
sage: C = matrix(3,[2,x,x^2,x+1,3-x,-1,3,2,1])
5771
sage: C.rref()
5772
[1 0 0]
5773
[0 1 0]
5774
[0 0 1]
5775
sage: C.base_ring()
5776
Univariate Polynomial Ring in x over Integer Ring
5777
sage: C.echelon_form()
5778
Traceback (most recent call last):
5779
...
5780
NotImplementedError: Ideal Ideal (2, x + 1) of Univariate Polynomial Ring in x over Integer Ring not principal
5781
Echelon form not implemented over 'Univariate Polynomial Ring in x over Integer Ring'.
5782
sage: C = matrix(3,[2,x,x^2,x+1,3-x,-1,3,2,1/2])
5783
sage: C.echelon_form()
5784
[ 2 x x^2]
5785
[ 0 1 15*x^2 - 3/2*x - 31/2]
5786
[ 0 0 5/2*x^3 - 15/4*x^2 - 9/4*x + 7/2]
5787
sage: C.rref()
5788
[1 0 0]
5789
[0 1 0]
5790
[0 0 1]
5791
sage: C = matrix(3,[2,x,x^2,x+1,3-x,-1/x,3,2,1/2])
5792
sage: C.echelon_form()
5793
[1 0 0]
5794
[0 1 0]
5795
[0 0 1]
5796
"""
5797
R=self.base_ring()
5798
if R.is_field():
5799
return self.echelon_form()
5800
else:
5801
F=R.fraction_field()
5802
return self.change_ring(F).echelon_form()
5803
5804
def _echelonize_ring(self, **kwds):
5805
r"""
5806
Echelonize self in place, where the base ring of self is assumed to
5807
be a ring (not a field).
5808
5809
Right now this *only* works over ZZ and some principal ideal domains;
5810
otherwise a ``NotImplementedError`` is raised. In the special case of
5811
sparse matrices over ZZ it makes them dense, gets the echelon form of
5812
the dense matrix, then sets self equal to the result.
5813
5814
EXAMPLES::
5815
5816
sage: a = matrix(ZZ, 3, 4, [1..12], sparse=True); a
5817
[ 1 2 3 4]
5818
[ 5 6 7 8]
5819
[ 9 10 11 12]
5820
sage: a._echelonize_ring()
5821
sage: a
5822
[ 1 2 3 4]
5823
[ 0 4 8 12]
5824
[ 0 0 0 0]
5825
5826
sage: L.<w> = NumberField(x^2 - x + 2)
5827
sage: OL = L.ring_of_integers()
5828
sage: m = matrix(OL, 2, 2, [1,2,3,4+w])
5829
sage: m.echelon_form()
5830
[ 1 2]
5831
[ 0 w - 2]
5832
sage: E, T = m.echelon_form(transformation=True); E,T
5833
(
5834
[ 1 2] [ 1 0]
5835
[ 0 w - 2], [-3 1]
5836
)
5837
sage: E == T*m
5838
True
5839
5840
TESTS:
5841
5842
Check that http://trac.sagemath.org/sage_trac/ticket/11558 is fixed::
5843
5844
sage: matrix(ZZ, [[1,2],[4,6]], sparse=False).echelon_form(transformation=True)
5845
(
5846
[1 0] [-3 1]
5847
[0 2], [ 4 -1]
5848
)
5849
sage: matrix(ZZ, [[1,2],[4,6]], sparse=True).echelon_form(transformation=True)
5850
(
5851
[1 0] [-3 1]
5852
[0 2], [ 4 -1]
5853
)
5854
"""
5855
self.check_mutability()
5856
cdef Matrix d, a
5857
cdef Py_ssize_t r, c
5858
cdef bint transformation = kwds.has_key('transformation') and kwds['transformation']
5859
if self._base_ring == ZZ:
5860
if kwds.has_key('include_zero_rows') and not kwds['include_zero_rows']:
5861
raise ValueError, "cannot echelonize in place and delete zero rows"
5862
if transformation:
5863
d, a = self.dense_matrix().echelon_form(**kwds)
5864
else:
5865
d = self.dense_matrix().echelon_form(**kwds)
5866
for c from 0 <= c < self.ncols():
5867
for r from 0 <= r < self.nrows():
5868
self.set_unsafe(r, c, d.get_unsafe(r,c))
5869
self.clear_cache()
5870
self.cache('pivots', d.pivots())
5871
self.cache('in_echelon_form', True)
5872
else:
5873
try:
5874
a, d, p = self._echelon_form_PID()
5875
except TypeError, msg:
5876
raise NotImplementedError, "%s\nechelon form over %s not yet implemented"%(msg, self.base_ring())
5877
5878
for c from 0 <= c < self.ncols():
5879
for r from 0 <= r < self.nrows():
5880
self.set_unsafe(r, c, d.get_unsafe(r,c))
5881
self.clear_cache()
5882
self.cache('pivots', tuple(p))
5883
self.cache('in_echelon_form', True)
5884
if transformation:
5885
return a
5886
else:
5887
return
5888
5889
def echelonize(self, algorithm="default", cutoff=0, **kwds):
5890
r"""
5891
Transform ``self`` into a matrix in echelon form over the same
5892
base ring as self.
5893
5894
.. note::
5895
5896
This row reduction does not use division if the
5897
matrix is not over a field (e.g., if the matrix is over
5898
the integers). If you want to calculate the echelon form
5899
using division, then use :meth:`rref`, which assumes that
5900
the matrix entries are in a field (specifically, the field
5901
of fractions of the base ring of the matrix).
5902
5903
INPUT:
5904
5905
- ``algorithm`` -- string. Which algorithm to use. Choices are
5906
5907
- ``'default'``: Let Sage choose an algorithm (default).
5908
5909
- ``'classical'``: Gauss elimination.
5910
5911
- ``'strassen'``: use a Strassen divide and conquer
5912
algorithm (if available)
5913
5914
- ``cutoff`` -- integer. Only used if the Strassen algorithm
5915
is selected.
5916
5917
- ``transformation`` -- boolean. Whether to also return the
5918
transformation matrix. Some matrix backends do not provide
5919
this information, in which case this option is ignored.
5920
5921
OUTPUT:
5922
5923
The matrix ``self`` is put into echelon form. Nothing is
5924
returned unless the keyword option ``transformation=True`` is
5925
specified, in which case the transformation matrix is
5926
returned.
5927
5928
EXAMPLES::
5929
5930
sage: a = matrix(QQ,3,range(9)); a
5931
[0 1 2]
5932
[3 4 5]
5933
[6 7 8]
5934
sage: a.echelonize()
5935
sage: a
5936
[ 1 0 -1]
5937
[ 0 1 2]
5938
[ 0 0 0]
5939
5940
An immutable matrix cannot be transformed into echelon form. Use
5941
``self.echelon_form()`` instead::
5942
5943
sage: a = matrix(QQ,3,range(9)); a.set_immutable()
5944
sage: a.echelonize()
5945
Traceback (most recent call last):
5946
...
5947
ValueError: matrix is immutable; please change a copy instead
5948
(i.e., use copy(M) to change a copy of M).
5949
sage: a.echelon_form()
5950
[ 1 0 -1]
5951
[ 0 1 2]
5952
[ 0 0 0]
5953
5954
Echelon form over the integers is what is also classically often
5955
known as Hermite normal form::
5956
5957
sage: a = matrix(ZZ,3,range(9))
5958
sage: a.echelonize(); a
5959
[ 3 0 -3]
5960
[ 0 1 2]
5961
[ 0 0 0]
5962
5963
We compute an echelon form both over a domain and fraction field::
5964
5965
sage: R.<x,y> = QQ[]
5966
sage: a = matrix(R, 2, [x,y,x,y])
5967
sage: a.echelon_form() # not very useful? -- why two copies of the same row?
5968
[x y]
5969
[x y]
5970
5971
::
5972
5973
sage: b = a.change_ring(R.fraction_field())
5974
sage: b.echelon_form() # potentially useful
5975
[ 1 y/x]
5976
[ 0 0]
5977
5978
Echelon form is not defined over arbitrary rings::
5979
5980
sage: a = matrix(Integers(9),3,range(9))
5981
sage: a.echelon_form()
5982
Traceback (most recent call last):
5983
...
5984
NotImplementedError: Echelon form not implemented over 'Ring of integers modulo 9'.
5985
5986
Involving a sparse matrix::
5987
5988
sage: m = matrix(3,[1, 1, 1, 1, 0, 2, 1, 2, 0], sparse=True); m
5989
[1 1 1]
5990
[1 0 2]
5991
[1 2 0]
5992
sage: m.echelon_form()
5993
[ 1 0 2]
5994
[ 0 1 -1]
5995
[ 0 0 0]
5996
sage: m.echelonize(); m
5997
[ 1 0 2]
5998
[ 0 1 -1]
5999
[ 0 0 0]
6000
6001
The transformation matrix is optionally returned::
6002
6003
sage: m_original = m
6004
sage: transformation_matrix = m.echelonize(transformation=True)
6005
sage: m == transformation_matrix * m_original
6006
True
6007
"""
6008
self.check_mutability()
6009
6010
if algorithm == 'default':
6011
if self._will_use_strassen_echelon():
6012
algorithm = 'strassen'
6013
else:
6014
algorithm = 'classical'
6015
try:
6016
if self.base_ring().is_field():
6017
if algorithm == 'classical':
6018
self._echelon_in_place_classical()
6019
elif algorithm == 'strassen':
6020
self._echelon_strassen(cutoff)
6021
else:
6022
raise ValueError, "Unknown algorithm '%s'"%algorithm
6023
else:
6024
if not (algorithm in ['classical', 'strassen']):
6025
kwds['algorithm'] = algorithm
6026
return self._echelonize_ring(**kwds)
6027
except ArithmeticError, msg:
6028
raise NotImplementedError, "%s\nEchelon form not implemented over '%s'."%(msg,self.base_ring())
6029
6030
def echelon_form(self, algorithm="default", cutoff=0, **kwds):
6031
"""
6032
Return the echelon form of self.
6033
6034
.. note::
6035
6036
This row reduction does not use division if the
6037
matrix is not over a field (e.g., if the matrix is over
6038
the integers). If you want to calculate the echelon form
6039
using division, then use :meth:`rref`, which assumes that
6040
the matrix entries are in a field (specifically, the field
6041
of fractions of the base ring of the matrix).
6042
6043
INPUT:
6044
6045
- ``algorithm`` -- string. Which algorithm to use. Choices are
6046
6047
- ``'default'``: Let Sage choose an algorithm (default).
6048
6049
- ``'classical'``: Gauss elimination.
6050
6051
- ``'strassen'``: use a Strassen divide and conquer
6052
algorithm (if available)
6053
6054
- ``cutoff`` -- integer. Only used if the Strassen algorithm is selected.
6055
6056
- ``transformation`` -- boolean. Whether to also return the
6057
transformation matrix. Some matrix backends do not provide
6058
this information, in which case this option is ignored.
6059
6060
OUTPUT:
6061
6062
The reduced row echelon form of ``self``, as an immutable
6063
matrix. Note that self is *not* changed by this command. Use
6064
:meth:`echelonize` to change ``self`` in place.
6065
6066
If the optional parameter ``transformation=True`` is
6067
specified, the output consists of a pair `(E,T)` of matrices
6068
where `E` is the echelon form of ``self`` and `T` is the
6069
transformation matrix.
6070
6071
EXAMPLES::
6072
6073
sage: MS = MatrixSpace(GF(19),2,3)
6074
sage: C = MS.matrix([1,2,3,4,5,6])
6075
sage: C.rank()
6076
2
6077
sage: C.nullity()
6078
0
6079
sage: C.echelon_form()
6080
[ 1 0 18]
6081
[ 0 1 2]
6082
6083
The matrix library used for `\ZZ/p`-matrices does not return
6084
the transformation matrix, so the ``transformation`` option is
6085
ignored::
6086
6087
sage: C.echelon_form(transformation=True)
6088
[ 1 0 18]
6089
[ 0 1 2]
6090
6091
sage: D = matrix(ZZ, 2, 3, [1,2,3,4,5,6])
6092
sage: D.echelon_form(transformation=True)
6093
(
6094
[1 2 3] [ 1 0]
6095
[0 3 6], [ 4 -1]
6096
)
6097
sage: E, T = D.echelon_form(transformation=True)
6098
sage: T*D == E
6099
True
6100
"""
6101
cdef bint transformation = (kwds.has_key('transformation') and kwds['transformation'])
6102
x = self.fetch('echelon_form')
6103
if x is not None:
6104
if not transformation:
6105
return x
6106
y = self.fetch('echelon_transformation')
6107
if y:
6108
return (x, y)
6109
6110
E = self.__copy__()
6111
if algorithm == 'default':
6112
v = E.echelonize(cutoff=cutoff, **kwds)
6113
else:
6114
v = E.echelonize(algorithm = algorithm, cutoff=cutoff, **kwds)
6115
E.set_immutable() # so we can cache the echelon form.
6116
self.cache('echelon_form', E)
6117
if v is not None:
6118
self.cache('echelon_transformation', v)
6119
self.cache('pivots', E.pivots())
6120
if transformation and v is not None:
6121
return (E, v)
6122
else:
6123
return E
6124
6125
def _echelon_classical(self):
6126
"""
6127
Return the echelon form of self.
6128
"""
6129
E = self.fetch('echelon_classical')
6130
if not E is None:
6131
return E
6132
E = self.__copy__()
6133
E._echelon_in_place_classical()
6134
self.cache('echelon_classical', E)
6135
return E
6136
6137
def _echelon_in_place_classical(self):
6138
"""
6139
Transform self into echelon form and set the pivots of self.
6140
6141
EXAMPLES::
6142
6143
sage: t = matrix(QQ, 3, range(9)); t
6144
[0 1 2]
6145
[3 4 5]
6146
[6 7 8]
6147
sage: E = t._echelon_in_place_classical(); t
6148
[ 1 0 -1]
6149
[ 0 1 2]
6150
[ 0 0 0]
6151
"""
6152
tm = verbose('generic in-place Gauss elimination on %s x %s matrix'%(self._nrows, self._ncols))
6153
cdef Py_ssize_t start_row, c, r, nr, nc, i
6154
if self.fetch('in_echelon_form'):
6155
return
6156
6157
self.check_mutability()
6158
cdef Matrix A
6159
6160
nr = self._nrows
6161
nc = self._ncols
6162
A = self
6163
6164
start_row = 0
6165
pivots = []
6166
6167
for c from 0 <= c < nc:
6168
sig_check()
6169
for r from start_row <= r < nr:
6170
if A.get_unsafe(r, c):
6171
pivots.append(c)
6172
a_inverse = ~A.get_unsafe(r,c)
6173
A.rescale_row(r, a_inverse, c)
6174
A.swap_rows(r, start_row)
6175
for i from 0 <= i < nr:
6176
if i != start_row:
6177
if A.get_unsafe(i,c):
6178
minus_b = -A.get_unsafe(i, c)
6179
A.add_multiple_of_row(i, start_row, minus_b, c)
6180
start_row = start_row + 1
6181
break
6182
self.cache('pivots', tuple(pivots))
6183
self.cache('in_echelon_form', True)
6184
self.cache('echelon_form', self)
6185
verbose('done with gauss echelon form', tm)
6186
6187
def extended_echelon_form(self, subdivide=False, **kwds):
6188
r"""
6189
Returns the echelon form of ``self`` augmented with an identity matrix.
6190
6191
INPUT:
6192
6193
- ``subdivide`` - default: ``False`` - determines if the
6194
returned matrix is subdivided. See the description of the
6195
(output) below for details.
6196
- ``kwds`` - additional keywords that can be passed to
6197
the method that computes the echelon form.
6198
6199
OUTPUT:
6200
6201
If `A` is an `m\times n` matrix, add the `m` columns of an
6202
`m\times m` identity matrix to the right of ``self``. Then
6203
row-reduce this `m\times(n+m)` matrix. This matrix is returned
6204
as an immutable matrix.
6205
6206
If ``subdivide`` is ``True`` then the returned matrix has a single
6207
division among the columns and a single division among the rows.
6208
The column subdivision has `n` columns to the left and `m`
6209
columns to the right. The row division separates the non-zero rows
6210
from the zero rows, when restricted to the first `n` columns.
6211
6212
For a nonsingular matrix the final `m` columns of the extended
6213
echelon form are the inverse of ``self``. For a matrix of
6214
any size, the final `m` columns provide a matrix that transforms
6215
``self`` to echelon form when it multiplies ``self`` from the left.
6216
When the base ring is a field, the uniqueness of reduced row-echelon
6217
form implies that this transformation matrix can be taken as the
6218
coefficients giving a
6219
canonical set of linear combinations of the rows of ``self`` that
6220
yield reduced row-echelon form.
6221
6222
When subdivided as described above, and again over a field, the
6223
parts of the subdivision in the upper-left corner and lower-right
6224
corner satisfy several interesting relationships with the row space,
6225
column space, left kernel and right kernel of ``self``. See the
6226
examples below.
6227
6228
.. note::
6229
6230
This method returns an echelon form. If the base ring
6231
is not a field, no atttempt is made to move to the fraction field.
6232
See an example below where the base ring is changed manually.
6233
6234
EXAMPLES:
6235
6236
The four relationships at the end of this example hold in general. ::
6237
6238
sage: A = matrix(QQ, [[2, -1, 7, -1, 0, -3],
6239
... [-1, 1, -5, 3, 4, 4],
6240
... [2, -1, 7, 0, 2, -2],
6241
... [2, 0, 4, 3, 6, 1],
6242
... [2, -1, 7, 0, 2, -2]])
6243
sage: E = A.extended_echelon_form(subdivide=True); E
6244
[ 1 0 2 0 0 -1| 0 -1 0 1 -1]
6245
[ 0 1 -3 0 -2 0| 0 -2 0 2 -3]
6246
[ 0 0 0 1 2 1| 0 2/3 0 -1/3 2/3]
6247
[-----------------------------+------------------------]
6248
[ 0 0 0 0 0 0| 1 2/3 0 -1/3 -1/3]
6249
[ 0 0 0 0 0 0| 0 0 1 0 -1]
6250
sage: J = E.matrix_from_columns(range(6,11)); J
6251
[ 0 -1 0 1 -1]
6252
[ 0 -2 0 2 -3]
6253
[ 0 2/3 0 -1/3 2/3]
6254
[ 1 2/3 0 -1/3 -1/3]
6255
[ 0 0 1 0 -1]
6256
sage: J*A == A.rref()
6257
True
6258
sage: C = E.subdivision(0,0); C
6259
[ 1 0 2 0 0 -1]
6260
[ 0 1 -3 0 -2 0]
6261
[ 0 0 0 1 2 1]
6262
sage: L = E.subdivision(1,1); L
6263
[ 1 2/3 0 -1/3 -1/3]
6264
[ 0 0 1 0 -1]
6265
sage: A.right_kernel() == C.right_kernel()
6266
True
6267
sage: A.row_space() == C.row_space()
6268
True
6269
sage: A.column_space() == L.right_kernel()
6270
True
6271
sage: A.left_kernel() == L.row_space()
6272
True
6273
6274
For a nonsingular matrix, the right half of the extended
6275
echelon form is the inverse matrix. ::
6276
6277
sage: B = matrix(QQ, [[1,3,4], [1,4,4], [0,-2,-1]])
6278
sage: E = B.extended_echelon_form()
6279
sage: J = E.matrix_from_columns(range(3,6)); J
6280
[-4 5 4]
6281
[-1 1 0]
6282
[ 2 -2 -1]
6283
sage: J == B.inverse()
6284
True
6285
6286
The result is in echelon form, so if the base ring is
6287
not a field, the leading entry of each row may not be 1.
6288
But you can easily change to the fraction field if necessary. ::
6289
6290
sage: A = matrix(ZZ, [[16, 20, 4, 5, -4, 13, 5],
6291
... [10, 13, 3, -3, 7, 11, 6],
6292
... [-12, -15, -3, -3, 2, -10, -4],
6293
... [10, 13, 3, 3, -1, 9, 4],
6294
... [4, 5, 1, 8, -10, 1, -1]])
6295
sage: E = A.extended_echelon_form(subdivide=True); E
6296
[ 2 0 -2 2 -9 -3 -4| 0 4 -3 -9 4]
6297
[ 0 1 1 2 0 1 1| 0 1 2 1 1]
6298
[ 0 0 0 3 -4 -1 -1| 0 3 1 -3 3]
6299
[--------------------+--------------]
6300
[ 0 0 0 0 0 0 0| 1 6 3 -6 5]
6301
[ 0 0 0 0 0 0 0| 0 7 2 -7 6]
6302
sage: J = E.matrix_from_columns(range(7,12)); J
6303
[ 0 4 -3 -9 4]
6304
[ 0 1 2 1 1]
6305
[ 0 3 1 -3 3]
6306
[ 1 6 3 -6 5]
6307
[ 0 7 2 -7 6]
6308
sage: J*A == A.echelon_form()
6309
True
6310
sage: B = A.change_ring(QQ)
6311
sage: B.extended_echelon_form(subdivide=True)
6312
[ 1 0 -1 0 -19/6 -7/6 -5/3| 0 0 -89/42 -5/2 1/7]
6313
[ 0 1 1 0 8/3 5/3 5/3| 0 0 34/21 2 -1/7]
6314
[ 0 0 0 1 -4/3 -1/3 -1/3| 0 0 1/21 0 1/7]
6315
[------------------------------------------------+----------------------------------]
6316
[ 0 0 0 0 0 0 0| 1 0 9/7 0 -1/7]
6317
[ 0 0 0 0 0 0 0| 0 1 2/7 -1 6/7]
6318
6319
Subdivided, or not, the result is immutable, so make a
6320
copy if you want to make changes. ::
6321
6322
sage: A = matrix(FiniteField(7), [[2,0,3], [5,5,3], [5,6,5]])
6323
sage: E = A.extended_echelon_form()
6324
sage: E.is_mutable()
6325
False
6326
sage: F = A.extended_echelon_form(subdivide=True)
6327
sage: F
6328
[1 0 0|0 4 6]
6329
[0 1 0|4 2 2]
6330
[0 0 1|5 2 3]
6331
[-----+-----]
6332
sage: F.is_mutable()
6333
False
6334
sage: G = copy(F)
6335
sage: G.subdivide([],[]); G
6336
[1 0 0 0 4 6]
6337
[0 1 0 4 2 2]
6338
[0 0 1 5 2 3]
6339
6340
If you want to determine exactly which algorithm is
6341
used to compute the echelon form, you can add additional
6342
keywords to pass on to the ``echelon_form()`` routine
6343
employed on the augmented matrix. Sending the flag
6344
``include_zero_rows`` is a bit silly, since the
6345
extended echelon form will never have any zero rows. ::
6346
6347
sage: A = matrix(ZZ, [[1,2], [5,0], [5,9]])
6348
sage: E = A.extended_echelon_form(algorithm='padic', include_zero_rows=False)
6349
sage: E
6350
[ 1 0 36 1 -8]
6351
[ 0 1 5 0 -1]
6352
[ 0 0 45 1 -10]
6353
6354
TESTS:
6355
6356
The ``subdivide`` keyword is checked. ::
6357
6358
sage: A = matrix(QQ, 2, range(4))
6359
sage: A.extended_echelon_form(subdivide='junk')
6360
Traceback (most recent call last):
6361
...
6362
TypeError: subdivide must be True or False, not junk
6363
6364
AUTHOR:
6365
6366
- Rob Beezer (2011-02-02)
6367
"""
6368
if not subdivide in [True, False]:
6369
raise TypeError("subdivide must be True or False, not %s" % subdivide)
6370
R = self.base_ring()
6371
import constructor
6372
ident = constructor.identity_matrix(R, self.nrows())
6373
E = self.augment(ident)
6374
extended = E.echelon_form(**kwds)
6375
if subdivide:
6376
from copy import copy
6377
extended = copy(extended)
6378
# pivots of E are cached from echelon form computation
6379
rank = len([c for c in E.pivots() if c < self.ncols()])
6380
extended.subdivide(rank, self.ncols())
6381
extended.set_immutable()
6382
return extended
6383
6384
def weak_popov_form(self, ascend=True):
6385
"""
6386
This function computes a weak Popov form of a matrix over a rational
6387
function field `k(x)`, for `k` a field.
6388
6389
INPUT:
6390
6391
- `ascend` - if True, rows of output matrix `W` are sorted so
6392
degree (= the maximum of the degrees of the elements in
6393
the row) increases monotonically, and otherwise degrees decrease.
6394
6395
OUTPUT:
6396
6397
A 3-tuple `(W,N,d)` consisting of:
6398
6399
1. `W` - a matrix over `k(x)` giving a weak the Popov form of self
6400
2. `N` - a matrix over `k[x]` representing row operations used to
6401
transform `self` to `W`
6402
3. `d` - degree of respective columns of W; the degree of a column is
6403
the maximum of the degree of its elements
6404
6405
`N` is invertible over `k(x)`. These matrices satisfy the relation
6406
`N*self = W`.
6407
6408
EXAMPLES:
6409
6410
The routine expects matrices over the rational function field, but
6411
other examples below show how one can provide matrices over the ring
6412
of polynomials (whose quotient field is the rational function field).
6413
6414
::
6415
6416
sage: R.<t> = GF(3)['t']
6417
sage: K = FractionField(R)
6418
sage: M = matrix([[(t-1)^2/t],[(t-1)]])
6419
sage: M.weak_popov_form()
6420
(
6421
[ 0] [ t 2*t + 1]
6422
[(2*t + 1)/t], [ 1 2], [-Infinity, 0]
6423
)
6424
6425
If `self` is an `n x 1` matrix with at least one non-zero entry, `W` has
6426
a single non-zero entry and that entry is a scalar multiple of the
6427
greatest-common-divisor of the entries of `self`.
6428
6429
::
6430
6431
sage: M1 = matrix([[t*(t-1)*(t+1)],[t*(t-2)*(t+2)],[t]])
6432
sage: output1 = M1.weak_popov_form()
6433
sage: output1
6434
(
6435
[0] [ 1 0 2*t^2 + 1]
6436
[0] [ 0 1 2*t^2 + 1]
6437
[t], [ 0 0 1], [-Infinity, -Infinity, 1]
6438
)
6439
6440
We check that the output is the same for a matrix `M` if its entries are
6441
rational functions intead of polynomials. We also check that the type of
6442
the output follows the documentation. See #9063
6443
6444
::
6445
6446
sage: M2 = M1.change_ring(K)
6447
sage: output2 = M2.weak_popov_form()
6448
sage: output1 == output2
6449
True
6450
sage: output1[0].base_ring() is K
6451
True
6452
sage: output2[0].base_ring() is K
6453
True
6454
sage: output1[1].base_ring() is R
6455
True
6456
sage: output2[1].base_ring() is R
6457
True
6458
6459
The following is the first half of example 5 in [H] *except* that we
6460
have transposed `self`; [H] uses column operations and we use row.
6461
6462
::
6463
6464
sage: R.<t> = QQ['t']
6465
sage: M = matrix([[t^3 - t,t^2 - 2],[0,t]]).transpose()
6466
sage: M.weak_popov_form()
6467
(
6468
[ t -t^2] [ 1 -t]
6469
[t^2 - 2 t], [ 0 1], [2, 2]
6470
)
6471
6472
The next example demonstrates what happens when `self` is a zero matrix.
6473
6474
::
6475
6476
sage: R.<t> = GF(5)['t']
6477
sage: K = FractionField(R)
6478
sage: M = matrix([[K(0),K(0)],[K(0),K(0)]])
6479
sage: M.weak_popov_form()
6480
(
6481
[0 0] [1 0]
6482
[0 0], [0 1], [-Infinity, -Infinity]
6483
)
6484
6485
In the following example, `self` has more rows than columns.
6486
6487
::
6488
6489
sage: R.<t> = QQ['t']
6490
sage: M = matrix([[t,t,t],[0,0,t]], ascend=False)
6491
sage: M.weak_popov_form()
6492
(
6493
[t t t] [1 0]
6494
[0 0 t], [0 1], [1, 1]
6495
)
6496
6497
The next example shows that M must be a matrix with
6498
coefficients in a rational function field `k(t)`.
6499
6500
::
6501
6502
sage: M = matrix([[1,0],[1,1]])
6503
sage: M.weak_popov_form()
6504
Traceback (most recent call last):
6505
...
6506
TypeError: the coefficients of M must lie in a univariate
6507
polynomial ring
6508
6509
6510
NOTES:
6511
6512
- For consistency with LLL and other algorithms in sage, we have opted
6513
for row operations; however, references such as [H] transpose and use
6514
column operations.
6515
6516
- There are multiple weak Popov forms of a matrix, so one may want to
6517
extend this code to produce a Popov form (see section 1.2 of [V]). The
6518
latter is canonical, but more work to produce.
6519
6520
REFERENCES:
6521
6522
.. [H] F. Hess, "Computing Riemann-Roch spaces in algebraic function
6523
fields and related topics," J. Symbolic Comput. 33 (2002), no. 4,
6524
425--445.
6525
6526
.. [MS] T. Mulders, A. Storjohann, "On lattice reduction for polynomial
6527
matrices," J. Symbolic Comput. 35 (2003), no. 4, 377--401
6528
6529
.. [V] G. Villard, "Computing Popov and Hermite forms of polynomial
6530
matrices", ISSAC '96: Proceedings of the 1996 international symposium
6531
on Symbolic and algebraic computation, 250--258.
6532
6533
"""
6534
import sage.matrix.matrix_misc
6535
return sage.matrix.matrix_misc.weak_popov_form(self)
6536
6537
#####################################################################################
6538
# Windowed Strassen Matrix Multiplication and Echelon
6539
# Precise algorithms invented and implemented by David Harvey and Robert Bradshaw
6540
# at William Stein's MSRI 2006 Summer Workshop on Modular Forms.
6541
#####################################################################################
6542
def _multiply_strassen(self, Matrix right, int cutoff=0):
6543
"""
6544
Multiply self by the matrix right using a Strassen-based
6545
asymptotically fast arithmetic algorithm.
6546
6547
ALGORITHM: Custom algorithm for arbitrary size matrices designed by
6548
David Harvey and Robert Bradshaw, based on Strassen's algorithm.
6549
6550
INPUT:
6551
6552
6553
- ``cutoff`` - integer (default: 0 - let class
6554
decide).
6555
6556
6557
EXAMPLES::
6558
6559
sage: a = matrix(ZZ,4,range(16))
6560
sage: a._multiply_strassen(a,2)
6561
[ 56 62 68 74]
6562
[152 174 196 218]
6563
[248 286 324 362]
6564
[344 398 452 506]
6565
"""
6566
if self._ncols != right._nrows:
6567
raise ArithmeticError, "Number of columns of self must equal number of rows of right."
6568
if not self._base_ring is right.base_ring():
6569
raise TypeError, "Base rings must be the same."
6570
6571
if cutoff == 0:
6572
cutoff = self._strassen_default_cutoff(right)
6573
6574
if cutoff <= 0:
6575
raise ValueError, "cutoff must be at least 1"
6576
6577
output = self.new_matrix(self._nrows, right._ncols)
6578
# The following used to be a little faster, but meanwhile
6579
# the previous line is faster.
6580
#if self.is_sparse():
6581
# output = self.matrix_space(self._nrows, right._ncols, sparse = True)(0)
6582
#else:
6583
# output = self.matrix_space(self._nrows, right._ncols, sparse = False).zero_matrix().__copy__()
6584
6585
self_window = self.matrix_window()
6586
right_window = right.matrix_window()
6587
output_window = output.matrix_window()
6588
6589
6590
import strassen
6591
strassen.strassen_window_multiply(output_window, self_window, right_window, cutoff)
6592
return output
6593
6594
def _echelon_strassen(self, int cutoff=0):
6595
"""
6596
In place Strassen echelon of self, and sets the pivots.
6597
6598
ALGORITHM: Custom algorithm for arbitrary size matrices designed by
6599
David Harvey and Robert Bradshaw, based on Strassen's algorithm.
6600
6601
EXAMPLES::
6602
6603
sage: A = matrix(QQ, 4, range(16))
6604
sage: A._echelon_strassen(2)
6605
sage: A
6606
[ 1 0 -1 -2]
6607
[ 0 1 2 3]
6608
[ 0 0 0 0]
6609
[ 0 0 0 0]
6610
"""
6611
tm = verbose('strassen echelon of %s x %s matrix'%(self._nrows, self._ncols))
6612
6613
self.check_mutability()
6614
6615
if not self._base_ring.is_field():
6616
raise ValueError, "Echelon form not defined over this base ring."
6617
6618
if cutoff == 0:
6619
cutoff = self._strassen_default_echelon_cutoff()
6620
6621
if cutoff < 1:
6622
raise ValueError, "cutoff must be at least 1"
6623
6624
if self._nrows < cutoff or self._ncols < cutoff:
6625
self._echelon_in_place_classical()
6626
return
6627
6628
import strassen
6629
pivots = strassen.strassen_echelon(self.matrix_window(), cutoff)
6630
self._set_pivots(pivots)
6631
verbose('done with strassen', tm)
6632
6633
cpdef matrix_window(self, Py_ssize_t row=0, Py_ssize_t col=0,
6634
Py_ssize_t nrows=-1, Py_ssize_t ncols=-1,
6635
bint check=1):
6636
"""
6637
Return the requested matrix window.
6638
6639
EXAMPLES::
6640
6641
sage: A = matrix(QQ, 3, range(9))
6642
sage: A.matrix_window(1,1, 2, 1)
6643
Matrix window of size 2 x 1 at (1,1):
6644
[0 1 2]
6645
[3 4 5]
6646
[6 7 8]
6647
6648
We test the optional check flag.
6649
6650
::
6651
6652
sage: matrix([1]).matrix_window(0,1,1,1, check=False)
6653
Matrix window of size 1 x 1 at (0,1):
6654
[1]
6655
sage: matrix([1]).matrix_window(0,1,1,1)
6656
Traceback (most recent call last):
6657
...
6658
IndexError: matrix window index out of range
6659
6660
Another test of bounds checking::
6661
6662
sage: matrix([1]).matrix_window(1,1,1,1)
6663
Traceback (most recent call last):
6664
...
6665
IndexError: matrix window index out of range
6666
"""
6667
import matrix_window
6668
if nrows == -1:
6669
nrows = self._nrows - row
6670
if ncols == -1:
6671
ncols = self._ncols - col
6672
if check and (row < 0 or col < 0 or row + nrows > self._nrows or \
6673
col + ncols > self._ncols):
6674
raise IndexError, "matrix window index out of range"
6675
return matrix_window.MatrixWindow(self, row, col, nrows, ncols)
6676
6677
def set_block(self, row, col, block):
6678
"""
6679
Sets the sub-matrix of self, with upper left corner given by row,
6680
col to block.
6681
6682
EXAMPLES::
6683
6684
sage: A = matrix(QQ, 3, 3, range(9))/2
6685
sage: B = matrix(ZZ, 2, 1, [100,200])
6686
sage: A.set_block(0, 1, B)
6687
sage: A
6688
[ 0 100 1]
6689
[3/2 200 5/2]
6690
[ 3 7/2 4]
6691
6692
We test that an exception is raised when the block is out of
6693
bounds::
6694
6695
sage: matrix([1]).set_block(0,1,matrix([1]))
6696
Traceback (most recent call last):
6697
...
6698
IndexError: matrix window index out of range
6699
"""
6700
self.check_mutability()
6701
if block.base_ring() is not self.base_ring():
6702
block = block.change_ring(self.base_ring())
6703
window = self.matrix_window(row, col, block.nrows(), block.ncols(), check=True)
6704
window.set(block.matrix_window())
6705
6706
def subdivide(self, row_lines=None, col_lines=None):
6707
"""
6708
Divides self into logical submatrices which can then be queried and
6709
extracted. If a subdivision already exists, this method forgets the
6710
previous subdivision and flushes the cache.
6711
6712
INPUT:
6713
6714
6715
- ``row_lines`` - None, an integer, or a list of
6716
integers
6717
6718
- ``col_lines`` - None, an integer, or a list of
6719
integers
6720
6721
6722
OUTPUT: changes self
6723
6724
.. note::
6725
6726
One may also pass a tuple into the first argument which
6727
will be interpreted as (row_lines, col_lines)
6728
6729
EXAMPLES::
6730
6731
sage: M = matrix(5, 5, prime_range(100))
6732
sage: M.subdivide(2,3); M
6733
[ 2 3 5| 7 11]
6734
[13 17 19|23 29]
6735
[--------+-----]
6736
[31 37 41|43 47]
6737
[53 59 61|67 71]
6738
[73 79 83|89 97]
6739
sage: M.subdivision(0,0)
6740
[ 2 3 5]
6741
[13 17 19]
6742
sage: M.subdivision(1,0)
6743
[31 37 41]
6744
[53 59 61]
6745
[73 79 83]
6746
sage: M.subdivision_entry(1,0,0,0)
6747
31
6748
sage: M.subdivisions()
6749
([2], [3])
6750
sage: M.subdivide(None, [1,3]); M
6751
[ 2| 3 5| 7 11]
6752
[13|17 19|23 29]
6753
[31|37 41|43 47]
6754
[53|59 61|67 71]
6755
[73|79 83|89 97]
6756
6757
Degenerate cases work too.
6758
6759
::
6760
6761
sage: M.subdivide([2,5], [0,1,3]); M
6762
[| 2| 3 5| 7 11]
6763
[|13|17 19|23 29]
6764
[+--+-----+-----]
6765
[|31|37 41|43 47]
6766
[|53|59 61|67 71]
6767
[|73|79 83|89 97]
6768
[+--+-----+-----]
6769
sage: M.subdivision(0,0)
6770
[]
6771
sage: M.subdivision(0,1)
6772
[ 2]
6773
[13]
6774
sage: M.subdivide([2,2,3], [0,0,1,1]); M
6775
[|| 2|| 3 5 7 11]
6776
[||13||17 19 23 29]
6777
[++--++-----------]
6778
[++--++-----------]
6779
[||31||37 41 43 47]
6780
[++--++-----------]
6781
[||53||59 61 67 71]
6782
[||73||79 83 89 97]
6783
sage: M.subdivision(0,0)
6784
[]
6785
sage: M.subdivision(2,4)
6786
[37 41 43 47]
6787
6788
AUTHORS:
6789
6790
- Robert Bradshaw (2007-06-14)
6791
"""
6792
6793
self.check_mutability()
6794
if col_lines is None and row_lines is not None and isinstance(row_lines, tuple):
6795
tmp = row_lines
6796
row_lines, col_lines = tmp
6797
if row_lines is None:
6798
row_lines = []
6799
elif not isinstance(row_lines, list):
6800
row_lines = [row_lines]
6801
if col_lines is None:
6802
col_lines = []
6803
elif not isinstance(col_lines, list):
6804
col_lines = [col_lines]
6805
row_lines = [0] + [int(ZZ(x)) for x in row_lines] + [self._nrows]
6806
col_lines = [0] + [int(ZZ(x)) for x in col_lines] + [self._ncols]
6807
if self._subdivisions is not None:
6808
self.clear_cache()
6809
self._subdivisions = (row_lines, col_lines)
6810
6811
def subdivision(self, i, j):
6812
"""
6813
Returns an immutable copy of the (i,j)th submatrix of self,
6814
according to a previously set subdivision.
6815
6816
Before a subdivision is set, the only valid arguments are (0,0)
6817
which returns self.
6818
6819
EXAMPLE::
6820
6821
sage: M = matrix(3, 4, range(12))
6822
sage: M.subdivide(1,2); M
6823
[ 0 1| 2 3]
6824
[-----+-----]
6825
[ 4 5| 6 7]
6826
[ 8 9|10 11]
6827
sage: M.subdivision(0,0)
6828
[0 1]
6829
sage: M.subdivision(0,1)
6830
[2 3]
6831
sage: M.subdivision(1,0)
6832
[4 5]
6833
[8 9]
6834
6835
It handles size-zero subdivisions as well.
6836
6837
::
6838
6839
sage: M = matrix(3, 4, range(12))
6840
sage: M.subdivide([0],[0,2,2,4]); M
6841
[+-----++-----+]
6842
[| 0 1|| 2 3|]
6843
[| 4 5|| 6 7|]
6844
[| 8 9||10 11|]
6845
sage: M.subdivision(0,0)
6846
[]
6847
sage: M.subdivision(1,1)
6848
[0 1]
6849
[4 5]
6850
[8 9]
6851
sage: M.subdivision(1,2)
6852
[]
6853
sage: M.subdivision(1,0)
6854
[]
6855
sage: M.subdivision(0,1)
6856
[]
6857
"""
6858
if self._subdivisions is None:
6859
self._subdivisions = ([0, self._nrows], [0, self._ncols])
6860
key = "subdivision %s %s"%(i,j)
6861
sd = self.fetch(key)
6862
if sd is None:
6863
sd = self[self._subdivisions[0][i]:self._subdivisions[0][i+1],
6864
self._subdivisions[1][j]:self._subdivisions[1][j+1]]
6865
sd.set_immutable()
6866
self.cache(key, sd)
6867
return sd
6868
6869
def subdivision_entry(self, i, j, x, y):
6870
"""
6871
Returns the x,y entry of the i,j submatrix of self.
6872
6873
EXAMPLES::
6874
6875
sage: M = matrix(5, 5, range(25))
6876
sage: M.subdivide(3,3); M
6877
[ 0 1 2| 3 4]
6878
[ 5 6 7| 8 9]
6879
[10 11 12|13 14]
6880
[--------+-----]
6881
[15 16 17|18 19]
6882
[20 21 22|23 24]
6883
sage: M.subdivision_entry(0,0,1,2)
6884
7
6885
sage: M.subdivision(0,0)[1,2]
6886
7
6887
sage: M.subdivision_entry(0,1,0,0)
6888
3
6889
sage: M.subdivision_entry(1,0,0,0)
6890
15
6891
sage: M.subdivision_entry(1,1,1,1)
6892
24
6893
6894
Even though this entry exists in the matrix, the index is invalid
6895
for the submatrix.
6896
6897
::
6898
6899
sage: M.subdivision_entry(0,0,4,0)
6900
Traceback (most recent call last):
6901
...
6902
IndexError: Submatrix 0,0 has no entry 4,0
6903
"""
6904
if self._subdivisions is None:
6905
if not i and not j:
6906
return self[x,y]
6907
else:
6908
raise IndexError, "No such submatrix %s, %s"%(i,j)
6909
if x >= self._subdivisions[0][i+1]-self._subdivisions[0][i] or \
6910
y >= self._subdivisions[1][j+1]-self._subdivisions[1][j]:
6911
raise IndexError, "Submatrix %s,%s has no entry %s,%s"%(i,j, x, y)
6912
return self[self._subdivisions[0][i] + x , self._subdivisions[1][j] + y]
6913
6914
def _subdivide_on_augment(self, left, right):
6915
r"""
6916
Helper method to manage subdivisions when augmenting a matrix.
6917
6918
INPUT:
6919
6920
- ``left``, ``right`` - two matrices, such that if ``left`` is
6921
augmented by placing ``right`` on the right side of ``left``,
6922
then the result is ``self``. It is the responsibility of the
6923
calling routine to ensure this condition holds.
6924
6925
OUTPUT:
6926
6927
``None``. A new subdivision is created between ``left`` and
6928
``right`` for ``self``. If possible, row subdivisions are
6929
preserved in ``self``, but if the two sets of row subdivisions
6930
are incompatible, they are removed.
6931
6932
EXAMPLE::
6933
6934
sage: A = matrix(QQ, 3, 4, range(12))
6935
sage: B = matrix(QQ, 3, 6, range(18))
6936
sage: C = A.augment(B)
6937
sage: C._subdivide_on_augment(A, B)
6938
sage: C
6939
[ 0 1 2 3| 0 1 2 3 4 5]
6940
[ 4 5 6 7| 6 7 8 9 10 11]
6941
[ 8 9 10 11|12 13 14 15 16 17]
6942
6943
More descriptive, but indirect, doctests are at
6944
:meth:`sage.matrix.matrix1.Matrix.augment`.
6945
"""
6946
left_rows, left_cols = left.subdivisions()
6947
right_rows, right_cols = right.subdivisions()
6948
if left_rows == right_rows:
6949
self_rows = left_rows
6950
else:
6951
self_rows = None
6952
nc = left.ncols()
6953
self_cols = left_cols + [nc]
6954
for col in right_cols:
6955
self_cols.append(col+nc)
6956
self.subdivide(self_rows, self_cols)
6957
return None
6958
6959
def _subdivide_on_stack(self, top, bottom):
6960
r"""
6961
Helper method to manage subdivisions when stacking a matrix.
6962
6963
INPUT:
6964
6965
- ``top``, ``bottom`` - two matrices, such that if ``top`` is
6966
stacked by placing ``top`` above ``bottom``, then the result
6967
is ``self``. It is the responsibility of the calling routine
6968
to ensure this condition holds.
6969
6970
OUTPUT:
6971
6972
``None``. A new subdivision is created between ``top`` and
6973
``bottom`` for ``self``. If possible, column subdivisions are
6974
preserved in ``self``, but if the two sets of solumn subdivisions
6975
are incompatible, they are removed.
6976
6977
EXAMPLE::
6978
6979
sage: A = matrix(QQ, 3, 2, range(6))
6980
sage: B = matrix(QQ, 4, 2, range(8))
6981
sage: C = A.stack(B)
6982
sage: C._subdivide_on_stack(A, B)
6983
sage: C
6984
[0 1]
6985
[2 3]
6986
[4 5]
6987
[---]
6988
[0 1]
6989
[2 3]
6990
[4 5]
6991
[6 7]
6992
6993
More descriptive, but indirect, doctests are at
6994
:meth:`sage.matrix.matrix1.Matrix.augment`.
6995
"""
6996
top_rows, top_cols = top.subdivisions()
6997
bottom_rows, bottom_cols = bottom.subdivisions()
6998
if top_cols == bottom_cols:
6999
self_cols = top_cols
7000
else:
7001
self_cols = None
7002
nr = top.nrows()
7003
self_rows = top_rows + [nr]
7004
for row in bottom_rows:
7005
self_rows.append(row+nr)
7006
self.subdivide(self_rows, self_cols)
7007
return None
7008
7009
def subdivisions(self):
7010
"""
7011
Returns the current subdivision of self.
7012
7013
EXAMPLES::
7014
7015
sage: M = matrix(5, 5, range(25))
7016
sage: M.subdivisions()
7017
([], [])
7018
sage: M.subdivide(2,3)
7019
sage: M.subdivisions()
7020
([2], [3])
7021
sage: N = M.parent()(1)
7022
sage: N.subdivide(M.subdivisions()); N
7023
[1 0 0|0 0]
7024
[0 1 0|0 0]
7025
[-----+---]
7026
[0 0 1|0 0]
7027
[0 0 0|1 0]
7028
[0 0 0|0 1]
7029
"""
7030
if self._subdivisions is None:
7031
return ([], [])
7032
else:
7033
return (self._subdivisions[0][1:-1], self._subdivisions[1][1:-1])
7034
7035
# 'get_subdivisions' is kept for backwards compatibility: see #4983.
7036
get_subdivisions = subdivisions
7037
7038
def tensor_product(self, A, subdivide=True):
7039
r"""
7040
Returns the tensor product of two matrices.
7041
7042
INPUT:
7043
7044
- ``A`` - a matrix
7045
- ``subdivide`` - default: True - whether or not to return
7046
natural subdivisions with the matrix
7047
7048
OUTPUT:
7049
7050
Replace each element of ``self`` by a copy of ``A``, but first
7051
create a scalar multiple of ``A`` by the element it replaces.
7052
So if ``self`` is an `m\times n` matrix and ``A`` is a
7053
`p\times q` matrix, then the tensor product is an `mp\times nq`
7054
matrix. By default, the matrix will be subdivided into
7055
submatrices of size `p\times q`.
7056
7057
EXAMPLES::
7058
7059
sage: M1=Matrix(QQ,[[-1,0],[-1/2,-1]])
7060
sage: M2=Matrix(ZZ,[[1,-1,2],[-2,4,8]])
7061
sage: M1.tensor_product(M2)
7062
[ -1 1 -2| 0 0 0]
7063
[ 2 -4 -8| 0 0 0]
7064
[--------------+--------------]
7065
[-1/2 1/2 -1| -1 1 -2]
7066
[ 1 -2 -4| 2 -4 -8]
7067
sage: M2.tensor_product(M1)
7068
[ -1 0| 1 0| -2 0]
7069
[-1/2 -1| 1/2 1| -1 -2]
7070
[---------+---------+---------]
7071
[ 2 0| -4 0| -8 0]
7072
[ 1 2| -2 -4| -4 -8]
7073
7074
Subdivisions can be optionally suppressed. ::
7075
7076
sage: M1.tensor_product(M2, subdivide=False)
7077
[ -1 1 -2 0 0 0]
7078
[ 2 -4 -8 0 0 0]
7079
[-1/2 1/2 -1 -1 1 -2]
7080
[ 1 -2 -4 2 -4 -8]
7081
7082
Different base rings are handled sensibly. ::
7083
7084
sage: A = matrix(ZZ, 2, 3, range(6))
7085
sage: B = matrix(FiniteField(23), 3, 4, range(12))
7086
sage: C = matrix(FiniteField(29), 4, 5, range(20))
7087
sage: D = A.tensor_product(B)
7088
sage: D.parent()
7089
Full MatrixSpace of 6 by 12 dense matrices over Finite Field of size 23
7090
sage: E = C.tensor_product(B)
7091
Traceback (most recent call last):
7092
...
7093
TypeError: unsupported operand parent(s) for '*': 'Finite Field of size 29' and 'Full MatrixSpace of 3 by 4 dense matrices over Finite Field of size 23'
7094
7095
The input is checked to be sure it is a matrix. ::
7096
7097
sage: A = matrix(QQ, 2, range(4))
7098
sage: A.tensor_product('junk')
7099
Traceback (most recent call last):
7100
...
7101
TypeError: tensor product requires a second matrix, not junk
7102
"""
7103
if not isinstance(A, Matrix):
7104
raise TypeError('tensor product requires a second matrix, not {0}'.format(A))
7105
return sage.matrix.constructor.block_matrix(self.nrows(),self.ncols(),[x*A for x in self.list()], subdivide=subdivide)
7106
7107
def randomize(self, density=1, nonzero=False, *args, **kwds):
7108
"""
7109
Randomize density proportion of the entries of this matrix, leaving
7110
the rest unchanged.
7111
7112
.. note::
7113
7114
We actually choose at random ``density`` proportion of entries of
7115
the matrix and set them to random elements. It's possible that the
7116
same position can be chosen multiple times, especially for a very
7117
small matrix.
7118
7119
INPUT:
7120
7121
- ``density`` - ``float`` (default: 1); rough measure of the
7122
proportion of nonzero entries in the random matrix
7123
- ``nonzero`` - Bool (default: ``False``); whether the new entries
7124
have to be non-zero
7125
- ``*args, **kwds`` - Remaining parameters may be passed to the
7126
``random_element`` function of the base ring
7127
7128
EXAMPLES:
7129
7130
We construct the zero matrix over a polynomial ring.
7131
7132
::
7133
7134
sage: a = matrix(QQ['x'], 3); a
7135
[0 0 0]
7136
[0 0 0]
7137
[0 0 0]
7138
7139
We then randomize roughly half the entries::
7140
7141
sage: a.randomize(0.5)
7142
sage: a
7143
[ 1/2*x^2 - x - 12 1/2*x^2 - 1/95*x - 1/2 0]
7144
[-5/2*x^2 + 2/3*x - 1/4 0 0]
7145
[ -x^2 + 2/3*x 0 0]
7146
7147
Now we randomize all the entries of the resulting matrix::
7148
7149
sage: a.randomize()
7150
sage: a
7151
[ 1/3*x^2 - x + 1 -x^2 + 1 x^2 - x]
7152
[ -1/14*x^2 - x - 1/4 -4*x - 1/5 -1/4*x^2 - 1/2*x + 4]
7153
[ 1/9*x^2 + 5/2*x - 3 -x^2 + 3/2*x + 1 -2/7*x^2 - x - 1/2]
7154
7155
We create the zero matrix over the integers::
7156
7157
sage: a = matrix(ZZ, 2); a
7158
[0 0]
7159
[0 0]
7160
7161
Then we randomize it; the x and y parameters, which determine the
7162
size of the random elements, are passed onto the ZZ random_element
7163
method.
7164
7165
::
7166
7167
sage: a.randomize(x=-2^64, y=2^64)
7168
sage: a
7169
[-12401200298100116246 1709403521783430739]
7170
[ -4417091203680573707 17094769731745295000]
7171
"""
7172
randint = current_randstate().python_random().randint
7173
7174
density = float(density)
7175
if density <= 0:
7176
return
7177
if density > 1:
7178
density = 1
7179
7180
self.check_mutability()
7181
self.clear_cache()
7182
7183
R = self.base_ring()
7184
7185
cdef Py_ssize_t i, j, num
7186
7187
if nonzero:
7188
if density >= 1:
7189
for i from 0 <= i < self._nrows:
7190
for j from 0 <= j < self._ncols:
7191
self.set_unsafe(i, j, R._random_nonzero_element(*args,\
7192
**kwds))
7193
else:
7194
num = int(self._nrows * self._ncols * density)
7195
for i from 0 <= i < num:
7196
self.set_unsafe(randint(0, self._nrows - 1),
7197
randint(0, self._ncols - 1),
7198
R._random_nonzero_element(*args, **kwds))
7199
else:
7200
if density >= 1:
7201
for i from 0 <= i < self._nrows:
7202
for j from 0 <= j < self._ncols:
7203
self.set_unsafe(i, j, R.random_element(*args, **kwds))
7204
else:
7205
num = int(self._nrows * self._ncols * density)
7206
for i from 0 <= i < num:
7207
self.set_unsafe(randint(0, self._nrows - 1),
7208
randint(0, self._ncols - 1),
7209
R.random_element(*args, **kwds))
7210
7211
def is_one(self):
7212
"""
7213
Return True if this matrix is the identity matrix.
7214
7215
EXAMPLES::
7216
7217
sage: m = matrix(QQ,2,range(4))
7218
sage: m.is_one()
7219
False
7220
sage: m = matrix(QQ,2,[5,0,0,5])
7221
sage: m.is_one()
7222
False
7223
sage: m = matrix(QQ,2,[1,0,0,1])
7224
sage: m.is_one()
7225
True
7226
sage: m = matrix(QQ,2,[1,1,1,1])
7227
sage: m.is_one()
7228
False
7229
"""
7230
return self.is_scalar(1)
7231
7232
def is_scalar(self, a = None):
7233
"""
7234
Return True if this matrix is a scalar matrix.
7235
7236
INPUT
7237
7238
- base_ring element a, which is chosen as self[0][0] if
7239
a = None
7240
7241
OUTPUT
7242
7243
- whether self is a scalar matrix (in fact the scalar matrix
7244
aI if a is input)
7245
7246
EXAMPLES::
7247
7248
sage: m = matrix(QQ,2,range(4))
7249
sage: m.is_scalar(5)
7250
False
7251
sage: m = matrix(QQ,2,[5,0,0,5])
7252
sage: m.is_scalar(5)
7253
True
7254
sage: m = matrix(QQ,2,[1,0,0,1])
7255
sage: m.is_scalar(1)
7256
True
7257
sage: m = matrix(QQ,2,[1,1,1,1])
7258
sage: m.is_scalar(1)
7259
False
7260
"""
7261
if not self.is_square():
7262
return False
7263
cdef Py_ssize_t i, j
7264
if a is None:
7265
if self._nrows == 0:
7266
return True
7267
a = self.get_unsafe(0,0)
7268
else:
7269
a = self.base_ring()(a)
7270
zero = self.base_ring()(0)
7271
for i from 0 <= i < self._nrows:
7272
for j from 0 <= j < self._ncols:
7273
if i != j:
7274
if self.get_unsafe(i,j) != zero:
7275
return False
7276
else:
7277
if self.get_unsafe(i, i) != a:
7278
return False
7279
return True
7280
7281
7282
def is_unitary(self):
7283
r"""
7284
Returns ``True`` if the columns of the matrix are an orthonormal basis.
7285
7286
For a matrix with real entries this determines if a matrix is
7287
"orthogonal" and for a matrix with complex entries this determines
7288
if the matrix is "unitary."
7289
7290
OUTPUT:
7291
7292
``True`` if the matrix is square and its conjugate-transpose is
7293
its inverse, and ``False`` otherwise. In other words, a matrix
7294
is orthogonal or unitary if the product of its conjugate-transpose
7295
times the matrix is the identity matrix.
7296
7297
For numerical matrices a specialized routine available
7298
over ``RDF`` and ``CDF`` is a good choice.
7299
7300
EXAMPLES::
7301
7302
sage: A = matrix(QQbar, [[(1/sqrt(5))*(1+i), (1/sqrt(55))*(3+2*I), (1/sqrt(22))*(2+2*I)],
7303
... [(1/sqrt(5))*(1-i), (1/sqrt(55))*(2+2*I), (1/sqrt(22))*(-3+I)],
7304
... [ (1/sqrt(5))*I, (1/sqrt(55))*(3-5*I), (1/sqrt(22))*(-2)]])
7305
sage: A.is_unitary()
7306
True
7307
7308
A permutation matrix is always orthogonal. ::
7309
7310
sage: sigma = Permutation([1,3,4,5,2])
7311
sage: P = sigma.to_matrix(); P
7312
[1 0 0 0 0]
7313
[0 0 0 0 1]
7314
[0 1 0 0 0]
7315
[0 0 1 0 0]
7316
[0 0 0 1 0]
7317
sage: P.is_unitary()
7318
True
7319
sage: P.change_ring(GF(3)).is_unitary()
7320
True
7321
sage: P.change_ring(GF(3)).is_unitary()
7322
True
7323
7324
A square matrix far from unitary. ::
7325
7326
sage: A = matrix(QQ, 4, range(16))
7327
sage: A.is_unitary()
7328
False
7329
7330
Rectangular matrices are never unitary. ::
7331
7332
sage: A = matrix(QQbar, 3, 4)
7333
sage: A.is_unitary()
7334
False
7335
"""
7336
import sage.matrix.constructor
7337
if not self.is_square():
7338
return False
7339
if hasattr(self.base_ring().an_element(), 'conjugate'):
7340
P = self.conjugate().transpose()*self # Unitary
7341
else:
7342
P = self.transpose()*self # Orthogonal
7343
return P.is_scalar(1)
7344
7345
def is_bistochastic(self, normalized = True):
7346
r"""
7347
Returns ``True`` if this matrix is bistochastic.
7348
7349
A matrix is said to be bistochastic if both the sums of the
7350
entries of each row and the sum of the entries of each column
7351
are equal to 1.
7352
7353
INPUT:
7354
7355
- ``normalized`` -- if set to ``True`` (default), checks that
7356
the sums are equal to 1. When set to ``False``, checks that
7357
the row sums and column sums are all equal to some constant
7358
possibly different from 1.
7359
7360
EXAMPLES:
7361
7362
The identity matrix is clearly bistochastic::
7363
7364
sage: Matrix(5,5,1).is_bistochastic()
7365
True
7366
7367
The same matrix, multiplied by 2, is not bistochastic anymore,
7368
though is verifies the constraints of ``normalized == False``::
7369
7370
sage: (2 * Matrix(5,5,1)).is_bistochastic()
7371
False
7372
sage: (2 * Matrix(5,5,1)).is_bistochastic(normalized = False)
7373
True
7374
"""
7375
7376
row_sums = map(sum, self.rows())
7377
col_sums = map(sum, self.columns())
7378
7379
return self.is_square() and\
7380
col_sums[0] == row_sums[0] and\
7381
row_sums == col_sums and\
7382
row_sums == len(row_sums) * [col_sums[0]] and\
7383
((not normalized) or col_sums[0] == self.base_ring()(1))
7384
7385
def is_normal(self):
7386
r"""
7387
Returns ``True`` if the matrix commutes with its conjugate-transpose.
7388
7389
OUTPUT:
7390
7391
``True`` if the matrix is square and commutes with its
7392
conjugate-transpose, and ``False`` otherwise.
7393
7394
Normal matrices are precisely those that can be diagonalized
7395
by a unitary matrix.
7396
7397
This routine is for matrices over exact rings and so may not
7398
work properly for matrices over ``RR`` or ``CC``. For matrices with
7399
approximate entries, the rings of double-precision floating-point
7400
numbers, ``RDF`` and ``CDF``, are a better choice since the
7401
:meth:`sage.matrix.matrix_double_dense.Matrix_double_dense.is_normal`
7402
method has a tolerance parameter. This provides control over
7403
allowing for minor discrepancies between entries when checking
7404
equality.
7405
7406
The result is cached.
7407
7408
EXAMPLES:
7409
7410
Hermitian matrices are normal. ::
7411
7412
sage: A = matrix(QQ, 5, range(25)) + I*matrix(QQ, 5, range(0, 50, 2))
7413
sage: B = A*A.conjugate_transpose()
7414
sage: B.is_hermitian()
7415
True
7416
sage: B.is_normal()
7417
True
7418
7419
Circulant matrices are normal. ::
7420
7421
sage: G = graphs.CirculantGraph(20, [3, 7])
7422
sage: D = digraphs.Circuit(20)
7423
sage: A = 3*D.adjacency_matrix() - 5*G.adjacency_matrix()
7424
sage: A.is_normal()
7425
True
7426
7427
Skew-symmetric matrices are normal. ::
7428
7429
sage: A = matrix(QQ, 5, range(25))
7430
sage: B = A - A.transpose()
7431
sage: B.is_skew_symmetric()
7432
True
7433
sage: B.is_normal()
7434
True
7435
7436
A small matrix that does not fit into any of the usual categories
7437
of normal matrices. ::
7438
7439
sage: A = matrix(ZZ, [[1, -1],
7440
... [1, 1]])
7441
sage: A.is_normal()
7442
True
7443
sage: not A.is_hermitian() and not A.is_skew_symmetric()
7444
True
7445
7446
Sage has several fields besides the entire complex numbers
7447
where conjugation is non-trivial. ::
7448
7449
sage: F.<b> = QuadraticField(-7)
7450
sage: C = matrix(F, [[-2*b - 3, 7*b - 6, -b + 3],
7451
... [-2*b - 3, -3*b + 2, -2*b],
7452
... [ b + 1, 0, -2]])
7453
sage: C = C*C.conjugate_transpose()
7454
sage: C.is_normal()
7455
True
7456
7457
A matrix that is nearly normal, but for a non-real
7458
diagonal entry. ::
7459
7460
sage: A = matrix(QQbar, [[ 2, 2-I, 1+4*I],
7461
... [ 2+I, 3+I, 2-6*I],
7462
... [1-4*I, 2+6*I, 5]])
7463
sage: A.is_normal()
7464
False
7465
sage: A[1,1] = 132
7466
sage: A.is_normal()
7467
True
7468
7469
Rectangular matrices are never normal. ::
7470
7471
sage: A = matrix(QQbar, 3, 4)
7472
sage: A.is_normal()
7473
False
7474
7475
A square, empty matrix is trivially normal. ::
7476
7477
sage: A = matrix(QQ, 0, 0)
7478
sage: A.is_normal()
7479
True
7480
7481
AUTHOR:
7482
7483
- Rob Beezer (2011-03-31)
7484
"""
7485
key = 'normal'
7486
n = self.fetch(key)
7487
if not n is None:
7488
return n
7489
if not self.is_square():
7490
self.cache(key, False)
7491
return False
7492
if self._nrows == 0:
7493
self.cache(key, True)
7494
return True
7495
7496
CT = self.conjugate_transpose()
7497
cdef Matrix left = self*CT
7498
cdef Matrix right = CT*self
7499
7500
cdef Py_ssize_t i,j
7501
normal = True
7502
# two products are Hermitian, need only check lower triangle
7503
for i from 0 <= i < self._nrows:
7504
for j from 0 <= j <= i:
7505
if left.get_unsafe(i,j) != right.get_unsafe(i,j):
7506
normal = False
7507
break
7508
if not normal:
7509
break
7510
self.cache(key, normal)
7511
return normal
7512
7513
def as_sum_of_permutations(self):
7514
r"""
7515
Returns the current matrix as a sum of permutation matrices
7516
7517
According to the Birkhoff-von Neumann Theorem, any bistochastic matrix
7518
can be written as a positive sum of permutation matrices, which also
7519
means that the polytope of bistochastic matrices is integer.
7520
7521
As a non-bistochastic matrix can obviously not be written as a sum of
7522
permutations, this theorem is an equivalence.
7523
7524
This function, given a bistochastic matrix, returns the corresponding
7525
decomposition.
7526
7527
.. SEEALSO:
7528
7529
- :meth:`bistochastic_as_sum_of_permutations <sage.combinat.permutation.bistochastic_as_sum_of_permutations>`
7530
-- for more information on this method.
7531
7532
EXAMPLE:
7533
7534
We create a bistochastic matrix from a convex sum of permutations, then
7535
try to deduce the decomposition from the matrix ::
7536
7537
sage: L = []
7538
sage: L.append((9,Permutation([4, 1, 3, 5, 2])))
7539
sage: L.append((6,Permutation([5, 3, 4, 1, 2])))
7540
sage: L.append((3,Permutation([3, 1, 4, 2, 5])))
7541
sage: L.append((2,Permutation([1, 4, 2, 3, 5])))
7542
sage: M = sum([c * p.to_matrix() for (c,p) in L])
7543
sage: decomp = sage.combinat.permutation.bistochastic_as_sum_of_permutations(M)
7544
sage: print decomp
7545
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]]
7546
7547
An exception is raised when the matrix is not bistochastic::
7548
7549
sage: M = Matrix([[2,3],[2,2]])
7550
sage: decomp = sage.combinat.permutation.bistochastic_as_sum_of_permutations(M)
7551
Traceback (most recent call last):
7552
...
7553
ValueError: The matrix is not bistochastic
7554
"""
7555
7556
from sage.combinat.permutation import bistochastic_as_sum_of_permutations
7557
return bistochastic_as_sum_of_permutations(self)
7558
7559
7560
def visualize_structure(self, filename=None, maxsize=512):
7561
"""
7562
Write a PNG image to 'filename' which visualizes self by putting
7563
black pixels in those positions which have nonzero entries.
7564
7565
White pixels are put at positions with zero entries. If 'maxsize'
7566
is given, then the maximal dimension in either x or y direction is
7567
set to 'maxsize' depending on which is bigger. If the image is
7568
scaled, the darkness of the pixel reflects how many of the
7569
represented entries are nonzero. So if e.g. one image pixel
7570
actually represents a 2x2 submatrix, the dot is darker the more of
7571
the four values are nonzero.
7572
7573
INPUT:
7574
7575
7576
- ``filename`` - either a path or None in which case a
7577
filename in the current directory is chosen automatically
7578
(default:None)
7579
7580
7581
maxsize - maximal dimension in either x or y direction of the
7582
resulting image. If None or a maxsize larger than
7583
max(self.nrows(),self.ncols()) is given the image will have the
7584
same pixelsize as the matrix dimensions (default: 512)
7585
7586
EXAMPLE::
7587
7588
sage: M = random_matrix(CC, 4)
7589
sage: M.visualize_structure(os.path.join(SAGE_TMP, "matrix.png"))
7590
"""
7591
import gd
7592
import os
7593
7594
cdef int x, y, _x, _y, v, bi, bisq
7595
cdef int ir,ic
7596
cdef float b, fct
7597
7598
mr, mc = self.nrows(), self.ncols()
7599
7600
if maxsize is None:
7601
7602
ir = mc
7603
ic = mr
7604
b = 1.0
7605
7606
elif max(mr,mc) > maxsize:
7607
7608
maxsize = float(maxsize)
7609
ir = int(mc * maxsize/max(mr,mc))
7610
ic = int(mr * maxsize/max(mr,mc))
7611
b = max(mr,mc)/maxsize
7612
7613
else:
7614
7615
ir = mc
7616
ic = mr
7617
b = 1.0
7618
7619
bi = round(b)
7620
bisq = bi*bi
7621
fct = 255.0/bisq
7622
7623
im = gd.image((ir,ic),1)
7624
white = im.colorExact((255,255,255))
7625
im.fill((0,0),white)
7626
7627
# these speed things up a bit
7628
colorExact = im.colorExact
7629
setPixel = im.setPixel
7630
7631
for x from 0 <= x < ic:
7632
for y from 0 <= y < ir:
7633
v = bisq
7634
for _x from 0 <= _x < bi:
7635
for _y from 0 <= _y < bi:
7636
if not self.get_unsafe(<int>(x*b + _x), <int>(y*b + _y)).is_zero():
7637
v-=1 #increase darkness
7638
7639
v = round(v*fct)
7640
val = colorExact((v,v,v))
7641
setPixel((y,x), val)
7642
7643
if filename is None:
7644
filename = graphics_filename()
7645
7646
im.writePng(filename)
7647
7648
def density(self):
7649
"""
7650
Return the density of the matrix.
7651
7652
By density we understand the ratio of the number of nonzero
7653
positions and the self.nrows() \* self.ncols(), i.e. the number of
7654
possible nonzero positions.
7655
7656
EXAMPLE:
7657
7658
First, note that the density parameter does not ensure the density
7659
of a matrix, it is only an upper bound.
7660
7661
::
7662
7663
sage: A = random_matrix(GF(127),200,200,density=0.3)
7664
sage: A.density()
7665
5211/20000
7666
7667
::
7668
7669
sage: A = matrix(QQ,3,3,[0,1,2,3,0,0,6,7,8])
7670
sage: A.density()
7671
2/3
7672
7673
::
7674
7675
sage: a = matrix([[],[],[],[]])
7676
sage: a.density()
7677
0
7678
"""
7679
cdef int x,y,k
7680
k = 0
7681
nr = self.nrows()
7682
nc = self.ncols()
7683
if nc == 0 or nr == 0:
7684
return 0
7685
for x from 0 <= x < nr:
7686
for y from 0 <= y < nc:
7687
if not self.get_unsafe(x,y).is_zero():
7688
k+=1
7689
return QQ(k)/QQ(nr*nc)
7690
7691
7692
def inverse(self):
7693
"""
7694
Returns the inverse of self, without changing self.
7695
7696
Note that one can use the Python inverse operator to obtain the
7697
inverse as well.
7698
7699
EXAMPLES::
7700
7701
sage: m = matrix([[1,2],[3,4]])
7702
sage: m^(-1)
7703
[ -2 1]
7704
[ 3/2 -1/2]
7705
sage: m.inverse()
7706
[ -2 1]
7707
[ 3/2 -1/2]
7708
sage: ~m
7709
[ -2 1]
7710
[ 3/2 -1/2]
7711
7712
::
7713
7714
sage: m = matrix([[1,2],[3,4]], sparse=True)
7715
sage: m^(-1)
7716
[ -2 1]
7717
[ 3/2 -1/2]
7718
sage: m.inverse()
7719
[ -2 1]
7720
[ 3/2 -1/2]
7721
sage: ~m
7722
[ -2 1]
7723
[ 3/2 -1/2]
7724
sage: m.I
7725
[ -2 1]
7726
[ 3/2 -1/2]
7727
7728
TESTS::
7729
7730
sage: matrix().inverse()
7731
[]
7732
"""
7733
return self.__invert__()
7734
7735
def adjoint(self):
7736
"""
7737
Returns the adjoint matrix of self (matrix of cofactors).
7738
7739
OUTPUT:
7740
7741
- ``N`` - the adjoint matrix, such that
7742
N \* M = M \* N = M.parent(M.det())
7743
7744
ALGORITHM:
7745
7746
Use PARI whenever the method ``self._adjoint`` is included to do so
7747
in an inheriting class. Otherwise, use a generic division-free
7748
algorithm to compute the characteristic polynomial and hence the
7749
adjoint.
7750
7751
The result is cached.
7752
7753
EXAMPLES::
7754
7755
sage: M = Matrix(ZZ,2,2,[5,2,3,4]) ; M
7756
[5 2]
7757
[3 4]
7758
sage: N = M.adjoint() ; N
7759
[ 4 -2]
7760
[-3 5]
7761
sage: M * N
7762
[14 0]
7763
[ 0 14]
7764
sage: N * M
7765
[14 0]
7766
[ 0 14]
7767
sage: M = Matrix(QQ,2,2,[5/3,2/56,33/13,41/10]) ; M
7768
[ 5/3 1/28]
7769
[33/13 41/10]
7770
sage: N = M.adjoint() ; N
7771
[ 41/10 -1/28]
7772
[-33/13 5/3]
7773
sage: M * N
7774
[7363/1092 0]
7775
[ 0 7363/1092]
7776
7777
AUTHORS:
7778
7779
- Unknown: No author specified in the file from 2009-06-25
7780
- Sebastian Pancratz (2009-06-25): Reflecting the change that
7781
``_adjoint`` is now implemented in this class
7782
"""
7783
7784
if self._nrows != self._ncols:
7785
raise ValueError, "self must be a square matrix"
7786
7787
X = self.fetch('adjoint')
7788
if not X is None:
7789
return X
7790
7791
X = self._adjoint()
7792
self.cache('adjoint', X)
7793
return X
7794
7795
def _adjoint(self):
7796
r"""
7797
Returns the adjoint of self.
7798
7799
OUTPUT:
7800
7801
- matrix - the adjoint of self
7802
7803
EXAMPLES:
7804
7805
Here is one example to illustrate this::
7806
7807
sage: A = matrix(ZZ, [[1,24],[3,5]])
7808
sage: A
7809
[ 1 24]
7810
[ 3 5]
7811
sage: A._adjoint()
7812
[ 5 -24]
7813
[ -3 1]
7814
7815
Secondly, here is an example over a polynomial ring::
7816
7817
sage: R.<t> = QQ[]
7818
sage: A = matrix(R, [[-2*t^2 + t + 3/2, 7*t^2 + 1/2*t - 1, \
7819
-6*t^2 + t - 2/11], \
7820
[-7/3*t^2 - 1/2*t - 1/15, -2*t^2 + 19/8*t, \
7821
-10*t^2 + 2*t + 1/2], \
7822
[6*t^2 - 1/2, -1/7*t^2 + 9/4*t, -t^2 - 4*t \
7823
- 1/10]])
7824
sage: A
7825
[ -2*t^2 + t + 3/2 7*t^2 + 1/2*t - 1 -6*t^2 + t - 2/11]
7826
[-7/3*t^2 - 1/2*t - 1/15 -2*t^2 + 19/8*t -10*t^2 + 2*t + 1/2]
7827
[ 6*t^2 - 1/2 -1/7*t^2 + 9/4*t -t^2 - 4*t - 1/10]
7828
sage: A._adjoint()
7829
[ 4/7*t^4 + 1591/56*t^3 - 961/70*t^2 - 109/80*t 55/7*t^4 + 104/7*t^3 + 6123/1540*t^2 - 959/220*t - 1/10 -82*t^4 + 101/4*t^3 + 1035/88*t^2 - 29/22*t - 1/2]
7830
[ -187/3*t^4 + 13/6*t^3 + 57/10*t^2 - 79/60*t - 77/300 38*t^4 + t^3 - 793/110*t^2 - 28/5*t - 53/220 -6*t^4 + 44/3*t^3 + 4727/330*t^2 - 1147/330*t - 487/660]
7831
[ 37/3*t^4 - 136/7*t^3 - 1777/840*t^2 + 83/80*t 292/7*t^4 + 107/14*t^3 - 323/28*t^2 - 29/8*t + 1/2 61/3*t^4 - 25/12*t^3 - 269/120*t^2 + 743/240*t - 1/15]
7832
7833
Finally, an example over a general ring, that is to say, as of
7834
version 4.0.2, SAGE does not even determine that ``S`` in the following
7835
example is an integral domain::
7836
7837
sage: R.<a,b> = QQ[]
7838
sage: S.<x,y> = R.quo((b^3))
7839
sage: A = matrix(S, [[x*y^2,2*x],[2,x^10*y]])
7840
sage: A
7841
[ x*y^2 2*x]
7842
[ 2 x^10*y]
7843
sage: A.det()
7844
-4*x
7845
sage: A.charpoly('T')
7846
T^2 + (-x^10*y - x*y^2)*T - 4*x
7847
sage: A.adjoint()
7848
[x^10*y -2*x]
7849
[ -2 x*y^2]
7850
sage: A.adjoint() * A
7851
[-4*x 0]
7852
[ 0 -4*x]
7853
7854
TESTS::
7855
7856
sage: A = matrix(ZZ, 0, 0)
7857
sage: A
7858
[]
7859
sage: A._adjoint()
7860
[]
7861
sage: A = matrix(ZZ, [[2]])
7862
sage: A
7863
[2]
7864
sage: A._adjoint()
7865
[1]
7866
7867
NOTES:
7868
7869
The key feature of this implementation is that it is division-free.
7870
This means that it can be used as a generic implementation for any
7871
ring (commutative and with multiplicative identity). The algorithm
7872
is described in full detail as Algorithm 3.1 in [Se02].
7873
7874
Note that this method does not utilise a lookup if the adjoint has
7875
already been computed previously, and it does not cache the result.
7876
This is all left to the method `adjoint`.
7877
7878
REFERENCES:
7879
7880
- [Se02] T. R. Seifullin, "Computation of determinants, adjoint
7881
matrices, and characteristic polynomials without division"
7882
7883
AUTHORS:
7884
7885
- Sebastian Pancratz (2009-06-12): Initial version
7886
"""
7887
7888
# Validate assertions
7889
#
7890
if self._nrows != self._ncols:
7891
raise ValueError("self must be a square matrix")
7892
7893
# Corner cases
7894
# N.B. We already tested for the matrix to be square, hence we do not
7895
# need to test for 0 x n or m x 0 matrices.
7896
#
7897
if self._ncols == 0:
7898
return self.copy()
7899
7900
# Extract parameters
7901
#
7902
n = self._ncols
7903
R = self._base_ring
7904
MS = self._parent
7905
7906
f = self.charpoly()
7907
7908
# Let A denote the adjoint of M, which we want to compute, and
7909
# N denote a copy of M used to store powers of M.
7910
#
7911
A = f[1] * MS.identity_matrix()
7912
N = R(1) * MS.identity_matrix()
7913
for i in range(1, n):
7914
# Set N to be M^i
7915
#
7916
N = N * self
7917
A = A + f[i+1] * N
7918
if not (n % 2):
7919
A = - A
7920
7921
return A
7922
7923
def QR(self, full=True):
7924
r"""
7925
Returns a factorization of ``self`` as a unitary matrix
7926
and an upper-triangular matrix.
7927
7928
INPUT:
7929
7930
- ``full`` - default: ``True`` - if ``True`` then the
7931
returned matrices have dimensions as described below.
7932
If ``False`` the ``R`` matrix has no zero rows and the
7933
columns of ``Q`` are a basis for the column space of
7934
``self``.
7935
7936
OUTPUT:
7937
7938
If ``self`` is an `m\times n` matrix and ``full=True`` then this
7939
method returns a pair of matrices: `Q` is an `m\times m` unitary
7940
matrix (meaning its inverse is its conjugate-transpose) and `R`
7941
is an `m\times n` upper-triangular matrix with non-negative entries
7942
on the diagonal. For a matrix of full rank this factorization is
7943
unique (due to the restriction to positive entries on the diagonal).
7944
7945
If ``full=False`` then `Q` has `m` rows and the columns form an
7946
orthonormal basis for the column space of ``self``. So, in particular,
7947
the conjugate-transpose of `Q` times `Q` will be an identity matrix.
7948
The matrix `R` will still be upper-triangular but will also have full
7949
rank, in particular it will lack the zero rows present in a full
7950
factorization of a rank-deficient matrix.
7951
7952
The results obtained when ``full=True`` are cached,
7953
hence `Q` and `R` are immutable matrices in this case.
7954
7955
.. note::
7956
7957
This is an exact computation, so limited to exact rings.
7958
Also the base ring needs to have a fraction field implemented
7959
in Sage and this field must contain square roots. One example
7960
is the field of algebraic numbers, ``QQbar``, as used in the
7961
examples below. If you need numerical results, convert the
7962
base ring to the field of complex double numbers, ``CDF``,
7963
which will use a faster routine that is careful about
7964
numerical subtleties.
7965
7966
ALGORITHM:
7967
7968
"Modified Gram-Schmidt," Algorithm 8.1 of [TREFETHEN-BAU]_.
7969
7970
EXAMPLES:
7971
7972
For a nonsingular matrix, the QR decomposition is unique. ::
7973
7974
sage: A = matrix(QQbar, [[-2, 0, -4, -1, -1],
7975
... [-2, 1, -6, -3, -1],
7976
... [1, 1, 7, 4, 5],
7977
... [3, 0, 8, 3, 3],
7978
... [-1, 1, -6, -6, 5]])
7979
sage: Q, R = A.QR()
7980
sage: Q
7981
[ -0.4588314677411235? -0.1260506983326509? 0.3812120831224489? -0.394573711338418? -0.687440062597?]
7982
[ -0.4588314677411235? 0.4726901187474409? -0.05198346588033394? 0.717294125164660? -0.220962877263?]
7983
[ 0.2294157338705618? 0.6617661662464172? 0.6619227988762521? -0.180872093737548? 0.1964114464561?]
7984
[ 0.6882472016116853? 0.1890760474989764? -0.2044682991293135? 0.096630296654307? -0.662888631790?]
7985
[ -0.2294157338705618? 0.5357154679137663? -0.609939332995919? -0.536422031427112? 0.0245514308070?]
7986
sage: R
7987
[ 4.358898943540674? -0.4588314677411235? 13.07669683062202? 6.194224814505168? 2.982404540317303?]
7988
[ 0 1.670171752907625? 0.5987408170800917? -1.292019657909672? 6.207996892883057?]
7989
[ 0 0 5.444401659866974? 5.468660610611130? -0.682716185228386?]
7990
[ 0 0 0 1.027626039419836? -3.61930014968662?]
7991
[ 0 0 0 0 0.02455143080702?]
7992
sage: Q.conjugate_transpose()*Q
7993
[1.000000000000000? 0.?e-18 0.?e-17 0.?e-15 0.?e-12]
7994
[ 0.?e-18 1.000000000000000? 0.?e-16 0.?e-15 0.?e-12]
7995
[ 0.?e-17 0.?e-16 1.000000000000000? 0.?e-15 0.?e-12]
7996
[ 0.?e-15 0.?e-15 0.?e-15 1.000000000000000? 0.?e-12]
7997
[ 0.?e-12 0.?e-12 0.?e-12 0.?e-12 1.000000000000?]
7998
sage: Q*R == A
7999
True
8000
8001
8002
An example with complex numbers in ``QQbar``, the field of algebraic
8003
numbers. ::
8004
8005
sage: A = matrix(QQbar, [[-8, 4*I + 1, -I + 2, 2*I + 1],
8006
... [1, -2*I - 1, -I + 3, -I + 1],
8007
... [I + 7, 2*I + 1, -2*I + 7, -I + 1],
8008
... [I + 2, 0, I + 12, -1]])
8009
sage: Q, R = A.QR()
8010
sage: Q
8011
[ -0.7302967433402215? 0.2070566455055649? + 0.5383472783144687?*I 0.2463049809998642? - 0.0764456358723292?*I 0.2381617683194332? - 0.1036596032779695?*I]
8012
[ 0.0912870929175277? -0.2070566455055649? - 0.3778783780476559?*I 0.3786559533863032? - 0.1952221495524667?*I 0.701244450214469? - 0.364371165098660?*I]
8013
[ 0.6390096504226938? + 0.0912870929175277?*I 0.1708217325420910? + 0.6677576817554466?*I -0.03411475806452072? + 0.04090198741767143?*I 0.3140171085506763? - 0.0825191718705412?*I]
8014
[ 0.1825741858350554? + 0.0912870929175277?*I -0.03623491296347385? + 0.0724698259269477?*I 0.8632284069415110? + 0.06322839976356195?*I -0.4499694867611521? - 0.0116119181208918?*I]
8015
sage: R
8016
[ 10.95445115010333? 0.?e-18 - 1.917028951268082?*I 5.385938482134133? - 2.190890230020665?*I -0.2738612787525831? - 2.190890230020665?*I]
8017
[ 0 4.829596256417300? + 0.?e-17*I -0.869637911123373? - 5.864879483945125?*I 0.993871898426712? - 0.3054085521207082?*I]
8018
[ 0 0 12.00160760935814? + 0.?e-16*I -0.2709533402297273? + 0.4420629644486323?*I]
8019
[ 0 0 0 1.942963944258992? + 0.?e-16*I]
8020
sage: Q.conjugate_transpose()*Q
8021
[1.000000000000000? + 0.?e-19*I 0.?e-18 + 0.?e-17*I 0.?e-17 + 0.?e-17*I 0.?e-16 + 0.?e-16*I]
8022
[ 0.?e-18 + 0.?e-17*I 1.000000000000000? + 0.?e-17*I 0.?e-17 + 0.?e-17*I 0.?e-16 + 0.?e-16*I]
8023
[ 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]
8024
[ 0.?e-16 + 0.?e-16*I 0.?e-16 + 0.?e-16*I 0.?e-16 + 0.?e-16*I 1.000000000000000? + 0.?e-15*I]
8025
sage: Q*R - A
8026
[ 0.?e-17 0.?e-17 + 0.?e-17*I 0.?e-16 + 0.?e-16*I 0.?e-16 + 0.?e-16*I]
8027
[ 0.?e-18 0.?e-17 + 0.?e-17*I 0.?e-16 + 0.?e-16*I 0.?e-15 + 0.?e-15*I]
8028
[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]
8029
[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]
8030
8031
A rank-deficient rectangular matrix, with both values of the ``full`` keyword. ::
8032
8033
sage: A = matrix(QQbar, [[2, -3, 3],
8034
... [-1, 1, -1],
8035
... [-1, 3, -3],
8036
... [-5, 1, -1]])
8037
sage: Q, R = A.QR()
8038
sage: Q
8039
[ 0.3592106040535498? -0.5693261797050169? 0.7239227659930268? 0.1509015305256380?]
8040
[ -0.1796053020267749? 0.1445907757980996? 0 0.9730546968377341?]
8041
[ -0.1796053020267749? 0.7048800320157352? 0.672213996993525? -0.1378927778941174?]
8042
[ -0.8980265101338745? -0.3976246334447737? 0.1551263069985058? -0.10667177157846818?]
8043
sage: R
8044
[ 5.567764362830022? -2.694079530401624? 2.694079530401624?]
8045
[ 0 3.569584777515583? -3.569584777515583?]
8046
[ 0 0 0]
8047
[ 0 0 0]
8048
sage: Q.conjugate_transpose()*Q
8049
[ 1 0.?e-18 0.?e-18 0.?e-18]
8050
[ 0.?e-18 1 0.?e-18 0.?e-18]
8051
[ 0.?e-18 0.?e-18 1.000000000000000? 0.?e-18]
8052
[ 0.?e-18 0.?e-18 0.?e-18 1.000000000000000?]
8053
8054
sage: Q, R = A.QR(full=False)
8055
sage: Q
8056
[ 0.3592106040535498? -0.5693261797050169?]
8057
[-0.1796053020267749? 0.1445907757980996?]
8058
[-0.1796053020267749? 0.7048800320157352?]
8059
[-0.8980265101338745? -0.3976246334447737?]
8060
sage: R
8061
[ 5.567764362830022? -2.694079530401624? 2.694079530401624?]
8062
[ 0 3.569584777515583? -3.569584777515583?]
8063
sage: Q.conjugate_transpose()*Q
8064
[ 1 0.?e-18]
8065
[0.?e-18 1]
8066
8067
Another rank-deficient rectangular matrix, with complex entries,
8068
as a reduced decomposition. ::
8069
8070
sage: A = matrix(QQbar, [[-3*I - 3, I - 3, -12*I + 1, -2],
8071
... [-I - 1, -2, 5*I - 1, -I - 2],
8072
... [-4*I - 4, I - 5, -7*I, -I - 4]])
8073
sage: Q, R = A.QR(full=False)
8074
sage: Q
8075
[ -0.4160251471689219? - 0.4160251471689219?*I 0.5370861555295747? + 0.1790287185098583?*I]
8076
[ -0.1386750490563073? - 0.1386750490563073?*I -0.7519206177414046? - 0.2506402059138015?*I]
8077
[ -0.5547001962252291? - 0.5547001962252291?*I -0.2148344622118299? - 0.07161148740394329?*I]
8078
sage: R
8079
[ 7.211102550927979? 3.328201177351375? - 5.269651864139676?*I 7.904477796209515? + 8.45917799243475?*I 4.021576422632911? - 2.634825932069838?*I]
8080
[ 0 1.074172311059150? -1.611258466588724? - 9.13046464400277?*I 1.611258466588724? + 0.5370861555295747?*I]
8081
sage: Q.conjugate_transpose()*Q
8082
[1.000000000000000? + 0.?e-18*I 0.?e-18 + 0.?e-18*I]
8083
[ 0.?e-17 + 0.?e-17*I 1.000000000000000? + 0.?e-17*I]
8084
sage: Q*R-A
8085
[0.?e-18 + 0.?e-18*I 0.?e-18 + 0.?e-18*I 0.?e-17 + 0.?e-17*I 0.?e-18 + 0.?e-18*I]
8086
[0.?e-18 + 0.?e-18*I 0.?e-18 + 0.?e-18*I 0.?e-18 + 0.?e-17*I 0.?e-18 + 0.?e-18*I]
8087
[0.?e-18 + 0.?e-18*I 0.?e-17 + 0.?e-18*I 0.?e-17 + 0.?e-17*I 0.?e-18 + 0.?e-18*I]
8088
8089
Results of full decompositions are cached and thus returned
8090
immutable. ::
8091
8092
sage: A = random_matrix(QQbar, 2, 2)
8093
sage: Q, R = A.QR()
8094
sage: Q.is_mutable()
8095
False
8096
sage: R.is_mutable()
8097
False
8098
8099
Trivial cases return trivial results of the correct size,
8100
and we check `Q` itself in one case. ::
8101
8102
sage: A = zero_matrix(QQbar, 0, 10)
8103
sage: Q, R = A.QR()
8104
sage: Q.nrows(), Q.ncols()
8105
(0, 0)
8106
sage: R.nrows(), R.ncols()
8107
(0, 10)
8108
sage: A = zero_matrix(QQbar, 3, 0)
8109
sage: Q, R = A.QR()
8110
sage: Q.nrows(), Q.ncols()
8111
(3, 3)
8112
sage: R.nrows(), R.ncols()
8113
(3, 0)
8114
sage: Q
8115
[1 0 0]
8116
[0 1 0]
8117
[0 0 1]
8118
8119
TESTS:
8120
8121
Inexact rings are caught and ``CDF`` suggested. ::
8122
8123
sage: A = matrix(RealField(100), 2, range(4))
8124
sage: A.QR()
8125
Traceback (most recent call last):
8126
...
8127
NotImplementedError: QR decomposition is implemented over exact rings, try CDF for numerical results, not Real Field with 100 bits of precision
8128
8129
Without a fraction field, we cannot hope to run the algorithm. ::
8130
8131
sage: A = matrix(Integers(6), 2, range(4))
8132
sage: A.QR()
8133
Traceback (most recent call last):
8134
...
8135
ValueError: QR decomposition needs a fraction field of Ring of integers modulo 6
8136
8137
The biggest obstacle is making unit vectors, thus requiring square
8138
roots, though some small cases pass through. ::
8139
8140
sage: A = matrix(ZZ, 3, range(9))
8141
sage: A.QR()
8142
Traceback (most recent call last):
8143
...
8144
TypeError: QR decomposition unable to compute square roots in Rational Field
8145
8146
sage: A = matrix(ZZ, 2, range(4))
8147
sage: Q, R = A.QR()
8148
sage: Q
8149
[0 1]
8150
[1 0]
8151
sage: R
8152
[2 3]
8153
[0 1]
8154
8155
REFERENCES:
8156
8157
.. [TREFETHEN-BAU] Trefethen, Lloyd N., Bau, David, III
8158
"Numerical Linear Algebra"
8159
SIAM, Philadelphia, 1997.
8160
8161
AUTHOR:
8162
8163
- Rob Beezer (2011-02-17)
8164
"""
8165
from sage.modules.free_module_element import zero_vector
8166
from sage.matrix.constructor import zero_matrix, matrix
8167
from sage.functions.other import sqrt
8168
8169
if full:
8170
QR = self.fetch('QR_factors')
8171
if QR is not None:
8172
return QR
8173
R = self.base_ring()
8174
if not R.is_exact():
8175
raise NotImplementedError('QR decomposition is implemented over exact rings, try CDF for numerical results, not %s' % R)
8176
try:
8177
F = R.fraction_field()
8178
except Exception:
8179
raise ValueError("QR decomposition needs a fraction field of %s" % R)
8180
m = self.nrows()
8181
n = self.ncols()
8182
8183
R = zero_matrix(F, m, n)
8184
V = self.columns(copy=True)
8185
Q = []
8186
row = 0 # row of R being filled
8187
for i in range(n):
8188
v = V[i]
8189
hip = v.hermitian_inner_product(v)
8190
if hip != 0:
8191
try:
8192
scale = sqrt(hip)
8193
q = (1/scale)*v
8194
Q.append(q)
8195
R[row,i] = scale
8196
for j in range(i+1, n):
8197
R[row,j] = q.hermitian_inner_product(V[j])
8198
V[j] = V[j] - R[row,j]*q
8199
row = row + 1
8200
except TypeError:
8201
raise TypeError('QR decomposition unable to compute square roots in %s' % F)
8202
# complete to full orthonormal basis, or reduce to truncated R
8203
if full:
8204
Qt = matrix(Q) # as rows here
8205
if Qt.nrows() == 0:
8206
Qt = zero_matrix(F, 0, m)
8207
orthogonal = Qt.right_kernel().basis_matrix().transpose()
8208
Qperp, _ = orthogonal.QR(full=False)
8209
Q = Q + Qperp.columns()
8210
else:
8211
R = R[0:len(Q), 0:n]
8212
Q = matrix(Q).transpose()
8213
# Adjust rows of Q if empty
8214
if Q.ncols() == 0:
8215
Q = zero_matrix(F, m, 0)
8216
QR = (Q, R)
8217
if full:
8218
Q.set_immutable()
8219
R.set_immutable()
8220
self.cache('QR_factors', QR)
8221
return QR
8222
8223
def _gram_schmidt_noscale(self):
8224
r"""
8225
Performs Gram-Schmidt orthogonalization, with no scaling to unit vectors.
8226
8227
INPUT:
8228
8229
- ``self`` - is a matrix whose columns are to be orthogonalized.
8230
The base ring of the matrix needs to have its fraction field
8231
implemented.
8232
8233
OUTPUT:
8234
8235
Two matrices, ``Q`` and ``R`` such that if ``A`` represents ``self``:
8236
8237
- ``A = Q*R``
8238
- The columns of ``Q`` are an orthogonal set which spans the
8239
column space of ``A``.
8240
- The conjugate-transpose of ``Q`` times ``Q`` is a diagonal matrix.
8241
- ``R`` is a full-rank matrix, that has all entries below the
8242
main diagonal equal to zero.
8243
8244
This is basically a "reduced" QR decomposition of ``self`` with
8245
the distinction that the orthogonal column vectors of ``Q`` have
8246
not been scaled to unit vectors, avoiding the need to take square
8247
roots.
8248
8249
EXAMPLES:
8250
8251
A rectangular matrix whose columns have full-rank. Notice that the
8252
routine computes in the fraction field, requiring the column space
8253
check to step up to ``QQ``. ::
8254
8255
sage: A = matrix(ZZ, [[-1, -3, 0, -1],
8256
... [ 1, 2, -1, 2],
8257
... [-3, -6, 4, -7]])
8258
sage: Q,R = A._gram_schmidt_noscale()
8259
sage: Q
8260
[ -1 -10/11 0]
8261
[ 1 -1/11 3/10]
8262
[ -3 3/11 1/10]
8263
sage: R
8264
[ 1 23/11 -13/11 24/11]
8265
[ 0 1 13/10 -13/10]
8266
[ 0 0 1 -1]
8267
sage: Q*R == A
8268
True
8269
sage: Q.transpose()*Q
8270
[ 11 0 0]
8271
[ 0 10/11 0]
8272
[ 0 0 1/10]
8273
sage: A.change_ring(QQ).column_space() == Q.column_space()
8274
True
8275
8276
A matrix over a subfield of the complex numbers, with four
8277
columns but rank 3, so the orthogonal set has just 3 vectors
8278
as well. Orthogonality comes from the Hermitian inner product
8279
so we need to check with the conjugate-transpose. This
8280
example verifies that the bug on #10791 is fixed. ::
8281
8282
sage: F.<a> = QuadraticField(-5)
8283
sage: A = matrix(F, [[ 1, a - 3, a - 2, a + 1],
8284
... [ a, 2*a + 1, 3*a + 1, 1],
8285
... [a + 1, a - 6, 2*a - 5, 1],
8286
... [ 2*a, a, 3*a, -3],
8287
... [ 1, a - 1, a, a - 1]])
8288
sage: A.rank()
8289
3
8290
sage: Q, R = A._gram_schmidt_noscale()
8291
sage: Q
8292
[ 1 25/33*a - 38/11 641/1163*a + 453/1163]
8293
[ a 17/11*a + 73/33 322/1163*a + 1566/1163]
8294
[ a + 1 10/33*a - 173/33 -784/1163*a + 1614/1163]
8295
[ 2*a 1/11*a + 80/33 196/1163*a - 1234/1163]
8296
[ 1 25/33*a - 16/11 855/1163*a - 1717/1163]
8297
sage: R
8298
[ 1 8/33*a + 5/11 8/33*a + 16/11 2/11*a + 1/33]
8299
[ 0 1 1 -107/1163*a - 78/1163]
8300
[ 0 0 0 1]
8301
sage: Q*R == A
8302
True
8303
sage: Q.transpose().conjugate()*Q
8304
[ 33 0 0]
8305
[ 0 2326/33 0]
8306
[ 0 0 16532/1163]
8307
sage: Q.column_space() == A.column_space()
8308
True
8309
8310
Some trivial cases. ::
8311
8312
sage: A = matrix(ZZ, 3, 0)
8313
sage: Q, R = A._gram_schmidt_noscale()
8314
sage: Q.parent()
8315
Full MatrixSpace of 3 by 0 dense matrices over Rational Field
8316
sage: R.parent()
8317
Full MatrixSpace of 0 by 0 dense matrices over Rational Field
8318
sage: Q*R == A
8319
True
8320
8321
sage: A = matrix(ZZ, 0, 3)
8322
sage: Q, R = A._gram_schmidt_noscale()
8323
sage: Q.parent()
8324
Full MatrixSpace of 0 by 0 dense matrices over Rational Field
8325
sage: R.parent()
8326
Full MatrixSpace of 0 by 3 dense matrices over Rational Field
8327
sage: Q*R == A
8328
True
8329
8330
TESTS:
8331
8332
Without a fraction field, we cannot hope to proceed. ::
8333
8334
sage: A = matrix(Integers(6), 2, range(4))
8335
sage: A._gram_schmidt_noscale()
8336
Traceback (most recent call last):
8337
...
8338
TypeError: Gram-Schmidt orthogonalization requires a base ring with a fraction field, not Ring of integers modulo 6
8339
8340
AUTHORS:
8341
8342
- William Stein (2007-11-18)
8343
- Rob Beezer (2011-02-25)
8344
"""
8345
import sage.matrix.constructor
8346
R = self.base_ring()
8347
try:
8348
F = R.fraction_field()
8349
except TypeError:
8350
raise TypeError("Gram-Schmidt orthogonalization requires a base ring with a fraction field, not %s" % R)
8351
n = self.ncols()
8352
B = self.columns()
8353
zero = F(0)
8354
Bstar = []
8355
R = sage.matrix.constructor.zero_matrix(F, n)
8356
nnz = 0 # number non-zero rows in R, or number of nonzero vectors in Bstar
8357
for i in range(n):
8358
ortho = B[i]
8359
for j in range(nnz):
8360
R[j,i] = Bstar[j].hermitian_inner_product(B[i])/Bstar[j].hermitian_inner_product(Bstar[j])
8361
ortho = ortho - R[j,i]*Bstar[j]
8362
if ortho.hermitian_inner_product(ortho) != zero:
8363
Bstar.append(ortho)
8364
R[nnz, i] = 1
8365
nnz = nnz + 1
8366
R = R[0:nnz]
8367
if Bstar == []:
8368
Q = sage.matrix.constructor.matrix(F, 0, self.nrows()).transpose()
8369
else:
8370
Q = sage.matrix.constructor.matrix(F, Bstar).transpose()
8371
return Q, R
8372
8373
def gram_schmidt(self, orthonormal=False):
8374
r"""
8375
Performs Gram-Schmidt orthogonalization on the rows of the matrix,
8376
returning a new matrix and a matrix accomplishing the transformation.
8377
8378
INPUT:
8379
8380
- ``self`` - a matrix whose rows are to be orthogonalized.
8381
- ``orthonormal`` - default: ``False`` - if ``True`` the
8382
returned orthogonal vectors are unit vectors. This keyword
8383
is ignored if the matrix is over ``RDF`` or ``CDF`` and the
8384
results are always orthonormal.
8385
8386
OUTPUT:
8387
8388
A pair of matrices, ``G`` and ``M`` such that if ``A``
8389
represents ``self``, where the parenthetical properties occur
8390
when ``orthonormal = True``:
8391
8392
- ``A = M*G``
8393
- The rows of ``G`` are an orthogonal (resp. orthonormal)
8394
set of vectors.
8395
- ``G`` times the conjugate-transpose of ``G`` is a diagonal
8396
(resp. identity) matrix.
8397
- The row space of ``G`` equals the row space of ``A``.
8398
- ``M`` is a full-rank matrix with zeros above the diagonal.
8399
8400
For exact rings, any zero vectors produced (when the original
8401
vectors are linearly dependent) are not output, thus the
8402
orthonormal set is linearly independent, and thus a basis for the
8403
row space of the original matrix.
8404
8405
Any notion of a Gram-Schmidt procedure requires that the base
8406
ring of the matrix has a fraction field implemented. In order
8407
to arrive at an orthonormal set, it must be possible to construct
8408
square roots of the elements of the base field. In Sage, your
8409
best option is the field of algebraic numbers, ``QQbar``, which
8410
properly contains the rationals and number fields.
8411
8412
If you have an approximate numerical matrix, then this routine
8413
requires that your base field be the real and complex
8414
double-precision floating point numbers, ``RDF`` and ``CDF``.
8415
In this case, the matrix is treated as having full rank, as no
8416
attempt is made to recognize linear dependence with approximate
8417
calculations.
8418
8419
EXAMPLES:
8420
8421
Inexact Rings, Numerical Matrices:
8422
8423
First, the inexact rings, ``CDF`` and ``RDF``. ::
8424
8425
sage: A = matrix(CDF, [[ 0.6454 + 0.7491*I, -0.8662 + 0.1489*I, 0.7656 - 0.00344*I],
8426
... [-0.2913 + 0.8057*I, 0.8321 + 0.8170*I, -0.6744 + 0.9248*I],
8427
... [ 0.2554 + 0.3517*I, -0.4454 - 0.1715*I, 0.8325 - 0.6282*I]])
8428
sage: G, M = A.gram_schmidt()
8429
sage: G.round(6) # random signs
8430
[-0.422243 - 0.490087*I 0.566698 - 0.097416*I -0.500882 + 0.002251*I]
8431
[-0.057002 - 0.495035*I -0.35059 - 0.625323*I 0.255514 - 0.415284*I]
8432
[ 0.394105 - 0.421778*I -0.392266 - 0.039345*I -0.352905 + 0.62195*I]
8433
sage: M.round(6) # random
8434
[ -1.528503 0.0 0.0]
8435
[ 0.459974 - 0.40061*I -1.741233 0.0]
8436
[-0.934304 + 0.148868*I 0.54833 + 0.073202*I -0.550725]
8437
sage: (A - M*G).zero_at(10^-12)
8438
[0.0 0.0 0.0]
8439
[0.0 0.0 0.0]
8440
[0.0 0.0 0.0]
8441
sage: (G*G.conjugate_transpose()).zero_at(10^-12)
8442
[1.0 0.0 0.0]
8443
[0.0 1.0 0.0]
8444
[0.0 0.0 1.0]
8445
8446
8447
A rectangular matrix. Note that the ``orthonormal`` keyword
8448
is ignored in these cases. ::
8449
8450
sage: A = matrix(RDF, [[-0.978325, -0.751994, 0.925305, -0.200512, 0.420458],
8451
... [-0.474877, -0.983403, 0.089836, 0.132218, 0.672965]])
8452
sage: G, M = A.gram_schmidt(orthonormal=False)
8453
sage: G.round(6).zero_at(10^-6)
8454
[-0.607223 -0.466745 0.574315 -0.124453 0.260968]
8455
[ 0.123203 -0.617909 -0.530578 0.289773 0.487368]
8456
sage: M.round(6).zero_at(10^-6)
8457
[1.611147 0.0]
8458
[0.958116 0.867778]
8459
sage: (A-M*G).zero_at(10^-12)
8460
[0.0 0.0 0.0 0.0 0.0]
8461
[0.0 0.0 0.0 0.0 0.0]
8462
sage: (G*G.transpose()).round(6).zero_at(10^-6)
8463
[1.0 0.0]
8464
[0.0 1.0]
8465
8466
Even though a set of vectors may be linearly dependent, no effort
8467
is made to decide when a zero vector is really the result of a
8468
relation of linear dependence. So in this regard, input matrices
8469
are treated as being of full rank. Try one of the base rings that
8470
provide exact results if you need exact results. ::
8471
8472
sage: entries = [[1,1,2], [2,1,3], [3,1,4]]
8473
sage: A = matrix(QQ, entries)
8474
sage: A.rank()
8475
2
8476
sage: B = matrix(RDF, entries)
8477
sage: G, M = B.gram_schmidt()
8478
sage: G.round(6) # random signs
8479
[-0.408248 -0.408248 -0.816497]
8480
[ 0.707107 -0.707107 -0.0]
8481
[ -0.57735 -0.57735 0.57735]
8482
sage: M.round(10) # random
8483
[-2.4494897428 0.0 0.0]
8484
[-3.6742346142 0.7071067812 0.0]
8485
[-4.8989794856 1.4142135624 0.0]
8486
sage: (A - M*G).zero_at(1e-14)
8487
[0.0 0.0 0.0]
8488
[0.0 0.0 0.0]
8489
[0.0 0.0 0.0]
8490
sage: (G*G.transpose()).zero_at(1e-14)
8491
[1.0 0.0 0.0]
8492
[0.0 1.0 0.0]
8493
[0.0 0.0 1.0]
8494
8495
Exact Rings, Orthonormalization:
8496
8497
To scale a vector to unit length requires taking
8498
a square root, which often takes us outside the base ring.
8499
For the integers and the rationals, the field of algebraic numbers
8500
(``QQbar``) is big enough to contain what we need, but the price
8501
is that the computations are very slow, hence mostly of value
8502
for small cases or instruction. Now we need to use the
8503
``orthonormal`` keyword. ::
8504
8505
sage: A = matrix(QQbar, [[6, -8, 1],
8506
... [4, 1, 3],
8507
... [6, 3, 3],
8508
... [7, 1, -5],
8509
... [7, -3, 5]])
8510
sage: G, M = A.gram_schmidt(orthonormal=True)
8511
sage: G
8512
[ 0.5970223141259934? -0.7960297521679913? 0.09950371902099891?]
8513
[ 0.6063218341690895? 0.5289635311888953? 0.5937772444966257?]
8514
[ 0.5252981913594170? 0.2941669871612735? -0.798453250866314?]
8515
sage: M
8516
[ 10.04987562112089? 0 0]
8517
[ 1.890570661398980? 4.735582601355131? 0]
8518
[ 1.492555785314984? 7.006153332071100? 1.638930357041381?]
8519
[ 2.885607851608969? 1.804330147889395? 7.963520581008761?]
8520
[ 7.064764050490923? 5.626248468100069? -1.197679876299471?]
8521
sage: M*G-A
8522
[0 0 0]
8523
[0 0 0]
8524
[0 0 0]
8525
[0 0 0]
8526
[0 0 0]
8527
sage: (G*G.transpose()-identity_matrix(3)).norm() < 10^-10
8528
True
8529
sage: G.row_space() == A.row_space()
8530
True
8531
8532
After :trac:`14047`, the matrix can also be over the algebraic reals
8533
``AA``::
8534
8535
sage: A = matrix(AA, [[6, -8, 1],
8536
... [4, 1, 3],
8537
... [6, 3, 3],
8538
... [7, 1, -5],
8539
... [7, -3, 5]])
8540
sage: G, M = A.gram_schmidt(orthonormal=True)
8541
sage: G
8542
[ 0.5970223141259934? -0.7960297521679913? 0.09950371902099891?]
8543
[ 0.6063218341690895? 0.5289635311888953? 0.5937772444966257?]
8544
[ 0.5252981913594170? 0.2941669871612735? -0.798453250866314?]
8545
sage: M
8546
[ 10.04987562112089? 0 0]
8547
[ 1.890570661398980? 4.735582601355131? 0]
8548
[ 1.492555785314984? 7.006153332071100? 1.638930357041381?]
8549
[ 2.885607851608969? 1.804330147889395? 7.963520581008761?]
8550
[ 7.064764050490923? 5.626248468100069? -1.197679876299471?]
8551
8552
Starting with complex numbers with rational real and imaginary parts.
8553
Note the use of the conjugate-transpose when checking the
8554
orthonormality. ::
8555
8556
sage: A = matrix(QQbar, [[ -2, -I - 1, 4*I + 2, -1],
8557
... [-4*I, -2*I + 17, 0, 9*I + 1],
8558
... [ 1, -2*I - 6, -I + 11, -5*I + 1]])
8559
sage: G, M = A.gram_schmidt(orthonormal=True)
8560
sage: (M*G-A).norm() < 10^-10
8561
True
8562
sage: id3 = G*G.conjugate().transpose()
8563
sage: (id3 - identity_matrix(3)).norm() < 10^-10
8564
True
8565
sage: G.row_space() == A.row_space() # long time
8566
True
8567
8568
A square matrix with small rank. The zero vectors produced as a
8569
result of linear dependence get eliminated, so the rows of ``G``
8570
are a basis for the row space of ``A``. ::
8571
8572
sage: A = matrix(QQbar, [[2, -6, 3, 8],
8573
... [1, -3, 2, 5],
8574
... [0, 0, 2, 4],
8575
... [2, -6, 3, 8]])
8576
sage: A.change_ring(QQ).rank()
8577
2
8578
sage: G, M = A.gram_schmidt(orthonormal=True)
8579
sage: G
8580
[ 0.1881441736767195? -0.5644325210301583? 0.2822162605150792? 0.7525766947068779?]
8581
[-0.2502818123591464? 0.750845437077439? 0.3688363550555841? 0.4873908977520218?]
8582
sage: M
8583
[10.630145812734649? 0]
8584
[ 6.208757731331742? 0.6718090752798139?]
8585
[ 3.574739299857670? 2.687236301119256?]
8586
[10.630145812734649? 0]
8587
sage: M*G-A
8588
[0 0 0 0]
8589
[0 0 0 0]
8590
[0 0 0 0]
8591
[0 0 0 0]
8592
sage: (G*G.transpose()-identity_matrix(2)).norm() < 10^-10
8593
True
8594
sage: G.row_space() == A.row_space()
8595
True
8596
8597
Exact Rings, Orthogonalization:
8598
8599
If we forego scaling orthogonal vectors to unit vectors, we
8600
can apply Gram-Schmidt to a much greater variety of rings.
8601
Use the ``orthonormal=False`` keyword (or assume it as the default).
8602
Note that now the orthogonality check creates a diagonal matrix
8603
whose diagonal entries are the squares of the lengths of the
8604
vectors.
8605
8606
First, in the rationals, without involving ``QQbar``. ::
8607
8608
sage: A = matrix(QQ, [[-1, 3, 2, 2],
8609
... [-1, 0, -1, 0],
8610
... [-1, -2, -3, -1],
8611
... [ 1, 1, 2, 0]])
8612
sage: A.rank()
8613
3
8614
sage: G, M = A.gram_schmidt()
8615
sage: G
8616
[ -1 3 2 2]
8617
[-19/18 1/6 -8/9 1/9]
8618
[ 2/35 -4/35 -2/35 9/35]
8619
sage: M
8620
[ 1 0 0]
8621
[ -1/18 1 0]
8622
[-13/18 59/35 1]
8623
[ 1/3 -48/35 -2]
8624
sage: M*G-A
8625
[0 0 0 0]
8626
[0 0 0 0]
8627
[0 0 0 0]
8628
[0 0 0 0]
8629
sage: G*G.transpose()
8630
[ 18 0 0]
8631
[ 0 35/18 0]
8632
[ 0 0 3/35]
8633
sage: G.row_space() == A.row_space()
8634
True
8635
8636
A complex subfield of the complex numbers. ::
8637
8638
sage: C.<z> = CyclotomicField(5)
8639
sage: A = matrix(C, [[ -z^3 - 2*z, -z^3 - 1, 2*z^3 - 2*z^2 + 2*z, 1],
8640
... [ z^3 - 2*z^2 + 1, -z^3 + 2*z^2 - z - 1, -1, z^2 + z],
8641
... [-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]])
8642
sage: G, M = A.gram_schmidt(orthonormal=False)
8643
sage: G
8644
[ -z^3 - 2*z -z^3 - 1 2*z^3 - 2*z^2 + 2*z 1]
8645
[ 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]
8646
[-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]
8647
sage: M
8648
[ 1 0 0]
8649
[ 14/139*z^3 + 47/139*z^2 + 145/139*z + 95/139 1 0]
8650
[ -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]
8651
sage: M*G - A
8652
[0 0 0 0]
8653
[0 0 0 0]
8654
[0 0 0 0]
8655
sage: G*G.conjugate().transpose()
8656
[ 15*z^3 + 15*z^2 + 28 0 0]
8657
[ 0 463/139*z^3 + 463/139*z^2 + 1971/139 0]
8658
[ 0 0 230983/19841*z^3 + 230983/19841*z^2 + 1003433/39682]
8659
sage: G.row_space() == A.row_space()
8660
True
8661
8662
A slightly edited legacy example. ::
8663
8664
sage: A = matrix(ZZ, 3, [-1, 2, 5, -11, 1, 1, 1, -1, -3]); A
8665
[ -1 2 5]
8666
[-11 1 1]
8667
[ 1 -1 -3]
8668
sage: G, mu = A.gram_schmidt()
8669
sage: G
8670
[ -1 2 5]
8671
[ -52/5 -1/5 -2]
8672
[ 2/187 36/187 -14/187]
8673
sage: mu
8674
[ 1 0 0]
8675
[ 3/5 1 0]
8676
[ -3/5 -7/187 1]
8677
sage: G.row(0) * G.row(1)
8678
0
8679
sage: G.row(0) * G.row(2)
8680
0
8681
sage: G.row(1) * G.row(2)
8682
0
8683
8684
The relation between mu and A is as follows. ::
8685
8686
sage: mu*G == A
8687
True
8688
"""
8689
import sage.rings.real_double
8690
import sage.rings.complex_double
8691
R = self.base_ring()
8692
if R in [sage.rings.real_double.RDF, sage.rings.complex_double.CDF]:
8693
Q, R = self.transpose().QR()
8694
m = R.nrows(); n = R.ncols()
8695
if m > n:
8696
Q = Q[0:m, 0:n]
8697
R = R[0:n, 0:n]
8698
elif R.is_exact():
8699
if orthonormal:
8700
Q, R = self.transpose().QR(full=False)
8701
else:
8702
Q, R = self.transpose()._gram_schmidt_noscale()
8703
else:
8704
raise NotImplementedError("Gram-Schmidt orthogonalization not implemented for matrices over inexact rings, except for RDF and CDF")
8705
return Q.transpose(), R.transpose()
8706
8707
def jordan_form(self, base_ring=None, sparse=False, subdivide=True, transformation=False, eigenvalues=None, check_input=True):
8708
r"""
8709
Compute the Jordan normal form of this square matrix `A`, if it exists.
8710
8711
This computation is performed in a naive way using the ranks of powers
8712
of `A-xI`, where `x` is an eigenvalue of the matrix `A`. If desired,
8713
a transformation matrix `P` can be returned, which is such that the
8714
Jordan canonical form is given by `P^{-1} A P`.
8715
8716
INPUT:
8717
8718
- ``base_ring`` - Ring in which to compute the Jordan form.
8719
8720
- ``sparse`` - (default ``False``) If ``sparse=True``, return a sparse
8721
matrix.
8722
8723
- ``subdivide`` - (default ``True``) If ``subdivide=True``, the
8724
subdivisions for the Jordan blocks in the matrix are shown.
8725
8726
- ``transformation`` - (default ``False``) If ``transformation=True``,
8727
computes also the transformation matrix.
8728
8729
- ``eigenvalues`` - (default ``None``) A complete set of roots, with
8730
multiplicity, of the characteristic polynomial of `A`, encoded as
8731
a list of pairs, each having the form `(r, m)` with `r` a root and
8732
`m` its multiplicity. If this is ``None``, then Sage computes this
8733
list itself, but this is only possible over base rings in whose
8734
quotient fields polynomial factorization is implemented. Over all
8735
other rings, providing this list manually is the only way to
8736
compute Jordan normal forms.
8737
8738
- ``check_input`` - (default ``True``) A Boolean specifying whether
8739
the list ``eigenvalues`` (if provided) has to be checked for
8740
correctness. Set this to ``False`` for a speedup if the eigenvalues
8741
are known to be correct.
8742
8743
NOTES:
8744
8745
Currently, the Jordan normal form is not computed over inexact rings
8746
in any but the trivial cases when the matrix is either `0 \times 0`
8747
or `1 \times 1`.
8748
8749
In the case of exact rings, this method does not compute any
8750
generalized form of the Jordan normal form, but is only able to
8751
compute the result if the characteristic polynomial of the matrix
8752
splits over the specific base ring.
8753
8754
Note that the base ring must be a field or a ring with an implemented
8755
fraction field.
8756
8757
EXAMPLES::
8758
8759
sage: a = matrix(ZZ,4,[1, 0, 0, 0, 0, 1, 0, 0, 1, \
8760
-1, 1, 0, 1, -1, 1, 2]); a
8761
[ 1 0 0 0]
8762
[ 0 1 0 0]
8763
[ 1 -1 1 0]
8764
[ 1 -1 1 2]
8765
sage: a.jordan_form()
8766
[2|0 0|0]
8767
[-+---+-]
8768
[0|1 1|0]
8769
[0|0 1|0]
8770
[-+---+-]
8771
[0|0 0|1]
8772
sage: a.jordan_form(subdivide=False)
8773
[2 0 0 0]
8774
[0 1 1 0]
8775
[0 0 1 0]
8776
[0 0 0 1]
8777
sage: b = matrix(ZZ,3,range(9)); b
8778
[0 1 2]
8779
[3 4 5]
8780
[6 7 8]
8781
sage: b.jordan_form()
8782
Traceback (most recent call last):
8783
...
8784
RuntimeError: Some eigenvalue does not exist in Rational Field.
8785
sage: b.jordan_form(RealField(15))
8786
Traceback (most recent call last):
8787
...
8788
ValueError: Jordan normal form not implemented over inexact rings.
8789
8790
Here we need to specify a field, since the eigenvalues are not defined
8791
in the smallest ring containing the matrix entries (:trac:`14508`)::
8792
8793
sage: c = matrix([[0,1,0],[0,0,1],[1,0,0]]);
8794
sage: c.jordan_form(CyclotomicField(3))
8795
[ 1| 0| 0]
8796
[----------+----------+----------]
8797
[ 0| zeta3| 0]
8798
[----------+----------+----------]
8799
[ 0| 0|-zeta3 - 1]
8800
8801
If you need the transformation matrix as well as the Jordan form of
8802
``self``, then pass the option ``transformation=True``. For example::
8803
8804
sage: m = matrix([[5,4,2,1],[0,1,-1,-1],[-1,-1,3,0],[1,1,-1,2]]); m
8805
[ 5 4 2 1]
8806
[ 0 1 -1 -1]
8807
[-1 -1 3 0]
8808
[ 1 1 -1 2]
8809
sage: jf, p = m.jordan_form(transformation=True)
8810
sage: jf
8811
[2|0|0 0]
8812
[-+-+---]
8813
[0|1|0 0]
8814
[-+-+---]
8815
[0|0|4 1]
8816
[0|0|0 4]
8817
sage: ~p * m * p
8818
[2 0 0 0]
8819
[0 1 0 0]
8820
[0 0 4 1]
8821
[0 0 0 4]
8822
8823
Note that for matrices over inexact rings, we do not attempt to
8824
compute the Jordan normal form, since it is not numerically
8825
stable::
8826
8827
sage: b = matrix(ZZ,3,3,range(9))
8828
sage: jf, p = b.jordan_form(RealField(15), transformation=True)
8829
Traceback (most recent call last):
8830
...
8831
ValueError: Jordan normal form not implemented over inexact rings.
8832
8833
TESTS::
8834
8835
sage: c = matrix(ZZ, 3, [1]*9); c
8836
[1 1 1]
8837
[1 1 1]
8838
[1 1 1]
8839
sage: c.jordan_form(subdivide=False)
8840
[3 0 0]
8841
[0 0 0]
8842
[0 0 0]
8843
8844
::
8845
8846
sage: evals = [(i,i) for i in range(1,6)]
8847
sage: n = sum(range(1,6))
8848
sage: jf = block_diagonal_matrix([jordan_block(ev,size) for ev,size in evals])
8849
sage: p = random_matrix(ZZ,n,n)
8850
sage: while p.rank() != n: p = random_matrix(ZZ,n,n)
8851
sage: m = p * jf * ~p
8852
sage: mjf, mp = m.jordan_form(transformation=True)
8853
sage: mjf == jf
8854
True
8855
sage: m = diagonal_matrix([1,1,0,0])
8856
sage: jf,P = m.jordan_form(transformation=True)
8857
sage: jf == ~P*m*P
8858
True
8859
8860
We verify that the bug from trac ticket #6942 is fixed::
8861
8862
sage: M = Matrix(GF(2),[[1,0,1,0,0,0,1],[1,0,0,1,1,1,0],[1,1,0,1,1,1,1],[1,1,1,0,1,1,1],[1,1,1,0,0,1,0],[1,1,1,0,1,0,0],[1,1,1,1,1,1,0]])
8863
sage: J, T = M.jordan_form(transformation=True)
8864
sage: J
8865
[1 1|0 0|0 0|0]
8866
[0 1|0 0|0 0|0]
8867
[---+---+---+-]
8868
[0 0|1 1|0 0|0]
8869
[0 0|0 1|0 0|0]
8870
[---+---+---+-]
8871
[0 0|0 0|1 1|0]
8872
[0 0|0 0|0 1|0]
8873
[---+---+---+-]
8874
[0 0|0 0|0 0|1]
8875
sage: M * T == T * J
8876
True
8877
sage: T.rank()
8878
7
8879
sage: M.rank()
8880
7
8881
8882
We verify that the bug from trac ticket #6932 is fixed::
8883
8884
sage: M=Matrix(1,1,[1])
8885
sage: M.jordan_form(transformation=True)
8886
([1], [1])
8887
8888
We now go through three `10 \times 10` matrices to exhibit cases where
8889
there are multiple blocks of the same size::
8890
8891
sage: A = matrix(QQ, [[15, 37/3, -16, -104/3, -29, -7/3, 0, 2/3, -29/3, -1/3], [2, 9, -1, -6, -6, 0, 0, 0, -2, 0], [24, 74/3, -41, -208/3, -58, -23/3, 0, 4/3, -58/3, -2/3], [-6, -19, 3, 21, 19, 0, 0, 0, 6, 0], [2, 6, 3, -6, -3, 1, 0, 0, -2, 0], [-96, -296/3, 176, 832/3, 232, 101/3, 0, -16/3, 232/3, 8/3], [-4, -2/3, 21, 16/3, 4, 14/3, 3, -1/3, 4/3, -25/3], [20, 26/3, -66, -199/3, -42, -41/3, 0, 13/3, -55/3, -2/3], [18, 57, -9, -54, -57, 0, 0, 0, -15, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 3]]); A
8892
[ 15 37/3 -16 -104/3 -29 -7/3 0 2/3 -29/3 -1/3]
8893
[ 2 9 -1 -6 -6 0 0 0 -2 0]
8894
[ 24 74/3 -41 -208/3 -58 -23/3 0 4/3 -58/3 -2/3]
8895
[ -6 -19 3 21 19 0 0 0 6 0]
8896
[ 2 6 3 -6 -3 1 0 0 -2 0]
8897
[ -96 -296/3 176 832/3 232 101/3 0 -16/3 232/3 8/3]
8898
[ -4 -2/3 21 16/3 4 14/3 3 -1/3 4/3 -25/3]
8899
[ 20 26/3 -66 -199/3 -42 -41/3 0 13/3 -55/3 -2/3]
8900
[ 18 57 -9 -54 -57 0 0 0 -15 0]
8901
[ 0 0 0 0 0 0 0 0 0 3]
8902
sage: J, T = A.jordan_form(transformation=True); J
8903
[3 1 0|0 0 0|0 0 0|0]
8904
[0 3 1|0 0 0|0 0 0|0]
8905
[0 0 3|0 0 0|0 0 0|0]
8906
[-----+-----+-----+-]
8907
[0 0 0|3 1 0|0 0 0|0]
8908
[0 0 0|0 3 1|0 0 0|0]
8909
[0 0 0|0 0 3|0 0 0|0]
8910
[-----+-----+-----+-]
8911
[0 0 0|0 0 0|3 1 0|0]
8912
[0 0 0|0 0 0|0 3 1|0]
8913
[0 0 0|0 0 0|0 0 3|0]
8914
[-----+-----+-----+-]
8915
[0 0 0|0 0 0|0 0 0|3]
8916
sage: T * J * T**(-1) == A
8917
True
8918
sage: T.rank()
8919
10
8920
8921
::
8922
8923
sage: A = matrix(QQ, [[15, 37/3, -16, -14/3, -29, -7/3, 0, 2/3, 1/3, 44/3], [2, 9, -1, 0, -6, 0, 0, 0, 0, 3], [24, 74/3, -41, -28/3, -58, -23/3, 0, 4/3, 2/3, 88/3], [-6, -19, 3, 3, 19, 0, 0, 0, 0, -9], [2, 6, 3, 0, -3, 1, 0, 0, 0, 3], [-96, -296/3, 176, 112/3, 232, 101/3, 0, -16/3, -8/3, -352/3], [-4, -2/3, 21, 16/3, 4, 14/3, 3, -1/3, 4/3, -25/3], [20, 26/3, -66, -28/3, -42, -41/3, 0, 13/3, 2/3, 82/3], [18, 57, -9, 0, -57, 0, 0, 0, 3, 28], [0, 0, 0, 0, 0, 0, 0, 0, 0, 3]]); A
8924
[ 15 37/3 -16 -14/3 -29 -7/3 0 2/3 1/3 44/3]
8925
[ 2 9 -1 0 -6 0 0 0 0 3]
8926
[ 24 74/3 -41 -28/3 -58 -23/3 0 4/3 2/3 88/3]
8927
[ -6 -19 3 3 19 0 0 0 0 -9]
8928
[ 2 6 3 0 -3 1 0 0 0 3]
8929
[ -96 -296/3 176 112/3 232 101/3 0 -16/3 -8/3 -352/3]
8930
[ -4 -2/3 21 16/3 4 14/3 3 -1/3 4/3 -25/3]
8931
[ 20 26/3 -66 -28/3 -42 -41/3 0 13/3 2/3 82/3]
8932
[ 18 57 -9 0 -57 0 0 0 3 28]
8933
[ 0 0 0 0 0 0 0 0 0 3]
8934
sage: J, T = A.jordan_form(transformation=True); J
8935
[3 1 0|0 0 0|0 0|0 0]
8936
[0 3 1|0 0 0|0 0|0 0]
8937
[0 0 3|0 0 0|0 0|0 0]
8938
[-----+-----+---+---]
8939
[0 0 0|3 1 0|0 0|0 0]
8940
[0 0 0|0 3 1|0 0|0 0]
8941
[0 0 0|0 0 3|0 0|0 0]
8942
[-----+-----+---+---]
8943
[0 0 0|0 0 0|3 1|0 0]
8944
[0 0 0|0 0 0|0 3|0 0]
8945
[-----+-----+---+---]
8946
[0 0 0|0 0 0|0 0|3 1]
8947
[0 0 0|0 0 0|0 0|0 3]
8948
sage: T * J * T**(-1) == A
8949
True
8950
sage: T.rank()
8951
10
8952
8953
::
8954
8955
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], [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]]); A
8956
[ 15 37/3 -16 -104/3 -29 -7/3 35 2/3 -29/3 -1/3]
8957
[ 2 9 -1 -6 -6 0 7 0 -2 0]
8958
[ 24 74/3 -29 -208/3 -58 -14/3 70 4/3 -58/3 -2/3]
8959
[ -6 -19 3 21 19 0 -21 0 6 0]
8960
[ 2 6 -1 -6 -3 0 7 0 -2 0]
8961
[ -96 -296/3 128 832/3 232 65/3 -279 -16/3 232/3 8/3]
8962
[ 0 0 0 0 0 0 3 0 0 0]
8963
[ 20 26/3 -30 -199/3 -42 -14/3 70 13/3 -55/3 -2/3]
8964
[ 18 57 -9 -54 -57 0 63 0 -15 0]
8965
[ 0 0 0 0 0 0 0 0 0 3]
8966
sage: J, T = A.jordan_form(transformation=True); J
8967
[3 1 0|0 0|0 0|0 0|0]
8968
[0 3 1|0 0|0 0|0 0|0]
8969
[0 0 3|0 0|0 0|0 0|0]
8970
[-----+---+---+---+-]
8971
[0 0 0|3 1|0 0|0 0|0]
8972
[0 0 0|0 3|0 0|0 0|0]
8973
[-----+---+---+---+-]
8974
[0 0 0|0 0|3 1|0 0|0]
8975
[0 0 0|0 0|0 3|0 0|0]
8976
[-----+---+---+---+-]
8977
[0 0 0|0 0|0 0|3 1|0]
8978
[0 0 0|0 0|0 0|0 3|0]
8979
[-----+---+---+---+-]
8980
[0 0 0|0 0|0 0|0 0|3]
8981
sage: T * J * T**(-1) == A
8982
True
8983
sage: T.rank()
8984
10
8985
8986
Verify that we smoothly move to QQ from ZZ (:trac:`12693`), i.e.
8987
we work in the vector space over the field::
8988
8989
sage: M = matrix(((2,2,2),(0,0,0),(-2,-2,-2)))
8990
sage: J, P = M.jordan_form(transformation=True)
8991
sage: J; P
8992
[0 1|0]
8993
[0 0|0]
8994
[---+-]
8995
[0 0|0]
8996
[ 2 1 0]
8997
[ 0 0 1]
8998
[-2 0 -1]
8999
sage: J - ~P * M * P
9000
[0 0 0]
9001
[0 0 0]
9002
[0 0 0]
9003
sage: parent(M)
9004
Full MatrixSpace of 3 by 3 dense matrices over Integer Ring
9005
sage: parent(J) == parent(P) == MatrixSpace(QQ, 3)
9006
True
9007
sage: M.jordan_form(transformation=True) == (M/1).jordan_form(transformation=True)
9008
True
9009
9010
By providing eigenvalues ourselves, we can compute the Jordan form even
9011
lacking a polynomial factorization algorithm. ::
9012
9013
sage: Qx = PolynomialRing(QQ, 'x11, x12, x13, x21, x22, x23, x31, x32, x33')
9014
sage: x11, x12, x13, x21, x22, x23, x31, x32, x33 = Qx.gens()
9015
sage: M = matrix(Qx, [[0, 0, x31], [0, 0, x21], [0, 0, 0]]) # This is a nilpotent matrix.
9016
sage: M.jordan_form(eigenvalues=[(0, 3)])
9017
[0 1|0]
9018
[0 0|0]
9019
[---+-]
9020
[0 0|0]
9021
sage: M.jordan_form(eigenvalues=[(0, 2)])
9022
Traceback (most recent call last):
9023
...
9024
ValueError: The provided list of eigenvalues is not correct.
9025
sage: M.jordan_form(transformation=True, eigenvalues=[(0, 3)])
9026
(
9027
[0 1|0]
9028
[0 0|0] [x31 0 1]
9029
[---+-] [x21 0 0]
9030
[0 0|0], [ 0 1 0]
9031
)
9032
9033
TESTS:
9034
9035
The base ring for the matrix needs to have a fraction field
9036
and it needs to be implemented. ::
9037
9038
sage: A = matrix(Integers(6), 2, 2, range(4))
9039
sage: A.jordan_form()
9040
Traceback (most recent call last):
9041
...
9042
ValueError: Matrix entries must be from a field, not Ring of integers modulo 6
9043
"""
9044
from sage.matrix.constructor import block_diagonal_matrix, jordan_block, diagonal_matrix
9045
from sage.combinat.partition import Partition
9046
9047
if self.ncols() != self.nrows():
9048
raise ValueError, "Jordan normal form not implemented for non-square matrices."
9049
9050
# Set ``n`` to the number of rows and handle trivial cases, regardless
9051
# of the underlying ring.
9052
n = self.nrows()
9053
if n == 0:
9054
if not transformation:
9055
return self
9056
else:
9057
return self, self
9058
elif n == 1:
9059
if not transformation:
9060
return self
9061
else:
9062
return self, self.parent().identity_matrix()
9063
9064
inferred_base_ring = base_ring
9065
9066
if base_ring is None:
9067
inferred_base_ring = self.base_ring()
9068
9069
if not inferred_base_ring.is_exact():
9070
raise ValueError("Jordan normal form not implemented over inexact rings.")
9071
9072
# Make sure we're working with a field.
9073
if inferred_base_ring.is_field():
9074
if base_ring is not None:
9075
A = self.change_ring(inferred_base_ring)
9076
else:
9077
A = self
9078
else:
9079
try:
9080
base_field = inferred_base_ring.fraction_field()
9081
except (NotImplementedError, TypeError, AttributeError):
9082
raise ValueError("Matrix entries must be from a field, not {0}".
9083
format(inferred_base_ring))
9084
A = self.change_ring(base_field)
9085
9086
# Compute the eigenvalues of the matrix, with multiplicities. Here,
9087
# ``evals`` is a list of pairs, each first entry a root and each
9088
# second entry the corresponding multiplicity.
9089
if eigenvalues is not None:
9090
if check_input: # Checking input for sanity.
9091
C1 = A.charpoly()
9092
Polyring = C1.parent()
9093
C2 = Polyring.one()
9094
x = Polyring.gens()[0]
9095
for z, i in eigenvalues:
9096
C2 *= (x - z) ** i
9097
if C1 != C2:
9098
raise ValueError("The provided list of eigenvalues is not correct.")
9099
evals = eigenvalues
9100
else:
9101
evals = A.charpoly().roots()
9102
if sum([mult for (_,mult) in evals]) < n:
9103
raise RuntimeError("Some eigenvalue does not exist in %s." %(A.base_ring()))
9104
9105
# Compute the block information. Here, ``blocks`` is a list of pairs,
9106
# each first entry a root and each second entry the size of a block.
9107
# Note that in general there is more than one block per eigenvalue!
9108
blocks = []
9109
for eval, mult in evals:
9110
if mult == 1:
9111
blocks.append((eval,1))
9112
else:
9113
B = A - diagonal_matrix([eval]*n, sparse=sparse)
9114
C = B
9115
ranks = [n, C.rank()]
9116
i = 0
9117
while ranks[i] > ranks[i+1] and ranks[i+1] > n-mult:
9118
C = B*C
9119
ranks.append(C.rank())
9120
i = i+1
9121
diagram = [ranks[i]-ranks[i+1] for i in xrange(len(ranks)-1)]
9122
blocks.extend([(eval, i) \
9123
for i in Partition(diagram).conjugate()])
9124
9125
# ``J`` is the matrix in Jordan canonical form. Note that the blocks
9126
# are ordered firstly by the eigenvalues, in the same order as obeyed
9127
# by ``.roots()``, and secondly by size from greatest to smallest.
9128
J = block_diagonal_matrix([jordan_block(eval, size, sparse=sparse) \
9129
for (eval, size) in blocks], subdivide=subdivide)
9130
9131
if transformation:
9132
from itertools import groupby
9133
9134
# ``jordan_chains`` is a dictionary with keys the eigenvalues.
9135
# For every eigenvalue, we consider all Jordan blocks and find
9136
# a Jordan chain for each, adding the chain (a sequence of
9137
# vectors) to the entry for the eigenvalue (which is a list).
9138
jordan_chains = {}
9139
for eval,_ in evals:
9140
jordan_chains[eval] = []
9141
9142
# Let B be the matrix `A - eval Id`.
9143
B = A - eval
9144
9145
block_sizes = [size for e,size in blocks if e == eval]
9146
block_size_pairs = [(val,len(list(c))) \
9147
for val,c in groupby(block_sizes)]
9148
9149
# Y is a list of vectors, spanning everything that we have
9150
# covered by the Jordan chains we developed so far.
9151
Y = []
9152
9153
for l,count in block_size_pairs:
9154
9155
# There are ``count`` Jordan blocks of size ``l``
9156
# associated to this eigenvalue.
9157
9158
# We want to find elements in `\ker B^l - \ker B^{l-1}`.
9159
Vlarge = (B**l).right_kernel().basis()
9160
Vsmall = (B**(l-1)).right_kernel().basis()
9161
9162
for i in range(count):
9163
# Let v be any vector in `\ker B^l` not in the kernel
9164
# of `\ker B^{l-1}` which is also not in the span(Y),
9165
# and start a chain from there.
9166
v = _jordan_form_vector_in_difference(Vlarge, Vsmall+Y)
9167
chain = [v]
9168
for i in range(l-1):
9169
chain.append(B*chain[-1])
9170
chain.reverse()
9171
Y.extend(chain)
9172
jordan_chains[eval].append(chain)
9173
9174
# Now ``jordan_chains`` has all the columns of the transformation
9175
# matrix; we just need to put them in the right order.
9176
jordan_basis = []
9177
for eval,size in blocks:
9178
# Find a block with the right size
9179
for index,chain in enumerate(jordan_chains[eval]):
9180
if len(chain)==size:
9181
jordan_basis += jordan_chains[eval].pop(index)
9182
break
9183
9184
transformation_matrix = (A.parent()(jordan_basis)).transpose()
9185
9186
if transformation:
9187
return J, transformation_matrix
9188
else:
9189
return J
9190
9191
def is_diagonalizable(self, base_field=None):
9192
r"""
9193
Determines if the matrix is similar to a diagonal matrix.
9194
9195
INPUT:
9196
9197
- ``base_field`` - a new field to use for entries
9198
of the matrix.
9199
9200
OUTPUT:
9201
9202
If ``self`` is the matrix `A`, then it is diagonalizable
9203
if there is an invertible matrix `S` and a diagonal matrix
9204
`D` such that
9205
9206
.. math::
9207
9208
S^{-1}AS = D
9209
9210
This routine returns ``True`` if ``self`` is diagonalizable.
9211
The diagonal entries of the matrix `D` are the eigenvalues
9212
of `A`. It may be necessary to "increase" the base field to
9213
contain all of the eigenvalues. Over the rationals, the field
9214
of algebraic numbers, :mod:`sage.rings.qqbar` is a good choice.
9215
9216
To obtain the matrices `S` and `D` use the :meth:`jordan_form`
9217
method with the ``transformation=True`` keyword.
9218
9219
ALGORITHM:
9220
9221
For each eigenvalue, this routine checks that the algebraic
9222
multiplicity (number of occurences as a root of the characteristic
9223
polynomial) is equal to the geometric multiplicity (dimension
9224
of the eigenspace), which is sufficient to ensure a basis of
9225
eigenvectors for the columns of `S`.
9226
9227
EXAMPLES:
9228
9229
A matrix that is diagonalizable over the rationals, as evidenced
9230
by its Jordan form. ::
9231
9232
sage: A = matrix(QQ, [[-7, 16, 12, 0, 6],
9233
... [-9, 15, 0, 12, -27],
9234
... [ 9, -8, 11, -12, 51],
9235
... [ 3, -4, 0, -1, 9],
9236
... [-1, 0, -4, 4, -12]])
9237
sage: A.jordan_form(subdivide=False)
9238
[ 2 0 0 0 0]
9239
[ 0 3 0 0 0]
9240
[ 0 0 3 0 0]
9241
[ 0 0 0 -1 0]
9242
[ 0 0 0 0 -1]
9243
sage: A.is_diagonalizable()
9244
True
9245
9246
A matrix that is not diagonalizable over the rationals, as evidenced
9247
by its Jordan form. ::
9248
9249
sage: A = matrix(QQ, [[-3, -14, 2, -1, 15],
9250
... [4, 6, -2, 3, -8],
9251
... [-2, -14, 0, 0, 10],
9252
... [3, 13, -2, 0, -11],
9253
... [-1, 6, 1, -3, 1]])
9254
sage: A.jordan_form(subdivide=False)
9255
[-1 1 0 0 0]
9256
[ 0 -1 0 0 0]
9257
[ 0 0 2 1 0]
9258
[ 0 0 0 2 1]
9259
[ 0 0 0 0 2]
9260
sage: A.is_diagonalizable()
9261
False
9262
9263
If any eigenvalue of a matrix is outside the base ring, then
9264
this routine raises an error. However, the ring can be
9265
"expanded" to contain the eigenvalues. ::
9266
9267
sage: A = matrix(QQ, [[1, 0, 1, 1, -1],
9268
... [0, 1, 0, 4, 8],
9269
... [2, 1, 3, 5, 1],
9270
... [2, -1, 1, 0, -2],
9271
... [0, -1, -1, -5, -8]])
9272
9273
sage: [e in QQ for e in A.eigenvalues()]
9274
[False, False, False, False, False]
9275
sage: A.is_diagonalizable()
9276
Traceback (most recent call last):
9277
...
9278
RuntimeError: an eigenvalue of the matrix is not contained in Rational Field
9279
9280
sage: [e in QQbar for e in A.eigenvalues()]
9281
[True, True, True, True, True]
9282
sage: A.is_diagonalizable(base_field=QQbar)
9283
True
9284
9285
Other exact fields may be employed, though it will not always
9286
be possible to expand their base fields to contain all
9287
the eigenvalues. ::
9288
9289
sage: F.<b> = FiniteField(5^2)
9290
sage: A = matrix(F, [[ 4, 3*b + 2, 3*b + 1, 3*b + 4],
9291
... [2*b + 1, 4*b, 0, 2],
9292
... [ 4*b, b + 2, 2*b + 3, 3],
9293
... [ 2*b, 3*b, 4*b + 4, 3*b + 3]])
9294
sage: A.jordan_form()
9295
[ 4 1| 0 0]
9296
[ 0 4| 0 0]
9297
[---------------+---------------]
9298
[ 0 0|2*b + 1 1]
9299
[ 0 0| 0 2*b + 1]
9300
sage: A.is_diagonalizable()
9301
False
9302
9303
sage: F.<c> = QuadraticField(-7)
9304
sage: A = matrix(F, [[ c + 3, 2*c - 2, -2*c + 2, c - 1],
9305
... [2*c + 10, 13*c + 15, -13*c - 17, 11*c + 31],
9306
... [2*c + 10, 14*c + 10, -14*c - 12, 12*c + 30],
9307
... [ 0, 2*c - 2, -2*c + 2, 2*c + 2]])
9308
sage: A.jordan_form(subdivide=False)
9309
[ 4 0 0 0]
9310
[ 0 -2 0 0]
9311
[ 0 0 c + 3 0]
9312
[ 0 0 0 c + 3]
9313
sage: A.is_diagonalizable()
9314
True
9315
9316
A trivial matrix is diagonalizable, trivially. ::
9317
9318
sage: A = matrix(QQ, 0, 0)
9319
sage: A.is_diagonalizable()
9320
True
9321
9322
A matrix must be square to be diagonalizable. ::
9323
9324
sage: A = matrix(QQ, 3, 4)
9325
sage: A.is_diagonalizable()
9326
False
9327
9328
The matrix must have entries from a field,
9329
and it must be an exact field. ::
9330
9331
sage: A = matrix(ZZ, 4, range(16))
9332
sage: A.is_diagonalizable()
9333
Traceback (most recent call last):
9334
...
9335
ValueError: matrix entries must be from a field, not Integer Ring
9336
9337
sage: A = matrix(RDF, 4, range(16))
9338
sage: A.is_diagonalizable()
9339
Traceback (most recent call last):
9340
...
9341
ValueError: base field must be exact, not Real Double Field
9342
9343
AUTHOR:
9344
9345
- Rob Beezer (2011-04-01)
9346
"""
9347
if not self.is_square():
9348
return False
9349
if not base_field is None:
9350
self = self.change_ring(base_field)
9351
if not self.base_ring().is_exact():
9352
raise ValueError('base field must be exact, not {0}'.format(self.base_ring()))
9353
if not self.base_ring().is_field():
9354
raise ValueError('matrix entries must be from a field, not {0}'.format(self.base_ring()))
9355
9356
evals = self.charpoly().roots()
9357
if sum([mult for (_,mult) in evals]) < self._nrows:
9358
raise RuntimeError('an eigenvalue of the matrix is not contained in {0}'.format(self.base_ring()))
9359
9360
# Obtaining a generic minimal polynomial requires much more
9361
# computation with kernels and their dimensions than the following.
9362
# However, if a derived class has a fast minimal polynomial routine
9363
# then overriding this by checking for repeated factors might be faster.
9364
9365
# check equality of algebraic multiplicity and geometric multiplicity
9366
for e, am in evals:
9367
gm = (self - e).right_kernel().dimension()
9368
if am != gm:
9369
return False
9370
return True
9371
9372
def is_similar(self, other, transformation=False):
9373
r"""
9374
Returns ``True`` if ``self`` and ``other`` are similar,
9375
i.e. related by a change-of-basis matrix.
9376
9377
INPUT:
9378
9379
- ``other`` - a matrix, which should be square, and of the same size
9380
as ``self``, where the entries of the matrix have a fraction field
9381
equal to that of ``self``. Inexact rings are not supported.
9382
9383
- ``transformation`` - default: ``False`` - if ``True``, the output
9384
will include the change-of-basis matrix. See below for an exact
9385
description.
9386
9387
OUTPUT:
9388
9389
Two matrices, $A$ and $B$ are similar if there is an invertible
9390
matrix $S$ such that $A=S^{-1}BS$. $S$ can be interpreted as a
9391
change-of-basis matrix if $A$ and $B$ are viewed as matrix
9392
representations of the same linear transformation.
9393
9394
When ``transformation=False`` this method will return ``True`` if
9395
such a matrix $S$ exists, otherwise it will return ``False``. When
9396
``transformation=True`` the method returns a pair. The first part
9397
of the pair is ``True`` or ``False`` depending on if the matrices
9398
are similar and the second part is the change-of-basis matrix, or
9399
``None`` should it not exist.
9400
9401
When the transformation matrix is requested, it will satisfy
9402
``self = S.inverse()*other*S``.
9403
9404
If the base rings for any of the matrices is the integers, the
9405
rationals, or the field of algebraic numbers (``QQbar``), then the
9406
matrices are converted to have ``QQbar`` as their base ring prior
9407
to checking the equality of the base rings.
9408
9409
It is possible for this routine to fail over most fields, even when
9410
the matrices are similar. However, since the field of algebraic
9411
numbers is algebraically closed, the routine will always produce
9412
a result for matrices with rational entries.
9413
9414
EXAMPLES:
9415
9416
The two matrices in this example were constructed to be similar.
9417
The computations happen in the field of algebraic numbers, but we
9418
are able to convert the change-of-basis matrix back to the rationals
9419
(which may not always be possible). ::
9420
9421
sage: A = matrix(ZZ, [[-5, 2, -11],
9422
... [-6, 7, -42],
9423
... [0, 1, -6]])
9424
sage: B = matrix(ZZ, [[ 1, 12, 3],
9425
... [-1, -6, -1],
9426
... [ 0, 6, 1]])
9427
sage: A.is_similar(B)
9428
True
9429
sage: _, T = A.is_similar(B, transformation=True)
9430
sage: T
9431
[ 1.0000000000000? + 0.?e-13*I 0.?e-13 + 0.?e-13*I 0.?e-13 + 0.?e-13*I]
9432
[-0.6666666666667? + 0.?e-13*I 0.16666666666667? + 0.?e-14*I -0.8333333333334? + 0.?e-13*I]
9433
[ 0.6666666666667? + 0.?e-13*I 0.?e-13 + 0.?e-13*I -0.333333333334? + 0.?e-13*I]
9434
sage: T.change_ring(QQ)
9435
[ 1 0 0]
9436
[-2/3 1/6 -5/6]
9437
[ 2/3 0 -1/3]
9438
sage: A == T.inverse()*B*T
9439
True
9440
9441
Other exact fields are supported. ::
9442
9443
sage: F.<a> = FiniteField(7^2)
9444
sage: A = matrix(F,[[2*a + 5, 6*a + 6, a + 3],
9445
... [ a + 3, 2*a + 2, 4*a + 2],
9446
... [2*a + 6, 5*a + 5, 3*a]])
9447
sage: B = matrix(F,[[5*a + 5, 6*a + 4, a + 1],
9448
... [ a + 5, 4*a + 3, 3*a + 3],
9449
... [3*a + 5, a + 4, 5*a + 6]])
9450
sage: A.is_similar(B)
9451
True
9452
sage: B.is_similar(A)
9453
True
9454
sage: _, T = A.is_similar(B, transformation=True)
9455
sage: T
9456
[ 1 0 0]
9457
[6*a + 1 4*a + 3 4*a + 2]
9458
[6*a + 3 3*a + 5 3*a + 6]
9459
sage: A == T.inverse()*B*T
9460
True
9461
9462
Two matrices with different sets of eigenvalues, so they
9463
cannot possibly be similar. ::
9464
9465
sage: A = matrix(QQ, [[ 2, 3, -3, -6],
9466
... [ 0, 1, -2, -8],
9467
... [-3, -3, 4, 3],
9468
... [-1, -2, 2, 6]])
9469
sage: B = matrix(QQ, [[ 1, 1, 2, 4],
9470
... [-1, 2, -3, -7],
9471
... [-2, 3, -4, -7],
9472
... [ 0, -1, 0, 0]])
9473
sage: A.eigenvalues() == B.eigenvalues()
9474
False
9475
sage: A.is_similar(B, transformation=True)
9476
(False, None)
9477
9478
Similarity is an equivalence relation, so this routine computes
9479
a representative of the equivalence class for each matrix, the
9480
Jordan form, as provided by :meth:`jordan_form`. The matrices
9481
below have identical eigenvalues (as evidenced by equal
9482
characteristic polynomials), but slightly different Jordan forms,
9483
and hence are not similar. ::
9484
9485
sage: A = matrix(QQ, [[ 19, -7, -29],
9486
... [-16, 11, 30],
9487
... [ 15, -7, -25]])
9488
sage: B = matrix(QQ, [[-38, -63, 42],
9489
... [ 14, 25, -14],
9490
... [-14, -21, 18]])
9491
sage: A.charpoly() == B.charpoly()
9492
True
9493
sage: A.jordan_form()
9494
[-3| 0 0]
9495
[--+-----]
9496
[ 0| 4 1]
9497
[ 0| 0 4]
9498
sage: B.jordan_form()
9499
[-3| 0| 0]
9500
[--+--+--]
9501
[ 0| 4| 0]
9502
[--+--+--]
9503
[ 0| 0| 4]
9504
sage: A.is_similar(B)
9505
False
9506
9507
Obtaining the Jordan form requires computing the eigenvalues of
9508
the matrix, which may not lie in the field used for entries of
9509
the matrix. So the routine first checks the characteristic
9510
polynomials - if they are unequal, then the matrices cannot be
9511
similar. However, when the characteristic polynomials are equal,
9512
we must examine the Jordan form. In this case, the method may fail,
9513
EVEN when the matrices are similar. This is not the case for
9514
matrices over the integers, rationals or algebraic numbers,
9515
since the computations are done in the algebraically closed
9516
field of algebraic numbers.
9517
9518
Here is an example where the similarity is obvious, but the
9519
routine fails to compute a result. ::
9520
9521
sage: F.<a> = FiniteField(7^2)
9522
sage: C = matrix(F,[[ a + 2, 5*a + 4],
9523
... [6*a + 6, 6*a + 4]])
9524
sage: S = matrix(ZZ, [[0, 1],
9525
... [1, 0]])
9526
sage: D = S.inverse()*C*S
9527
sage: C.is_similar(D)
9528
Traceback (most recent call last):
9529
...
9530
ValueError: unable to compute Jordan canonical form for a matrix
9531
sage: C.jordan_form()
9532
Traceback (most recent call last):
9533
...
9534
RuntimeError: Some eigenvalue does not exist in Finite Field in a of size 7^2.
9535
9536
Inexact rings and fields are also not supported. ::
9537
9538
sage: A = matrix(CDF, 2, 2, range(4))
9539
sage: B = copy(A)
9540
sage: A.is_similar(B)
9541
Traceback (most recent call last):
9542
...
9543
ValueError: unable to compute Jordan canonical form for a matrix
9544
9545
Rectangular matrices and mismatched sizes return quickly. ::
9546
9547
sage: A = matrix(3, 2, range(6))
9548
sage: B = copy(A)
9549
sage: A.is_similar(B)
9550
False
9551
sage: A = matrix(2, 2, range(4))
9552
sage: B = matrix(3, 3, range(9))
9553
sage: A.is_similar(B, transformation=True)
9554
(False, None)
9555
9556
If the fraction fields of the entries are unequal, it is an error,
9557
except in the case when the rationals gets promoted to the
9558
algebraic numbers. ::
9559
9560
sage: A = matrix(ZZ, 2, 2, range(4))
9561
sage: B = matrix(GF(2), 2, 2, range(4))
9562
sage: A.is_similar(B, transformation=True)
9563
Traceback (most recent call last):
9564
...
9565
TypeError: matrices need to have entries with identical fraction fields, not Algebraic Field and Finite Field of size 2
9566
sage: A = matrix(ZZ, 2, 2, range(4))
9567
sage: B = matrix(QQbar, 2, 2, range(4))
9568
sage: A.is_similar(B)
9569
True
9570
9571
Inputs are checked. ::
9572
9573
sage: A = matrix(ZZ, 2, 2, range(4))
9574
sage: A.is_similar('garbage')
9575
Traceback (most recent call last):
9576
...
9577
TypeError: similarity requires a matrix as an argument, not garbage
9578
sage: B = copy(A)
9579
sage: A.is_similar(B, transformation='junk')
9580
Traceback (most recent call last):
9581
...
9582
ValueError: transformation keyword must be True or False, not junk
9583
"""
9584
import sage.matrix.matrix
9585
import sage.rings.qqbar
9586
if not sage.matrix.matrix.is_Matrix(other):
9587
raise TypeError('similarity requires a matrix as an argument, not {0}'.format(other))
9588
if transformation not in [True, False]:
9589
raise ValueError('transformation keyword must be True or False, not {0}'.format(transformation))
9590
# easy false situations
9591
if not self.is_square() or not other.is_square():
9592
if transformation:
9593
return (False, None)
9594
else:
9595
return False
9596
if self.nrows() != other.nrows():
9597
if transformation:
9598
return (False, None)
9599
else:
9600
return False
9601
# convert to fraction fields for base rings
9602
A = self.matrix_over_field()
9603
B = other.matrix_over_field()
9604
# move rationals to algebraically closed algebraic numbers
9605
if A.base_ring() == QQ:
9606
A = A.change_ring(sage.rings.qqbar.QQbar)
9607
if B.base_ring() == QQ:
9608
B = B.change_ring(sage.rings.qqbar.QQbar)
9609
# require identical base fields
9610
if A.base_ring() != B.base_ring():
9611
raise TypeError('matrices need to have entries with identical fraction fields, not {0} and {1}'.format(A.base_ring(), B.base_ring()))
9612
# unequal characteristic polynomials implies not similar
9613
# and avoids any problems with eigenvalues not in the base field
9614
if A.charpoly() != B.charpoly():
9615
if transformation:
9616
return (False, None)
9617
else:
9618
return False
9619
# now more precisely compare Jordan form, and optionally get transformations
9620
try:
9621
if transformation:
9622
JA, SA = A.jordan_form(transformation=True)
9623
else:
9624
JA = A.jordan_form(transformation=False)
9625
except Exception:
9626
raise ValueError('unable to compute Jordan canonical form for a matrix')
9627
try:
9628
if transformation:
9629
JB, SB = B.jordan_form(transformation=True)
9630
else:
9631
JB = B.jordan_form(transformation=False)
9632
except Exception:
9633
raise ValueError('unable to compute Jordan canonical form for a matrix')
9634
similar = (JA == JB)
9635
transform = None
9636
if similar and transformation:
9637
transform = SB*SA.inverse()
9638
if transformation:
9639
return (similar, transform)
9640
else:
9641
return similar
9642
9643
def symplectic_form(self):
9644
r"""
9645
Find a symplectic form for self if self is an anti-symmetric,
9646
alternating matrix defined over a field.
9647
9648
Returns a pair (F, C) such that the rows of C form a symplectic
9649
basis for self and F = C \* self \* C.transpose().
9650
9651
Raises a ValueError if not over a field, or self is not
9652
anti-symmetric, or self is not alternating.
9653
9654
Anti-symmetric means that `M = -M^t`. Alternating means
9655
that the diagonal of `M` is identically zero.
9656
9657
A symplectic basis is a basis of the form
9658
`e_1, \ldots, e_j, f_1, \ldots f_j, z_1, \dots, z_k`
9659
such that
9660
9661
- `z_i M v^t` = 0 for all vectors `v`
9662
9663
- `e_i M {e_j}^t = 0` for all `i, j`
9664
9665
- `f_i M {f_j}^t = 0` for all `i, j`
9666
9667
- `e_i M {f_i}^t = 1` for all `i`
9668
9669
- `e_i M {f_j}^t = 0` for all `i` not equal
9670
`j`.
9671
9672
See the example for a pictorial description of such a basis.
9673
9674
EXAMPLES::
9675
9676
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
9677
[ 0 -1/2 -2 1/2 2 0 -2 1]
9678
[ 1/2 0 -1 -3 0 2 5/2 -3]
9679
[ 2 1 0 3/2 -1 0 -1 -2]
9680
[-1/2 3 -3/2 0 1 3/2 -1/2 -1/2]
9681
[ -2 0 1 -1 0 0 1 -1]
9682
[ 0 -2 0 -3/2 0 0 1/2 -2]
9683
[ 2 -5/2 1 1/2 -1 -1/2 0 -1]
9684
[ -1 3 2 1/2 1 2 1 0]
9685
sage: F, C = E.symplectic_form(); F
9686
[ 0 0 0 0 1 0 0 0]
9687
[ 0 0 0 0 0 1 0 0]
9688
[ 0 0 0 0 0 0 1 0]
9689
[ 0 0 0 0 0 0 0 1]
9690
[-1 0 0 0 0 0 0 0]
9691
[ 0 -1 0 0 0 0 0 0]
9692
[ 0 0 -1 0 0 0 0 0]
9693
[ 0 0 0 -1 0 0 0 0]
9694
sage: F == C * E * C.transpose()
9695
True
9696
"""
9697
import sage.matrix.symplectic_basis
9698
return sage.matrix.symplectic_basis.symplectic_basis_over_field(self)
9699
9700
def _cyclic_subspace(self, v):
9701
r"""
9702
Helper function for computing with cyclic (Krylov) subspaces.
9703
9704
For a square matrix `A` and a vector `v`, the cyclic subspace
9705
is spanned by the vectors
9706
9707
.. math::
9708
9709
\{v, Av, A^2v, A^3v, \dots \}
9710
9711
INPUT:
9712
9713
- ``self`` - a square matrix over a field.
9714
9715
- ``v`` - a vector with a degree equal to the size of the matrix.
9716
9717
There is no explicit error-checking, it is the responsibility of
9718
the calling routine to provide accurate input.
9719
9720
OUTPUT:
9721
9722
Four related items are output. Principally this routine
9723
determines the dimension of a cyclic subspace, but also
9724
creates two bases for the subspace. Let `k` be the smallest
9725
integer such that `A^kv` is a linear combination of the
9726
products with smaller powers of `A`, i.e. the dimension
9727
of the cyclic subspace.
9728
9729
- A list of the vectors `v, Av, A^2v,\dots, A^{k-1}v`
9730
(the "iterates"). These vectors give one basis of
9731
the subspace.
9732
9733
- A list of scalars giving a linear combination of
9734
`v, Av, A^2v,\dots, A^kv` that equals the zero vector.
9735
This is the unique such set of such scalars where the
9736
last one in the list is 1. These can be used to form
9737
a monic polynomial in `A` that has `v` in its right kernel.
9738
the length of this list is `k+1`.
9739
9740
- Form a matrix whose rows are the linearly independent iterates.
9741
Augment with a `k\times k` identity matrix. Apply row operations,
9742
scaling and adding multiples of rows, but never swap rows. Do
9743
this to create `k` pivot columns. The third output is this
9744
augmented, nearly row-reduced, matrix. The rows of the left
9745
portion will form a basis for the subspace, while the right
9746
portion will record linear combinations of the iterates that
9747
equal these basis vectors.
9748
9749
- A list of length `k` with the location of the pivots
9750
in the augmented matrix. Specifically, entry ``i`` of this
9751
list is the column index of the pivot column containing its
9752
lone 1 in row ``i``.
9753
9754
ALGORITHM:
9755
9756
This could be called an "online echelon form" routine. As each
9757
new power of the matrix is built, the iterate is added to the bottom
9758
of the augmented matrix and row operations are used to update
9759
the pivot columns. Rows are never swapped, so this is not
9760
strictly reduced row-echelon form, but the running time will
9761
be similar. The main difference is that it "discovers" the
9762
dimension of the subspace as quickly as possible.
9763
9764
EXAMPLE::
9765
9766
sage: A = matrix(QQ, [[5,4,2,1],[0,1,-1,-1],[-1,-1,3,0],[1,1,-1,2]])
9767
sage: v = vector(QQ, [0,1,0,0])
9768
sage: (QQ^4).span([v, A*v, A^2*v, A^3*v]).dimension()
9769
3
9770
9771
sage: iterates, poly, augmented, pivots = A._cyclic_subspace(v)
9772
9773
sage: iterates
9774
[(0, 1, 0, 0), (4, 1, -1, 1), (23, 1, -8, 8)]
9775
sage: poly
9776
[-16, 24, -9, 1]
9777
sage: lindep = iterates + [A^3*v]
9778
sage: sum(poly[i]*lindep[i] for i in range(4))
9779
(0, 0, 0, 0)
9780
sage: B = sum(poly[i]*A^i for i in range(4))
9781
sage: v in B.right_kernel()
9782
True
9783
9784
sage: augmented
9785
[ 0 1 0 0 1 0 0]
9786
[ 1 0 0 0 -7/9 8/9 -1/9]
9787
[ 0 0 1 -1 -19/9 23/9 -4/9]
9788
sage: pivots
9789
[1, 0, 2]
9790
sage: transform = augmented[:, 4:7]
9791
sage: transform*matrix(iterates) == augmented[:, 0:4]
9792
True
9793
sage: (QQ^4).span(iterates) == (QQ^4).span(augmented[:, 0:4].rows())
9794
True
9795
9796
AUTHOR:
9797
9798
- Rob Beezer (2011-05-20)
9799
"""
9800
cdef Py_ssize_t n, i, j, k, pivcol
9801
cdef Matrix aug
9802
n = self.ncols()
9803
aug = self.new_matrix(nrows=n+1, ncols=n+(n+1))
9804
iterate = v.__copy__()
9805
iterates = []
9806
pivots = []
9807
for k in range(n+1):
9808
for j in range(n):
9809
aug[k, j] = iterate[j]
9810
# record keeping in augmented identity matrix
9811
aug[k, n+k] = 1
9812
# clear out pivot cols of row k, using pivots of previous rows
9813
for i in range(k):
9814
aug.add_multiple_of_row(k, i, -aug[k, pivots[i]])
9815
# identify new pivot
9816
# no new pivot is all zeros, ie linear dependence
9817
pivcol = -1
9818
for j in range(n):
9819
if aug[k, j] != 0:
9820
pivcol = j
9821
pivots.append(pivcol)
9822
break
9823
# scale pivot, and clear its column
9824
if pivcol != -1:
9825
aug.rescale_row(k, 1/aug[k, pivcol])
9826
for i in range(k):
9827
aug.add_multiple_of_row(i, k, -aug[i, pivcol])
9828
iterates.append(iterate)
9829
iterate = self*iterate
9830
else:
9831
break
9832
poly = []
9833
for j in range(n, n+k+1):
9834
poly.append(aug[k, j])
9835
return iterates, poly, aug.submatrix(0, 0, k, n+k), pivots
9836
9837
def cyclic_subspace(self, v, var=None, basis='echelon'):
9838
r"""
9839
Create a cyclic subspace for a vector, and optionally,
9840
a minimal polynomial for the iterated powers.
9841
9842
These subspaces are also known as Krylov subspaces. They are
9843
spanned by the vectors
9844
9845
.. math::
9846
9847
\{v, Av, A^2v, A^3v, \dots \}
9848
9849
INPUT:
9850
9851
- ``self`` - a square matrix with entries from a field.
9852
9853
- ``v`` - a vector with a degree equal to the size of the matrix
9854
and entries compatible with the entries of the matrix.
9855
9856
- ``var`` - default: ``None`` - if specified as a string or
9857
a generator of a polynomial ring, then this will be used
9858
to construct a polynomial reflecting a relation of linear
9859
dependence on the powers `A^iv` *and* this will cause
9860
the polynomial to be returned along with the subspace.
9861
A generator must create polynomials with coefficients from
9862
the same field as the matrix entries.
9863
9864
- ``basis`` - default: ``echelon`` - the basis for the
9865
subspace is "echelonized" by default, but the keyword
9866
'iterates' will return a subspace with a user basis
9867
equal to the largest linearly independent
9868
set `\{v, Av, A^2v, A^3v, \dots, A^{k-1}v \}`.
9869
9870
OUTPUT:
9871
9872
Suppose `k` is the smallest power such that
9873
`\{v, Av, A^2v, A^3v, \dots, A^{k}v \}` is linearly
9874
dependent. Then the subspace returned will have
9875
dimension `k` and be spanned by the powers `0` through
9876
`k-1`.
9877
9878
If a polynomial is requested through the use of the
9879
``var`` keyword, then a pair is returned, with the
9880
polynomial first and the subspace second. The polynomial
9881
is the unique monic polynomial whose coefficients provide
9882
a relation of linear dependence on the first `k` powers.
9883
9884
For less convenient, but more flexible output, see the
9885
helper method "_cyclic_subspace" in this module.
9886
9887
EXAMPLES::
9888
9889
sage: A = matrix(QQ, [[5,4,2,1],[0,1,-1,-1],[-1,-1,3,0],[1,1,-1,2]])
9890
sage: v = vector(QQ, [0,1,0,0])
9891
sage: E = A.cyclic_subspace(v); E
9892
Vector space of degree 4 and dimension 3 over Rational Field
9893
Basis matrix:
9894
[ 1 0 0 0]
9895
[ 0 1 0 0]
9896
[ 0 0 1 -1]
9897
sage: F = A.cyclic_subspace(v, basis='iterates'); F
9898
Vector space of degree 4 and dimension 3 over Rational Field
9899
User basis matrix:
9900
[ 0 1 0 0]
9901
[ 4 1 -1 1]
9902
[23 1 -8 8]
9903
sage: E == F
9904
True
9905
sage: p, S = A.cyclic_subspace(v, var='T'); p
9906
T^3 - 9*T^2 + 24*T - 16
9907
sage: gen = polygen(QQ, 'z')
9908
sage: p, S = A.cyclic_subspace(v, var=gen); p
9909
z^3 - 9*z^2 + 24*z - 16
9910
sage: p.degree() == E.dimension()
9911
True
9912
9913
The polynomial has coefficients that yield a non-trivial
9914
relation of linear dependence on the iterates. Or,
9915
equivalently, evaluating the polynomial with the matrix
9916
will create a matrix that annihilates the vector. ::
9917
9918
sage: A = matrix(QQ, [[15, 37/3, -16, -104/3, -29, -7/3, 35, 2/3, -29/3, -1/3],
9919
... [ 2, 9, -1, -6, -6, 0, 7, 0, -2, 0],
9920
... [24, 74/3, -29, -208/3, -58, -14/3, 70, 4/3, -58/3, -2/3],
9921
... [-6, -19, 3, 21, 19, 0, -21, 0, 6, 0],
9922
... [2, 6, -1, -6, -3, 0, 7, 0, -2, 0],
9923
... [-96, -296/3, 128, 832/3, 232, 65/3, -279, -16/3, 232/3, 8/3],
9924
... [0, 0, 0, 0, 0, 0, 3, 0, 0, 0],
9925
... [20, 26/3, -30, -199/3, -42, -14/3, 70, 13/3, -55/3, -2/3],
9926
... [18, 57, -9, -54, -57, 0, 63, 0, -15, 0],
9927
... [0, 0, 0, 0, 0, 0, 0, 0, 0, 3]])
9928
sage: u = zero_vector(QQ, 10); u[0] = 1
9929
sage: p, S = A.cyclic_subspace(u, var='t', basis='iterates')
9930
sage: S
9931
Vector space of degree 10 and dimension 3 over Rational Field
9932
User basis matrix:
9933
[ 1 0 0 0 0 0 0 0 0 0]
9934
[ 15 2 24 -6 2 -96 0 20 18 0]
9935
[ 79 12 140 -36 12 -560 0 116 108 0]
9936
sage: p
9937
t^3 - 9*t^2 + 27*t - 27
9938
sage: k = p.degree()
9939
sage: coeffs = p.list()
9940
sage: iterates = S.basis() + [A^k*u]
9941
sage: sum(coeffs[i]*iterates[i] for i in range(k+1))
9942
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
9943
sage: u in p(A).right_kernel()
9944
True
9945
9946
TESTS:
9947
9948
A small case. ::
9949
9950
sage: A = matrix(QQ, 5, range(25))
9951
sage: u = zero_vector(QQ, 5)
9952
sage: A.cyclic_subspace(u)
9953
Vector space of degree 5 and dimension 0 over Rational Field
9954
Basis matrix:
9955
[]
9956
9957
Various problem inputs. Notice the vector must have entries
9958
that coerce into the base ring of the matrix, and a polynomial
9959
ring generator must have a base ring that agrees with the
9960
base ring of the matrix. ::
9961
9962
sage: A = matrix(QQ, 4, range(16))
9963
sage: v = vector(QQ, 4, range(4))
9964
9965
sage: A.cyclic_subspace('junk')
9966
Traceback (most recent call last):
9967
...
9968
TypeError: first input should be a vector, not junk
9969
9970
sage: A.cyclic_subspace(v, var=sin(x))
9971
Traceback (most recent call last):
9972
...
9973
TypeError: polynomial variable must be a string or polynomial ring generator, not sin(x)
9974
9975
sage: t = polygen(GF(7), 't')
9976
sage: A.cyclic_subspace(v, var=t)
9977
Traceback (most recent call last):
9978
...
9979
TypeError: polynomial generator must be over the same ring as the matrix entries
9980
9981
sage: A.cyclic_subspace(v, basis='garbage')
9982
Traceback (most recent call last):
9983
...
9984
ValueError: basis format must be 'echelon' or 'iterates', not garbage
9985
9986
sage: B = matrix(QQ, 4, 5, range(20))
9987
sage: B.cyclic_subspace(v)
9988
Traceback (most recent call last):
9989
...
9990
TypeError: matrix must be square, not 4 x 5
9991
9992
sage: C = matrix(QQ, 5, 5, range(25))
9993
sage: C.cyclic_subspace(v)
9994
Traceback (most recent call last):
9995
...
9996
TypeError: vector must have degree equal to the size of the matrix, not 4
9997
9998
sage: D = matrix(RDF, 4, 4, range(16))
9999
sage: D.cyclic_subspace(v)
10000
Traceback (most recent call last):
10001
...
10002
TypeError: matrix entries must be from an exact ring, not Real Double Field
10003
10004
sage: E = matrix(Integers(6), 4, 4, range(16))
10005
sage: E.cyclic_subspace(v)
10006
Traceback (most recent call last):
10007
...
10008
TypeError: matrix entries must be from an exact field, not Ring of integers modulo 6
10009
10010
sage: F.<a> = GF(2^4)
10011
sage: G = matrix(QQ, 4, range(16))
10012
sage: w = vector(F, 4, [1, a, a^2, a^3])
10013
sage: G.cyclic_subspace(w)
10014
Traceback (most recent call last):
10015
...
10016
TypeError: unable to make vector entries compatible with matrix entries
10017
10018
AUTHOR:
10019
10020
- Rob Beezer (2011-05-20)
10021
"""
10022
import sage.rings.polynomial.polynomial_ring
10023
n = self.ncols()
10024
R = self.base_ring()
10025
if not is_Vector(v):
10026
raise TypeError('first input should be a vector, not {0}'.format(v))
10027
if not (var is None or isinstance(var, basestring)):
10028
generator = False
10029
try:
10030
generator = var.is_gen()
10031
except AttributeError:
10032
pass
10033
if not generator:
10034
raise TypeError('polynomial variable must be a string or polynomial ring generator, not {0}'.format(var))
10035
elif var.base_ring() != R:
10036
raise TypeError('polynomial generator must be over the same ring as the matrix entries')
10037
if not basis in ['echelon', 'iterates']:
10038
raise ValueError("basis format must be 'echelon' or 'iterates', not {0}".format(basis))
10039
if not self.is_square():
10040
raise TypeError('matrix must be square, not {0} x {1}'.format(self.nrows(), self.ncols()))
10041
if v.degree() != n:
10042
raise TypeError('vector must have degree equal to the size of the matrix, not {0}'.format(v.degree()))
10043
if not (R.is_field() and R.is_exact()):
10044
try:
10045
fraction_field = R.fraction_field()
10046
except TypeError:
10047
raise TypeError('matrix entries must be from an exact field, not {0}'.format(R))
10048
if fraction_field.is_exact():
10049
return self.change_ring(R.fraction_field()).cyclic_subspace(v, var, basis)
10050
raise TypeError('matrix entries must be from an exact ring, not {0}'.format(R))
10051
try:
10052
v = v.change_ring(R)
10053
except TypeError:
10054
raise TypeError('unable to make vector entries compatible with matrix entries')
10055
10056
iterates, poly, augmented, pivots = self._cyclic_subspace(v)
10057
k = len(pivots)
10058
polynomial = not var is None
10059
if polynomial:
10060
x = sage.rings.polynomial.polynomial_ring.polygen(R, var)
10061
poly = sum([poly[i]*x**i for i in range(len(poly))])
10062
ambient = R**n
10063
if basis == 'echelon':
10064
echelon = []
10065
pivot_col_row = zip(pivots, range(k))
10066
pivot_col_row.sort()
10067
aug = augmented.submatrix(0, 0, k, n)
10068
for _, pivrow in pivot_col_row:
10069
echelon.append(aug.row(pivrow))
10070
subspace = ambient.subspace(echelon, check=False, already_echelonized=True)
10071
elif basis == 'iterates':
10072
subspace = ambient.subspace_with_basis(iterates, check=False)
10073
if polynomial:
10074
return poly, subspace
10075
else:
10076
return subspace
10077
10078
def cholesky_decomposition(self):
10079
r"""
10080
Return the Cholesky decomposition of ``self``.
10081
10082
.. WARNING::
10083
10084
``cholesky_decomposition()`` is deprecated,
10085
please use :meth:`cholesky` instead.
10086
10087
The computed decomposition is cached and returned on
10088
subsequent calls. Methods such as :meth:`solve_left` may also
10089
take advantage of the cached decomposition depending on the
10090
exact implementation.
10091
10092
INPUT:
10093
10094
The input matrix must be:
10095
10096
- real, symmetric, and positive definite; or
10097
10098
- complex, Hermitian, and positive definite.
10099
10100
If not, a ``ValueError`` exception will be raised.
10101
10102
OUTPUT:
10103
10104
An immutable lower triangular matrix `L` such that `L L^t` equals ``self``.
10105
10106
ALGORITHM:
10107
10108
Calls the method ``_cholesky_decomposition_``, which by
10109
default uses a standard recursion.
10110
10111
.. warning::
10112
10113
This implementation uses a standard recursion that is not known to
10114
be numerically stable.
10115
10116
.. warning::
10117
10118
It is potentially expensive to ensure that the input is
10119
positive definite. Therefore this is not checked and it
10120
is possible that the output matrix is *not* a valid
10121
Cholesky decomposition of ``self``. An example of this is
10122
given in the tests below.
10123
10124
EXAMPLES:
10125
10126
Here is an example over the real double field; internally, this uses SciPy::
10127
10128
sage: r = matrix(RDF, 5, 5, [ 0,0,0,0,1, 1,1,1,1,1, 16,8,4,2,1, 81,27,9,3,1, 256,64,16,4,1 ])
10129
sage: m = r * r.transpose(); m
10130
[ 1.0 1.0 1.0 1.0 1.0]
10131
[ 1.0 5.0 31.0 121.0 341.0]
10132
[ 1.0 31.0 341.0 1555.0 4681.0]
10133
[ 1.0 121.0 1555.0 7381.0 22621.0]
10134
[ 1.0 341.0 4681.0 22621.0 69905.0]
10135
sage: L = m.cholesky_decomposition(); L
10136
doctest:...: DeprecationWarning:
10137
cholesky_decomposition() is deprecated; please use cholesky() instead.
10138
See http://trac.sagemath.org/13045 for details.
10139
[ 1.0 0.0 0.0 0.0 0.0]
10140
[ 1.0 2.0 0.0 0.0 0.0]
10141
[ 1.0 15.0 10.7238052948 0.0 0.0]
10142
[ 1.0 60.0 60.9858144589 7.79297342371 0.0]
10143
[ 1.0 170.0 198.623524155 39.3665667796 1.72309958068]
10144
sage: L.parent()
10145
Full MatrixSpace of 5 by 5 dense matrices over Real Double Field
10146
sage: L*L.transpose()
10147
[ 1.0 1.0 1.0 1.0 1.0]
10148
[ 1.0 5.0 31.0 121.0 341.0]
10149
[ 1.0 31.0 341.0 1555.0 4681.0]
10150
[ 1.0 121.0 1555.0 7381.0 22621.0]
10151
[ 1.0 341.0 4681.0 22621.0 69905.0]
10152
sage: ( L*L.transpose() - m ).norm(1) < 2^-30
10153
True
10154
10155
The result is immutable::
10156
10157
sage: L[0,0] = 0
10158
Traceback (most recent call last):
10159
...
10160
ValueError: matrix is immutable; please change a copy instead (i.e., use copy(M) to change a copy of M).
10161
10162
Here is an example over a higher precision real field::
10163
10164
sage: r = matrix(RealField(100), 5, 5, [ 0,0,0,0,1, 1,1,1,1,1, 16,8,4,2,1, 81,27,9,3,1, 256,64,16,4,1 ])
10165
sage: m = r * r.transpose()
10166
sage: L = m.cholesky_decomposition()
10167
sage: L.parent()
10168
Full MatrixSpace of 5 by 5 dense matrices over Real Field with 100 bits of precision
10169
sage: ( L*L.transpose() - m ).norm(1) < 2^-50
10170
True
10171
10172
Here is a Hermitian example::
10173
10174
sage: r = matrix(CDF, 2, 2, [ 1, -2*I, 2*I, 6 ]); r
10175
[ 1.0 -2.0*I]
10176
[ 2.0*I 6.0]
10177
sage: r.eigenvalues()
10178
[0.298437881284, 6.70156211872]
10179
sage: ( r - r.conjugate().transpose() ).norm(1) < 1e-30
10180
True
10181
sage: L = r.cholesky_decomposition(); L
10182
[ 1.0 0.0]
10183
[ 2.0*I 1.41421356237]
10184
sage: ( r - L*L.conjugate().transpose() ).norm(1) < 1e-30
10185
True
10186
sage: L.parent()
10187
Full MatrixSpace of 2 by 2 dense matrices over Complex Double Field
10188
10189
TESTS:
10190
10191
The following examples are not positive definite::
10192
10193
sage: m = -identity_matrix(3).change_ring(RDF)
10194
sage: m.cholesky_decomposition()
10195
Traceback (most recent call last):
10196
...
10197
ValueError: The input matrix was not symmetric and positive definite
10198
10199
sage: m = -identity_matrix(2).change_ring(RealField(100))
10200
sage: m.cholesky_decomposition()
10201
Traceback (most recent call last):
10202
...
10203
ValueError: The input matrix was not symmetric and positive definite
10204
10205
Here is a large example over a higher precision complex field::
10206
10207
sage: r = MatrixSpace(ComplexField(100), 6, 6).random_element()
10208
sage: m = r * r.conjugate().transpose()
10209
sage: m.change_ring(CDF) # for display purposes
10210
[ 4.03491289478 1.65865229397 + 1.20395241554*I -0.275377464753 - 0.392579363912*I 0.646019176609 - 1.80427378747*I 1.15898675468 + 2.35202344518*I -1.07920143474 + 1.37815737417*I]
10211
[ 1.65865229397 - 1.20395241554*I 5.19463366777 0.192784646673 + 0.217539084881*I -1.24630239913 - 1.00510523556*I 1.65179716714 + 1.27031304403*I 1.17275462994 + 0.565615358757*I]
10212
[-0.275377464753 + 0.392579363912*I 0.192784646673 - 0.217539084881*I 2.04647180997 -0.550558880479 + 0.379933796418*I 1.00862850855 + 0.945317139306*I -0.740344951784 - 0.46578741292*I]
10213
[ 0.646019176609 + 1.80427378747*I -1.24630239913 + 1.00510523556*I -0.550558880479 - 0.379933796418*I 4.07227967662 -2.81600845862 - 0.56060176804*I -2.28695708255 - 0.360066613053*I]
10214
[ 1.15898675468 - 2.35202344518*I 1.65179716714 - 1.27031304403*I 1.00862850855 - 0.945317139306*I -2.81600845862 + 0.56060176804*I 5.26892394669 0.964830717551 + 0.111780339251*I]
10215
[ -1.07920143474 - 1.37815737417*I 1.17275462994 - 0.565615358757*I -0.740344951784 + 0.46578741292*I -2.28695708255 + 0.360066613053*I 0.964830717551 - 0.111780339251*I 3.49912480167]
10216
sage: eigs = m.change_ring(CDF).eigenvalues() # again for display purposes
10217
sage: all(abs(imag(e)) < 1.3e-15 for e in eigs)
10218
True
10219
sage: [real(e) for e in eigs]
10220
[12.1121838768, 5.17714373118, 0.183583821657, 0.798520682956, 2.03399202232, 3.81092266261]
10221
10222
sage: ( m - m.conjugate().transpose() ).norm(1) < 1e-50
10223
True
10224
sage: L = m.cholesky_decomposition(); L.change_ring(CDF)
10225
[ 2.00870926089 0.0 0.0 0.0 0.0 0.0]
10226
[ 0.825730396261 - 0.599366189511*I 2.03802923221 0.0 0.0 0.0 0.0]
10227
[ -0.137091748475 + 0.195438618996*I 0.20761467212 - 0.145606613292*I 1.38750721467 0.0 0.0 0.0]
10228
[ 0.321609099528 + 0.898225453828*I -0.477666770113 + 0.0346666053769*I -0.416429223553 - 0.094835914364*I 1.65839194165 0.0 0.0]
10229
[ 0.576980839012 - 1.17091282993*I 0.232362216253 - 0.318581071175*I 0.880672963687 - 0.692440838276*I -0.920603548686 + 0.566479149373*I 0.992988116915 0.0]
10230
[ -0.537261143636 - 0.686091014267*I 0.591339766401 + 0.158450627525*I -0.561877938537 + 0.106470627954*I -0.871217053358 + 0.176042897482*I 0.0516893015902 + 0.656402869037*I 0.902427551681]
10231
sage: ( m - L*L.conjugate().transpose() ).norm(1) < 1e-20
10232
True
10233
sage: L.parent()
10234
Full MatrixSpace of 6 by 6 dense matrices over Complex Field with 100 bits of precision
10235
sage: L[0,0] = 0
10236
Traceback (most recent call last):
10237
...
10238
ValueError: matrix is immutable; please change a copy instead (i.e., use copy(M) to change a copy of M).
10239
10240
Here is an example that returns an incorrect answer, because the input is *not* positive definite::
10241
10242
sage: r = matrix(CDF, 2, 2, [ 1, -2*I, 2*I, 0 ]); r
10243
[ 1.0 -2.0*I]
10244
[ 2.0*I 0.0]
10245
sage: r.eigenvalues()
10246
[2.56155281281, -1.56155281281]
10247
sage: ( r - r.conjugate().transpose() ).norm(1) < 1e-30
10248
True
10249
sage: L = r.cholesky_decomposition(); L
10250
[ 1.0 0.0]
10251
[2.0*I 2.0*I]
10252
sage: L*L.conjugate().transpose()
10253
[ 1.0 -2.0*I]
10254
[ 2.0*I 8.0]
10255
10256
This test verifies that the caching of the two variants
10257
of the Cholesky decomposition have been cleanly separated.
10258
It can be safely removed as part of removing this method
10259
at the end of the deprecation period.
10260
(From :trac:`13045`.) ::
10261
10262
sage: r = matrix(CDF, 2, 2, [ 0, -2*I, 2*I, 0 ]); r
10263
[ 0.0 -2.0*I]
10264
[ 2.0*I 0.0]
10265
sage: r.cholesky_decomposition()
10266
[ 0.0 0.0]
10267
[NaN + NaN*I NaN + NaN*I]
10268
sage: r.cholesky()
10269
Traceback (most recent call last):
10270
...
10271
ValueError: matrix is not positive definite
10272
sage: r[0,0] = 0 # clears cache
10273
sage: r.cholesky()
10274
Traceback (most recent call last):
10275
...
10276
ValueError: matrix is not positive definite
10277
sage: r.cholesky_decomposition()
10278
[ 0.0 0.0]
10279
[NaN + NaN*I NaN + NaN*I]
10280
"""
10281
from sage.misc.superseded import deprecation
10282
deprecation(13045, "cholesky_decomposition() is deprecated; please use cholesky() instead.")
10283
assert self._nrows == self._ncols, "Can only Cholesky decompose square matrices"
10284
if self._nrows == 0:
10285
return self.__copy__()
10286
return self._cholesky_decomposition_()
10287
10288
def _cholesky_decomposition_(self):
10289
r"""
10290
Return the Cholesky decomposition of ``self``; see ``cholesky_decomposition``.
10291
10292
This generic implementation uses a standard recursion.
10293
"""
10294
L = self.fetch('cholesky_broken')
10295
if L is None:
10296
A = self.__copy__()
10297
L = A.parent()(0)
10298
n = self.nrows()
10299
for k in range(0, n-1 + 1):
10300
try:
10301
L[k, k] = A[k, k].sqrt()
10302
except TypeError:
10303
raise ValueError, "The input matrix was not symmetric and positive definite"
10304
10305
for s in range(k+1, n):
10306
L[s, k] = A[s, k] / L[k, k]
10307
for j in range(k+1, n):
10308
for i in range(j, n):
10309
A[i, j] -= L[i, k]*L[j, k].conjugate()
10310
L.set_immutable()
10311
self.cache('cholesky_broken', L)
10312
return L
10313
10314
def cholesky(self):
10315
r"""
10316
Returns the Cholesky decomposition of a symmetric or Hermitian matrix.
10317
10318
INPUT:
10319
10320
A square matrix that is real, symmetric and positive definite.
10321
Or a square matrix that is complex, Hermitian and positive
10322
definite. Generally, the base ring for the entries of the
10323
matrix needs to be a subfield of the algebraic numbers
10324
(``QQbar``). Examples include the rational numbers (``QQ``),
10325
some number fields, and real algebraic numbers and the
10326
algebraic numbers themselves.
10327
10328
OUTPUT:
10329
10330
For a matrix `A` the routine returns a lower triangular
10331
matrix `L` such that,
10332
10333
.. math::
10334
10335
A = LL^\ast
10336
10337
where `L^\ast` is the conjugate-transpose in the complex case,
10338
and just the transpose in the real case. If the matrix
10339
fails to be positive definite (perhaps because it is not
10340
symmetric or Hermitian), then a ``ValueError`` results.
10341
10342
ALGORITHM:
10343
10344
Whether or not the matrix is positive definite is checked
10345
first in every case. This is accomplished with an
10346
indefinite factorization (see :meth:`indefinite_factorization`)
10347
which caches its result. This algorithm is of an order `n^3/3`.
10348
If the matrix is positive definite, this computation always
10349
succeeds, using just field operations. The transistion to a
10350
Cholesky decomposition "only" requires computing square roots
10351
of the positive (real) entries of the diagonal matrix produced in
10352
the indefinite factorization. Hence, there is no real penalty
10353
in the positive definite check (here, or prior to calling this
10354
routine), but a field extension with square roots may not be
10355
implemented in all reasonable cases.
10356
10357
EXAMPLES:
10358
10359
This simple example has a result with entries that remain
10360
in the field of rational numbers. ::
10361
10362
sage: A = matrix(QQ, [[ 4, -2, 4, 2],
10363
... [-2, 10, -2, -7],
10364
... [ 4, -2, 8, 4],
10365
... [ 2, -7, 4, 7]])
10366
sage: A.is_symmetric()
10367
True
10368
sage: L = A.cholesky()
10369
sage: L
10370
[ 2 0 0 0]
10371
[-1 3 0 0]
10372
[ 2 0 2 0]
10373
[ 1 -2 1 1]
10374
sage: L.parent()
10375
Full MatrixSpace of 4 by 4 dense matrices over Rational Field
10376
sage: L*L.transpose() == A
10377
True
10378
10379
This seemingly simple example requires first moving to
10380
the rational numbers for field operations, and then square
10381
roots necessitate that the result has entries in the field
10382
of algebraic numbers. ::
10383
10384
sage: A = matrix(ZZ, [[ 78, -30, -37, -2],
10385
... [-30, 102, 179, -18],
10386
... [-37, 179, 326, -38],
10387
... [ -2, -18, -38, 15]])
10388
sage: A.is_symmetric()
10389
True
10390
sage: L = A.cholesky()
10391
sage: L
10392
[ 8.83176086632785? 0 0 0]
10393
[ -3.396831102433787? 9.51112708681461? 0 0]
10394
[ -4.189425026335004? 17.32383862241232? 2.886751345948129? 0]
10395
[-0.2264554068289192? -1.973397116652010? -1.649572197684645? 2.886751345948129?]
10396
sage: L.parent()
10397
Full MatrixSpace of 4 by 4 dense matrices over Algebraic Field
10398
sage: L*L.transpose() == A
10399
True
10400
10401
Some subfields of the complex numbers, such as this number
10402
field of complex numbers with rational real and imaginary parts,
10403
allow for this computation. ::
10404
10405
sage: C.<I> = QuadraticField(-1)
10406
sage: A = matrix(C, [[ 23, 17*I + 3, 24*I + 25, 21*I],
10407
... [ -17*I + 3, 38, -69*I + 89, 7*I + 15],
10408
... [-24*I + 25, 69*I + 89, 976, 24*I + 6],
10409
... [ -21*I, -7*I + 15, -24*I + 6, 28]])
10410
sage: A.is_hermitian()
10411
True
10412
sage: L = A.cholesky()
10413
sage: L
10414
[ 4.79...? 0 0 0]
10415
[ 0.62...? - 3.54...?*I 5.00...? 0 0]
10416
[ 5.21...? - 5.00...?*I 13.58...? + 10.72...?*I 24.98...? 0]
10417
[ -4.37...?*I -0.10...? - 0.85...?*I -0.21...? + 0.37...?*I 2.81...?]
10418
sage: L.parent()
10419
Full MatrixSpace of 4 by 4 dense matrices over Algebraic Field
10420
sage: (L*L.conjugate_transpose() - A.change_ring(QQbar)).norm() < 10^-10
10421
True
10422
10423
The field of algebraic numbers is an ideal setting for this
10424
computation. ::
10425
10426
sage: A = matrix(QQbar, [[ 2, 4 + 2*I, 6 - 4*I],
10427
... [ -2*I + 4, 11, 10 - 12*I],
10428
... [ 4*I + 6, 10 + 12*I, 37]])
10429
sage: A.is_hermitian()
10430
True
10431
sage: L = A.cholesky()
10432
sage: L
10433
[ 1.414213562373095? 0 0]
10434
[2.828427124746190? - 1.414213562373095?*I 1 0]
10435
[4.242640687119285? + 2.828427124746190?*I -2*I + 2 1.732050807568878?]
10436
sage: L.parent()
10437
Full MatrixSpace of 3 by 3 dense matrices over Algebraic Field
10438
sage: (L*L.conjugate_transpose() - A.change_ring(QQbar)).norm() < 10^-10
10439
True
10440
10441
10442
Results are cached, hence immutable. Use the ``copy`` function
10443
if you need to make a change. ::
10444
10445
sage: A = matrix(QQ, [[ 4, -2, 4, 2],
10446
... [-2, 10, -2, -7],
10447
... [ 4, -2, 8, 4],
10448
... [ 2, -7, 4, 7]])
10449
sage: L = A.cholesky()
10450
sage: L.is_immutable()
10451
True
10452
10453
sage: from copy import copy
10454
sage: LC = copy(L)
10455
sage: LC[0,0] = 1000
10456
sage: LC
10457
[1000 0 0 0]
10458
[ -1 3 0 0]
10459
[ 2 0 2 0]
10460
[ 1 -2 1 1]
10461
10462
There are a variety of situations which will prevent the computation of a Cholesky decomposition.
10463
10464
The base ring must be exact. For numerical work, create a
10465
matrix with a base ring of ``RDF`` or ``CDF`` and use the
10466
:meth:`~sage.matrix.matrix_double_dense.Matrix_double_dense.cholesky`
10467
method for matrices of that type. ::
10468
10469
sage: F = RealField(100)
10470
sage: A = matrix(F, [[1.0, 3.0], [3.0, -6.0]])
10471
sage: A.cholesky()
10472
Traceback (most recent call last):
10473
...
10474
TypeError: base ring of the matrix must be exact, not Real Field with 100 bits of precision
10475
10476
The base ring may not have a fraction field. ::
10477
10478
sage: A = matrix(Integers(6), [[2, 0], [0, 4]])
10479
sage: A.cholesky()
10480
Traceback (most recent call last):
10481
...
10482
ValueError: unable to check positive definiteness because
10483
Unable to create the fraction field of Ring of integers modulo 6
10484
10485
The base field may not have elements that are comparable to zero. ::
10486
10487
sage: F.<a> = FiniteField(5^4)
10488
sage: A = matrix(F, [[2+a^3, 3], [3, 3]])
10489
sage: A.cholesky()
10490
Traceback (most recent call last):
10491
...
10492
ValueError: unable to check positive definiteness because
10493
cannot convert computations from Finite Field in a of size 5^4 into real numbers
10494
10495
The algebraic closure of the fraction field of the base ring may not be implemented. ::
10496
10497
sage: F = Integers(7)
10498
sage: A = matrix(F, [[4, 0], [0, 3]])
10499
sage: A.cholesky()
10500
Traceback (most recent call last):
10501
...
10502
TypeError: base field needs an algebraic closure with square roots,
10503
not Ring of integers modulo 7
10504
10505
The matrix may not be positive definite. ::
10506
10507
sage: C.<I> = QuadraticField(-1)
10508
sage: B = matrix(C, [[ 2, 4 - 2*I, 2 + 2*I],
10509
... [4 + 2*I, 8, 10*I],
10510
... [2 - 2*I, -10*I, -3]])
10511
sage: B.is_positive_definite()
10512
False
10513
sage: B.cholesky()
10514
Traceback (most recent call last):
10515
...
10516
ValueError: matrix is not positive definite,
10517
so cannot compute Cholesky decomposition
10518
10519
The matrix could be positive semi-definite, and thus
10520
lack a Cholesky decomposition. ::
10521
10522
sage: A = matrix(QQ, [[21, 15, 12, -3],
10523
... [15, 12, 9, 12],
10524
... [12, 9, 7, 3],
10525
... [-3, 12, 3, 8]])
10526
sage: A.is_positive_definite()
10527
False
10528
sage: [A[:i,:i].determinant() for i in range(1,A.nrows()+1)]
10529
[21, 27, 0, 0]
10530
sage: A.cholesky()
10531
Traceback (most recent call last):
10532
...
10533
ValueError: matrix is not positive definite,
10534
so cannot compute Cholesky decomposition
10535
10536
Even in light of the above, you can sometimes get lucky
10537
and arrive at a situation where a particular matrix has
10538
a Cholesky decomposition when the general characteristics
10539
of the matrix suggest this routine would fail. In this
10540
example, the indefinite factorization produces a
10541
diagonal matrix whose elements from the finite field
10542
convert naturally to positive integers and are also
10543
perfect squares. ::
10544
10545
sage: F.<a> = FiniteField(5^3)
10546
sage: A = matrix(F, [[ 4, 2*a^2 + 3, 4*a + 1],
10547
... [ 2*a^2 + 3, 2*a + 2, 4*a^2 + 4*a + 4],
10548
... [ 4*a + 1, 4*a^2 + 4*a + 4, a^2 + 4*a]])
10549
sage: A.is_symmetric()
10550
True
10551
sage: L = A.cholesky()
10552
sage: L*L.transpose() == A
10553
True
10554
10555
TESTS:
10556
10557
This verifies that :trac:`11274` is resolved. ::
10558
10559
sage: E = matrix(QQ, [[2, 1], [1, 1]])
10560
sage: E.is_symmetric()
10561
True
10562
sage: E.eigenvalues()
10563
[0.38...?, 2.61...?]
10564
sage: E.det()
10565
1
10566
sage: E.cholesky()
10567
[ 1.414213562373095? 0]
10568
[0.7071067811865475? 0.7071067811865475?]
10569
10570
AUTHOR:
10571
10572
- Rob Beezer (2012-05-27)
10573
"""
10574
from copy import copy
10575
C = self.fetch('cholesky')
10576
if C is None:
10577
if not self.is_square():
10578
msg = "matrix must be square, not {0} x {1}"
10579
raise ValueError(msg.format(self.nrows(), self.ncols()))
10580
if not self.base_ring().is_exact():
10581
msg = 'base ring of the matrix must be exact, not {0}'
10582
raise TypeError(msg.format(self.base_ring()))
10583
try:
10584
posdef = self.is_positive_definite()
10585
except (ValueError, TypeError) as e:
10586
msg = "unable to check positive definiteness because {0}"
10587
raise ValueError(msg.format(e))
10588
if not posdef:
10589
msg = "matrix is not positive definite, so cannot compute Cholesky decomposition"
10590
raise ValueError(msg)
10591
# the successful positive definite check will cache a Hermitian
10592
# or symmetric indefinite factorization, as appropriate
10593
factors = self.fetch('indefinite_factorization_hermitian')
10594
if factors is None:
10595
factors = self.fetch('indefinite_factorization_symmetric')
10596
L = factors[0]
10597
d = factors[1]
10598
F = L.base_ring() # field really
10599
splits = [] # square roots of diagonal entries
10600
for x in d:
10601
try:
10602
sqrt = F(x.sqrt())
10603
except (TypeError, ValueError):
10604
try:
10605
F = F.algebraic_closure()
10606
except (NotImplementedError, AttributeError):
10607
msg = "base field needs an algebraic closure with square roots, not {0}"
10608
raise TypeError(msg.format(F))
10609
# try again
10610
sqrt = F(x.sqrt())
10611
splits.append(sqrt)
10612
# move square root of the diagonal matrix
10613
# into the lower triangular matrix
10614
# We need a copy, to break immutability
10615
# and the field may have changed as well
10616
C = copy(L)
10617
if F != C.base_ring():
10618
C = C.change_ring(F)
10619
for c in range(C.ncols()):
10620
C.rescale_col(c, splits[c])
10621
C.set_immutable()
10622
self.cache('cholesky', C)
10623
return C
10624
10625
def LU(self, pivot=None, format='plu'):
10626
r"""
10627
Finds a decomposition into a lower-triangular matrix and
10628
an upper-triangular matrix.
10629
10630
INPUT:
10631
10632
- ``pivot`` - pivoting strategy
10633
10634
- 'auto' (default) - see if the matrix entries are
10635
ordered (i.e. if they have an absolute value method),
10636
and if so, use a the partial pivoting strategy.
10637
Otherwise, fall back to the nonzero strategy. This
10638
is the best choice for general routines that may
10639
call this for matrix entries of a variety of types.
10640
10641
- 'partial' - each column is examined for
10642
the element with the largest absolute value and the
10643
row containing this element is swapped into place.
10644
10645
- 'nonzero' - the first nonzero element in a column
10646
is located and the row with this element is used.
10647
10648
- ``format`` - contents of output, see more discussion
10649
below about output.
10650
10651
- 'plu' (default) - a triple; matrices P, L and U
10652
such that A = P*L*U.
10653
10654
- 'compact' - a pair; row permutation as a tuple, and the
10655
matrices L and U combined into one matrix.
10656
10657
OUTPUT:
10658
10659
Suppose that `A` is an `m\times n` matrix, then an LU
10660
decomposition is a lower-triangular `m\times m` matrix
10661
`L` with every diagonal element equal to 1, and an
10662
upper-triangular `m\times n` matrix, `U` such that the
10663
product `LU`, after a permutation of the rows, is then
10664
equal to `A`. For the 'plu' format the permutation is
10665
returned as an `m\times m` permutation matrix `P` such
10666
that
10667
10668
.. math::
10669
10670
A = PLU
10671
10672
It is more common to place the permutation matrix just
10673
to the left of `A`. If you desire this version, then
10674
use the inverse of `P` which is computed most efficiently
10675
as its transpose.
10676
10677
If the 'partial' pivoting strategy is used, then the
10678
non-diagonal entries of `L` will be less than or equal
10679
to 1 in absolute value. The 'nonzero' pivot strategy may
10680
be faster, but the growth of data structures for elements of
10681
the decomposition might counteract the advantage.
10682
10683
By necessity, returned matrices have a base ring equal
10684
to the fraction field of the base ring of the original matrix.
10685
10686
In the 'compact' format, the first returned value is a
10687
tuple that is a permutation of the rows of `LU` that yields
10688
`A`. See the doctest for how you might employ this
10689
permutation. Then the matrices `L` and `U` are merged
10690
into one matrix -- remove the diagonal of ones in `L`
10691
and the remaining nonzero entries can replace the
10692
entries of `U` beneath the diagonal.
10693
10694
The results are cached, only in the compact format, separately
10695
for each pivot strategy called. Repeated requests for the
10696
'plu' format will require just a small amount of overhead
10697
in each call to bust out the compact format to the three
10698
matrices. Since only the compact format is cached, the
10699
components of the compact format are immutable, while the
10700
components of the 'plu' format are regenerated, and hence
10701
are mutable.
10702
10703
Notice that while `U` is similar to row-echelon form and the
10704
rows of `U` span the row space of `A`, the rows of `U` are not
10705
generally linearly independent. Nor are the pivot columns
10706
(or rank) immediately obvious. However for rings without
10707
specialized echelon form routines, this method is about
10708
twice as fast as the generic echelon form routine since
10709
it only acts "below the diagonal", as would be predicted
10710
from a theoretical analysis of the algorithms.
10711
10712
.. note::
10713
10714
This is an exact computation, so limited to exact
10715
rings. If you need numerical results, convert the
10716
base ring to the field of real double numbers,
10717
``RDF`` or the field of complex double numbers,
10718
``CDF``, which will use a faster routine that
10719
is careful about numerical subtleties.
10720
10721
ALGORITHM:
10722
10723
"Gaussian Elimination with Partial Pivoting,"
10724
Algorithm 21.1 of [TREFETHEN-BAU]_.
10725
10726
EXAMPLES:
10727
10728
Notice the difference in the `L` matrix as a result of different
10729
pivoting strategies. With partial pivoting, every entry of `L`
10730
has absolute value 1 or less. ::
10731
10732
sage: A = matrix(QQ, [[1, -1, 0, 2, 4, 7, -1],
10733
... [2, -1, 0, 6, 4, 8, -2],
10734
... [2, 0, 1, 4, 2, 6, 0],
10735
... [1, 0, -1, 8, -1, -1, -3],
10736
... [1, 1, 2, -2, -1, 1, 3]])
10737
sage: P, L, U = A.LU(pivot='partial')
10738
sage: P
10739
[0 0 0 0 1]
10740
[1 0 0 0 0]
10741
[0 0 0 1 0]
10742
[0 0 1 0 0]
10743
[0 1 0 0 0]
10744
sage: L
10745
[ 1 0 0 0 0]
10746
[ 1/2 1 0 0 0]
10747
[ 1/2 1/3 1 0 0]
10748
[ 1 2/3 1/5 1 0]
10749
[ 1/2 -1/3 -2/5 0 1]
10750
sage: U
10751
[ 2 -1 0 6 4 8 -2]
10752
[ 0 3/2 2 -5 -3 -3 4]
10753
[ 0 0 -5/3 20/3 -2 -4 -10/3]
10754
[ 0 0 0 0 2/5 4/5 0]
10755
[ 0 0 0 0 1/5 2/5 0]
10756
sage: A == P*L*U
10757
True
10758
sage: P, L, U = A.LU(pivot='nonzero')
10759
sage: P
10760
[1 0 0 0 0]
10761
[0 1 0 0 0]
10762
[0 0 1 0 0]
10763
[0 0 0 1 0]
10764
[0 0 0 0 1]
10765
sage: L
10766
[ 1 0 0 0 0]
10767
[ 2 1 0 0 0]
10768
[ 2 2 1 0 0]
10769
[ 1 1 -1 1 0]
10770
[ 1 2 2 0 1]
10771
sage: U
10772
[ 1 -1 0 2 4 7 -1]
10773
[ 0 1 0 2 -4 -6 0]
10774
[ 0 0 1 -4 2 4 2]
10775
[ 0 0 0 0 1 2 0]
10776
[ 0 0 0 0 -1 -2 0]
10777
sage: A == P*L*U
10778
True
10779
10780
An example of the compact format. ::
10781
10782
sage: B = matrix(QQ, [[ 1, 3, 5, 5],
10783
... [ 1, 4, 7, 8],
10784
... [-1, -4, -6, -6],
10785
... [ 0, -2, -5, -8],
10786
... [-2, -6, -6, -2]])
10787
sage: perm, M = B.LU(format='compact')
10788
sage: perm
10789
(4, 3, 0, 1, 2)
10790
sage: M
10791
[ -2 -6 -6 -2]
10792
[ 0 -2 -5 -8]
10793
[-1/2 0 2 4]
10794
[-1/2 -1/2 3/4 0]
10795
[ 1/2 1/2 -1/4 0]
10796
10797
We can easily illustrate the relationships between
10798
the two formats with a square matrix. ::
10799
10800
sage: C = matrix(QQ, [[-2, 3, -2, -5],
10801
... [ 1, -2, 1, 3],
10802
... [-4, 7, -3, -8],
10803
... [-3, 8, -1, -5]])
10804
sage: P, L, U = C.LU(format='plu')
10805
sage: perm, M = C.LU(format='compact')
10806
sage: (L - identity_matrix(4)) + U == M
10807
True
10808
sage: p = [perm[i]+1 for i in range(len(perm))]
10809
sage: PP = Permutation(p).to_matrix()
10810
sage: PP == P
10811
True
10812
10813
For a nonsingular matrix, and the 'nonzero' pivot
10814
strategy there is no need to permute rows, so the
10815
permutation matrix will be the identity. Furthermore,
10816
it can be shown that then the `L` and `U` matrices
10817
are uniquely determined by requiring `L` to have ones
10818
on the diagonal. ::
10819
10820
sage: D = matrix(QQ, [[ 1, 0, 2, 0, -2, -1],
10821
... [ 3, -2, 3, -1, 0, 6],
10822
... [-4, 2, -3, 1, -1, -8],
10823
... [-2, 2, -3, 2, 1, 0],
10824
... [ 0, -1, -1, 0, 2, 5],
10825
... [-1, 2, -4, -1, 5, -3]])
10826
sage: P, L, U = D.LU(pivot='nonzero')
10827
sage: P
10828
[1 0 0 0 0 0]
10829
[0 1 0 0 0 0]
10830
[0 0 1 0 0 0]
10831
[0 0 0 1 0 0]
10832
[0 0 0 0 1 0]
10833
[0 0 0 0 0 1]
10834
sage: L
10835
[ 1 0 0 0 0 0]
10836
[ 3 1 0 0 0 0]
10837
[ -4 -1 1 0 0 0]
10838
[ -2 -1 -1 1 0 0]
10839
[ 0 1/2 1/4 1/2 1 0]
10840
[ -1 -1 -5/2 -2 -6 1]
10841
sage: U
10842
[ 1 0 2 0 -2 -1]
10843
[ 0 -2 -3 -1 6 9]
10844
[ 0 0 2 0 -3 -3]
10845
[ 0 0 0 1 0 4]
10846
[ 0 0 0 0 -1/4 -3/4]
10847
[ 0 0 0 0 0 1]
10848
sage: D == L*U
10849
True
10850
10851
The base ring of the matrix may be any field, or a ring
10852
which has a fraction field implemented in Sage. The ring
10853
needs to be exact (there is a numerical LU decomposition
10854
for matrices over ``RDF`` and ``CDF``). Matrices returned
10855
are over the original field, or the fraction field of the
10856
ring. If the field is not ordered (i.e. the absolute value
10857
function is not implemented), then the pivot strategy needs
10858
to be 'nonzero'. ::
10859
10860
sage: A = matrix(RealField(100), 3, 3, range(9))
10861
sage: P, L, U = A.LU()
10862
Traceback (most recent call last):
10863
...
10864
TypeError: base ring of the matrix must be exact, not Real Field with 100 bits of precision
10865
10866
sage: A = matrix(Integers(6), 3, 2, range(6))
10867
sage: A.LU()
10868
Traceback (most recent call last):
10869
...
10870
TypeError: base ring of the matrix needs a field of fractions, not Ring of integers modulo 6
10871
10872
sage: R.<y> = PolynomialRing(QQ, 'y')
10873
sage: B = matrix(R, [[y+1, y^2+y], [y^2, y^3]])
10874
sage: P, L, U = B.LU(pivot='partial')
10875
Traceback (most recent call last):
10876
...
10877
TypeError: cannot take absolute value of matrix entries, try 'pivot=nonzero'
10878
sage: P, L, U = B.LU(pivot='nonzero')
10879
sage: P
10880
[1 0]
10881
[0 1]
10882
sage: L
10883
[ 1 0]
10884
[y^2/(y + 1) 1]
10885
sage: U
10886
[ y + 1 y^2 + y]
10887
[ 0 0]
10888
sage: L.base_ring()
10889
Fraction Field of Univariate Polynomial Ring in y over Rational Field
10890
sage: B == P*L*U
10891
True
10892
10893
sage: F.<a> = FiniteField(5^2)
10894
sage: C = matrix(F, [[a + 3, 4*a + 4, 2, 4*a + 2],
10895
... [3, 2*a + 4, 2*a + 4, 2*a + 1],
10896
... [3*a + 1, a + 3, 2*a + 4, 4*a + 3],
10897
... [a, 3, 3*a + 1, a]])
10898
sage: P, L, U = C.LU(pivot='nonzero')
10899
sage: P
10900
[1 0 0 0]
10901
[0 1 0 0]
10902
[0 0 1 0]
10903
[0 0 0 1]
10904
sage: L
10905
[ 1 0 0 0]
10906
[3*a + 3 1 0 0]
10907
[ 2*a 4*a + 2 1 0]
10908
[2*a + 3 2 2*a + 4 1]
10909
sage: U
10910
[ a + 3 4*a + 4 2 4*a + 2]
10911
[ 0 a + 1 a + 3 2*a + 4]
10912
[ 0 0 1 4*a + 2]
10913
[ 0 0 0 0]
10914
sage: L.base_ring()
10915
Finite Field in a of size 5^2
10916
sage: C == P*L*U
10917
True
10918
10919
With no pivoting strategy given (i.e. ``pivot=None``)
10920
the routine will try to use partial pivoting, but then
10921
fall back to the nonzero strategy. For the nonsingular
10922
matrix below, we see evidence of pivoting when viewed
10923
over the rationals, and no pivoting over the integers
10924
mod 29. ::
10925
10926
sage: entries = [3, 20, 11, 7, 16, 28, 5, 15, 21, 23, 22, 18, 8, 23, 15, 2]
10927
sage: A = matrix(Integers(29), 4, 4, entries)
10928
sage: perm, _ = A.LU(format='compact'); perm
10929
(0, 1, 2, 3)
10930
sage: B = matrix(QQ, 4, 4, entries)
10931
sage: perm, _ = B.LU(format='compact'); perm
10932
(2, 0, 1, 3)
10933
10934
The `U` matrix is only guaranteed to be upper-triangular.
10935
The rows are not necessarily linearly independent, nor are
10936
the pivots columns or rank in evidence. ::
10937
10938
sage: A = matrix(QQ, [[ 1, -4, 1, 0, -2, 1, 3, 3, 2],
10939
... [-1, 4, 0, -4, 0, -4, 5, -7, -7],
10940
... [ 0, 0, 1, -4, -1, -3, 6, -5, -6],
10941
... [-2, 8, -1, -4, 2, -4, 1, -8, -7],
10942
... [ 1, -4, 2, -4, -3, 2, 5, 6, 4]])
10943
sage: P, L, U = A.LU()
10944
sage: U
10945
[ -2 8 -1 -4 2 -4 1 -8 -7]
10946
[ 0 0 1/2 -2 -1 -2 9/2 -3 -7/2]
10947
[ 0 0 3/2 -6 -2 0 11/2 2 1/2]
10948
[ 0 0 0 0 -1/3 -1 5/3 -5/3 -5/3]
10949
[ 0 0 0 0 1/3 -3 7/3 -19/3 -19/3]
10950
sage: A.rref()
10951
[ 1 -4 0 4 0 0 -1 -1 -1]
10952
[ 0 0 1 -4 0 0 1 0 -1]
10953
[ 0 0 0 0 1 0 -2 -1 -1]
10954
[ 0 0 0 0 0 1 -1 2 2]
10955
[ 0 0 0 0 0 0 0 0 0]
10956
sage: A.pivots()
10957
(0, 2, 4, 5)
10958
10959
TESTS:
10960
10961
Unknown keywords are caught. ::
10962
10963
sage: A = matrix(ZZ, 2, range(4))
10964
sage: A.LU(pivot='junk')
10965
Traceback (most recent call last):
10966
...
10967
ValueError: pivot strategy must be None, 'partial' or 'nonzero', not junk
10968
sage: A.LU(format='garbage')
10969
Traceback (most recent call last):
10970
...
10971
ValueError: format must be 'plu' or 'compact', not garbage
10972
10973
Components of the 'compact' format are immutable, while
10974
components of the 'plu' format are not. ::
10975
10976
sage: A = matrix(ZZ, 2, range(4))
10977
sage: perm, M = A.LU(format='compact')
10978
sage: perm[0] = 25
10979
Traceback (most recent call last):
10980
...
10981
TypeError: 'tuple' object does not support item assignment
10982
sage: M.is_immutable()
10983
True
10984
sage: P, L, U = A.LU(format='plu')
10985
sage: all([A.is_mutable() for A in [P, L, U]])
10986
True
10987
10988
Partial pivoting is based on the absolute values of entries
10989
of a column. Trac #12208 shows that the return value of the
10990
absolute value must be handled carefully. This tests that
10991
situation in the case of cylotomic fields. ::
10992
10993
sage: C = SymmetricGroup(5).character_table()
10994
sage: C.base_ring()
10995
Cyclotomic Field of order 1 and degree 1
10996
sage: P, L, U = C.LU(pivot='partial')
10997
sage: C == P*L*U
10998
True
10999
11000
AUTHOR:
11001
11002
- Rob Beezer (2011-04-26)
11003
"""
11004
if not pivot in [None, 'partial', 'nonzero']:
11005
msg = "pivot strategy must be None, 'partial' or 'nonzero', not {0}"
11006
raise ValueError(msg.format(pivot))
11007
if not format in ['compact', 'plu']:
11008
msg = "format must be 'plu' or 'compact', not {0}"
11009
raise ValueError(msg.format(format))
11010
11011
# exact rings only, must have fraction field
11012
R = self.base_ring()
11013
if not R.is_exact():
11014
msg = 'base ring of the matrix must be exact, not {0}'
11015
raise TypeError(msg.format(R))
11016
if not R.is_field():
11017
try:
11018
F = R.fraction_field()
11019
except Exception:
11020
msg = 'base ring of the matrix needs a field of fractions, not {0}'
11021
raise TypeError(msg.format(R))
11022
else:
11023
F = R
11024
11025
# 'nonzero' strategy passes through untouched
11026
# 'partial' survives iff field has absolute value
11027
# None will use 'partial' iff possible, else fallback to nonzero
11028
if pivot in [None, 'partial']:
11029
try:
11030
abs(F.an_element())
11031
pivot = 'partial'
11032
except Exception:
11033
if pivot == 'partial':
11034
msg = "cannot take absolute value of matrix entries, try 'pivot=nonzero'"
11035
raise TypeError(msg)
11036
pivot = 'nonzero'
11037
partial = (pivot == 'partial')
11038
11039
cdef Py_ssize_t m, n, d, i, j, k, p, max_location
11040
cdef Matrix M
11041
11042
# can now access cache, else compute
11043
# the compact version of LU decomposition
11044
key = 'LU_' + pivot
11045
compact = self.fetch(key)
11046
if compact is None:
11047
if F == R:
11048
M = self.__copy__()
11049
else:
11050
M = self.change_ring(F)
11051
m, n = M._nrows, M._ncols
11052
d = min(m, n)
11053
perm = range(m)
11054
zero = F(0)
11055
for k in range(d):
11056
max_location = -1
11057
if partial:
11058
# abs() necessary to convert zero to the
11059
# correct type for comparisons (Trac #12208)
11060
max_entry = abs(zero)
11061
for i in range(k,m):
11062
entry = abs(M.get_unsafe(i,k))
11063
if entry > max_entry:
11064
max_location = i
11065
max_entry = entry
11066
else:
11067
for i in range(k,m):
11068
if M.get_unsafe(i,k) != zero:
11069
max_location = i
11070
break
11071
if max_location != -1:
11072
perm[k], perm[max_location] = perm[max_location], perm[k]
11073
M.swap_rows(k, max_location)
11074
for j in range(k+1, m):
11075
scale = -M.get_unsafe(j,k)/M.get_unsafe(k,k)
11076
M.set_unsafe(j,k, -scale)
11077
for p in range(k+1,n):
11078
M.set_unsafe(j,p, M.get_unsafe(j,p) + scale*M.get_unsafe(k,p))
11079
perm = tuple(perm)
11080
M.set_immutable()
11081
compact = (perm, M)
11082
self.cache(key, compact)
11083
11084
if format == 'compact':
11085
return compact
11086
elif format == 'plu':
11087
import sage.matrix.constructor
11088
import sage.combinat.permutation
11089
perm = compact[0]
11090
M = compact[1].__copy__()
11091
F = M.base_ring()
11092
m, n = M._nrows, M._ncols
11093
d = min(m, n)
11094
zero = F(0)
11095
perm = [perm[i]+1 for i in range(m)]
11096
P = sage.combinat.permutation.Permutation(perm).to_matrix()
11097
L = sage.matrix.constructor.identity_matrix(F, m)
11098
for i in range(1, m):
11099
for k in range(min(i,d)):
11100
L[i,k] = M[i,k]
11101
M[i,k] = zero
11102
return P, L, M
11103
11104
def _indefinite_factorization(self, algorithm, check=True):
11105
r"""
11106
Utility function to decomposes a symmetric or
11107
Hermitian matrix into a lower triangular matrix
11108
and tuple of elements for the diagonal of a diagonal matrix.
11109
11110
INPUT:
11111
11112
- ``self`` - a matrix that is symmetric or Hermitian,
11113
over a ring that has a fraction field implemented.
11114
11115
- ``algorithm`` - ``'symmetric'`` or ``'hermitian'``,
11116
according to the corresponding property of the matrix.
11117
11118
- ``check`` - default: ``True`` - if ``True`` then
11119
performs the check that the matrix is consistent with the
11120
``algorithm`` keyword.
11121
11122
OUTPUT:
11123
11124
Given a square matrix ``A``, the routine returns a
11125
pair: a matrix ``L`` and a list ``d``.
11126
11127
``L`` is a unit lower-triangular matrix. ``d`` is
11128
the entries of a diagonal matrix. Suppose this diagonal
11129
matrix is ``D``. Then, for a symmetric matrix, these items
11130
are related as:
11131
11132
.. math::
11133
11134
A = LDL^T
11135
11136
For a Hermitian matrix, the transpose can be replaced by
11137
the conjugate-transpose.
11138
11139
If any leading principal submatrix is singular, then the
11140
computation cannot be performed and a ``ValueError`` results.
11141
11142
Results are cached, and hence are immutable. Caching
11143
eliminates redundant computations across
11144
:meth:`indefinite_factorization_`, :meth:`is_positive_definite`
11145
and :meth:`cholesky_decomposition`.
11146
11147
EXAMPLES:
11148
11149
A simple symmetric matrix. ::
11150
11151
sage: A = matrix(QQ, [[ 4, -2, 4, 2],
11152
... [-2, 10, -2, -7],
11153
... [ 4, -2, 8, 4],
11154
... [ 2, -7, 4, 7]])
11155
sage: A.is_symmetric()
11156
True
11157
sage: L, d = A._indefinite_factorization('symmetric')
11158
sage: L
11159
[ 1 0 0 0]
11160
[-1/2 1 0 0]
11161
[ 1 0 1 0]
11162
[ 1/2 -2/3 1/2 1]
11163
sage: d
11164
(4, 9, 4, 1)
11165
sage: A == L*diagonal_matrix(QQ, d)*L.transpose()
11166
True
11167
11168
A Hermitian matrix. ::
11169
11170
sage: x = var('x')
11171
sage: C.<I> = NumberField(x^2 + 1)
11172
sage: A = matrix(C, [[ 23, 17*I + 3, 24*I + 25, 21*I],
11173
... [ -17*I + 3, 38, -69*I + 89, 7*I + 15],
11174
... [-24*I + 25, 69*I + 89, 976, 24*I + 6],
11175
... [ -21*I, -7*I + 15, -24*I + 6, 28]])
11176
sage: A.is_hermitian()
11177
True
11178
sage: L, d = A._indefinite_factorization('hermitian')
11179
sage: L
11180
[ 1 0 0 0]
11181
[ -17/23*I + 3/23 1 0 0]
11182
[ -24/23*I + 25/23 617/288*I + 391/144 1 0]
11183
[ -21/23*I -49/288*I - 1/48 1336/89885*I - 773/89885 1]
11184
sage: d
11185
(23, 576/23, 89885/144, 142130/17977)
11186
sage: A == L*diagonal_matrix(C, d)*L.conjugate_transpose()
11187
True
11188
11189
A matrix may have a singular submatrix in the upper-left
11190
corner ("a leading principal submatrix") which will unavoidably
11191
lead to division by zero. This is the only situation when this
11192
algorithm fails. ::
11193
11194
sage: A = matrix(QQ, [[4, 6, 1], [6, 9, 5], [1, 5, 2]])
11195
sage: B = A[0:2, 0:2]; B.determinant()
11196
0
11197
sage: A._indefinite_factorization('symmetric')
11198
Traceback (most recent call last):
11199
...
11200
ValueError: 2x2 leading principal submatrix is singular,
11201
so cannot create indefinite factorization
11202
11203
TESTS:
11204
11205
The matrix must be square. ::
11206
11207
sage: A = matrix(QQ, 3, 2, range(6))
11208
sage: A._indefinite_factorization('symmetric')
11209
Traceback (most recent call last):
11210
...
11211
ValueError: matrix must be square, not 3 x 2
11212
11213
The lone argument must describe the matrix. ::
11214
11215
sage: A = matrix(QQ, [[1, 5], [5, 8]])
11216
sage: A._indefinite_factorization('junk')
11217
Traceback (most recent call last):
11218
...
11219
ValueError: 'algorithm' must be 'symmetric' or 'hermitian',
11220
not junk
11221
11222
The matrix must contain entries from an exact ring. ::
11223
11224
sage: F = RealField(100)
11225
sage: A = matrix(F, [[1.0, 3.0], [3.0, -6.0]])
11226
sage: A._indefinite_factorization('symmetric')
11227
Traceback (most recent call last):
11228
...
11229
TypeError: entries of the matrix must be in an exact ring,
11230
not Real Field with 100 bits of precision
11231
11232
The base ring must have a fraction field. ::
11233
11234
sage: A = matrix(Integers(6), [[1, 5], [5, 8]])
11235
sage: A._indefinite_factorization('symmetric')
11236
Traceback (most recent call last):
11237
...
11238
TypeError: Unable to create the fraction field of
11239
Ring of integers modulo 6
11240
11241
When ``check`` is ``True`` (the default), the matrix is
11242
checked to see if it conforms with the ``algorithm``
11243
keyword. ::
11244
11245
sage: A = matrix(QQ, 4, 4, range(16))
11246
sage: A._indefinite_factorization('symmetric', check=True)
11247
Traceback (most recent call last):
11248
...
11249
ValueError: matrix is not symmetric (maybe try the 'hermitian' keyword)
11250
11251
sage: A = matrix([[3, 2+3*I], [5+6*I, 12]])
11252
sage: A._indefinite_factorization('hermitian', check=True)
11253
Traceback (most recent call last):
11254
...
11255
ValueError: matrix is not hermitian
11256
11257
Results are cached and hence immutable, according
11258
to the ``algorithm``. ::
11259
11260
sage: A = matrix(QQ, [[ 4, -2, 4, 2],
11261
... [-2, 10, -2, -7],
11262
... [ 4, -2, 8, 4],
11263
... [ 2, -7, 4, 7]])
11264
sage: Ls, ds = A._indefinite_factorization('symmetric')
11265
sage: Lh, dh = A._indefinite_factorization('hermitian')
11266
sage: Ls.is_immutable(), Lh.is_immutable()
11267
(True, True)
11268
sage: isinstance(ds, tuple), isinstance(dh, tuple)
11269
(True, True)
11270
11271
AUTHOR:
11272
11273
- Rob Beezer (2012-05-24)
11274
"""
11275
# Implementation note: L begins as a copy of self.
11276
# Entries below the diagonal are replaced as the loops proceed.
11277
# Entries above the diagonal are used to store entries of D*L^T,
11278
# which halves the number of multiplications needed otherwise.
11279
# The list d_inv holds reciprocals of the diagonal entries
11280
# So, below the diagonal, the main computation is:
11281
# A_ij = A_ij - (1/d_j)*sum(d_k*L_ik*L_jk, 0 <= k < j)
11282
11283
cdef Py_ssize_t m, i, j, k
11284
cdef Matrix L
11285
11286
if not algorithm in ['symmetric', 'hermitian']:
11287
msg = "'algorithm' must be 'symmetric' or 'hermitian', not {0}"
11288
raise ValueError(msg.format(algorithm))
11289
cache_string = 'indefinite_factorization_' + algorithm
11290
factors = self.fetch(cache_string)
11291
if factors is None:
11292
R = self.base_ring()
11293
if not self.is_square():
11294
msg = "matrix must be square, not {0} x {1}"
11295
raise ValueError(msg.format(self.nrows(), self.ncols()))
11296
if not algorithm in ['symmetric', 'hermitian']:
11297
msg = "'algorithm' must be 'symmetric' or 'hermitian', not {0}"
11298
raise ValueError(msg.format(algorithm))
11299
if not R.is_exact():
11300
msg = "entries of the matrix must be in an exact ring, not {0}"
11301
raise TypeError(msg.format(R))
11302
try:
11303
F = R.fraction_field()
11304
except (NotImplementedError, TypeError):
11305
msg = 'Unable to create the fraction field of {0}'
11306
raise TypeError(msg.format(R))
11307
if check and algorithm == 'symmetric':
11308
if not self.is_symmetric():
11309
msg = "matrix is not symmetric (maybe try the 'hermitian' keyword)"
11310
raise ValueError(msg)
11311
if check and algorithm == 'hermitian':
11312
if not self.is_hermitian():
11313
raise ValueError('matrix is not hermitian')
11314
conjugate = (algorithm == 'hermitian')
11315
# we need a copy no matter what, so we
11316
# (potentially) change to fraction field at the same time
11317
L = self.change_ring(F)
11318
m = L._nrows
11319
zero = F(0)
11320
one = F(1)
11321
d = []
11322
d_inv = []
11323
for i in range(m):
11324
for j in range(i+1):
11325
t = L.get_unsafe(i, j)
11326
if conjugate:
11327
for k in range(j):
11328
t -= L.get_unsafe(k,i)*L.get_unsafe(j,k).conjugate()
11329
else:
11330
for k in range(j):
11331
t -= L.get_unsafe(k,i)*L.get_unsafe(j,k)
11332
if i == j:
11333
if t == zero:
11334
msg = "{0}x{0} leading principal submatrix is singular, so cannot create indefinite factorization"
11335
raise ValueError(msg.format(i+1))
11336
d.append(t)
11337
d_inv.append(one/t)
11338
L.set_unsafe(i, i, one)
11339
else:
11340
L.set_unsafe(j, i, t)
11341
L.set_unsafe(i, j, (d_inv[j] * t))
11342
# Triangularize output matrix
11343
for i in range(m):
11344
for j in range(i+1, m):
11345
L.set_unsafe(i, j, zero)
11346
L.set_immutable()
11347
d = tuple(d)
11348
factors = (L, d)
11349
self.cache(cache_string, factors)
11350
return factors
11351
11352
def indefinite_factorization(self, algorithm='symmetric', check=True):
11353
r"""
11354
Decomposes a symmetric or Hermitian matrix into a
11355
lower triangular matrix and a diagonal matrix.
11356
11357
INPUT:
11358
11359
- ``self`` - a square matrix over a ring. The base ring
11360
must have an implemented fraction field.
11361
11362
- ``algorithm`` - default: ``'symmetric'``. Either
11363
``'symmetric'`` or ``'hermitian'``, according to if
11364
the input matrix is symmetric or hermitian.
11365
11366
- ``check`` - default: ``True`` - if ``True`` then
11367
performs the check that the matrix is consistent with the
11368
``algorithm`` keyword.
11369
11370
OUTPUT:
11371
11372
A lower triangular matrix `L` with each diagonal element
11373
equal to `1` and a vector of entries that form a
11374
diagonal matrix `D`. The vector of diagonal entries
11375
can be easily used to form the matrix, as demonstrated
11376
below in the examples.
11377
11378
For a symmetric matrix, `A`, these will be related by
11379
11380
.. math::
11381
11382
A = LDL^T
11383
11384
If `A` is Hermitian matrix, then the transpose of `L`
11385
should be replaced by the conjugate-transpose of `L`.
11386
11387
If any leading principal submatrix (a square submatrix
11388
in the upper-left corner) is singular then this method will
11389
fail with a ``ValueError``.
11390
11391
ALGORITHM:
11392
11393
The algorithm employed only uses field operations,
11394
but the compuation of each diagonal entry has the potential
11395
for division by zero. The number of operations is of order
11396
`n^3/3`, which is half the count for an LU decomposition.
11397
This makes it an appropriate candidate for solving systems
11398
with symmetric (or Hermitian) coefficient matrices.
11399
11400
EXAMPLES:
11401
11402
There is no requirement that a matrix be positive definite, as
11403
indicated by the negative entries in the resulting diagonal
11404
matrix. The default is that the input matrix is symmetric. ::
11405
11406
sage: A = matrix(QQ, [[ 3, -6, 9, 6, -9],
11407
... [-6, 11, -16, -11, 17],
11408
... [ 9, -16, 28, 16, -40],
11409
... [ 6, -11, 16, 9, -19],
11410
... [-9, 17, -40, -19, 68]])
11411
sage: A.is_symmetric()
11412
True
11413
sage: L, d = A.indefinite_factorization()
11414
sage: D = diagonal_matrix(d)
11415
sage: L
11416
[ 1 0 0 0 0]
11417
[-2 1 0 0 0]
11418
[ 3 -2 1 0 0]
11419
[ 2 -1 0 1 0]
11420
[-3 1 -3 1 1]
11421
sage: D
11422
[ 3 0 0 0 0]
11423
[ 0 -1 0 0 0]
11424
[ 0 0 5 0 0]
11425
[ 0 0 0 -2 0]
11426
[ 0 0 0 0 -1]
11427
sage: A == L*D*L.transpose()
11428
True
11429
11430
Optionally, Hermitian matrices can be factored
11431
and the result has a similar property (but not
11432
identical). Here, the field is all complex numbers
11433
with rational real and imaginary parts. As theory
11434
predicts, the diagonal entries will be real numbers. ::
11435
11436
sage: C.<I> = QuadraticField(-1)
11437
sage: B = matrix(C, [[ 2, 4 - 2*I, 2 + 2*I],
11438
... [4 + 2*I, 8, 10*I],
11439
... [2 - 2*I, -10*I, -3]])
11440
sage: B.is_hermitian()
11441
True
11442
sage: L, d = B.indefinite_factorization(algorithm='hermitian')
11443
sage: D = diagonal_matrix(d)
11444
sage: L
11445
[ 1 0 0]
11446
[ I + 2 1 0]
11447
[ -I + 1 2*I + 1 1]
11448
sage: D
11449
[ 2 0 0]
11450
[ 0 -2 0]
11451
[ 0 0 3]
11452
sage: B == L*D*L.conjugate_transpose()
11453
True
11454
11455
If a leading principal submatrix has zero determinant, this
11456
algorithm will fail. This will never happen with a positive
11457
definite matrix. ::
11458
11459
sage: A = matrix(QQ, [[21, 15, 12, -2],
11460
... [15, 12, 9, 6],
11461
... [12, 9, 7, 3],
11462
... [-2, 6, 3, 8]])
11463
sage: A.is_symmetric()
11464
True
11465
sage: A[0:3,0:3].det() == 0
11466
True
11467
sage: A.indefinite_factorization()
11468
Traceback (most recent call last):
11469
...
11470
ValueError: 3x3 leading principal submatrix is singular,
11471
so cannot create indefinite factorization
11472
11473
This algorithm only depends on field operations, so
11474
outside of the singular submatrix situation, any matrix
11475
may be factored. This provides a reasonable alternative
11476
to the Cholesky decomposition. ::
11477
11478
sage: F.<a> = FiniteField(5^3)
11479
sage: A = matrix(F,
11480
... [[ a^2 + 2*a, 4*a^2 + 3*a + 4, 3*a^2 + a, 2*a^2 + 2*a + 1],
11481
... [4*a^2 + 3*a + 4, 4*a^2 + 2, 3*a, 2*a^2 + 4*a + 2],
11482
... [ 3*a^2 + a, 3*a, 3*a^2 + 2, 3*a^2 + 2*a + 3],
11483
... [2*a^2 + 2*a + 1, 2*a^2 + 4*a + 2, 3*a^2 + 2*a + 3, 3*a^2 + 2*a + 4]])
11484
sage: A.is_symmetric()
11485
True
11486
sage: L, d = A.indefinite_factorization()
11487
sage: D = diagonal_matrix(d)
11488
sage: L
11489
[ 1 0 0 0]
11490
[4*a^2 + 4*a + 3 1 0 0]
11491
[ 3 4*a^2 + a + 2 1 0]
11492
[ 4*a^2 + 4 2*a^2 + 3*a + 3 2*a^2 + 3*a + 1 1]
11493
sage: D
11494
[ a^2 + 2*a 0 0 0]
11495
[ 0 2*a^2 + 2*a + 4 0 0]
11496
[ 0 0 3*a^2 + 4*a + 3 0]
11497
[ 0 0 0 a^2 + 3*a]
11498
sage: A == L*D*L.transpose()
11499
True
11500
11501
AUTHOR:
11502
11503
- Rob Beezer (2012-05-24)
11504
"""
11505
from sage.modules.free_module_element import vector
11506
L, d = self._indefinite_factorization(algorithm, check=check)
11507
return L, vector(L.base_ring(), d)
11508
11509
def is_positive_definite(self):
11510
r"""
11511
Determines if a real or symmetric matrix is positive definite.
11512
11513
A square matrix `A` is postive definite if it is
11514
symmetric with real entries or Hermitan with complex entries,
11515
and for every non-zero vector `\vec{x}`
11516
11517
.. math::
11518
11519
\vec{x}^\ast A\vec{x} > 0
11520
11521
Here `\vec{x}^\ast` is the conjugate-transpose, which can be
11522
simplified to just the transpose in the real case.
11523
11524
ALGORITHM:
11525
11526
A matrix is positive definite if and only if the
11527
diagonal entries from the indefinite factorization
11528
are all positive (see :meth:`indefinite_factorization`).
11529
So this algorithm is of order ``n^3/3`` and may be applied
11530
to matrices with elements of any ring that has a fraction
11531
field contained within the reals or complexes.
11532
11533
INPUT:
11534
11535
Any square matrix.
11536
11537
OUTPUT:
11538
11539
This routine will return ``True`` if the matrix is square,
11540
symmetric or Hermitian, and meets the condition above
11541
for the quadratic form.
11542
11543
The base ring for the elements of the matrix needs to
11544
have a fraction field implemented and the computations
11545
that result from the indefinite factorization must be
11546
convertable to real numbers that are comparable to zero.
11547
11548
EXAMPLES:
11549
11550
A real symmetric matrix that is positive definite,
11551
as evidenced by the positive entries for the diagonal
11552
matrix of the indefinite factorization and the postive
11553
determinants of the leading principal submatrices. ::
11554
11555
sage: A = matrix(QQ, [[ 4, -2, 4, 2],
11556
... [-2, 10, -2, -7],
11557
... [ 4, -2, 8, 4],
11558
... [ 2, -7, 4, 7]])
11559
sage: A.is_positive_definite()
11560
True
11561
sage: _, d = A.indefinite_factorization(algorithm='symmetric')
11562
sage: d
11563
(4, 9, 4, 1)
11564
sage: [A[:i,:i].determinant() for i in range(1,A.nrows()+1)]
11565
[4, 36, 144, 144]
11566
11567
A real symmetric matrix which is not positive definite, along
11568
with a vector that makes the quadratic form negative. ::
11569
11570
sage: A = matrix(QQ, [[ 3, -6, 9, 6, -9],
11571
... [-6, 11, -16, -11, 17],
11572
... [ 9, -16, 28, 16, -40],
11573
... [ 6, -11, 16, 9, -19],
11574
... [-9, 17, -40, -19, 68]])
11575
sage: A.is_positive_definite()
11576
False
11577
sage: _, d = A.indefinite_factorization(algorithm='symmetric')
11578
sage: d
11579
(3, -1, 5, -2, -1)
11580
sage: [A[:i,:i].determinant() for i in range(1,A.nrows()+1)]
11581
[3, -3, -15, 30, -30]
11582
sage: u = vector(QQ, [2, 2, 0, 1, 0])
11583
sage: u.row()*A*u
11584
(-3)
11585
11586
A real symmetric matrix with a singular leading
11587
principal submatrix, that is therefore not positive definite.
11588
The vector ``u`` makes the quadratic form zero. ::
11589
11590
sage: A = matrix(QQ, [[21, 15, 12, -2],
11591
... [15, 12, 9, 6],
11592
... [12, 9, 7, 3],
11593
... [-2, 6, 3, 8]])
11594
sage: A.is_positive_definite()
11595
False
11596
sage: [A[:i,:i].determinant() for i in range(1,A.nrows()+1)]
11597
[21, 27, 0, -75]
11598
sage: u = vector(QQ, [1,1,-3,0])
11599
sage: u.row()*A*u
11600
(0)
11601
11602
An Hermitian matrix that is positive definite. ::
11603
11604
sage: C.<I> = NumberField(x^2 + 1)
11605
sage: A = matrix(C, [[ 23, 17*I + 3, 24*I + 25, 21*I],
11606
... [ -17*I + 3, 38, -69*I + 89, 7*I + 15],
11607
... [-24*I + 25, 69*I + 89, 976, 24*I + 6],
11608
... [ -21*I, -7*I + 15, -24*I + 6, 28]])
11609
sage: A.is_positive_definite()
11610
True
11611
sage: _, d = A.indefinite_factorization(algorithm='hermitian')
11612
sage: d
11613
(23, 576/23, 89885/144, 142130/17977)
11614
sage: [A[:i,:i].determinant() for i in range(1,A.nrows()+1)]
11615
[23, 576, 359540, 2842600]
11616
11617
An Hermitian matrix that is not positive definite.
11618
The vector ``u`` makes the quadratic form negative. ::
11619
11620
sage: C.<I> = QuadraticField(-1)
11621
sage: B = matrix(C, [[ 2, 4 - 2*I, 2 + 2*I],
11622
... [4 + 2*I, 8, 10*I],
11623
... [2 - 2*I, -10*I, -3]])
11624
sage: B.is_positive_definite()
11625
False
11626
sage: _, d = B.indefinite_factorization(algorithm='hermitian')
11627
sage: d
11628
(2, -2, 3)
11629
sage: [B[:i,:i].determinant() for i in range(1,B.nrows()+1)]
11630
[2, -4, -12]
11631
sage: u = vector(C, [-5 + 10*I, 4 - 3*I, 0])
11632
sage: u.row().conjugate()*B*u
11633
(-50)
11634
11635
A positive definite matrix over an algebraically closed field. ::
11636
11637
sage: A = matrix(QQbar, [[ 2, 4 + 2*I, 6 - 4*I],
11638
... [ -2*I + 4, 11, 10 - 12*I],
11639
... [ 4*I + 6, 10 + 12*I, 37]])
11640
sage: A.is_positive_definite()
11641
True
11642
sage: [A[:i,:i].determinant() for i in range(1,A.nrows()+1)]
11643
[2, 2, 6]
11644
11645
TESTS:
11646
11647
If the base ring lacks a ``conjugate`` method, it
11648
will be assumed to not be Hermitian and thus symmetric.
11649
If the base ring does not make sense as a subfield of
11650
the reals, then this routine will fail since comparison
11651
to zero is meaningless. ::
11652
11653
sage: F.<a> = FiniteField(5^3)
11654
sage: a.conjugate()
11655
Traceback (most recent call last):
11656
...
11657
AttributeError: 'sage.rings.finite_rings.element_givaro.FiniteField_givaroElement'
11658
object has no attribute 'conjugate'
11659
sage: A = matrix(F,
11660
... [[ a^2 + 2*a, 4*a^2 + 3*a + 4, 3*a^2 + a, 2*a^2 + 2*a + 1],
11661
... [4*a^2 + 3*a + 4, 4*a^2 + 2, 3*a, 2*a^2 + 4*a + 2],
11662
... [ 3*a^2 + a, 3*a, 3*a^2 + 2, 3*a^2 + 2*a + 3],
11663
... [2*a^2 + 2*a + 1, 2*a^2 + 4*a + 2, 3*a^2 + 2*a + 3, 3*a^2 + 2*a + 4]])
11664
sage: A.is_positive_definite()
11665
Traceback (most recent call last):
11666
...
11667
TypeError: cannot convert computations from
11668
Finite Field in a of size 5^3 into real numbers
11669
11670
AUTHOR:
11671
11672
- Rob Beezer (2012-05-24)
11673
"""
11674
from sage.rings.all import RR
11675
# check to see if the Hermitian routine is usable
11676
# otherwise we will assume the symmetric case
11677
imaginary = True
11678
a = self.base_ring().an_element()
11679
try:
11680
a.conjugate()
11681
except AttributeError:
11682
imaginary = False
11683
if imaginary:
11684
if not self.is_hermitian():
11685
return False
11686
else:
11687
if not self.is_symmetric():
11688
return False
11689
try:
11690
if imaginary:
11691
_, d = self._indefinite_factorization('hermitian', check=False)
11692
else:
11693
_, d = self._indefinite_factorization('symmetric', check=False)
11694
except ValueError as e:
11695
# a zero singular leading principal submatrix is one
11696
# indicator that the matrix is not positive definite
11697
if str(e).find('leading principal submatrix is singular') != -1:
11698
return False
11699
else:
11700
raise ValueError(e)
11701
# Now have diagonal entries (hopefully real) and so can
11702
# test with a generator (which will short-circuit)
11703
# positive definite iff all entries of d are positive
11704
try:
11705
posdef = all( RR(x) > 0 for x in d )
11706
except TypeError:
11707
universe = Sequence(d).universe()
11708
msg = "cannot convert computations from {0} into real numbers"
11709
raise TypeError(msg.format(universe))
11710
return posdef
11711
11712
def hadamard_bound(self):
11713
r"""
11714
Return an int n such that the absolute value of the determinant of
11715
this matrix is at most `10^n`.
11716
11717
This is got using both the row norms and the column norms.
11718
11719
This function only makes sense when the base field can be coerced
11720
to the real double field RDF or the MPFR Real Field with 53-bits
11721
precision.
11722
11723
EXAMPLES::
11724
11725
sage: a = matrix(ZZ, 3, [1,2,5,7,-3,4,2,1,123])
11726
sage: a.hadamard_bound()
11727
4
11728
sage: a.det()
11729
-2014
11730
sage: 10^4
11731
10000
11732
11733
In this example the Hadamard bound has to be computed
11734
(automatically) using MPFR instead of doubles, since doubles
11735
overflow::
11736
11737
sage: a = matrix(ZZ, 2, [2^10000,3^10000,2^50,3^19292])
11738
sage: a.hadamard_bound()
11739
12215
11740
sage: len(str(a.det()))
11741
12215
11742
"""
11743
from sage.rings.all import RDF, RealField
11744
try:
11745
A = self.change_ring(RDF)
11746
m1 = A._hadamard_row_bound()
11747
A = A.transpose()
11748
m2 = A._hadamard_row_bound()
11749
return min(m1, m2)
11750
except (OverflowError, TypeError):
11751
# Try using MPFR, which handles large numbers much better, but is slower.
11752
import misc
11753
R = RealField(53, rnd='RNDU')
11754
A = self.change_ring(R)
11755
m1 = misc.hadamard_row_bound_mpfr(A)
11756
A = A.transpose()
11757
m2 = misc.hadamard_row_bound_mpfr(A)
11758
return min(m1, m2)
11759
11760
def find(self,f, indices=False):
11761
r"""
11762
Find elements in this matrix satisfying the constraints in the
11763
function `f`. The function is evaluated on each element of
11764
the matrix .
11765
11766
INPUT:
11767
11768
11769
- ``f`` - a function that is evaluated on each
11770
element of this matrix.
11771
11772
- ``indices`` - whether or not to return the indices
11773
and elements of this matrix that satisfy the function.
11774
11775
11776
OUTPUT: If ``indices`` is not specified, return a
11777
matrix with 1 where `f` is satisfied and 0 where it is not.
11778
If ``indices`` is specified, return a dictionary
11779
containing the elements of this matrix satisfying `f`.
11780
11781
EXAMPLES::
11782
11783
sage: M = matrix(4,3,[1, -1/2, -1, 1, -1, -1/2, -1, 0, 0, 2, 0, 1])
11784
sage: M.find(lambda entry:entry==0)
11785
[0 0 0]
11786
[0 0 0]
11787
[0 1 1]
11788
[0 1 0]
11789
11790
::
11791
11792
sage: M.find(lambda u:u<0)
11793
[0 1 1]
11794
[0 1 1]
11795
[1 0 0]
11796
[0 0 0]
11797
11798
::
11799
11800
sage: M = matrix(4,3,[1, -1/2, -1, 1, -1, -1/2, -1, 0, 0, 2, 0, 1])
11801
sage: len(M.find(lambda u:u<1 and u>-1,indices=True))
11802
5
11803
11804
::
11805
11806
sage: M.find(lambda u:u!=1/2)
11807
[1 1 1]
11808
[1 1 1]
11809
[1 1 1]
11810
[1 1 1]
11811
11812
::
11813
11814
sage: M.find(lambda u:u>1.2)
11815
[0 0 0]
11816
[0 0 0]
11817
[0 0 0]
11818
[1 0 0]
11819
11820
::
11821
11822
sage: sorted(M.find(lambda u:u!=0,indices=True).keys()) == M.nonzero_positions()
11823
True
11824
"""
11825
11826
cdef Py_ssize_t size,i,j
11827
cdef object M
11828
11829
if indices is False:
11830
L = self._list()
11831
size = PyList_GET_SIZE(L)
11832
M = PyList_New(0)
11833
11834
for i from 0 <= i < size:
11835
PyList_Append(M,<object>f(<object>PyList_GET_ITEM(L,i)))
11836
11837
return matrix_space.MatrixSpace(IntegerModRing(2),
11838
nrows=self._nrows,ncols=self._ncols).matrix(M)
11839
11840
else:
11841
# return matrix along with indices in a dictionary
11842
d = {}
11843
for i from 0 <= i < self._nrows:
11844
for j from 0 <= j < self._ncols:
11845
if f(self.get_unsafe(i,j)):
11846
d[(i,j)] = self.get_unsafe(i,j)
11847
11848
return d
11849
11850
def conjugate(self):
11851
r"""
11852
Return the conjugate of self, i.e. the matrix whose entries are the
11853
conjugates of the entries of self.
11854
11855
EXAMPLES::
11856
11857
sage: A = matrix(CDF, [[1+I,1],[0,2*I]])
11858
sage: A.conjugate()
11859
[1.0 - 1.0*I 1.0]
11860
[ 0.0 -2.0*I]
11861
11862
A matrix over a not-totally-real number field::
11863
11864
sage: K.<j> = NumberField(x^2+5)
11865
sage: M = matrix(K, [[1+j,1], [0,2*j]])
11866
sage: M.conjugate()
11867
[-j + 1 1]
11868
[ 0 -2*j]
11869
11870
There is a shortcut for the conjugate::
11871
11872
sage: M.C
11873
[-j + 1 1]
11874
[ 0 -2*j]
11875
11876
There is also a shortcut for the conjugate transpose, or "Hermitian transpose"::
11877
11878
sage: M.H
11879
[-j + 1 0]
11880
[ 1 -2*j]
11881
11882
Conjugates work (trivially) for matrices over rings that embed
11883
canonically into the real numbers::
11884
11885
sage: M = random_matrix(ZZ, 2)
11886
sage: M == M.conjugate()
11887
True
11888
sage: M = random_matrix(QQ, 3)
11889
sage: M == M.conjugate()
11890
True
11891
sage: M = random_matrix(RR, 2)
11892
sage: M == M.conjugate()
11893
True
11894
"""
11895
return self.new_matrix(self.nrows(), self.ncols(), [z.conjugate() for z in self.list()])
11896
11897
def conjugate_transpose(self):
11898
r"""
11899
Returns the transpose of ``self`` after each entry has been converted to its complex conjugate.
11900
11901
.. note::
11902
This function is sometimes known as the "adjoint" of a matrix,
11903
though there is substantial variation and some confusion with
11904
the use of that term.
11905
11906
OUTPUT:
11907
11908
A matrix formed by taking the complex conjugate of every entry
11909
of ``self`` and then transposing the resulting matrix.
11910
11911
Complex conjugation is implemented for many subfields
11912
of the complex numbers. See the examples below, or more
11913
at :meth:`~conjugate`.
11914
11915
EXAMPLES::
11916
11917
sage: M = matrix(SR, 2, 2, [[2-I, 3+4*I], [9-6*I, 5*I]])
11918
sage: M.base_ring()
11919
Symbolic Ring
11920
sage: M.conjugate_transpose()
11921
[ I + 2 6*I + 9]
11922
[-4*I + 3 -5*I]
11923
11924
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])
11925
sage: P.base_ring()
11926
Complex Field with 53 bits of precision
11927
sage: P.conjugate_transpose()
11928
[ 0.950... + 0.630...*I 0.940... - 0.230...*I 0.520... + 0.410...*I]
11929
[ 0.840... - 0.130...*I 0.230... - 0.590...*I -0.500... - 0.900...*I]
11930
11931
There is also a shortcut for the conjugate transpose, or "Hermitian transpose"::
11932
11933
sage: M.H
11934
[ I + 2 6*I + 9]
11935
[-4*I + 3 -5*I]
11936
11937
Matrices over base rings that can be embedded in the
11938
real numbers will behave as expected. ::
11939
11940
sage: P = random_matrix(QQ, 3, 4)
11941
sage: P.conjugate_transpose() == P.transpose()
11942
True
11943
11944
The conjugate of a matrix is formed by taking conjugates of
11945
all the entries. Some specialized subfields of the complex numbers
11946
are implemented in Sage and complex conjugation can be applied.
11947
(Matrices over quadratic number fields are another
11948
class of examples.) ::
11949
11950
sage: C = CyclotomicField(5)
11951
sage: a = C.gen(); a
11952
zeta5
11953
sage: CC(a)
11954
0.309016994374947 + 0.951056516295154*I
11955
sage: M = matrix(C, 1, 2, [a^2, a+a^3])
11956
sage: M.conjugate_transpose()
11957
[ zeta5^3]
11958
[-zeta5^3 - zeta5 - 1]
11959
11960
Conjugation does not make sense over rings not containing complex numbers. ::
11961
11962
sage: N = matrix(GF(5), 2, [0,1,2,3])
11963
sage: N.conjugate_transpose()
11964
Traceback (most recent call last):
11965
...
11966
AttributeError: 'sage.rings.finite_rings.integer_mod.IntegerMod_int' object has no attribute 'conjugate'
11967
11968
AUTHOR:
11969
11970
Rob Beezer (2010-12-13)
11971
"""
11972
# limited testing on a 1000 x 1000 matrix over CC:
11973
# transpose is fast, conjugate is slow
11974
# so perhaps direct speed improvements to the conjugate() method
11975
return self.conjugate().transpose()
11976
11977
def norm(self, p=2):
11978
r"""
11979
Return the p-norm of this matrix, where `p` can be 1, 2,
11980
`\inf`, or the Frobenius norm.
11981
11982
INPUT:
11983
11984
11985
- ``self`` - a matrix whose entries are coercible into
11986
CDF
11987
11988
- ``p`` - one of the following options:
11989
11990
- ``1`` - the largest column-sum norm
11991
11992
- ``2 (default)`` - the Euclidean norm
11993
11994
- ``Infinity`` - the largest row-sum norm
11995
11996
- ``'frob'`` - the Frobenius (sum of squares) norm
11997
11998
11999
OUTPUT: RDF number
12000
12001
.. SEEALSO::
12002
12003
- :func:`sage.misc.functional.norm`
12004
12005
EXAMPLES::
12006
12007
sage: A = matrix(ZZ, [[1,2,4,3],[-1,0,3,-10]])
12008
sage: A.norm(1)
12009
13.0
12010
sage: A.norm(Infinity)
12011
14.0
12012
sage: B = random_matrix(QQ, 20, 21)
12013
sage: B.norm(Infinity) == (B.transpose()).norm(1)
12014
True
12015
12016
::
12017
12018
sage: Id = identity_matrix(12)
12019
sage: Id.norm(2)
12020
1.0
12021
sage: A = matrix(RR, 2, 2, [13,-4,-4,7])
12022
sage: A.norm()
12023
15.0
12024
12025
Norms of numerical matrices over high-precision reals are computed by this routine.
12026
Faster routines for double precision entries from `RDF` or `CDF` are provided by
12027
the :class:`~sage.matrix.matrix_double_dense.Matrix_double_dense` class. ::
12028
12029
sage: A = matrix(CC, 2, 3, [3*I,4,1-I,1,2,0])
12030
sage: A.norm('frob')
12031
5.65685424949
12032
sage: A.norm(2)
12033
5.47068444321
12034
sage: A.norm(1)
12035
6.0
12036
sage: A.norm(Infinity)
12037
8.41421356237
12038
sage: a = matrix([[],[],[],[]])
12039
sage: a.norm()
12040
0.0
12041
sage: a.norm(Infinity) == a.norm(1)
12042
True
12043
"""
12044
12045
if self._nrows == 0 or self._ncols == 0:
12046
return RDF(0)
12047
12048
# 2-norm:
12049
if p == 2:
12050
A = self.change_ring(CDF)
12051
A = A.conjugate().transpose() * A
12052
U, S, V = A.SVD()
12053
return max(S.list()).real().sqrt()
12054
12055
A = self.apply_map(abs).change_ring(RDF)
12056
12057
# 1-norm: largest column-sum
12058
if p == 1:
12059
A = A.transpose()
12060
return max([sum(i) for i in list(A)])
12061
12062
# Infinity norm: largest row-sum
12063
if p == sage.rings.infinity.Infinity:
12064
return max([sum(i) for i in list(A)])
12065
12066
# Frobenius norm: square root of sum of squares of entries of self
12067
if p == 'frob':
12068
return sum([i**2 for i in A.list()]).sqrt()
12069
12070
def _numerical_approx(self,prec=None,digits=None):
12071
r"""
12072
Return a numerical approximation of ``self`` as either
12073
a real or complex number with at least the requested number of bits
12074
or digits of precision.
12075
12076
INPUT:
12077
12078
12079
- ``prec`` - an integer: the number of bits of
12080
precision
12081
12082
- ``digits`` - an integer: digits of precision
12083
12084
12085
OUTPUT: A matrix coerced to a real or complex field with prec bits
12086
of precision.
12087
12088
EXAMPLES::
12089
12090
sage: d = matrix([[3, 0],[0,sqrt(2)]]) ;
12091
sage: b = matrix([[1, -1], [2, 2]]) ; e = b * d * b.inverse();e
12092
[ 1/2*sqrt(2) + 3/2 -1/4*sqrt(2) + 3/4]
12093
[ -sqrt(2) + 3 1/2*sqrt(2) + 3/2]
12094
12095
::
12096
12097
sage: e.numerical_approx(53)
12098
[ 2.20710678118655 0.396446609406726]
12099
[ 1.58578643762690 2.20710678118655]
12100
12101
::
12102
12103
sage: e.numerical_approx(20)
12104
[ 2.2071 0.39645]
12105
[ 1.5858 2.2071]
12106
12107
::
12108
12109
sage: (e-I).numerical_approx(20)
12110
[2.2071 - 1.0000*I 0.39645]
12111
[ 1.5858 2.2071 - 1.0000*I]
12112
12113
::
12114
12115
sage: M=matrix(QQ,4,[i/(i+1) for i in range(12)]);M
12116
[ 0 1/2 2/3]
12117
[ 3/4 4/5 5/6]
12118
[ 6/7 7/8 8/9]
12119
[ 9/10 10/11 11/12]
12120
12121
::
12122
12123
sage: M.numerical_approx()
12124
[0.000000000000000 0.500000000000000 0.666666666666667]
12125
[0.750000000000000 0.800000000000000 0.833333333333333]
12126
[0.857142857142857 0.875000000000000 0.888888888888889]
12127
[0.900000000000000 0.909090909090909 0.916666666666667]
12128
12129
::
12130
12131
sage: matrix(SR, 2, 2, range(4)).n()
12132
[0.000000000000000 1.00000000000000]
12133
[ 2.00000000000000 3.00000000000000]
12134
12135
::
12136
12137
sage: numerical_approx(M)
12138
[0.000000000000000 0.500000000000000 0.666666666666667]
12139
[0.750000000000000 0.800000000000000 0.833333333333333]
12140
[0.857142857142857 0.875000000000000 0.888888888888889]
12141
[0.900000000000000 0.909090909090909 0.916666666666667]
12142
12143
"""
12144
12145
if prec is None:
12146
if digits is None:
12147
prec = 53
12148
else:
12149
prec = int(digits * 3.4) + 2
12150
12151
try:
12152
return self.change_ring(sage.rings.real_mpfr.RealField(prec))
12153
except TypeError:
12154
# try to return a complex result
12155
return self.change_ring(sage.rings.complex_field.ComplexField(prec))
12156
12157
#This line is added so the doctest are visible
12158
numerical_approx=_numerical_approx
12159
n=_numerical_approx
12160
N=_numerical_approx
12161
12162
def plot(self, *args, **kwds):
12163
"""
12164
A plot of this matrix.
12165
12166
Each (ith, jth) matrix element is given a different color value
12167
depending on its relative size compared to the other elements in
12168
the matrix.
12169
12170
The tick marks drawn on the frame axes denote the (ith, jth)
12171
element of the matrix.
12172
12173
This method just calls ``matrix_plot``.
12174
``*args`` and ``**kwds`` are passed to
12175
``matrix_plot``.
12176
12177
EXAMPLES:
12178
12179
A matrix over ZZ colored with different grey levels::
12180
12181
sage: A = matrix([[1,3,5,1],[2,4,5,6],[1,3,5,7]])
12182
sage: A.plot()
12183
12184
Here we make a random matrix over RR and use cmap='hsv' to color
12185
the matrix elements different RGB colors (see documentation for
12186
``matrix_plot`` for more information on cmaps)::
12187
12188
sage: A = random_matrix(RDF, 50)
12189
sage: plot(A, cmap='hsv')
12190
12191
Another random plot, but over GF(389)::
12192
12193
sage: A = random_matrix(GF(389), 10)
12194
sage: A.plot(cmap='Oranges')
12195
"""
12196
from sage.plot.plot import matrix_plot
12197
return matrix_plot(self, *args, **kwds)
12198
12199
#added this to make doctests visible to users
12200
numerical_approx=_numerical_approx
12201
12202
def derivative(self, *args):
12203
"""
12204
Derivative with respect to variables supplied in args.
12205
12206
Multiple variables and iteration counts may be supplied; see
12207
documentation for the global derivative() function for more
12208
details.
12209
12210
EXAMPLES::
12211
12212
sage: v = vector([1,x,x^2])
12213
sage: v.derivative(x)
12214
(0, 1, 2*x)
12215
sage: type(v.derivative(x)) == type(v)
12216
True
12217
sage: v = vector([1,x,x^2], sparse=True)
12218
sage: v.derivative(x)
12219
(0, 1, 2*x)
12220
sage: type(v.derivative(x)) == type(v)
12221
True
12222
sage: v.derivative(x,x)
12223
(0, 0, 2)
12224
"""
12225
return multi_derivative(self, args)
12226
12227
def exp(self):
12228
r"""
12229
Calculate the exponential of this matrix X, which is the matrix
12230
12231
.. math::
12232
12233
e^X = \sum_{k=0}^{\infty} \frac{X^k}{k!}.
12234
12235
This function depends on maxima's matrix exponentiation
12236
function, which does not deal well with floating point
12237
numbers. If the matrix has floating point numbers, they will
12238
be rounded automatically to rational numbers during the
12239
computation. If you want approximations to the exponential
12240
that are calculated numerically, you may get better results by
12241
first converting your matrix to RDF or CDF, as shown in the
12242
last example.
12243
12244
EXAMPLES::
12245
12246
sage: a=matrix([[1,2],[3,4]])
12247
sage: a.exp()
12248
[-1/22*(e^sqrt(33)*(sqrt(33) - 11) - 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)]
12249
[ 1/11*(sqrt(33)*e^sqrt(33) - sqrt(33))*e^(-1/2*sqrt(33) + 5/2) 1/22*(e^sqrt(33)*(sqrt(33) + 11) - sqrt(33) + 11)*e^(-1/2*sqrt(33) + 5/2)]
12250
12251
sage: type(a.exp())
12252
<type 'sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense'>
12253
12254
sage: a=matrix([[1/2,2/3],[3/4,4/5]])
12255
sage: a.exp()
12256
[-1/418*(e^(1/10*sqrt(209))*(3*sqrt(209) - 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)]
12257
[ 15/418*(sqrt(209)*e^(1/10*sqrt(209)) - sqrt(209))*e^(-1/20*sqrt(209) + 13/20) 1/418*(e^(1/10*sqrt(209))*(3*sqrt(209) + 209) - 3*sqrt(209) + 209)*e^(-1/20*sqrt(209) + 13/20)]
12258
12259
sage: a=matrix(RR,[[1,pi.n()],[1e2,1e-2]])
12260
sage: a.exp()
12261
[ 1/11882424341266*(e^(3/1275529100*sqrt(227345670387496707609))*(11*sqrt(227345670387496707609) + 5941212170633) - 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)]
12262
[ 10000/53470909535697*(sqrt(227345670387496707609)*e^(3/1275529100*sqrt(227345670387496707609)) - sqrt(227345670387496707609))*e^(-3/2551058200*sqrt(227345670387496707609) + 101/200) -1/11882424341266*(e^(3/1275529100*sqrt(227345670387496707609))*(11*sqrt(227345670387496707609) - 5941212170633) - 11*sqrt(227345670387496707609) - 5941212170633)*e^(-3/2551058200*sqrt(227345670387496707609) + 101/200)]
12263
sage: a.change_ring(RDF).exp()
12264
[42748127.3153 7368259.24416]
12265
[234538976.138 40426191.4516]
12266
"""
12267
from sage.symbolic.ring import SR
12268
return self.change_ring(SR).exp()
12269
12270
def elementary_divisors(self):
12271
r"""
12272
If self is a matrix over a principal ideal domain R, return
12273
elements `d_i` for `1 \le i \le k = \min(r,s)`
12274
where `r` and `s` are the number of rows and
12275
columns of self, such that the cokernel of self is isomorphic to
12276
12277
.. math::
12278
12279
R/(d_1) \oplus R/(d_2) \oplus R/(d_k)
12280
12281
with `d_i \mid d_{i+1}` for all `i`. These are
12282
the diagonal entries of the Smith form of self (see
12283
:meth:`smith_form()`).
12284
12285
EXAMPLES::
12286
12287
sage: OE = EquationOrder(x^2 - x + 2, 'w')
12288
sage: w = OE.ring_generators()[0]
12289
sage: m = Matrix([ [1, w],[w,7]])
12290
sage: m.elementary_divisors()
12291
[1, -w + 9]
12292
12293
.. seealso::
12294
12295
:meth:`smith_form`
12296
"""
12297
d, u, v = self.smith_form()
12298
r = min(self.nrows(), self.ncols())
12299
return [d[i,i] for i in xrange(r)]
12300
12301
def smith_form(self):
12302
r"""
12303
If self is a matrix over a principal ideal domain R, return
12304
matrices D, U, V over R such that D = U \* self \* V, U and V have
12305
unit determinant, and D is diagonal with diagonal entries the
12306
ordered elementary divisors of self, ordered so that
12307
`D_{i} \mid D_{i+1}`. Note that U and V are not uniquely
12308
defined in general, and D is defined only up to units.
12309
12310
INPUT:
12311
12312
12313
- ``self`` - a matrix over an integral domain. If the
12314
base ring is not a PID, the routine might work, or else it will
12315
fail having found an example of a non-principal ideal. Note that we
12316
do not call any methods to check whether or not the base ring is a
12317
PID, since this might be quite expensive (e.g. for rings of
12318
integers of number fields of large degree).
12319
12320
12321
ALGORITHM: Lifted wholesale from
12322
http://en.wikipedia.org/wiki/Smith_normal_form
12323
12324
.. seealso::
12325
12326
:meth:`elementary_divisors`
12327
12328
AUTHORS:
12329
12330
- David Loeffler (2008-12-05)
12331
12332
EXAMPLES:
12333
12334
An example over the ring of integers of a number field (of class
12335
number 1)::
12336
12337
sage: OE = NumberField(x^2 - x + 2,'w').ring_of_integers()
12338
sage: w = OE.ring_generators()[0]
12339
sage: m = Matrix([ [1, w],[w,7]])
12340
sage: d, u, v = m.smith_form()
12341
sage: (d, u, v)
12342
(
12343
[ 1 0] [ 1 0] [ 1 -w]
12344
[ 0 -w + 9], [-w 1], [ 0 1]
12345
)
12346
sage: u * m * v == d
12347
True
12348
sage: u.base_ring() == v.base_ring() == d.base_ring() == OE
12349
True
12350
sage: u.det().is_unit() and v.det().is_unit()
12351
True
12352
12353
An example over the polynomial ring QQ[x]::
12354
12355
sage: R.<x> = QQ[]; m=x*matrix(R,2,2,1) - matrix(R, 2,2,[3,-4,1,-1]); m.smith_form()
12356
(
12357
[ 1 0] [ 0 -1] [ 1 x + 1]
12358
[ 0 x^2 - 2*x + 1], [ 1 x - 3], [ 0 1]
12359
)
12360
12361
An example over a field::
12362
12363
sage: m = matrix( GF(17), 3, 3, [11,5,1,3,6,8,1,16,0]); d,u,v = m.smith_form()
12364
sage: d
12365
[1 0 0]
12366
[0 1 0]
12367
[0 0 0]
12368
sage: u*m*v == d
12369
True
12370
12371
Some examples over non-PID's work anyway::
12372
12373
sage: R = EquationOrder(x^2 + 5, 's') # class number 2
12374
sage: s = R.ring_generators()[0]
12375
sage: A = matrix(R, 2, 2, [s-1,-s,-s,2*s+1])
12376
sage: D, U, V = A.smith_form()
12377
sage: D, U, V
12378
(
12379
[ 1 0] [ 4 s + 4] [ 1 -5*s + 6]
12380
[ 0 -s - 6], [ s s - 1], [ 0 1]
12381
)
12382
sage: D == U*A*V
12383
True
12384
12385
Others don't, but they fail quite constructively::
12386
12387
sage: matrix(R,2,2,[s-1,-s-2,-2*s,-s-2]).smith_form()
12388
Traceback (most recent call last):
12389
...
12390
ArithmeticError: Ideal Fractional ideal (2, s + 1) not principal
12391
12392
Empty matrices are handled safely::
12393
12394
sage: m = MatrixSpace(OE, 2,0)(0); d,u,v=m.smith_form(); u*m*v == d
12395
True
12396
sage: m = MatrixSpace(OE, 0,2)(0); d,u,v=m.smith_form(); u*m*v == d
12397
True
12398
sage: m = MatrixSpace(OE, 0,0)(0); d,u,v=m.smith_form(); u*m*v == d
12399
True
12400
12401
Some pathological cases that crashed earlier versions::
12402
12403
sage: 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]]); d, u, v = m.smith_form(); u * m * v == d
12404
True
12405
sage: m = matrix(OE, 3, 3, [-5*w-1,-2*w-2,4*w-10,8*w,-w,w-1,-1,1,-8]); d,u,v = m.smith_form(); u*m*v == d
12406
True
12407
"""
12408
R = self.base_ring()
12409
left_mat = self.new_matrix(self.nrows(), self.nrows(), 1)
12410
right_mat = self.new_matrix(self.ncols(), self.ncols(), 1)
12411
if self == 0 or (self.nrows() <= 1 and self.ncols() <= 1):
12412
return self.__copy__(), left_mat, right_mat
12413
12414
# data type checks on R
12415
if not R.is_integral_domain() or not R.is_noetherian():
12416
raise TypeError, "Smith form only defined over Noetherian integral domains"
12417
if not R.is_exact():
12418
raise NotImplementedError, "Smith form over non-exact rings not implemented at present"
12419
12420
# first clear the first row and column
12421
u,t,v = _smith_onestep(self)
12422
12423
# now recurse: t now has a nonzero entry at 0,0 and zero entries in the rest
12424
# of the 0th row and column, so we apply smith_form to the smaller submatrix
12425
mm = t.submatrix(1,1)
12426
dd, uu, vv = mm.smith_form()
12427
mone = self.new_matrix(1, 1, [1])
12428
d = dd.new_matrix(1,1,[t[0,0]]).block_sum(dd)
12429
u = uu.new_matrix(1,1,[1]).block_sum(uu) * u
12430
v = v * vv.new_matrix(1,1,[1]).block_sum(vv)
12431
dp, up, vp = _smith_diag(d)
12432
return dp,up*u,v*vp
12433
12434
def hermite_form(self, include_zero_rows=True, transformation=False):
12435
"""
12436
Return the Hermite form of self, if it is defined.
12437
12438
INPUT:
12439
12440
- ``include_zero_rows`` -- bool (default: True); if False
12441
the zero rows in the output matrix are deleted.
12442
12443
- ``transformation`` -- bool (default: False) a matrix U such that U*self == H.
12444
12445
OUTPUT:
12446
12447
- matrix H
12448
- (optional) transformation matrix U such that U*self == H, possibly with zero
12449
rows deleted...
12450
12451
12452
EXAMPLES::
12453
12454
sage: M = FunctionField(GF(7),'x').maximal_order()
12455
sage: K.<x> = FunctionField(GF(7)); M = K.maximal_order()
12456
sage: A = matrix(M, 2, 3, [x, 1, 2*x, x, 1+x, 2])
12457
sage: A.hermite_form()
12458
[ x 1 2*x]
12459
[ 0 x 5*x + 2]
12460
sage: A.hermite_form(transformation=True)
12461
(
12462
[ x 1 2*x] [1 0]
12463
[ 0 x 5*x + 2], [6 1]
12464
)
12465
sage: A = matrix(M, 2, 3, [x, 1, 2*x, 2*x, 2, 4*x])
12466
sage: A.hermite_form(transformation=True, include_zero_rows=False)
12467
([ x 1 2*x], [1 0])
12468
sage: H, U = A.hermite_form(transformation=True, include_zero_rows=True); H, U
12469
(
12470
[ x 1 2*x] [1 0]
12471
[ 0 0 0], [5 1]
12472
)
12473
sage: U*A == H
12474
True
12475
sage: H, U = A.hermite_form(transformation=True, include_zero_rows=False)
12476
sage: U*A
12477
[ x 1 2*x]
12478
sage: U*A == H
12479
True
12480
"""
12481
left, H, pivots = self._echelon_form_PID()
12482
if not include_zero_rows:
12483
i = H.nrows() - 1
12484
while H.row(i) == 0:
12485
i -= 1
12486
H = H[:i+1]
12487
if transformation:
12488
left = left[:i+1]
12489
if transformation:
12490
return H, left
12491
else:
12492
return H
12493
12494
def _echelon_form_PID(self):
12495
r"""
12496
Return a triple (left, a, pivots) where left*self == a and a is row
12497
echelon form (which in this case we define to mean Hermite normal
12498
form).
12499
12500
When ideals of the base ring have a "small_residue" method (as is the
12501
case for number field ideals), we use this to reduce entries above each
12502
column pivot.
12503
12504
AUTHOR:
12505
12506
- David Loeffler (2009-06-01)
12507
12508
- Moritz Minzlaff (2011-03-17): corrected code for matrices of one row;
12509
this fixed trac 9053
12510
12511
EXAMPLES::
12512
12513
sage: L.<a> = NumberField(x^3 - 2)
12514
sage: OL = L.ring_of_integers()
12515
12516
We check some degenerate cases::
12517
12518
sage: m = matrix(OL, 0, 0, []); r,s,p = m._echelon_form_PID();
12519
sage: (r,s,p)
12520
([], [], [])
12521
sage: r * m == s and r.det() == 1
12522
True
12523
sage: m = matrix(OL, 0, 1, []); r,s,p = m._echelon_form_PID();
12524
sage: (r,s,p)
12525
([], [], [])
12526
sage: r * m == s and r.det() == 1
12527
True
12528
sage: m = matrix(OL, 1, 0, []); r,s,p = m._echelon_form_PID();
12529
sage: (r,s,p)
12530
([1], [], [])
12531
sage: r * m == s and r.det() == 1
12532
True
12533
12534
A 2x2 matrix::
12535
12536
sage: m = matrix(OL, 2, 2, [1,0, a, 2]);
12537
sage: r,s,p = m._echelon_form_PID(); (r,s,p)
12538
(
12539
[ 1 0] [1 0]
12540
[-a 1], [0 2], [0, 1]
12541
)
12542
sage: r * m == s and r.det() == 1
12543
True
12544
12545
A larger example::
12546
12547
sage: m = matrix(OL, 3, 5, [a^2 - 3*a - 1, a^2 - 3*a + 1, a^2 + 1,
12548
... -a^2 + 2, -3*a^2 - a - 1, -6*a - 1, a^2 - 3*a - 1,
12549
... 2*a^2 + a + 5, -2*a^2 + 5*a + 1, -a^2 + 13*a - 3,
12550
... -2*a^2 + 4*a - 2, -2*a^2 + 1, 2*a, a^2 - 6, 3*a^2 - a ])
12551
sage: r,s,p = m._echelon_form_PID()
12552
sage: s[2]
12553
(0, 0, -3*a^2 - 18*a + 34, -68*a^2 + 134*a - 53, -111*a^2 + 275*a - 90)
12554
sage: r * m == s and r.det() == 1
12555
True
12556
12557
We verify that trac 9053 is resolved::
12558
12559
sage: R.<x> = GF(7)[]
12560
sage: A = R^3
12561
sage: L = A.span([x*A.0 + (x^3 + 1)*A.1, x*A.2])
12562
sage: M = A.span([x*L.0])
12563
sage: M.0 in L
12564
True
12565
12566
"""
12567
if self.ncols() == 0:
12568
return self.new_matrix(self.nrows(), self.nrows(), 1), self, []
12569
12570
if self.nrows() == 0:
12571
return self.new_matrix(self.nrows(), self.nrows(), 1), self, []
12572
12573
if self.nrows() == 1:
12574
if self.is_zero():
12575
return self.new_matrix(self.nrows(), self.nrows(), 1), self, []
12576
else:
12577
return self.new_matrix(self.nrows(), self.nrows(), 1), self, [
12578
self.nonzero_positions_in_row(0)[0] ]
12579
12580
R = self.base_ring()
12581
12582
# data type checks on R
12583
if not R.is_integral_domain():
12584
raise TypeError, ( "Generic echelon form only defined over "
12585
"integral domains" )
12586
if not R.is_exact():
12587
raise NotImplementedError, ( "Echelon form over generic non-exact "
12588
"rings not implemented at present" )
12589
12590
left_mat, a = _generic_clear_column(self)
12591
assert left_mat * self == a
12592
12593
if a[0,0] != 0:
12594
aa = a.submatrix(1, 1)
12595
s, t, pivs = aa._echelon_form_PID()
12596
left_mat = s.new_matrix(1,1,[1]).block_sum(s) * left_mat
12597
a = left_mat * self
12598
pivs = [0] + [x + 1 for x in pivs]
12599
12600
else:
12601
aa = a.submatrix(0, 1)
12602
s, t, pivs = aa._echelon_form_PID()
12603
left_mat = s * left_mat
12604
a = left_mat * self
12605
pivs = [x+1 for x in pivs]
12606
12607
12608
try:
12609
for i in xrange(1, len(pivs)):
12610
y = a[i][pivs[i]]
12611
I = R.ideal(y)
12612
s = a[0][pivs[i]]
12613
t = I.small_residue(s)
12614
v = R( (s-t) / y)
12615
12616
left_mat.add_multiple_of_row(0, i, -v)
12617
a.add_multiple_of_row(0, i, -v)
12618
assert left_mat * self == a
12619
except AttributeError: # on I.small_residue
12620
pass
12621
12622
return left_mat, a, pivs
12623
12624
def _zigzag_form(self, basis=True):
12625
r"""
12626
Helper method for computation of ZigZag form.
12627
12628
INPUT:
12629
12630
- ``self`` - a square matrix over an exact field.
12631
12632
- ``basis`` - default; ``True`` - controls whether or not to
12633
compute a change-of-basis matrix (also called a transformation
12634
matrix).
12635
12636
OUTPUT:
12637
12638
See the documentation for the :meth:`zigzag_form` method for a
12639
description of ZigZag form and notes on the algorithm employed.
12640
12641
When ``basis=True`` four items are returned. The first is a matrix
12642
whose columns form a basis so that a matrix representation of ``self``
12643
relative to this basis will be the ZigZag form. More precisely, if
12644
`A` is the matrix, `U` is the change-of-basis matrix and `Z` is
12645
the ZigZag form, then
12646
12647
.. math::
12648
12649
U^{-1}*A*U = Z
12650
12651
The second item returned is the ZigZag form of the matrix. The
12652
third item is a list of lists, where each list is the coefficients
12653
of the polynomial associated with a companion matrix in the form.
12654
Finally, the fourth item is a list of the entries in the upper-left
12655
corner of each off-diagonal block, which will be a zero or a one.
12656
The length of the list of corner entries will be one less than the
12657
length of list of polynomials.
12658
12659
When ``basis=False`` only three items are returned. These are
12660
just as above, but without the change-of-basis matrix.
12661
12662
The compuation of the change-of-basis matrix has not been optimized.
12663
As a helper method, no error checking is performed on the inputs -
12664
that should be performed by the calling method.
12665
12666
ALGORITHM:
12667
12668
ZigZag form, and its computation, are due to Arne Storjohann
12669
and are described in [STORJOHANN-THESIS]_ and
12670
[STORJOHANN-ISACC98]_, where the former is more
12671
representative of the code here.
12672
12673
EXAMPLE:
12674
12675
sage: A = matrix(QQ, [[-68, 69, -27, -11, -65, 9, -181, -32],
12676
... [-52, 52, -27, -8, -52, -16, -133, -14],
12677
... [ 92, -97, 47, 14, 90, 32, 241, 18],
12678
... [139, -144, 60, 18, 148, -10, 362, 77],
12679
... [ 40, -41, 12, 6, 45, -24, 105, 42],
12680
... [-46, 48, -20, -7, -47, 0, -122, -22],
12681
... [-26, 27, -13, -4, -29, -6, -66, -14],
12682
... [-33, 34, -13, -5, -35, 7, -87, -23]])
12683
sage: Z, polys, corners = A._zigzag_form(basis=False)
12684
sage: Z
12685
[ 0 0 0 40 1 0 0 0]
12686
[ 1 0 0 52 0 0 0 0]
12687
[ 0 1 0 18 0 0 0 0]
12688
[ 0 0 1 -1 0 0 0 0]
12689
[ 0 0 0 0 0 1 0 0]
12690
[ 0 0 0 0 -25 10 0 0]
12691
[ 0 0 0 0 1 0 0 -4]
12692
[ 0 0 0 0 0 0 1 -4]
12693
sage: polys
12694
[[-40, -52, -18, 1, 1], [25, -10, 1], [4, 4, 1]]
12695
sage: corners
12696
[1, 1]
12697
sage: len(polys) == len(corners) + 1
12698
True
12699
12700
sage: U, X, polys, corners = A._zigzag_form()
12701
sage: 38416*U
12702
[ 38416 -2612288 -8797264 -47943168 83753660284 -16775074316 1574993574 -12141218334]
12703
[ 0 -1997632 -7222208 -38108672 66323477868 -13362573684 3694412232 -12414630592]
12704
[ 0 3534272 12523616 66920672 -116699384082 23442252424 -4176610942 18012693216]
12705
[ 0 5339824 18631760 100842000 -175585304193 35191011843 -3619613634 22708786576]
12706
[ 0 1536640 5301408 28812000 -50432310506 10071675864 79884994 5258177064]
12707
[ 0 -1767136 -6261808 -33460336 58377759731 -11719115889 1849749314 -8725304756]
12708
[ 0 -998816 -3611104 -19054336 33189768208 -6681286842 1651135654 -5815174372]
12709
[ 0 -1267728 -4456256 -23933168 41831027339 -8380482791 785625330 -5536675718]
12710
sage: X == Z
12711
True
12712
sage: U.inverse()*A*U == X
12713
True
12714
12715
AUTHOR:
12716
12717
- Rob Beezer (2011-06-09)
12718
"""
12719
import sage.matrix.constructor
12720
cdef Py_ssize_t n, s, c, i, j, k
12721
12722
n = self._ncols
12723
R = self.base_ring()
12724
zero = R(0)
12725
one = R(1)
12726
cdef Matrix Z
12727
Z = self.__copy__()
12728
polys = [] # coefficients for polynomials of companion matrices
12729
corners = [] # zero or one in corner of off-diagonal blocks
12730
if basis:
12731
U = sage.matrix.constructor.identity_matrix(R, n) # transformation matrix
12732
# parity switch, True iff working on transpose
12733
# if False, mimic row operations only on U
12734
# if True, mimic column operations only on U
12735
trans = False
12736
s = 0 # index of top row of current block
12737
c = 0 # index of current row of current block
12738
while s < n:
12739
zigging = True
12740
# check for totally zero column below diagonal
12741
while zigging: # zigging means we are building a block
12742
nonzero = -1
12743
for i in range(c+1, n):
12744
if Z[i, c] != 0:
12745
nonzero = i
12746
break
12747
zigging = (nonzero != -1)
12748
if zigging:
12749
Z.swap_rows(nonzero, c+1)
12750
Z.swap_columns(nonzero, c+1)
12751
if basis:
12752
if trans:
12753
U.swap_columns(nonzero, c+1)
12754
else:
12755
U.swap_rows(nonzero, c+1)
12756
12757
# create a subdiagonal entry 1
12758
scale = Z[c+1, c]
12759
Z.rescale_row(c+1, 1/scale)
12760
Z.rescale_col(c+1, scale)
12761
if basis:
12762
if trans:
12763
U.rescale_col(c+1, scale)
12764
else:
12765
U.rescale_row(c+1, 1/scale)
12766
12767
# clear column throughout the block,and in all rows below
12768
for i in range(s, n):
12769
if i != c+1:
12770
scale = Z[i, c]
12771
Z.add_multiple_of_row(i, c+1, -scale)
12772
Z.add_multiple_of_column(c+1, i, scale)
12773
if basis:
12774
if trans:
12775
U.add_multiple_of_column(c+1, i, scale)
12776
else:
12777
U.add_multiple_of_row(i, c+1, -scale)
12778
# move to next column
12779
# column of coefficients will cause zero search to fail
12780
# at the top of this loop, and then we leave the column alone
12781
# having built a block
12782
c = c + 1
12783
12784
# now have a companion matrix between rows s and c
12785
# (inclusive), use it to clear entries to the right
12786
# but first record polynomial for block just built
12787
# this is the full monic polynomial, with correct coefficients
12788
p = []
12789
for i in range(s, c+1):
12790
p.append(-Z[i, c])
12791
p.append(R(1))
12792
polys.append(p)
12793
12794
# use new unit columns (i) to clear rows to right (j)
12795
# all but top row of block to the right will become zero
12796
# it is important that the loop on i goes in reverse
12797
for i in range(c-1, s-1, -1):
12798
for j in range(c+1, n):
12799
scale = Z[i+1, j]
12800
# Effectively: Z.add_multiple_of_column(j, i, -scale)
12801
Z.set_unsafe(i+1, j, zero)
12802
# row j leads with zeros, up to, and including column c
12803
# Effectively: Z.add_multiple_of_row(i, j, scale)
12804
for k in range(c+1, n):
12805
# Z[i,k] = Z[i,k] + scale*Z[j,k]
12806
Z.set_unsafe(i, k, Z.get_unsafe(i,k)+scale*Z.get_unsafe(j,k))
12807
if basis:
12808
if trans:
12809
U.add_multiple_of_column(j, i, -scale)
12810
else:
12811
U.add_multiple_of_row(i, j, scale)
12812
12813
# row s to the right of the block needs care
12814
# we will be left with a leading one, or totally zeros
12815
nonzero = -1
12816
# locate a nonzero entry in row s
12817
for j in range(c+1, n):
12818
if Z[s, j] != 0:
12819
nonzero = j
12820
break
12821
if (nonzero != -1):
12822
# swap column wih nonzero entry just outside block
12823
if nonzero != c+1:
12824
Z.swap_columns(c+1, nonzero)
12825
Z.swap_rows(c+1, nonzero)
12826
if basis:
12827
if trans:
12828
U.swap_columns(c+1, nonzero)
12829
else:
12830
U.swap_rows(c+1, nonzero)
12831
scale = Z[s, c+1]
12832
Z.rescale_col(c+1, 1/scale)
12833
Z.rescale_row(c+1, scale)
12834
if basis:
12835
if trans:
12836
U.rescale_col(c+1, 1/scale)
12837
else:
12838
U.rescale_row(c+1, scale)
12839
for j in range(c+2, n):
12840
scale = Z[s, j]
12841
# exploiting leading zeros does not seem too beneficial here
12842
Z.add_multiple_of_column(j, c+1, -scale)
12843
Z.add_multiple_of_row(c+1, j, scale)
12844
if basis:
12845
if trans:
12846
U.add_multiple_of_column(j, c+1, -scale)
12847
else:
12848
U.add_multiple_of_row(c+1, j, scale)
12849
12850
# maybe move this closer to where we know which it is
12851
if c < n-1:
12852
corners.append(Z[s, c+1])
12853
# reset indices for constructing next block
12854
# transpose all elements, this is a zig or a zag
12855
c = c+1
12856
s = c
12857
Z = Z.transpose()
12858
if basis:
12859
U = U.transpose()
12860
trans = not trans
12861
12862
# maybe return to un-transposed state
12863
if trans:
12864
Z = Z.transpose()
12865
if basis:
12866
U = U.transpose()
12867
if basis:
12868
# Storjohann computes U, we return its inverse
12869
# after this step, the columns of U are basis for representing self
12870
# code could be re-arranged to compute U's inverse directly
12871
return U.inverse(), Z, polys, corners
12872
return Z, polys, corners
12873
12874
def zigzag_form(self, subdivide=True, transformation=False):
12875
r"""
12876
Find a matrix in ZigZag form that is similar to ``self``.
12877
12878
INPUT:
12879
12880
- ``self`` - a square matrix with entries from an exact field.
12881
12882
- ``transformation`` - default: False - if ``True`` return a
12883
change-of-basis matrix relating the matrix and its ZigZag form.
12884
12885
- ``subdivide`` - default: ``True`` - if ``True`` the ZigZag
12886
form matrix is subdivided according to the companion matrices
12887
described in the output section below.
12888
12889
OUTPUT:
12890
12891
A matrix in ZigZag form has blocks on the main diagonal that are
12892
companion matrices. The first companion matrix has ones just below
12893
the main diagonal. The last column has the negatives of coefficients
12894
of a monic polynomial, but not the leading one. Low degree monomials
12895
have their coefficients in the earlier rows. The second companion
12896
matrix is like the first only transposed. The third is like the first.
12897
The fourth is like the second. And so on.
12898
12899
These blocks on the main diagonal define blocks just off the diagonal.
12900
To the right of the first companion matrix, and above the second
12901
companion matrix is a block that is totally zero, except the entry
12902
of the first row and first column may be a one. Below the second
12903
block and to the left of the third block is a block that is totally
12904
zero, except the entry of the first row and first column may be one.
12905
This alternating pattern continues. It may now be apparent how this
12906
form gets its name. Any other entry of the matrix is zero. So this
12907
form is reminiscent of rational canonical form and is a good precursor
12908
to that form.
12909
12910
If ``transformation`` is ``True``, then the output is a pair of
12911
matrices. The first is the form ``Z`` and the second is an invertible
12912
matrix ``U`` such that ``U.inverse()*self*U`` equals ``Z``. In other
12913
words, the repsentation of ``self`` with respect to the columns
12914
of ``U`` will be ``Z``.
12915
12916
If subdivide is ``True`` then the matrix returned as the form is
12917
partitioned according to the companion matrices and these may be
12918
manipulated by several different matrix methods.
12919
12920
For output that may be more useful as input to other routines,
12921
see the helper method :meth:`_zigzag_form`.
12922
12923
.. note::
12924
12925
An efffort has been made to optimize computation of the form,
12926
but no such work has been done for the computation of the
12927
transformation matrix, so for fastest results do not request the
12928
transformation matrix.
12929
12930
ALGORITHM:
12931
12932
ZigZag form, and its computation, are due to Arne Storjohann
12933
and are described in [STORJOHANN-THESIS]_ and
12934
[STORJOHANN-ISACC98]_, where the former is more
12935
representative of the code here.
12936
12937
EXAMPLES:
12938
12939
Two examples that illustrate ZigZag form well. Notice that this is
12940
*not* a canonical form. The two matrices below are similar, since
12941
they have equal Jordan canonical forms, yet their ZigZag forms are
12942
quite different. In other words, while the computation of the form
12943
is deterministic, the final result, when viewed as a property of a
12944
linear transformation, is dependent on the basis used for the
12945
matrix representation. ::
12946
12947
sage: A = matrix(QQ, [[-68, 69, -27, -11, -65, 9, -181, -32],
12948
... [-52, 52, -27, -8, -52, -16, -133, -14],
12949
... [ 92, -97, 47, 14, 90, 32, 241, 18],
12950
... [139, -144, 60, 18, 148, -10, 362, 77],
12951
... [ 40, -41, 12, 6, 45, -24, 105, 42],
12952
... [-46, 48, -20, -7, -47, 0, -122, -22],
12953
... [-26, 27, -13, -4, -29, -6, -66, -14],
12954
... [-33, 34, -13, -5, -35, 7, -87, -23]])
12955
sage: Z, U = A.zigzag_form(transformation=True)
12956
sage: Z
12957
[ 0 0 0 40| 1 0| 0 0]
12958
[ 1 0 0 52| 0 0| 0 0]
12959
[ 0 1 0 18| 0 0| 0 0]
12960
[ 0 0 1 -1| 0 0| 0 0]
12961
[---------------+-------+-------]
12962
[ 0 0 0 0| 0 1| 0 0]
12963
[ 0 0 0 0|-25 10| 0 0]
12964
[---------------+-------+-------]
12965
[ 0 0 0 0| 1 0| 0 -4]
12966
[ 0 0 0 0| 0 0| 1 -4]
12967
sage: U.inverse()*A*U == Z
12968
True
12969
12970
sage: B = matrix(QQ, [[ 16, 69, -13, 2, -52, 143, 90, -3],
12971
... [ 26, 54, 6, -5, -28, 73, 73, -48],
12972
... [-16, -79, 12, -10, 64, -142, -115, 41],
12973
... [ 27, -7, 21, -33, 39, -20, -42, 43],
12974
... [ 8, -75, 34, -32, 86, -156, -130, 42],
12975
... [ 2, -17, 7, -8, 20, -33, -31, 16],
12976
... [-24, -80, 7, -3, 56, -136, -112, 42],
12977
... [ -6, -19, 0, -1, 13, -28, -27, 15]])
12978
sage: Z, U = B.zigzag_form(transformation=True)
12979
sage: Z
12980
[ 0 0 0 0 0 1000| 0| 0]
12981
[ 1 0 0 0 0 900| 0| 0]
12982
[ 0 1 0 0 0 -30| 0| 0]
12983
[ 0 0 1 0 0 -153| 0| 0]
12984
[ 0 0 0 1 0 3| 0| 0]
12985
[ 0 0 0 0 1 9| 0| 0]
12986
[-----------------------------+----+----]
12987
[ 0 0 0 0 0 0| -2| 0]
12988
[-----------------------------+----+----]
12989
[ 0 0 0 0 0 0| 1| -2]
12990
sage: U.inverse()*B*U == Z
12991
True
12992
12993
sage: A.jordan_form() == B.jordan_form()
12994
True
12995
12996
Two more examples, illustrating the two extremes of the zig-zag
12997
nature of this form. The first has a one in each of the
12998
off-diagonal blocks, the second has all zeros in each off-diagonal
12999
block. Notice again that the two matrices are similar, since their
13000
Jordan canonical forms are equal. ::
13001
13002
sage: C = matrix(QQ, [[2, 31, -10, -9, -125, 13, 62, -12],
13003
... [0, 48, -16, -16, -188, 20, 92, -16],
13004
... [0, 9, -1, 2, -33, 5, 18, 0],
13005
... [0, 15, -5, 0, -59, 7, 30, -4],
13006
... [0, -21, 7, 2, 84, -10, -42, 5],
13007
... [0, -42, 14, 8, 167, -17, -84, 13],
13008
... [0, -50, 17, 10, 199, -23, -98, 14],
13009
... [0, 15, -5, -2, -59, 7, 30, -2]])
13010
sage: Z, U = C.zigzag_form(transformation=True)
13011
sage: Z
13012
[2|1|0|0|0|0|0|0]
13013
[-+-+-+-+-+-+-+-]
13014
[0|2|0|0|0|0|0|0]
13015
[-+-+-+-+-+-+-+-]
13016
[0|1|2|1|0|0|0|0]
13017
[-+-+-+-+-+-+-+-]
13018
[0|0|0|2|0|0|0|0]
13019
[-+-+-+-+-+-+-+-]
13020
[0|0|0|1|2|1|0|0]
13021
[-+-+-+-+-+-+-+-]
13022
[0|0|0|0|0|2|0|0]
13023
[-+-+-+-+-+-+-+-]
13024
[0|0|0|0|0|1|2|1]
13025
[-+-+-+-+-+-+-+-]
13026
[0|0|0|0|0|0|0|2]
13027
sage: U.inverse()*C*U == Z
13028
True
13029
13030
sage: D = matrix(QQ, [[ -4, 3, 7, 2, -4, 5, 7, -3],
13031
... [ -6, 5, 7, 2, -4, 5, 7, -3],
13032
... [ 21, -12, 89, 25, 8, 27, 98, -95],
13033
... [ -9, 5, -44, -11, -3, -13, -48, 47],
13034
... [ 23, -13, 74, 21, 12, 22, 85, -84],
13035
... [ 31, -18, 135, 38, 12, 47, 155, -147],
13036
... [-33, 19, -138, -39, -13, -45, -156, 151],
13037
... [ -7, 4, -29, -8, -3, -10, -34, 34]])
13038
sage: Z, U = D.zigzag_form(transformation=True)
13039
sage: Z
13040
[ 0 -4| 0 0| 0 0| 0 0]
13041
[ 1 4| 0 0| 0 0| 0 0]
13042
[-----+-----+-----+-----]
13043
[ 0 0| 0 1| 0 0| 0 0]
13044
[ 0 0|-4 4| 0 0| 0 0]
13045
[-----+-----+-----+-----]
13046
[ 0 0| 0 0| 0 -4| 0 0]
13047
[ 0 0| 0 0| 1 4| 0 0]
13048
[-----+-----+-----+-----]
13049
[ 0 0| 0 0| 0 0| 0 1]
13050
[ 0 0| 0 0| 0 0|-4 4]
13051
sage: U.inverse()*D*U == Z
13052
True
13053
13054
sage: C.jordan_form() == D.jordan_form()
13055
True
13056
13057
ZigZag form is achieved entirely with the operations of the field, so
13058
while the eigenvalues may lie outside the field, this does not impede
13059
the computation of the form. ::
13060
13061
sage: F.<a> = GF(5^4)
13062
sage: A = matrix(F, [[ a, 0, 0, a + 3],
13063
... [ 0,a^2 + 1, 0, 0],
13064
... [ 0, 0,a^3, 0],
13065
... [a^2 +4 , 0, 0,a + 2]])
13066
sage: A.zigzag_form()
13067
[ 0 a^3 + 2*a^2 + 2*a + 2| 0| 0]
13068
[ 1 2*a + 2| 0| 0]
13069
[-------------------------------------------+---------------------+---------------------]
13070
[ 0 0| a^3| 0]
13071
[-------------------------------------------+---------------------+---------------------]
13072
[ 0 0| 0| a^2 + 1]
13073
sage: A.eigenvalues()
13074
Traceback (most recent call last):
13075
...
13076
NotImplementedError: eigenvalues() is not implemented for matrices with eigenvalues that are not in the fraction field of the base ring or in QQbar
13077
13078
Subdivisions are optional. ::
13079
13080
sage: F.<a> = GF(5^4)
13081
sage: A = matrix(F, [[ a, 0, 0, a + 3],
13082
... [ 0,a^2 + 1, 0, 0],
13083
... [ 0, 0,a^3, 0],
13084
... [a^2 +4 , 0, 0,a + 2]])
13085
sage: A.zigzag_form(subdivide=False)
13086
[ 0 a^3 + 2*a^2 + 2*a + 2 0 0]
13087
[ 1 2*a + 2 0 0]
13088
[ 0 0 a^3 0]
13089
[ 0 0 0 a^2 + 1]
13090
13091
TESTS::
13092
13093
sage: A = matrix(QQ, 2, 3, range(6))
13094
sage: A.zigzag_form()
13095
Traceback (most recent call last):
13096
...
13097
TypeError: matrix must be square, not 2 x 3
13098
13099
sage: A = matrix(Integers(6), 2, 2, range(4))
13100
sage: A.zigzag_form()
13101
Traceback (most recent call last):
13102
...
13103
TypeError: matrix entries must come from an exact field, not Ring of integers modulo 6
13104
13105
sage: A = matrix(RDF, 2, 2, range(4))
13106
sage: A.zigzag_form()
13107
Traceback (most recent call last):
13108
...
13109
TypeError: matrix entries must come from an exact field, not Real Double Field
13110
13111
sage: A = matrix(QQ, 2, range(4))
13112
sage: A.zigzag_form(transformation='junk')
13113
Traceback (most recent call last):
13114
...
13115
ValueError: 'transformation' keyword must be True or False, not junk
13116
13117
sage: A = matrix(QQ, 2, range(4))
13118
sage: A.zigzag_form(subdivide='garbage')
13119
Traceback (most recent call last):
13120
...
13121
ValueError: 'subdivide' keyword must be True or False, not garbage
13122
13123
.. rubric:: Citations
13124
13125
.. [STORJOHANN-THESIS] A. Storjohann, Algorithms
13126
for Matrix Canonical Forms. PhD Thesis. Department
13127
of Computer Science, Swiss Federal Institute of
13128
Technology -- ETH, 2000.
13129
13130
.. [STORJOHANN-ISACC98] A. Storjohann, An O(n^3)
13131
algorithm for Frobenius normal form. Proceedings
13132
of the International Symposium on Symbolic and
13133
Algebraic Computation (ISSAC'98), ACM Press, 1998, pp. 101-104.
13134
13135
AUTHOR:
13136
13137
- Rob Beezer (2011-06-09)
13138
"""
13139
R = self.base_ring()
13140
if not self.is_square():
13141
raise TypeError("matrix must be square, not {0} x {1}".format(self.nrows(), self.ncols()))
13142
if not (R.is_field() and R.is_exact()):
13143
raise TypeError("matrix entries must come from an exact field, not {0}".format(R))
13144
if transformation not in [True, False]:
13145
raise ValueError("'transformation' keyword must be True or False, not {0}".format(transformation))
13146
if subdivide not in [True, False]:
13147
raise ValueError("'subdivide' keyword must be True or False, not {0}".format(subdivide))
13148
if transformation:
13149
U, Z, polys, corners = self._zigzag_form(basis=True)
13150
else:
13151
Z, polys, corners = self._zigzag_form(basis=False)
13152
if subdivide:
13153
s = 0
13154
splits = []
13155
for p in polys[:-1]:
13156
s = s + len(p) - 1
13157
splits.append(s)
13158
Z.subdivide(splits, splits)
13159
if transformation:
13160
return Z, U
13161
else:
13162
return Z
13163
13164
def rational_form(self, format='right', subdivide=True):
13165
r"""
13166
Returns the rational canonical form, also known as Frobenius form.
13167
13168
INPUT:
13169
13170
- ``self`` - a square matrix with entries from an exact field.
13171
13172
- ``format`` - default: 'right' - one of 'right', 'bottom',
13173
'left', 'top' or 'invariants'. The first four will cause a
13174
matrix to be returned with companion matrices dictated by the
13175
keyword. The value 'invariants' will cause a list of lists to
13176
be returned, where each list contains coefficients of a
13177
polynomial associated with a companion matrix.
13178
13179
- ``subdivide`` - default: 'True' - if 'True' and a matrix is
13180
returned, then it contains subdivisions delineating the
13181
companion matrices along the diagonal.
13182
13183
OUTPUT:
13184
13185
The rational form of a matrix is a similar matrix composed of
13186
submatrices ("blocks") placed on the main diagonal. Each block
13187
is a companion matrix. Associated with each companion matrix is a
13188
polynomial. In rational form, the polynomial of one block will
13189
divide the polynomial of the next block (and thus, the polynomials
13190
of all subsequent blocks).
13191
13192
Rational form, also known as Frobenius form, is a canonical form.
13193
In other words, two matrices are similar if and only if their
13194
rational canonical forms are equal. The algorithm used does not
13195
provide the similarity transformation matrix (also known as the
13196
change-of-basis matrix).
13197
13198
Companion matrices may be written in one of four styles, and any
13199
such style may be selected with the ``format`` keyword. See the
13200
companion matrix constructor,
13201
:meth:`sage.matrix.constructor.companion_matrix`,
13202
for more information about companion matrices.
13203
13204
If the 'invariants' value is used for the ``format`` keyword,
13205
then the return value is a list of lists, where each list is the
13206
coefficients of the polynomial associated with one of the companion
13207
matrices on the diagonal. These coefficients include the leading
13208
one of the monic polynomial and are ready to be coerced into
13209
any polynomial ring over the same field (see examples of this below).
13210
This return value is intended to be the most compact representation
13211
and the easiest to use for testing equality of rational forms.
13212
13213
Because the minimal and characteristic polynomials of a companion
13214
matrix are the associated polynomial, it is easy to see that the
13215
product of the polynomials of the blocks will be the characteristic
13216
polynomial and the final polynomial will be the minimal polynomial
13217
of the entire matrix.
13218
13219
ALGORITHM:
13220
13221
We begin with ZigZag form, which is due to Arne Storjohann
13222
and is documented at :meth:`zigzag_form`. Then we eliminate
13223
''corner'' entries enroute to rational form via an additional
13224
algorithm of Storjohann's [STORJOHANN-EMAIL]_.
13225
13226
EXAMPLES:
13227
13228
The lists of coefficients returned with the ``invariants`` keyword
13229
are designed to easily convert to the polynomials associated with
13230
the companion matrices. This is illustrated by the construction
13231
below of the ``polys`` list. Then we can test the divisibility
13232
condition on the list of polynomials. Also the minimal and
13233
characteristic polynomials are easy to determine from this list. ::
13234
13235
sage: A = matrix(QQ, [[ 11, 14, -15, -4, -38, -29, 1, 23, 14, -63, 17, 24, 36, 32],
13236
... [ 18, 6, -17, -11, -31, -43, 12, 26, 0, -69, 11, 13, 17, 24],
13237
... [ 11, 16, -22, -8, -48, -34, 0, 31, 16, -82, 26, 31, 39, 37],
13238
... [ -8, -18, 22, 10, 46, 33, 3, -27, -12, 70, -19, -20, -42, -31],
13239
... [-13, -21, 16, 10, 52, 43, 4, -28, -25, 89, -37, -20, -53, -62],
13240
... [ -2, -6, 0, 0, 6, 10, 1, 1, -7, 14, -11, -3, -10, -18],
13241
... [ -9, -19, -3, 4, 23, 30, 8, -3, -27, 55, -40, -5, -40, -69],
13242
... [ 4, -8, -1, -1, 5, -4, 9, 5, -11, 4, -14, -2, -13, -17],
13243
... [ 1, -2, 16, -1, 19, -2, -1, -17, 2, 19, 5, -25, -7, 14],
13244
... [ 7, 7, -13, -4, -26, -21, 3, 18, 5, -40, 7, 15, 20, 14],
13245
... [ -6, -7, -12, 4, -1, 18, 3, 8, -11, 15, -18, 17, -15, -41],
13246
... [ 5, 11, -11, -3, -26, -19, -1, 14, 10, -42, 14, 17, 25, 23],
13247
... [-16, -15, 3, 10, 29, 45, -1, -13, -19, 71, -35, -2, -35, -65],
13248
... [ 4, 2, 3, -2, -2, -10, 1, 0, 3, -11, 6, -4, 6, 17]])
13249
sage: A.rational_form()
13250
[ 0 -4| 0 0 0 0| 0 0 0 0 0 0 0 0]
13251
[ 1 4| 0 0 0 0| 0 0 0 0 0 0 0 0]
13252
[---------+-------------------+---------------------------------------]
13253
[ 0 0| 0 0 0 12| 0 0 0 0 0 0 0 0]
13254
[ 0 0| 1 0 0 -4| 0 0 0 0 0 0 0 0]
13255
[ 0 0| 0 1 0 -9| 0 0 0 0 0 0 0 0]
13256
[ 0 0| 0 0 1 6| 0 0 0 0 0 0 0 0]
13257
[---------+-------------------+---------------------------------------]
13258
[ 0 0| 0 0 0 0| 0 0 0 0 0 0 0 -216]
13259
[ 0 0| 0 0 0 0| 1 0 0 0 0 0 0 108]
13260
[ 0 0| 0 0 0 0| 0 1 0 0 0 0 0 306]
13261
[ 0 0| 0 0 0 0| 0 0 1 0 0 0 0 -271]
13262
[ 0 0| 0 0 0 0| 0 0 0 1 0 0 0 -41]
13263
[ 0 0| 0 0 0 0| 0 0 0 0 1 0 0 134]
13264
[ 0 0| 0 0 0 0| 0 0 0 0 0 1 0 -64]
13265
[ 0 0| 0 0 0 0| 0 0 0 0 0 0 1 13]
13266
13267
sage: R = PolynomialRing(QQ, 'x')
13268
sage: invariants = A.rational_form(format='invariants')
13269
sage: invariants
13270
[[4, -4, 1], [-12, 4, 9, -6, 1], [216, -108, -306, 271, 41, -134, 64, -13, 1]]
13271
sage: polys = [R(p) for p in invariants]
13272
sage: [p.factor() for p in polys]
13273
[(x - 2)^2, (x - 3) * (x + 1) * (x - 2)^2, (x + 1)^2 * (x - 3)^3 * (x - 2)^3]
13274
sage: all(polys[i].divides(polys[i+1]) for i in range(len(polys)-1))
13275
True
13276
sage: polys[-1] == A.minimal_polynomial(var='x')
13277
True
13278
sage: prod(polys) == A.characteristic_polynomial(var='x')
13279
True
13280
13281
Rational form is a canonical form. Any two matrices are similar
13282
if and only if their rational forms are equal. By starting with
13283
Jordan canonical forms, the matrices ``C`` and ``D`` below were
13284
built as similar matrices, while ``E`` was built to be just
13285
slightly different. All three matrices have equal characteristic
13286
polynomials though ``E``'s minimal polynomial differs. ::
13287
13288
sage: C = matrix(QQ, [[2, 31, -10, -9, -125, 13, 62, -12],
13289
... [0, 48, -16, -16, -188, 20, 92, -16],
13290
... [0, 9, -1, 2, -33, 5, 18, 0],
13291
... [0, 15, -5, 0, -59, 7, 30, -4],
13292
... [0, -21, 7, 2, 84, -10, -42, 5],
13293
... [0, -42, 14, 8, 167, -17, -84, 13],
13294
... [0, -50, 17, 10, 199, -23, -98, 14],
13295
... [0, 15, -5, -2, -59, 7, 30, -2]])
13296
sage: C.minimal_polynomial().factor()
13297
(x - 2)^2
13298
sage: C.characteristic_polynomial().factor()
13299
(x - 2)^8
13300
sage: C.rational_form()
13301
[ 0 -4| 0 0| 0 0| 0 0]
13302
[ 1 4| 0 0| 0 0| 0 0]
13303
[-----+-----+-----+-----]
13304
[ 0 0| 0 -4| 0 0| 0 0]
13305
[ 0 0| 1 4| 0 0| 0 0]
13306
[-----+-----+-----+-----]
13307
[ 0 0| 0 0| 0 -4| 0 0]
13308
[ 0 0| 0 0| 1 4| 0 0]
13309
[-----+-----+-----+-----]
13310
[ 0 0| 0 0| 0 0| 0 -4]
13311
[ 0 0| 0 0| 0 0| 1 4]
13312
13313
sage: D = matrix(QQ, [[ -4, 3, 7, 2, -4, 5, 7, -3],
13314
... [ -6, 5, 7, 2, -4, 5, 7, -3],
13315
... [ 21, -12, 89, 25, 8, 27, 98, -95],
13316
... [ -9, 5, -44, -11, -3, -13, -48, 47],
13317
... [ 23, -13, 74, 21, 12, 22, 85, -84],
13318
... [ 31, -18, 135, 38, 12, 47, 155, -147],
13319
... [-33, 19, -138, -39, -13, -45, -156, 151],
13320
... [ -7, 4, -29, -8, -3, -10, -34, 34]])
13321
sage: D.minimal_polynomial().factor()
13322
(x - 2)^2
13323
sage: D.characteristic_polynomial().factor()
13324
(x - 2)^8
13325
sage: D.rational_form()
13326
[ 0 -4| 0 0| 0 0| 0 0]
13327
[ 1 4| 0 0| 0 0| 0 0]
13328
[-----+-----+-----+-----]
13329
[ 0 0| 0 -4| 0 0| 0 0]
13330
[ 0 0| 1 4| 0 0| 0 0]
13331
[-----+-----+-----+-----]
13332
[ 0 0| 0 0| 0 -4| 0 0]
13333
[ 0 0| 0 0| 1 4| 0 0]
13334
[-----+-----+-----+-----]
13335
[ 0 0| 0 0| 0 0| 0 -4]
13336
[ 0 0| 0 0| 0 0| 1 4]
13337
13338
sage: E = matrix(QQ, [[ 0, -8, 4, -6, -2, 5, -3, 11],
13339
... [-2, -4, 2, -4, -2, 4, -2, 6],
13340
... [ 5, 14, -7, 12, 3, -8, 6, -27],
13341
... [-3, -8, 7, -5, 0, 2, -6, 17],
13342
... [ 0, 5, 0, 2, 4, -4, 1, 2],
13343
... [-3, -7, 5, -6, -1, 5, -4, 14],
13344
... [ 6, 18, -10, 14, 4, -10, 10, -28],
13345
... [-2, -6, 4, -5, -1, 3, -3, 13]])
13346
sage: E.minimal_polynomial().factor()
13347
(x - 2)^3
13348
sage: E.characteristic_polynomial().factor()
13349
(x - 2)^8
13350
sage: E.rational_form()
13351
[ 2| 0 0| 0 0| 0 0 0]
13352
[---+-------+-------+-----------]
13353
[ 0| 0 -4| 0 0| 0 0 0]
13354
[ 0| 1 4| 0 0| 0 0 0]
13355
[---+-------+-------+-----------]
13356
[ 0| 0 0| 0 -4| 0 0 0]
13357
[ 0| 0 0| 1 4| 0 0 0]
13358
[---+-------+-------+-----------]
13359
[ 0| 0 0| 0 0| 0 0 8]
13360
[ 0| 0 0| 0 0| 1 0 -12]
13361
[ 0| 0 0| 0 0| 0 1 6]
13362
13363
13364
The principal feature of rational canonical form is that it
13365
can be computed over any field using only field operations. Other
13366
forms, such as Jordan canonical form, are complicated by the need to
13367
determine the eigenvalues of the matrix, which can lie outside
13368
the field. The following matrix has all of its eigenvalues
13369
outside the rationals - some are irrational (`\pm\sqrt{2}`) and
13370
the rest are complex (`-1\pm 2i`). ::
13371
13372
sage: A = matrix(QQ,
13373
... [[-154, -3, -54, 44, 48, -244, -19, 67, -326, 85, 355, 581],
13374
... [ 504, 25, 156, -145, -171, 793, 99, -213, 1036, -247, -1152, -1865],
13375
... [ 294, -1, 112, -89, -90, 469, 36, -128, 634, -160, -695, -1126],
13376
... [ -49, -32, 25, 7, 37, -64, -58, 12, -42, -14, 72, 106],
13377
... [-261, -123, 65, 47, 169, -358, -254, 70, -309, -29, 454, 673],
13378
... [-448, -123, -10, 109, 227, -668, -262, 163, -721, 95, 896, 1410],
13379
... [ 38, 7, 8, -14, -17, 66, 6, -23, 73, -29, -78, -143],
13380
... [ -96, 10, -55, 37, 24, -168, 17, 56, -231, 88, 237, 412],
13381
... [ 310, 67, 31, -81, -143, 473, 143, -122, 538, -98, -641, -1029],
13382
... [ 139, -35, 99, -49, -18, 236, -41, -70, 370, -118, -377, -619],
13383
... [ 243, 9, 81, -72, -81, 386, 43, -105, 508, -124, -564, -911],
13384
... [-155, -3, -55, 45, 50, -245, -27, 65, -328, 77, 365, 583]])
13385
sage: A.characteristic_polynomial().factor()
13386
(x^2 - 2)^2 * (x^2 + 2*x + 5)^4
13387
sage: A.eigenvalues(extend=False)
13388
[]
13389
sage: A.rational_form()
13390
[ 0 -5| 0 0 0 0| 0 0 0 0 0 0]
13391
[ 1 -2| 0 0 0 0| 0 0 0 0 0 0]
13392
[-------+---------------+-----------------------]
13393
[ 0 0| 0 0 0 10| 0 0 0 0 0 0]
13394
[ 0 0| 1 0 0 4| 0 0 0 0 0 0]
13395
[ 0 0| 0 1 0 -3| 0 0 0 0 0 0]
13396
[ 0 0| 0 0 1 -2| 0 0 0 0 0 0]
13397
[-------+---------------+-----------------------]
13398
[ 0 0| 0 0 0 0| 0 0 0 0 0 50]
13399
[ 0 0| 0 0 0 0| 1 0 0 0 0 40]
13400
[ 0 0| 0 0 0 0| 0 1 0 0 0 3]
13401
[ 0 0| 0 0 0 0| 0 0 1 0 0 -12]
13402
[ 0 0| 0 0 0 0| 0 0 0 1 0 -12]
13403
[ 0 0| 0 0 0 0| 0 0 0 0 1 -4]
13404
sage: F.<x> = QQ[]
13405
sage: polys = A.rational_form(format='invariants')
13406
sage: [F(p).factor() for p in polys]
13407
[x^2 + 2*x + 5, (x^2 - 2) * (x^2 + 2*x + 5), (x^2 - 2) * (x^2 + 2*x + 5)^2]
13408
13409
Rational form may be computed over any field. The matrix below is
13410
an example where the eigenvalues lie outside the field. ::
13411
13412
sage: F.<a> = FiniteField(7^2)
13413
sage: A = matrix(F,
13414
... [[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],
13415
... [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],
13416
... [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],
13417
... [ 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],
13418
... [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],
13419
... [ 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],
13420
... [4*a + 5, 3*a + 3, 6, 4*a + 1, 4*a + 3, 6*a + 3, 6, 3*a + 3, 3, a + 3, 0],
13421
... [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],
13422
... [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],
13423
... [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],
13424
... [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]])
13425
sage: A.rational_form()
13426
[ a + 2| 0 0 0| 0 0 0 0 0 0 0]
13427
[-------+-----------------------+-------------------------------------------------------]
13428
[ 0| 0 0 a + 6| 0 0 0 0 0 0 0]
13429
[ 0| 1 0 6*a + 4| 0 0 0 0 0 0 0]
13430
[ 0| 0 1 6*a + 4| 0 0 0 0 0 0 0]
13431
[-------+-----------------------+-------------------------------------------------------]
13432
[ 0| 0 0 0| 0 0 0 0 0 0 2*a]
13433
[ 0| 0 0 0| 1 0 0 0 0 0 6*a + 3]
13434
[ 0| 0 0 0| 0 1 0 0 0 0 6*a + 1]
13435
[ 0| 0 0 0| 0 0 1 0 0 0 a + 2]
13436
[ 0| 0 0 0| 0 0 0 1 0 0 a + 6]
13437
[ 0| 0 0 0| 0 0 0 0 1 0 2*a + 1]
13438
[ 0| 0 0 0| 0 0 0 0 0 1 2*a + 1]
13439
sage: invariants = A.rational_form(format='invariants')
13440
sage: invariants
13441
[[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]]
13442
sage: R.<x> = F[]
13443
sage: polys = [R(p) for p in invariants]
13444
sage: [p.factor() for p in polys]
13445
[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]
13446
sage: polys[-1] == A.minimal_polynomial()
13447
True
13448
sage: prod(polys) == A.characteristic_polynomial()
13449
True
13450
sage: A.eigenvalues()
13451
Traceback (most recent call last):
13452
...
13453
NotImplementedError: eigenvalues() is not implemented for matrices with eigenvalues that are not in the fraction field of the base ring or in QQbar
13454
13455
Companion matrices may be selected as any one of four different types.
13456
See the documentation for the companion matrix constructor,
13457
:meth:`sage.matrix.constructor.companion_matrix`, for more information. ::
13458
13459
sage: A = matrix(QQ, [[35, -18, -2, -45],
13460
... [22, -22, 12, -16],
13461
... [ 5, -12, 12, 4],
13462
... [16, -6, -4, -23]])
13463
sage: A.rational_form(format='right')
13464
[ 2| 0 0 0]
13465
[--+--------]
13466
[ 0| 0 0 10]
13467
[ 0| 1 0 -1]
13468
[ 0| 0 1 0]
13469
sage: A.rational_form(format='bottom')
13470
[ 2| 0 0 0]
13471
[--+--------]
13472
[ 0| 0 1 0]
13473
[ 0| 0 0 1]
13474
[ 0|10 -1 0]
13475
sage: A.rational_form(format='left')
13476
[ 2| 0 0 0]
13477
[--+--------]
13478
[ 0| 0 1 0]
13479
[ 0|-1 0 1]
13480
[ 0|10 0 0]
13481
sage: A.rational_form(format='top')
13482
[ 2| 0 0 0]
13483
[--+--------]
13484
[ 0| 0 -1 10]
13485
[ 0| 1 0 0]
13486
[ 0| 0 1 0]
13487
13488
TESTS::
13489
13490
sage: A = matrix(QQ, 2, 3, range(6))
13491
sage: A.rational_form()
13492
Traceback (most recent call last):
13493
...
13494
TypeError: matrix must be square, not 2 x 3
13495
13496
sage: A = matrix(Integers(6), 2, 2, range(4))
13497
sage: A.rational_form()
13498
Traceback (most recent call last):
13499
...
13500
TypeError: matrix entries must come from an exact field, not Ring of integers modulo 6
13501
13502
sage: A = matrix(RDF, 2, 2, range(4))
13503
sage: A.rational_form()
13504
Traceback (most recent call last):
13505
...
13506
TypeError: matrix entries must come from an exact field, not Real Double Field
13507
13508
sage: A = matrix(QQ, 2, range(4))
13509
sage: A.rational_form(format='junk')
13510
Traceback (most recent call last):
13511
...
13512
ValueError: 'format' keyword must be 'right', 'bottom', 'left', 'top' or 'invariants', not junk
13513
13514
sage: A = matrix(QQ, 2, range(4))
13515
sage: A.rational_form(subdivide='garbage')
13516
Traceback (most recent call last):
13517
...
13518
ValueError: 'subdivide' keyword must be True or False, not garbage
13519
13520
.. rubric:: Citations
13521
13522
.. [STORJOHANN-EMAIL] A. Storjohann, Email Communication. 30 May 2011.
13523
13524
AUTHOR:
13525
13526
- Rob Beezer (2011-06-09)
13527
"""
13528
from sage.rings.arith import gcd # remove if translated to object-oriented calls
13529
import sage.rings.polynomial.polynomial_ring_constructor
13530
import sage.matrix.constructor
13531
13532
R = self.base_ring()
13533
if not self.is_square():
13534
raise TypeError("matrix must be square, not {0} x {1}".format(self.nrows(), self.ncols()))
13535
if not (R.is_field() and R.is_exact()):
13536
raise TypeError("matrix entries must come from an exact field, not {0}".format(R))
13537
if format not in ['right', 'bottom', 'left', 'top', 'invariants']:
13538
raise ValueError("'format' keyword must be 'right', 'bottom', 'left', 'top' or 'invariants', not {0}".format(format))
13539
if subdivide not in [True, False]:
13540
raise ValueError("'subdivide' keyword must be True or False, not {0}".format(subdivide))
13541
13542
_, polys, corners = self._zigzag_form(basis=False)
13543
k = len(polys)
13544
F = sage.rings.polynomial.polynomial_ring_constructor.PolynomialRing(R, 'x')
13545
C = [F(p) for p in polys]
13546
B = [(b == 1) for b in corners]
13547
B.append(False) # no last block, so no corner
13548
13549
if B[0]:
13550
V = [F(1)]
13551
else:
13552
V = [F(0)]
13553
13554
for j in range(1, k):
13555
V[j-1] = gcd([V[j-1],C[j],C[j-1]])
13556
for i in range(j-2, -1, -1):
13557
V[i] = gcd([V[i], V[i+1], C[i]])
13558
m = F(-1)
13559
for i in range(j):
13560
g = gcd(m*V[i], C[i])
13561
q, _ = C[i].quo_rem(g)
13562
C[i] = g
13563
if B[j]:
13564
_, V[i] = m.quo_rem(C[i])
13565
else:
13566
V[i] = F(0)
13567
m = m * q
13568
C[j] = m * C[j]
13569
if B[j]:
13570
V.append(m)
13571
else:
13572
V.append(F(0))
13573
13574
# Leading constant polynomials in C are size zero blocks, so toss them
13575
# Massage remainder to have leading coefficient 1
13576
while (len(C) > 0) and C[0].degree() == 0:
13577
C.remove(C[0])
13578
for i in range(len(C)):
13579
unit = C[i].list()[-1]
13580
if unit != R(1):
13581
C[i] = (1/unit)*C[i]
13582
13583
if format == 'invariants':
13584
inv = []
13585
for poly in C:
13586
inv.append(poly.list())
13587
return inv
13588
elif format in ['right', 'left', 'top', 'bottom']:
13589
companions = []
13590
for poly in C:
13591
companions.append(sage.matrix.constructor.companion_matrix(poly, format=format))
13592
return sage.matrix.constructor.block_diagonal_matrix(companions, subdivide=subdivide)
13593
13594
# A limited number of access-only properties are provided for matrices
13595
property T:
13596
r"""
13597
Returns the transpose of a matrix.
13598
13599
EXAMPLE::
13600
13601
sage: A = matrix(QQ, 5, range(25))
13602
sage: A.T
13603
[ 0 5 10 15 20]
13604
[ 1 6 11 16 21]
13605
[ 2 7 12 17 22]
13606
[ 3 8 13 18 23]
13607
[ 4 9 14 19 24]
13608
"""
13609
def __get__(self):
13610
return self.transpose()
13611
13612
property C:
13613
r"""
13614
Returns the conjugate matrix.
13615
13616
EXAMPLE::
13617
13618
sage: A = matrix(QQbar, [[ -3, 5 - 3*I, 7 - 4*I],
13619
... [7 + 3*I, -1 + 6*I, 3 + 5*I],
13620
... [3 + 3*I, -3 + 6*I, 5 + I]])
13621
sage: A.C
13622
[ -3 5 + 3*I 7 + 4*I]
13623
[ 7 - 3*I -1 - 6*I 3 - 5*I]
13624
[ 3 - 3*I -3 - 6*I 5 - 1*I]
13625
13626
"""
13627
def __get__(self):
13628
return self.conjugate()
13629
13630
property H:
13631
r"""
13632
Returns the conjugate-transpose (Hermitian) matrix.
13633
13634
EXAMPLE::
13635
13636
sage: A = matrix(QQbar, [[ -3, 5 - 3*I, 7 - 4*I],
13637
... [7 + 3*I, -1 + 6*I, 3 + 5*I],
13638
... [3 + 3*I, -3 + 6*I, 5 + I]])
13639
sage: A.H
13640
[ -3 7 - 3*I 3 - 3*I]
13641
[ 5 + 3*I -1 - 6*I -3 - 6*I]
13642
[ 7 + 4*I 3 - 5*I 5 - 1*I]
13643
"""
13644
def __get__(self):
13645
return self.conjugate().transpose()
13646
13647
property I:
13648
r"""
13649
Returns the inverse of the matrix, if it exists.
13650
13651
EXAMPLES::
13652
13653
sage: A = matrix(QQ, [[-5, -3, -1, -7],
13654
... [ 1, 1, 1, 0],
13655
... [-1, -2, -2, 0],
13656
... [-2, -1, 0, -4]])
13657
sage: A.I
13658
[ 0 2 1 0]
13659
[-4 -8 -2 7]
13660
[ 4 7 1 -7]
13661
[ 1 1 0 -2]
13662
13663
sage: B = matrix(QQ, [[-11, -5, 18, -6],
13664
... [ 1, 2, -6, 8],
13665
... [ -4, -2, 7, -3],
13666
... [ 1, -2, 5, -11]])
13667
sage: B.I
13668
Traceback (most recent call last):
13669
...
13670
ZeroDivisionError: input matrix must be nonsingular
13671
"""
13672
def __get__(self):
13673
return self.inverse()
13674
13675
# end of Matrix class methods
13676
13677
def _smith_diag(d):
13678
r"""
13679
For internal use by the smith_form routine. Given a diagonal matrix d
13680
over a ring r, return matrices d', a,b such that a\*d\*b = d' and
13681
d' is diagonal with each entry dividing the next.
13682
13683
If any of the d's is a unit, it replaces it with 1 (but no other
13684
attempt is made to pick "good" representatives of ideals).
13685
13686
EXAMPLE::
13687
13688
sage: from sage.matrix.matrix2 import _smith_diag
13689
sage: OE = EquationOrder(x^2 - x + 2, 'w')
13690
sage: A = matrix(OE, 2, [2,0,0,3])
13691
sage: D,U,V = _smith_diag(A); D,U,V
13692
(
13693
[1 0] [2 1] [ 1 -3]
13694
[0 6], [3 2], [-1 4]
13695
)
13696
sage: D == U*A*V
13697
True
13698
sage: m = matrix(GF(7),2, [3,0,0,6]); d,u,v = _smith_diag(m); d
13699
[1 0]
13700
[0 1]
13701
sage: u*m*v == d
13702
True
13703
"""
13704
13705
dp = d.__copy__()
13706
n = min(d.nrows(), d.ncols())
13707
R = d.base_ring()
13708
left = d.new_matrix(d.nrows(), d.nrows(), 1)
13709
right = d.new_matrix(d.ncols(), d.ncols(), 1)
13710
for i in xrange(n):
13711
I = R.ideal(dp[i,i])
13712
13713
if I == R.unit_ideal():
13714
if dp[i,i] != 1:
13715
left.add_multiple_of_row(i,i,R(R(1)/(dp[i,i])) - 1)
13716
dp[i,i] = R(1)
13717
continue
13718
13719
for j in xrange(i+1,n):
13720
if dp[j,j] not in I:
13721
t = R.ideal([dp[i,i], dp[j,j]]).gens_reduced()
13722
if len(t) > 1: raise ArithmeticError
13723
t = t[0]
13724
# find lambda, mu such that lambda*d[i,i] + mu*d[j,j] = t
13725
lamb = R(dp[i,i]/t).inverse_mod( R.ideal(dp[j,j]/t))
13726
mu = R((t - lamb*dp[i,i]) / dp[j,j])
13727
13728
newlmat = dp.new_matrix(dp.nrows(), dp.nrows(), 1)
13729
newlmat[i,i] = lamb
13730
newlmat[i,j] = 1
13731
newlmat[j,i] = R(-dp[j,j]*mu/t)
13732
newlmat[j,j] = R(dp[i,i]/t)
13733
newrmat = dp.new_matrix(dp.ncols(), dp.ncols(), 1)
13734
newrmat[i,i] = 1
13735
newrmat[i,j] = R(-dp[j,j]/t)
13736
newrmat[j,i] = mu
13737
newrmat[j,j] = R(lamb*dp[i,i] / t)
13738
13739
left = newlmat*left
13740
right = right*newrmat
13741
dp = newlmat*dp*newrmat
13742
return dp, left, right
13743
13744
def _generic_clear_column(m):
13745
r"""
13746
Reduce the first column of m to canonical form -- that is, all entries
13747
below the first are nonzero -- by multiplying on the left by invertible
13748
matrices over the given base ring. This assumes that the base ring is a
13749
PID. Returns a pair (left, a) where left*self = a and a has first column in
13750
canonical form.
13751
13752
If the first column is zero, then this function doesn't do anything very
13753
exciting.
13754
13755
Used by the smith_form and hermite_form methods.
13756
13757
EXAMPLES::
13758
13759
sage: L.<w> = NumberField(x^2 - x + 2)
13760
sage: OL = L.ring_of_integers(); w = OL(w)
13761
sage: m = matrix(OL, 8, 4, [2*w - 2, 2*w + 1, -2, w, 2, -2,-2*w - 2, -2*w + 2, -w + 2, 2*w + 1, -w + 2, -w - 2, -2*w, 2*w, -w+ 2, w - 1, -2*w + 2, 2*w + 2, 2*w - 1, -w, 2*w + 2, -w + 2, 2, 2*w -1, w - 4, -2*w - 2, 2*w - 1, 0, 6, 7, 2*w + 1, 14])
13762
sage: s,t = m.echelon_form(transformation=True); t*m == s # indirect doctest
13763
True
13764
sage: s[0]
13765
(w, 0, 0, 0)
13766
"""
13767
if m.nrows() <= 1 or m.ncols() <= 0:
13768
return m.new_matrix(m.nrows(), m.nrows(), 1), m
13769
13770
a = m.__copy__()
13771
left_mat = m.new_matrix(m.nrows(), m.nrows(), 1)
13772
R = m.base_ring()
13773
13774
# case 1: if a_{0, 0} = 0 and a_{k, 0} != 0 for some k, swap rows 0 and k.
13775
if a[0, 0] == 0:
13776
k = 0
13777
while a[k, 0] == 0:
13778
k += 1
13779
if k == a.nrows(): # first column is zero
13780
return left_mat, a
13781
# k is now first row such that a[k, 0] is nonzero
13782
left_mat[0,0] = 0
13783
left_mat[k,k] = 0
13784
left_mat[0,k] = 1
13785
left_mat[k,0] = -1
13786
a = left_mat*a
13787
if left_mat * m != a:
13788
raise ArithmeticError, "Something went wrong"
13789
13790
# case 2: if there is an entry at position (k,j) such that a_{0,j}
13791
# does not divide a_{k,j}, then we know that there are c,d in R such
13792
# that c.a_{0,j} - d.a_{k,j} = B where B = gcd(a_{0,j}, a_{k,j}) (which
13793
# is well-defined since R is a PID).
13794
# Then for appropriate e,f the matrix
13795
# [c,-d]
13796
# [e,f]
13797
# is invertible over R
13798
13799
if a[0,0] != 0:
13800
I = R.ideal(a[0, 0]) # need to make sure we change this when a[0,0] changes
13801
else:
13802
I = R.zero_ideal()
13803
for k in xrange(1, a.nrows()):
13804
if a[k,0] not in I:
13805
try:
13806
v = R.ideal(a[0,0], a[k,0]).gens_reduced()
13807
except Exception, msg:
13808
raise ArithmeticError, "%s\nCan't create ideal on %s and %s" % (msg, a[0,0], a[k,0])
13809
if len(v) > 1:
13810
raise ArithmeticError, "Ideal %s not principal" % R.ideal(a[0,0], a[k,0])
13811
B = v[0]
13812
13813
# now we find c,d, using the fact that c * (a_{0,0}/B) - d *
13814
# (a_{k,0}/B) = 1, so c is the inverse of a_{0,0}/B modulo
13815
# a_{k,0}/B.
13816
# need to handle carefully the case when a_{k,0}/B is a unit, i.e. a_{k,0} divides
13817
# a_{0,0}.
13818
13819
c = R(a[0,0] / B).inverse_mod(R.ideal(a[k,0] / B))
13820
d = R( (c*a[0,0] - B)/(a[k,0]) )
13821
13822
# sanity check
13823
if c*a[0,0] - d*a[k,0] != B:
13824
raise ArithmeticError
13825
13826
# now we find e,f such that e*d + c*f = 1 in the same way
13827
if c != 0:
13828
e = d.inverse_mod( R.ideal(c) )
13829
f = R((1 - d*e)/c)
13830
else:
13831
e = R(-a[k,0]/B) # here d is a unit and this is just 1/d
13832
f = R(1)
13833
13834
if e*d + c*f != 1:
13835
raise ArithmeticError
13836
newlmat = left_mat.parent()(1)
13837
newlmat[0,0] = c
13838
newlmat[0,k] = -d
13839
newlmat[k,0] = e
13840
newlmat[k,k] = f
13841
if newlmat.det() != 1:
13842
raise ArithmeticError
13843
a = newlmat*a
13844
I = R.ideal(a[0,0])
13845
left_mat = newlmat*left_mat
13846
if left_mat * m != a:
13847
raise ArithmeticError
13848
13849
# now everything in column 0 is divisible by the pivot
13850
for i in xrange(1,a.nrows()):
13851
s = R( a[i, 0]/a[0, 0])
13852
a.add_multiple_of_row(i, 0, -s )
13853
left_mat.add_multiple_of_row(i, 0, -s)
13854
if left_mat * m != a:
13855
raise ArithmeticError
13856
13857
return left_mat, a
13858
13859
def _smith_onestep(m):
13860
r"""
13861
Carry out one step of Smith normal form for matrix m. Returns three matrices a,b,c over
13862
the same base ring as m, such that a \* m \* c = b, a and c have
13863
determinant 1, and the zeroth row and column of b have no nonzero
13864
entries except b[0,0].
13865
13866
EXAMPLE::
13867
13868
sage: from sage.matrix.matrix2 import _smith_onestep
13869
sage: OE = NumberField(x^2 - x + 2,'w').ring_of_integers()
13870
sage: w = OE.ring_generators()[0]
13871
sage: m = matrix(OE, 3,3,[1,0,7,2,w, w+17, 13+8*w, 0, 6])
13872
sage: a,b,c = _smith_onestep(m); b
13873
[ 1 0 0]
13874
[ 0 w w + 3]
13875
[ 0 0 -56*w - 85]
13876
sage: a * m * c == b
13877
True
13878
"""
13879
13880
a = m.__copy__()
13881
left_mat = m.new_matrix(m.nrows(), m.nrows(), 1)
13882
right_mat = m.new_matrix(m.ncols(), m.ncols(), 1)
13883
13884
if m == 0 or (m.nrows() <= 1 and m.ncols() <= 1):
13885
return left_mat, m, right_mat
13886
13887
# preparation: if column 0 is zero, swap it with the first nonzero column
13888
j = 0
13889
while a.column(j) == 0: j += 1
13890
if j > 0:
13891
right_mat[0,0] = right_mat[j,j] = 0
13892
right_mat[0,j] = 1
13893
right_mat[j,0] = -1
13894
a = a*right_mat
13895
if m * right_mat != a:
13896
raise ArithmeticError
13897
13898
left_mat, a = _generic_clear_column(a)
13899
assert left_mat * m * right_mat == a
13900
13901
# test if everything to the right of the pivot in row 0 is good as well
13902
isdone = True
13903
for jj in xrange(j+1, a.ncols()):
13904
if a[0,jj] != 0:
13905
isdone = False
13906
13907
# if not we recurse -- algorithm must terminate if R is Noetherian.
13908
if isdone == False:
13909
s,t,u = _smith_onestep(a.transpose())
13910
left_mat = u.transpose() * left_mat
13911
a = t.transpose()
13912
right_mat = right_mat* s.transpose()
13913
13914
return left_mat, a, right_mat
13915
13916
def _dim_cmp(x,y):
13917
"""
13918
Used internally by matrix functions. Given 2-tuples (x,y), returns
13919
their comparison based on the first component.
13920
13921
EXAMPLES::
13922
13923
sage: from sage.matrix.matrix2 import _dim_cmp
13924
sage: V = [(QQ^3, 2), (QQ^2, 1)]
13925
sage: _dim_cmp(V[0], V[1])
13926
1
13927
"""
13928
return cmp(x[0].dimension(), y[0].dimension())
13929
13930
def decomp_seq(v):
13931
"""
13932
This function is used internally be the decomposition matrix
13933
method. It takes a list of tuples and produces a sequence that is
13934
correctly sorted and prints with carriage returns.
13935
13936
EXAMPLES::
13937
13938
sage: from sage.matrix.matrix2 import decomp_seq
13939
sage: V = [(QQ^3, 2), (QQ^2, 1)]
13940
sage: decomp_seq(V)
13941
[
13942
(Vector space of dimension 2 over Rational Field, 1),
13943
(Vector space of dimension 3 over Rational Field, 2)
13944
]
13945
"""
13946
list.sort(v, _dim_cmp)
13947
return Sequence(v, universe=tuple, check=False, cr=True)
13948
13949
13950
def cmp_pivots(x,y):
13951
"""
13952
Compare two sequences of pivot columns.
13953
13954
- If x is shorter than y, return -1, i.e., x < y, "not as good".
13955
13956
- If x is longer than y, x > y, "better".
13957
13958
- If the length is the same then x is better, i.e., x > y if the
13959
entries of x are correspondingly >= those of y with one being
13960
greater.
13961
"""
13962
if len(x) < len(y):
13963
return -1
13964
if len(x) > len(y):
13965
return 1
13966
if x < y:
13967
return 1
13968
elif x == y:
13969
return 0
13970
else:
13971
return -1
13972
13973
13974
def _choose(Py_ssize_t n, Py_ssize_t t):
13975
"""
13976
Returns all possible sublists of length t from range(n)
13977
13978
Based on algorithm T from Knuth's taocp part 4: 7.2.1.3 p.5 This
13979
function replaces the one based on algorithm L because it is
13980
faster.
13981
13982
EXAMPLES::
13983
13984
sage: from sage.matrix.matrix2 import _choose
13985
sage: _choose(1,1)
13986
[[0]]
13987
sage: _choose(4,1)
13988
[[0], [1], [2], [3]]
13989
sage: _choose(4,4)
13990
[[0, 1, 2, 3]]
13991
13992
AUTHORS:
13993
13994
- Jaap Spies (2007-11-14)
13995
"""
13996
cdef Py_ssize_t j, temp
13997
13998
x = [] # initialize T1
13999
c = range(t)
14000
if t == n:
14001
x.append(c)
14002
return x
14003
c.append(n)
14004
c.append(0)
14005
j = t-1
14006
14007
while True:
14008
x.append(c[:t]) # visit T2
14009
if j >= 0:
14010
c[j] = j+1
14011
j = j-1
14012
continue # goto T2
14013
14014
if c[0]+1 < c[1]: # T3 easy case!
14015
c[0] = c[0]+1
14016
continue
14017
else:
14018
j = 1
14019
14020
while True:
14021
c[j-1] = j-1 # T4 find j
14022
temp = c[j]+1
14023
if temp == c[j+1]:
14024
j = j+1
14025
else:
14026
break
14027
14028
14029
if j >= t: # T5 stop?
14030
break
14031
14032
c[j] = temp # T6
14033
j = j-1
14034
14035
return x
14036
14037
14038
def _binomial(Py_ssize_t n, Py_ssize_t k):
14039
"""
14040
Fast and unchecked implementation of binomial(n,k) This is only for
14041
internal use.
14042
14043
EXAMPLES::
14044
14045
sage: from sage.matrix.matrix2 import _binomial
14046
sage: _binomial(10,2)
14047
45
14048
sage: _binomial(10,5)
14049
252
14050
14051
AUTHORS:
14052
14053
- Jaap Spies (2007-10-26)
14054
"""
14055
cdef Py_ssize_t i
14056
14057
if k > (n/2):
14058
k = n-k
14059
if k == 0:
14060
return 1
14061
14062
result = n
14063
n, k = n-1, k-1
14064
i = 2
14065
while k > 0:
14066
result = (result*n)/i
14067
i, n, k = i+1, n-1, k-1
14068
return result
14069
14070
def _jordan_form_vector_in_difference(V, W):
14071
r"""
14072
Given two lists of vectors ``V`` and ``W`` over the same base field,
14073
returns a vector in the difference ``V - W``. If the difference is
14074
empty, returns ``None``.
14075
14076
NOTES:
14077
14078
This is meant to be a private helper method for the ``jordan_form`` method
14079
in the above class.
14080
14081
TEST::
14082
14083
sage: v = vector(ZZ, [1,0,0,0])
14084
sage: w = vector(ZZ, [0,1,0,0])
14085
sage: u = vector(ZZ, [1,1,0,0])
14086
sage: sage.matrix.matrix2._jordan_form_vector_in_difference([v,w], [u])
14087
(1, 0, 0, 0)
14088
"""
14089
if len(V) == 0:
14090
return None
14091
if len(W) == 0:
14092
return V[0]
14093
W_space = sage.all.span(W)
14094
for v in V:
14095
if v not in W_space:
14096
return v
14097
return None
14098
14099
14100