Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/matrix/matrix2.pyx
4057 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 "../ext/stdsage.pxi"
31
include "../ext/python.pxi"
32
include "../ext/interrupt.pxi"
33
34
from sage.misc.randstate cimport randstate, current_randstate
35
from sage.structure.sequence import Sequence
36
from sage.combinat.combinat import combinations_iterator
37
from sage.structure.element import is_Vector
38
from sage.misc.misc import verbose, get_verbose, 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
128
"""
129
if is_Vector(B):
130
return self.transpose().solve_right(B, check=check)
131
else:
132
return self.transpose().solve_right(B.transpose(), check=check).transpose()
133
134
def solve_right(self, B, check=True):
135
r"""
136
If self is a matrix `A`, then this function returns a
137
vector or matrix `X` such that `A X = B`. If
138
`B` is a vector then `X` is a vector and if
139
`B` is a matrix, then `X` is a matrix.
140
141
.. note::
142
143
In Sage one can also write ``A \backslash B`` for
144
``A.solve_right(B)``, i.e., Sage implements the "the
145
MATLAB/Octave backslash operator".
146
147
INPUT:
148
149
150
- ``B`` - a matrix or vector
151
152
- ``check`` - bool (default: True) - if False and self
153
is nonsquare, may not raise an error message even if there is no
154
solution. This is faster but more dangerous.
155
156
157
OUTPUT: a matrix or vector
158
159
.. seealso::
160
161
:meth:`solve_left`
162
163
EXAMPLES::
164
165
sage: A = matrix(QQ, 3, [1,2,3,-1,2,5,2,3,1])
166
sage: b = vector(QQ,[1,2,3])
167
sage: x = A \ b; x
168
(-13/12, 23/12, -7/12)
169
sage: A * x
170
(1, 2, 3)
171
172
We solve with A nonsquare::
173
174
sage: A = matrix(QQ,2,4, [0, -1, 1, 0, -2, 2, 1, 0]); B = matrix(QQ,2,2, [1, 0, 1, -1])
175
sage: X = A.solve_right(B); X
176
[-3/2 1/2]
177
[ -1 0]
178
[ 0 0]
179
[ 0 0]
180
sage: A*X == B
181
True
182
183
Another nonsingular example::
184
185
sage: A = matrix(QQ,2,3, [1,2,3,2,4,6]); v = vector([-1/2,-1])
186
sage: x = A \ v; x
187
(-1/2, 0, 0)
188
sage: A*x == v
189
True
190
191
Same example but over `\ZZ`::
192
193
sage: A = matrix(ZZ,2,3, [1,2,3,2,4,6]); v = vector([-1,-2])
194
sage: A \ v
195
(-1, 0, 0)
196
197
An example in which there is no solution::
198
199
sage: A = matrix(QQ,2,3, [1,2,3,2,4,6]); v = vector([1,1])
200
sage: A \ v
201
Traceback (most recent call last):
202
...
203
ValueError: matrix equation has no solutions
204
205
A ValueError is raised if the input is invalid::
206
207
sage: A = matrix(QQ,4,2, [0, -1, 1, 0, -2, 2, 1, 0])
208
sage: B = matrix(QQ,2,2, [1, 0, 1, -1])
209
sage: X = A.solve_right(B)
210
Traceback (most recent call last):
211
...
212
ValueError: number of rows of self must equal number of rows of B
213
214
We solve with A singular::
215
216
sage: A = matrix(QQ,2,3, [1,2,3,2,4,6]); B = matrix(QQ,2,2, [6, -6, 12, -12])
217
sage: X = A.solve_right(B); X
218
[ 6 -6]
219
[ 0 0]
220
[ 0 0]
221
sage: A*X == B
222
True
223
224
We illustrate left associativity, etc., of the backslash operator.
225
226
::
227
228
sage: A = matrix(QQ, 2, [1,2,3,4])
229
sage: A \ A
230
[1 0]
231
[0 1]
232
sage: A \ A \ A
233
[1 2]
234
[3 4]
235
sage: A.parent()(1) \ A
236
[1 2]
237
[3 4]
238
sage: A \ (A \ A)
239
[ -2 1]
240
[ 3/2 -1/2]
241
sage: X = A \ (A - 2); X
242
[ 5 -2]
243
[-3 2]
244
sage: A * X
245
[-1 2]
246
[ 3 2]
247
248
Solving over a polynomial ring::
249
250
sage: x = polygen(QQ, 'x')
251
sage: A = matrix(2, [x,2*x,-5*x^2+1,3])
252
sage: v = vector([3,4*x - 2])
253
sage: X = A \ v
254
sage: X
255
((-8*x^2 + 4*x + 9)/(10*x^3 + x), (19*x^2 - 2*x - 3)/(10*x^3 + x))
256
sage: A * X == v
257
True
258
259
Solving a system over the p-adics::
260
261
sage: k = Qp(5,4)
262
sage: a = matrix(k, 3, [1,7,3,2,5,4,1,1,2]); a
263
[ 1 + O(5^4) 2 + 5 + O(5^4) 3 + O(5^4)]
264
[ 2 + O(5^4) 5 + O(5^5) 4 + O(5^4)]
265
[ 1 + O(5^4) 1 + O(5^4) 2 + O(5^4)]
266
sage: v = vector(k, 3, [1,2,3])
267
sage: x = a \ v; x
268
(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))
269
sage: a * x == v
270
True
271
"""
272
273
if is_Vector(B):
274
if self.nrows() != B.degree():
275
raise ValueError, "number of rows of self must equal degree of B"
276
else:
277
if self.nrows() != B.nrows():
278
raise ValueError, "number of rows of self must equal number of rows of B"
279
280
K = self.base_ring()
281
if not K.is_integral_domain():
282
raise TypeError, "base ring must be an integral domain"
283
if not K.is_field():
284
K = K.fraction_field()
285
self = self.change_ring(K)
286
287
matrix = True
288
if is_Vector(B):
289
matrix = False
290
C = self.matrix_space(self.nrows(), 1)(B.list())
291
else:
292
C = B
293
294
if not self.is_square():
295
X = self._solve_right_general(C, check=check)
296
if not matrix:
297
# Convert back to a vector
298
return (X.base_ring() ** X.nrows())(X.list())
299
else:
300
return X
301
302
if self.rank() != self.nrows():
303
X = self._solve_right_general(C, check=check)
304
else:
305
X = self._solve_right_nonsingular_square(C, check_rank=False)
306
307
if not matrix:
308
# Convert back to a vector
309
return X.column(0)
310
else:
311
return X
312
313
def _solve_right_nonsingular_square(self, B, check_rank=True):
314
r"""
315
If self is a matrix `A` of full rank, then this function
316
returns a matrix `X` such that `A X = B`.
317
318
.. seealso::
319
320
:meth:`solve_right` and :meth:`solve_left`
321
322
INPUT:
323
324
325
- ``B`` - a matrix
326
327
- ``check_rank`` - bool (default: True)
328
329
330
OUTPUT: matrix
331
332
EXAMPLES::
333
334
sage: A = matrix(QQ,3,[1,2,4,5,3,1,1,2,-1])
335
sage: B = matrix(QQ,3,2,[1,5,1,2,1,5])
336
sage: A._solve_right_nonsingular_square(B)
337
[ -1/7 -11/7]
338
[ 4/7 23/7]
339
[ 0 0]
340
sage: A._solve_right_nonsingular_square(B, check_rank=False)
341
[ -1/7 -11/7]
342
[ 4/7 23/7]
343
[ 0 0]
344
sage: X = A._solve_right_nonsingular_square(B, check_rank=False)
345
sage: A*X == B
346
True
347
"""
348
D = self.augment(B).echelon_form()
349
return D.matrix_from_columns(range(self.ncols(),D.ncols()))
350
351
352
def pivot_rows(self):
353
"""
354
Return the pivot row positions for this matrix, which are a topmost
355
subset of the rows that span the row space and are linearly
356
independent.
357
358
OUTPUT: a tuple of integers
359
360
EXAMPLES::
361
362
sage: A = matrix(QQ,3,3, [0,0,0,1,2,3,2,4,6]); A
363
[0 0 0]
364
[1 2 3]
365
[2 4 6]
366
sage: A.pivot_rows()
367
(1,)
368
sage: A.pivot_rows() # testing cached value
369
(1,)
370
"""
371
v = self.fetch('pivot_rows')
372
if v is not None:
373
return tuple(v)
374
v = self.transpose().pivots()
375
self.cache('pivot_rows', v)
376
return v
377
378
def _solve_right_general(self, B, check=True):
379
r"""
380
This is used internally by the ``solve_right`` command
381
to solve for self\*X = B when self is not square or not of full
382
rank. It does some linear algebra, then solves a full-rank square
383
system.
384
385
INPUT:
386
387
388
- ``B`` - a matrix
389
390
- ``check`` - bool (default: True); if False, if there
391
is no solution this function will not detect that fact.
392
393
394
OUTPUT: matrix
395
396
EXAMPLES::
397
398
sage: A = matrix(QQ,2,3, [1,2,3,2,4,6]); B = matrix(QQ,2,2, [6, -6, 12, -12])
399
sage: A._solve_right_general(B)
400
[ 6 -6]
401
[ 0 0]
402
[ 0 0]
403
"""
404
pivot_cols = self.pivots()
405
A = self.matrix_from_columns(pivot_cols)
406
pivot_rows = A.pivot_rows()
407
A = A.matrix_from_rows(pivot_rows)
408
X = A.solve_right(B.matrix_from_rows(pivot_rows), check=False)
409
if len(pivot_cols) < self.ncols():
410
# Now we have to put in zeros for the non-pivot ROWS, i.e.,
411
# make a matrix from X with the ROWS of X interspersed with
412
# 0 ROWS.
413
Y = X.new_matrix(self.ncols(), X.ncols())
414
# Put the columns of X into the matrix Y at the pivot_cols positions
415
for i, c in enumerate(pivot_cols):
416
Y.set_row(c, X.row(i))
417
X = Y
418
if check:
419
# Have to check that we actually solved the equation.
420
if self*X != B:
421
raise ValueError, "matrix equation has no solutions"
422
return X
423
424
def prod_of_row_sums(self, cols):
425
r"""
426
Calculate the product of all row sums of a submatrix of `A`
427
for a list of selected columns ``cols``.
428
429
EXAMPLES::
430
431
sage: a = matrix(QQ, 2,2, [1,2,3,2]); a
432
[1 2]
433
[3 2]
434
sage: a.prod_of_row_sums([0,1])
435
15
436
437
Another example::
438
439
sage: a = matrix(QQ, 2,3, [1,2,3,2,5,6]); a
440
[1 2 3]
441
[2 5 6]
442
sage: a.prod_of_row_sums([1,2])
443
55
444
445
AUTHORS:
446
447
- Jaap Spies (2006-02-18)
448
"""
449
cdef Py_ssize_t c, row
450
pr = 1
451
for row from 0 <= row < self._nrows:
452
tmp = []
453
for c in cols:
454
# if c<0 or c >= self._ncols:
455
# raise IndexError, "matrix column index out of range"
456
tmp.append(self.get_unsafe(row, c))
457
pr = pr * sum(tmp)
458
return pr
459
460
def elementwise_product(self, right):
461
r"""
462
Returns the elementwise product of two matrices
463
of the same size (also known as the Hadamard product).
464
465
INPUT:
466
467
- ``right`` - the right operand of the product. A matrix
468
of the same size as ``self`` such that multiplication
469
of elements of the base rings of ``self`` and ``right``
470
is defined, once Sage's coercion model is applied. If
471
the matrices have different sizes, or if multiplication
472
of individual entries cannot be achieved, a ``TypeError``
473
will result.
474
475
OUTPUT:
476
477
A matrix of the same size as ``self`` and ``right``. The
478
entry in location `(i,j)` of the output is the product of
479
the two entries in location `(i,j)` of ``self`` and
480
``right`` (in that order).
481
482
The parent of the result is determined by Sage's coercion
483
model. If the base rings are identical, then the result
484
is dense or sparse according to this property for
485
the left operand. If the base rings must be adjusted
486
for one, or both, matrices then the result will be sparse
487
only if both operands are sparse. No subdivisions are
488
present in the result.
489
490
If the type of the result is not to your liking, or
491
the ring could be "tighter," adjust the operands with
492
:meth:`~sage.matrix.matrix0.Matrix.change_ring`.
493
Adjust sparse versus dense inputs with the methods
494
:meth:`~sage.matrix.matrix1.Matrix.sparse_matrix` and
495
:meth:`~sage.matrix.matrix1.Matrix.dense_matrix`.
496
497
EXAMPLES::
498
499
sage: A = matrix(ZZ, 2, range(6))
500
sage: B = matrix(QQ, 2, [5, 1/3, 2/7, 11/2, -3/2, 8])
501
sage: C = A.elementwise_product(B)
502
sage: C
503
[ 0 1/3 4/7]
504
[33/2 -6 40]
505
sage: C.parent()
506
Full MatrixSpace of 2 by 3 dense matrices over Rational Field
507
508
509
Notice the base ring of the results in the next two examples. ::
510
511
sage: D = matrix(ZZ[x],2,[1+x^2,2,3,4-x])
512
sage: E = matrix(QQ,2,[1,2,3,4])
513
sage: F = D.elementwise_product(E)
514
sage: F
515
[ x^2 + 1 4]
516
[ 9 -4*x + 16]
517
sage: F.parent()
518
Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Rational Field
519
520
::
521
522
sage: G = matrix(GF(3),2,[0,1,2,2])
523
sage: H = matrix(ZZ,2,[1,2,3,4])
524
sage: J = G.elementwise_product(H)
525
sage: J
526
[0 2]
527
[0 2]
528
sage: J.parent()
529
Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 3
530
531
Non-commutative rings behave as expected. These are the usual quaternions. ::
532
533
sage: R.<i,j,k> = QuaternionAlgebra(-1, -1)
534
sage: A = matrix(R, 2, [1,i,j,k])
535
sage: B = matrix(R, 2, [i,i,i,i])
536
sage: A.elementwise_product(B)
537
[ i -1]
538
[-k j]
539
sage: B.elementwise_product(A)
540
[ i -1]
541
[ k -j]
542
543
Input that is not a matrix will raise an error. ::
544
545
sage: A = random_matrix(ZZ,5,10,x=20)
546
sage: A.elementwise_product(vector(ZZ, [1,2,3,4]))
547
Traceback (most recent call last):
548
...
549
TypeError: operand must be a matrix, not an element of Ambient free module of rank 4 over the principal ideal domain Integer Ring
550
551
Matrices of different sizes for operands will raise an error. ::
552
553
sage: A = random_matrix(ZZ,5,10,x=20)
554
sage: B = random_matrix(ZZ,10,5,x=40)
555
sage: A.elementwise_product(B)
556
Traceback (most recent call last):
557
...
558
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
559
560
Some pairs of rings do not have a common parent where
561
multiplication makes sense. This will raise an error. ::
562
563
sage: A = matrix(QQ, 3, range(6))
564
sage: B = matrix(GF(3), 3, [2]*6)
565
sage: A.elementwise_product(B)
566
Traceback (most recent call last):
567
...
568
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'
569
570
We illustrate various combinations of sparse and dense matrices.
571
Notice how if base rings are unequal, both operands must be sparse
572
to get a sparse result. ::
573
574
sage: A = matrix(ZZ, 5, range(30), sparse=False)
575
sage: B = matrix(ZZ, 5, range(30), sparse=True)
576
sage: C = matrix(QQ, 5, range(30), sparse=True)
577
sage: A.elementwise_product(C).is_dense()
578
True
579
sage: B.elementwise_product(C).is_sparse()
580
True
581
sage: A.elementwise_product(B).is_dense()
582
True
583
sage: B.elementwise_product(A).is_dense()
584
True
585
586
TESTS:
587
588
Implementation for dense and sparse matrices are
589
different, this will provide a trivial test that
590
they are working identically. ::
591
592
sage: A = random_matrix(ZZ, 10, x=1000, sparse=False)
593
sage: B = random_matrix(ZZ, 10, x=1000, sparse=False)
594
sage: C = A.sparse_matrix()
595
sage: D = B.sparse_matrix()
596
sage: E = A.elementwise_product(B)
597
sage: F = C.elementwise_product(D)
598
sage: E.is_dense() and F.is_sparse() and (E == F)
599
True
600
601
If the ring has zero divisors, the routines for setting
602
entries of a sparse matrix should intercept zero results
603
and not create an entry. ::
604
605
sage: R = Integers(6)
606
sage: A = matrix(R, 2, [3, 2, 0, 0], sparse=True)
607
sage: B = matrix(R, 2, [2, 3, 1, 0], sparse=True)
608
sage: C = A.elementwise_product(B)
609
sage: len(C.nonzero_positions()) == 0
610
True
611
612
AUTHOR:
613
614
- Rob Beezer (2009-07-13)
615
"""
616
# Optimized routines for specialized classes would likely be faster
617
# See the "pairwise_product" of vectors for some guidance on doing this
618
from sage.structure.element import canonical_coercion
619
if not PY_TYPE_CHECK(right, Matrix):
620
raise TypeError('operand must be a matrix, not an element of %s' % right.parent())
621
if (self.nrows() != right.nrows()) or (self.ncols() != right.ncols()):
622
raise TypeError('incompatible sizes for matrices from: %s and %s'%(self.parent(), right.parent()))
623
if self._parent is not (<Matrix>right)._parent:
624
self, right = canonical_coercion(self, right)
625
return self._elementwise_product(right)
626
627
def permanent(self):
628
r"""
629
Calculate and return the permanent of this `m \times n`
630
matrix using Ryser's algorithm.
631
632
Let `A = (a_{i,j})` be an `m \times n` matrix over
633
any commutative ring, with `m \le n`. The permanent of
634
`A` is
635
636
.. math::
637
638
\text{per}(A) = \sum_\pi a_{1,\pi(1)}a_{2,\pi(2)} \cdots a_{m,\pi(m)}
639
640
641
where the summation extends over all one-to-one functions
642
`\pi` from `\{1, \ldots, m\}` to
643
`\{1, \ldots, n\}`.
644
645
The product
646
`a_{1,\pi(1)}a_{2,\pi(2)} \cdots a_{m,\pi(m)}` is
647
called diagonal product. So the permanent of an
648
`m \times n` matrix `A` is the sum of all the
649
diagonal products of `A`.
650
651
Modification of theorem 7.1.1. from Brualdi and Ryser:
652
Combinatorial Matrix Theory. Instead of deleting columns from
653
`A`, we choose columns from `A` and calculate the
654
product of the row sums of the selected submatrix.
655
656
INPUT:
657
658
659
- ``A`` - matrix of size m x n with m = n
660
661
662
OUTPUT: permanent of matrix A
663
664
EXAMPLES::
665
666
sage: M = MatrixSpace(ZZ,4,4)
667
sage: A = M([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1])
668
sage: A.permanent()
669
24
670
671
::
672
673
sage: M = MatrixSpace(QQ,3,6)
674
sage: A = M([1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1])
675
sage: A.permanent()
676
36
677
678
::
679
680
sage: M = MatrixSpace(RR,3,6)
681
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])
682
sage: A.permanent()
683
36.0000000000000
684
685
See Sloane's sequence OEIS A079908(3) = 36, "The Dancing School
686
Problems"
687
688
::
689
690
sage: print sloane_sequence(79908) # optional (internet connection)
691
Searching Sloane's online database...
692
[79908, 'Solution to the Dancing School Problem with 3 girls and n+3 boys: f(3,n).', [1, 4, 14, 36, 76, 140, 234, 364, 536, 756, 1030, 1364, 1764, 2236, 2786, 3420, 4144, 4964, 5886, 6916, 8060, 9324, 10714, 12236, 13896, 15700, 17654, 19764, 22036, 24476, 27090, 29884, 32864, 36036, 39406, 42980, 46764, 50764, 54986, 59436]]
693
694
::
695
696
sage: M = MatrixSpace(ZZ,4,5)
697
sage: A = M([1,1,0,1,1,0,1,1,1,1,1,0,1,0,1,1,1,0,1,0])
698
sage: A.permanent()
699
32
700
701
See Minc: Permanents, Example 2.1, p. 5.
702
703
::
704
705
sage: M = MatrixSpace(QQ,2,2)
706
sage: A = M([1/5,2/7,3/2,4/5])
707
sage: A.permanent()
708
103/175
709
710
::
711
712
sage: R.<a> = PolynomialRing(ZZ)
713
sage: A = MatrixSpace(R,2)([[a,1], [a,a+1]])
714
sage: A.permanent()
715
a^2 + 2*a
716
717
::
718
719
sage: R.<x,y> = PolynomialRing(ZZ,2)
720
sage: A = MatrixSpace(R,2)([x, y, x^2, y^2])
721
sage: A.permanent()
722
x^2*y + x*y^2
723
724
AUTHORS:
725
726
- Jaap Spies (2006-02-16)
727
728
- Jaap Spies (2006-02-21): added definition of permanent
729
"""
730
cdef Py_ssize_t m, n, r
731
cdef int sn
732
733
perm = 0
734
m = self._nrows
735
n = self._ncols
736
if not m <= n:
737
raise ValueError, "must have m <= n, but m (=%s) and n (=%s)"%(m,n)
738
739
for r from 1 <= r < m+1:
740
lst = _choose(n, r)
741
tmp = []
742
for cols in lst:
743
tmp.append(self.prod_of_row_sums(cols))
744
s = sum(tmp)
745
# sn = (-1)^(m-r)
746
if (m - r) % 2 == 0:
747
sn = 1
748
else:
749
sn = -1
750
perm = perm + sn * _binomial(n-r, m-r) * s
751
return perm
752
753
754
def permanental_minor(self, Py_ssize_t k):
755
r"""
756
Calculates the permanental `k`-minor of a
757
`m \times n` matrix.
758
759
This is the sum of the permanents of all possible `k` by
760
`k` submatrices of `A`.
761
762
See Brualdi and Ryser: Combinatorial Matrix Theory, p. 203. Note
763
the typo `p_0(A) = 0` in that reference! For applications
764
see Theorem 7.2.1 and Theorem 7.2.4.
765
766
Note that the permanental `m`-minor equals
767
`per(A)`.
768
769
For a (0,1)-matrix `A` the permanental `k`-minor
770
counts the number of different selections of `k` 1's of
771
`A` with no two of the 1's on the same line.
772
773
INPUT:
774
775
776
- ``self`` - matrix of size m x n with m = n
777
778
779
OUTPUT: permanental k-minor of matrix A
780
781
EXAMPLES::
782
783
sage: M = MatrixSpace(ZZ,4,4)
784
sage: A = M([1,0,1,0,1,0,1,0,1,0,10,10,1,0,1,1])
785
sage: A.permanental_minor(2)
786
114
787
788
::
789
790
sage: M = MatrixSpace(ZZ,3,6)
791
sage: A = M([1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1])
792
sage: A.permanental_minor(0)
793
1
794
sage: A.permanental_minor(1)
795
12
796
sage: A.permanental_minor(2)
797
40
798
sage: A.permanental_minor(3)
799
36
800
801
Note that if k == m the permanental k-minor equals per(A)
802
803
::
804
805
sage: A.permanent()
806
36
807
808
::
809
810
sage: A.permanental_minor(5)
811
0
812
813
For C the "complement" of A::
814
815
sage: M = MatrixSpace(ZZ,3,6)
816
sage: C = M([0,0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0])
817
sage: m, n = 3, 6
818
sage: sum([(-1)^k * C.permanental_minor(k)*factorial(n-k)/factorial(n-m) for k in range(m+1)])
819
36
820
821
See Theorem 7.2.1 of Brualdi: and Ryser: Combinatorial Matrix
822
Theory: per(A)
823
824
AUTHORS:
825
826
- Jaap Spies (2006-02-19)
827
"""
828
m = self._nrows
829
n = self._ncols
830
if not m <= n:
831
raise ValueError, "must have m <= n, but m (=%s) and n (=%s)"%(m,n)
832
833
R = self._base_ring
834
if k == 0:
835
return R(1)
836
if k > m:
837
return R(0)
838
839
pm = 0
840
for cols in _choose(n,k):
841
for rows in _choose(m,k):
842
pm = pm + self.matrix_from_rows_and_columns(rows, cols).permanent()
843
return pm
844
845
846
def rook_vector(self, check = False):
847
r"""
848
Returns rook vector of this matrix.
849
850
Let `A` be a general `m` by `n`
851
(0,1)-matrix with `m \le n`. We identify `A` with a
852
chessboard where rooks can be placed on the fields corresponding
853
with `a_{ij} = 1`. The number
854
`r_k = p_k(A)` (the permanental
855
`k`-minor) counts the number of ways to place `k`
856
rooks on this board so that no two rooks can attack another.
857
858
The rook vector is the list consisting of
859
`r_0, r_1, \ldots, r_m`.
860
861
The rook polynomial is defined by
862
`r(x) = \sum_{k=0}^m r_k x^k`.
863
864
INPUT:
865
866
867
- ``self`` - m by n matrix with m = n
868
869
- ``check`` - True or False (default), optional
870
871
872
OUTPUT: rook vector
873
874
EXAMPLES::
875
876
sage: M = MatrixSpace(ZZ,3,6)
877
sage: A = M([1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1])
878
sage: A.rook_vector()
879
[1, 12, 40, 36]
880
881
::
882
883
sage: R.<x> = PolynomialRing(ZZ)
884
sage: rv = A.rook_vector()
885
sage: rook_polynomial = sum([rv[k] * x^k for k in range(len(rv))])
886
sage: rook_polynomial
887
36*x^3 + 40*x^2 + 12*x + 1
888
889
AUTHORS:
890
891
- Jaap Spies (2006-02-24)
892
"""
893
m = self._nrows
894
n = self._ncols
895
if not m <= n:
896
raise ValueError, "must have m <= n, but m (=%s) and n (=%s)"%(m,n)
897
898
if check:
899
# verify that self[i, j] in {0, 1}
900
for i in range(m):
901
for j in range(n):
902
x = self.get_unsafe(i, j)
903
if not (x == 0 or x == 1):
904
raise ValueError, "must have zero or one, but we have (=%s)"%x
905
906
tmp = []
907
for k in range(m+1):
908
tmp.append(self.permanental_minor(k))
909
return tmp
910
911
def minors(self,k):
912
"""
913
Return the list of all k-minors of self.
914
915
Let A be an m x n matrix and k an integer with 0 < k, k <= m, and
916
k <= n. A k x k minor of A is the determinant of a k x k matrix
917
obtained from A by deleting m - k rows and n - k columns.
918
919
The returned list is sorted in lexicographical row major ordering,
920
e.g., if A is a 3 x 3 matrix then the minors returned are with for
921
these rows/columns: [ [0, 1]x[0, 1], [0, 1]x[0, 2], [0, 1]x[1, 2],
922
[0, 2]x[0, 1], [0, 2]x[0, 2], [0, 2]x[1, 2], [1, 2]x[0, 1], [1,
923
2]x[0, 2], [1, 2]x[1, 2] ].
924
925
INPUT:
926
927
928
- ``k`` - integer
929
930
931
EXAMPLE::
932
933
sage: A = Matrix(ZZ,2,3,[1,2,3,4,5,6]); A
934
[1 2 3]
935
[4 5 6]
936
sage: A.minors(2)
937
[-3, -6, -3]
938
939
::
940
941
sage: k = GF(37)
942
sage: P.<x0,x1,x2> = PolynomialRing(k)
943
sage: A = Matrix(P,2,3,[x0*x1, x0, x1, x2, x2 + 16, x2 + 5*x1 ])
944
sage: A.minors(2)
945
[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]
946
"""
947
from sage.combinat.combinat import combinations_iterator
948
all_rows = range(self.nrows())
949
all_cols = range(self.ncols())
950
m = []
951
for rows in combinations_iterator(all_rows,k):
952
for cols in combinations_iterator(all_cols,k):
953
m.append(self.matrix_from_rows_and_columns(rows,cols).determinant())
954
return m
955
956
def determinant(self, algorithm=None):
957
r"""
958
Returns the determinant of self.
959
960
ALGORITHM:
961
962
For small matrices (n less than 4), this is computed using the naive
963
formula. In the specific case of matrices over the integers modulo a
964
non-prime, the determinant of a lift is computed over the integers.
965
In general, the characteristic polynomial is computed either using
966
the Hessenberg form (specified by ``"hessenberg"``) or the generic
967
division-free algorithm (specified by ``"df"``). When the base ring
968
is an exact field, the default choice is ``"hessenberg"``, otherwise
969
it is ``"df"``. Note that for matrices over most rings, more
970
sophisticated algorithms can be used. (Type ``A.determinant?`` to
971
see what is done for a specific matrix ``A``.)
972
973
INPUT:
974
975
- ``algorithm`` - string:
976
- ``"df"`` - Generic O(n^4) division-free algorithm
977
- ``"hessenberg"`` - Use the Hessenberg form of the matrix
978
979
EXAMPLES::
980
981
sage: A = MatrixSpace(Integers(8),3)([1,7,3, 1,1,1, 3,4,5])
982
sage: A.determinant()
983
6
984
sage: A.determinant() is A.determinant()
985
True
986
sage: A[0,0] = 10
987
sage: A.determinant()
988
7
989
990
We compute the determinant of the arbitrary 3x3 matrix::
991
992
sage: R = PolynomialRing(QQ,9,'x')
993
sage: A = matrix(R,3,R.gens())
994
sage: A
995
[x0 x1 x2]
996
[x3 x4 x5]
997
[x6 x7 x8]
998
sage: A.determinant()
999
-x2*x4*x6 + x1*x5*x6 + x2*x3*x7 - x0*x5*x7 - x1*x3*x8 + x0*x4*x8
1000
1001
We create a matrix over `\ZZ[x,y]` and compute its
1002
determinant.
1003
1004
::
1005
1006
sage: R.<x,y> = PolynomialRing(IntegerRing(),2)
1007
sage: A = MatrixSpace(R,2)([x, y, x**2, y**2])
1008
sage: A.determinant()
1009
-x^2*y + x*y^2
1010
1011
TESTS::
1012
1013
sage: A = matrix(5, 5, [next_prime(i^2) for i in range(25)])
1014
sage: B = MatrixSpace(ZZ['x'], 5, 5)(A)
1015
sage: A.det() - B.det()
1016
0
1017
1018
We verify that trac 5569 is resolved (otherwise the following will hang for hours)::
1019
1020
sage: d = random_matrix(GF(next_prime(10^20)),50).det()
1021
sage: d = random_matrix(Integers(10^50),50).det()
1022
1023
We verify that trac 7704 is resolved::
1024
1025
sage: matrix(ZZ, {(0,0):1,(1,1):2,(2,2):3,(3,3):4}).det()
1026
24
1027
sage: matrix(QQ, {(0,0):1,(1,1):2,(2,2):3,(3,3):4}).det()
1028
24
1029
1030
We verify that trac 10063 is resolved::
1031
1032
sage: A = GF(2)['x,y,z']
1033
sage: A.inject_variables()
1034
Defining x, y, z
1035
sage: R = A.quotient(x^2 + 1).quotient(y^2 + 1).quotient(z^2 + 1)
1036
sage: R.inject_variables()
1037
Defining xbarbarbar, ybarbarbar, zbarbarbar
1038
sage: M = matrix([[1,1,1,1],[xbarbarbar,ybarbarbar,1,1],[0,1,zbarbarbar,1],[xbarbarbar,zbarbarbar,1,1]])
1039
sage: M.determinant()
1040
xbarbarbar*ybarbarbar*zbarbarbar + xbarbarbar*ybarbarbar + xbarbarbar*zbarbarbar + ybarbarbar*zbarbarbar + xbarbarbar + ybarbarbar + zbarbarbar + 1
1041
1042
Check that the determinant is computed from a cached charpoly
1043
properly::
1044
1045
sage: A = matrix(RR, [ [1, 0, 1/2],
1046
... [0, 1, 0 ],
1047
... [0, 0, -2 ] ])
1048
sage: B = copy(A)
1049
sage: _ = A.charpoly()
1050
sage: A.determinant() == B.determinant()
1051
True
1052
1053
AUTHORS:
1054
1055
- Unknown: No author specified in the file from 2009-06-25
1056
- Sebastian Pancratz (2009-06-25): Use the division-free
1057
algorithm for charpoly
1058
- Thierry Monteil (2010-10-05): Bugfix for trac ticket #10063,
1059
so that the determinant is computed even for rings for which
1060
the is_field method is not implemented.
1061
"""
1062
1063
from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing
1064
1065
if self._nrows != self._ncols:
1066
raise ValueError, "self must be a square matrix"
1067
1068
d = self.fetch('det')
1069
if not d is None:
1070
return d
1071
1072
# If charpoly known, then det is easy.
1073
f = self.fetch('charpoly')
1074
if f is not None:
1075
c = f[0]
1076
if self._nrows % 2 != 0:
1077
c = -c
1078
d = self._coerce_element(c)
1079
self.cache('det', d)
1080
return d
1081
1082
cdef Py_ssize_t n
1083
n = self._ncols
1084
R = self._base_ring
1085
1086
# For small matrices, you can't beat the naive formula.
1087
if n <= 3:
1088
if n == 0:
1089
d = R(1)
1090
elif n == 1:
1091
d = self.get_unsafe(0,0)
1092
elif n == 2:
1093
d = self.get_unsafe(0,0)*self.get_unsafe(1,1) - self.get_unsafe(1,0)*self.get_unsafe(0,1)
1094
elif n == 3:
1095
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)) \
1096
- 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)) \
1097
+ 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))
1098
self.cache('det', d)
1099
return d
1100
1101
# As of Sage 3.4, computing determinants directly in Z/nZ for
1102
# n composite is too slow, so we lift to Z and compute there.
1103
if is_IntegerModRing(R):
1104
from matrix_modn_dense import is_Matrix_modn_dense
1105
if not (is_Matrix_modn_dense(self) and R.characteristic().is_prime()):
1106
return R(self.lift().det())
1107
1108
# N.B. The following comment should be obsolete now that the generic
1109
# code to compute the determinant has been replaced by generic
1110
# division-free code to compute the characteristic polynomial and read
1111
# off the determinant from this.
1112
#
1113
# If R is an exact integral domain, we could get the det by computing
1114
# charpoly. The generic fraction field implementation is so slow that
1115
# the naive algorithm is much faster in practice despite
1116
# asymptotics.
1117
# TODO: Find a reasonable cutoff point. (This is field specific, but
1118
# seems to be quite large for Q[x].)
1119
if algorithm is None:
1120
try:
1121
R_is_field_attempt = R.is_field()
1122
except NotImplementedError:
1123
R_is_field_attempt = False
1124
if (algorithm is None and R_is_field_attempt and R.is_exact()) or (algorithm == "hessenberg"):
1125
try:
1126
c = self.charpoly('x', algorithm="hessenberg")[0]
1127
except ValueError:
1128
# Hessenberg algorithm not supported, so we use whatever the default algorithm is.
1129
c = self.charpoly('x')[0]
1130
if self._nrows % 2:
1131
c = -c
1132
d = self._coerce_element(c)
1133
self.cache('det', d)
1134
return d
1135
1136
# Generic division-free algorithm to compute the characteristic
1137
# polynomial.
1138
#
1139
# N.B. The case of symbolic rings is quite specific. It would be
1140
# nice to avoid hardcoding a reserved variable name as below, as this
1141
# is then assumed to not be a variable in the symbolic ring. But this
1142
# resulted in further exceptions/ errors.
1143
from sage.symbolic.ring import is_SymbolicExpressionRing
1144
1145
var = R('A0123456789') if is_SymbolicExpressionRing(R) else 'x'
1146
try:
1147
c = self.charpoly(var, algorithm="df")[0]
1148
except ValueError:
1149
# Division free algorithm not supported, so we use whatever the default algorithm is.
1150
c = self.charpoly(var)[0]
1151
1152
if self._nrows % 2:
1153
c = -c
1154
d = self._coerce_element(c)
1155
self.cache('det', d)
1156
return d
1157
1158
cdef _det_by_minors(self, Py_ssize_t level):
1159
"""
1160
Compute the determinant of the upper-left level x level submatrix
1161
of self. Does not handle degenerate cases, level MUST be >= 2
1162
"""
1163
cdef Py_ssize_t n, i
1164
if level == 2:
1165
return self.get_unsafe(0,0) * self.get_unsafe(1,1) - self.get_unsafe(0,1) * self.get_unsafe(1,0)
1166
else:
1167
level -= 1
1168
d = self.get_unsafe(level,level) * self._det_by_minors(level)
1169
# on each iteration, row i will be missing in the first (level) rows
1170
# swapping is much faster than taking submatrices
1171
for i from level > i >= 0:
1172
self.swap_rows(level, i)
1173
if (level - i) % 2:
1174
d -= self.get_unsafe(level,level) * self._det_by_minors(level)
1175
else:
1176
d += self.get_unsafe(level,level) * self._det_by_minors(level)
1177
# undo all our permutations to get us back to where we started
1178
for i from 0 <= i < level:
1179
self.swap_rows(level, i)
1180
return d
1181
1182
1183
# shortcuts
1184
def det(self, *args, **kwds):
1185
"""
1186
Synonym for self.determinant(...).
1187
1188
EXAMPLES::
1189
1190
sage: A = MatrixSpace(Integers(8),3)([1,7,3, 1,1,1, 3,4,5])
1191
sage: A.det()
1192
6
1193
"""
1194
return self.determinant(*args, **kwds)
1195
1196
def __abs__(self):
1197
"""
1198
Synonym for self.determinant(...).
1199
1200
EXAMPLES::
1201
1202
sage: a = matrix(QQ, 2,2, [1,2,3,4]); a
1203
[1 2]
1204
[3 4]
1205
sage: abs(a)
1206
-2
1207
"""
1208
return self.determinant()
1209
1210
def characteristic_polynomial(self, *args, **kwds):
1211
"""
1212
Synonym for self.charpoly(...).
1213
1214
EXAMPLES::
1215
1216
sage: a = matrix(QQ, 2,2, [1,2,3,4]); a
1217
[1 2]
1218
[3 4]
1219
sage: a.characteristic_polynomial('T')
1220
T^2 - 5*T - 2
1221
"""
1222
return self.charpoly(*args, **kwds)
1223
1224
def minimal_polynomial(self, var='x', **kwds):
1225
r"""
1226
This is a synonym for ``self.minpoly``
1227
1228
EXAMPLES::
1229
1230
sage: a = matrix(QQ, 4, range(16))
1231
sage: a.minimal_polynomial('z')
1232
z^3 - 30*z^2 - 80*z
1233
sage: a.minpoly()
1234
x^3 - 30*x^2 - 80*x
1235
"""
1236
return self.minpoly(var, **kwds)
1237
1238
def minpoly(self, var='x', **kwds):
1239
r"""
1240
Return the minimal polynomial of self.
1241
1242
This uses a simplistic - and potentially very very slow - algorithm
1243
that involves computing kernels to determine the powers of the
1244
factors of the charpoly that divide the minpoly.
1245
1246
EXAMPLES::
1247
1248
sage: A = matrix(GF(9,'c'), 4, [1, 1, 0,0, 0,1,0,0, 0,0,5,0, 0,0,0,5])
1249
sage: factor(A.minpoly())
1250
(x + 1) * (x + 2)^2
1251
sage: A.minpoly()(A) == 0
1252
True
1253
sage: factor(A.charpoly())
1254
(x + 1)^2 * (x + 2)^2
1255
1256
The default variable name is `x`, but you can specify
1257
another name::
1258
1259
sage: factor(A.minpoly('y'))
1260
(y + 1) * (y + 2)^2
1261
1262
We can take the minimal polynomail of symbolic matrices::
1263
1264
sage: t = var('t')
1265
sage: m = matrix(2,[1,2,4,t])
1266
sage: m.minimal_polynomial()
1267
x^2 + (-t - 1)*x + t - 8
1268
"""
1269
f = self.fetch('minpoly')
1270
if not f is None:
1271
return f.change_variable_name(var)
1272
f = self.charpoly(var=var, **kwds)
1273
if f.is_squarefree(): # is_squarefree for polys much faster than factor.
1274
# Then f must be the minpoly
1275
self.cache('minpoly', f)
1276
return f
1277
1278
# Now we have to work harder. We find the power of each
1279
# irreducible factor that divides the minpoly.
1280
mp = f.radical()
1281
for h, e in f.factor():
1282
if e > 1:
1283
# Find the power of B so that the dimension
1284
# of the kernel equals e*deg(h)
1285
B = h(self) # this is the killer.
1286
C = B
1287
n = 1
1288
while C.kernel().dimension() < e*h.degree():
1289
if n == e - 1:
1290
n += 1
1291
break
1292
C *= B
1293
n += 1
1294
mp *= h**(n-1)
1295
self.cache('minpoly', mp)
1296
return mp
1297
1298
def charpoly(self, var = 'x', algorithm = None):
1299
r"""
1300
Returns the characteristic polynomial of self, as a polynomial over
1301
the base ring.
1302
1303
ALGORITHM:
1304
1305
In the generic case of matrices over a ring (commutative and with
1306
unity), there is a division-free algorithm, which can be accessed
1307
using ``"df"``, with complexity `O(n^4)`. Alternatively, by
1308
specifying ``"hessenberg"``, this method computes the Hessenberg
1309
form of the matrix and then reads off the characteristic polynomial.
1310
Moreover, for matrices over number fields, this method can use
1311
PARI's charpoly implementation instead.
1312
1313
The method's logic is as follows: If no algorithm is specified,
1314
first check if the base ring is a number field (and then use PARI),
1315
otherwise check if the base ring is the ring of integers modulo n (in
1316
which case compute the characteristic polynomial of a lift of the
1317
matrix to the integers, and then coerce back to the base), next check
1318
if the base ring is an exact field (and then use the Hessenberg form),
1319
or otherwise, use the generic division-free algorithm.
1320
If an algorithm is specified explicitly, if
1321
``algorithm == "hessenberg"``, use the Hessenberg form, or otherwise
1322
use the generic division-free algorithm.
1323
1324
The result is cached.
1325
1326
INPUT:
1327
1328
- ``var`` - a variable name (default: 'x')
1329
- ``algorithm`` - string:
1330
- ``"df"`` - Generic `O(n^4)` division-free algorithm
1331
- ``"hessenberg"`` - Use the Hessenberg form of the matrix
1332
1333
EXAMPLES:
1334
1335
First a matrix over `\ZZ`::
1336
1337
sage: A = MatrixSpace(ZZ,2)( [1,2, 3,4] )
1338
sage: f = A.charpoly('x')
1339
sage: f
1340
x^2 - 5*x - 2
1341
sage: f.parent()
1342
Univariate Polynomial Ring in x over Integer Ring
1343
sage: f(A)
1344
[0 0]
1345
[0 0]
1346
1347
An example over `\QQ`::
1348
1349
sage: A = MatrixSpace(QQ,3)(range(9))
1350
sage: A.charpoly('x')
1351
x^3 - 12*x^2 - 18*x
1352
sage: A.trace()
1353
12
1354
sage: A.determinant()
1355
0
1356
1357
We compute the characteristic polynomial of a matrix over the
1358
polynomial ring `\ZZ[a]`::
1359
1360
sage: R.<a> = PolynomialRing(ZZ)
1361
sage: M = MatrixSpace(R,2)([a,1, a,a+1]); M
1362
[ a 1]
1363
[ a a + 1]
1364
sage: f = M.charpoly('x'); f
1365
x^2 + (-2*a - 1)*x + a^2
1366
sage: f.parent()
1367
Univariate Polynomial Ring in x over Univariate Polynomial Ring in a over Integer Ring
1368
sage: M.trace()
1369
2*a + 1
1370
sage: M.determinant()
1371
a^2
1372
1373
We compute the characteristic polynomial of a matrix over the
1374
multi-variate polynomial ring `\ZZ[x,y]`::
1375
1376
sage: R.<x,y> = PolynomialRing(ZZ,2)
1377
sage: A = MatrixSpace(R,2)([x, y, x^2, y^2])
1378
sage: f = A.charpoly('x'); f
1379
x^2 + (-y^2 - x)*x - x^2*y + x*y^2
1380
1381
It's a little difficult to distinguish the variables. To fix this,
1382
we temporarily view the indeterminate as `Z`::
1383
1384
sage: with localvars(f.parent(), 'Z'): print f
1385
Z^2 + (-y^2 - x)*Z - x^2*y + x*y^2
1386
1387
We could also compute f in terms of Z from the start::
1388
1389
sage: A.charpoly('Z')
1390
Z^2 + (-y^2 - x)*Z - x^2*y + x*y^2
1391
1392
Here is an example over a number field::
1393
1394
sage: x = QQ['x'].gen()
1395
sage: K.<a> = NumberField(x^2 - 2)
1396
sage: m = matrix(K, [[a-1, 2], [a, a+1]])
1397
sage: m.charpoly('Z')
1398
Z^2 - 2*a*Z - 2*a + 1
1399
sage: m.charpoly('a')(m) == 0
1400
True
1401
1402
Here is an example over a general commutative ring, that is to say,
1403
as of version 4.0.2, SAGE does not even positively determine that
1404
``S`` in the following example is an integral domain. But the
1405
computation of the characteristic polynomial succeeds as follows::
1406
1407
sage: R.<a,b> = QQ[]
1408
sage: S.<x,y> = R.quo((b^3))
1409
sage: A = matrix(S, [[x*y^2,2*x],[2,x^10*y]])
1410
sage: A
1411
[ x*y^2 2*x]
1412
[ 2 x^10*y]
1413
sage: A.charpoly('T')
1414
T^2 + (-x^10*y - x*y^2)*T - 4*x
1415
1416
TESTS::
1417
1418
sage: P.<a,b,c> = PolynomialRing(Rationals())
1419
sage: u = MatrixSpace(P,3)([[0,0,a],[1,0,b],[0,1,c]])
1420
sage: Q.<x> = PolynomialRing(P)
1421
sage: u.charpoly('x')
1422
x^3 - c*x^2 - b*x - a
1423
1424
A test case from :trac:`6442`. Prior to :trac:`12292`, the
1425
call to ``A.det()`` would attempt to use the cached charpoly,
1426
and crash if an empty dictionary was cached. We don't cache
1427
dictionaries anymore, but this test should still pass::
1428
1429
sage: z = Zp(p=5)
1430
sage: A = matrix(z, [ [3 + O(5^1), 4 + O(5^1), 4 + O(5^1)],
1431
... [2*5^2 + O(5^3), 2 + O(5^1), 1 + O(5^1)],
1432
... [5 + O(5^2), 1 + O(5^1), 1 + O(5^1)] ])
1433
sage: A.charpoly(algorithm='hessenberg')
1434
Traceback (most recent call last):
1435
...
1436
ValueError: element has negative valuation.
1437
sage: A.det()
1438
3 + O(5)
1439
1440
The cached polynomial should be independent of the ``var``
1441
argument (:trac:`12292`). We check (indirectly) that the
1442
second call uses the cached value by noting that its result is
1443
not cached::
1444
1445
sage: M = MatrixSpace(RR, 2)
1446
sage: A = M(range(0, 2^2))
1447
sage: type(A)
1448
<type 'sage.matrix.matrix_generic_dense.Matrix_generic_dense'>
1449
sage: A.charpoly('x')
1450
x^2 - 3.00000000000000*x - 2.00000000000000
1451
sage: A.charpoly('y')
1452
y^2 - 3.00000000000000*y - 2.00000000000000
1453
sage: A._cache['charpoly']
1454
x^2 - 3.00000000000000*x - 2.00000000000000
1455
1456
AUTHORS:
1457
1458
- Unknown: No author specified in the file from 2009-06-25
1459
- Sebastian Pancratz (2009-06-25): Include the division-free algorithm
1460
"""
1461
1462
f = self.fetch('charpoly')
1463
if f is not None:
1464
return f.change_variable_name(var)
1465
1466
from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing
1467
1468
if algorithm is None:
1469
R = self._base_ring
1470
if is_NumberField(R):
1471
f = self._charpoly_over_number_field(var)
1472
elif is_IntegerModRing(R):
1473
f = self.lift().charpoly(var).change_ring(R)
1474
elif R.is_field(proof = False) and R.is_exact():
1475
f = self._charpoly_hessenberg(var)
1476
else:
1477
f = self._charpoly_df(var)
1478
else:
1479
if algorithm == "hessenberg":
1480
f = self._charpoly_hessenberg(var)
1481
else:
1482
f = self._charpoly_df(var)
1483
1484
# Cache the result, and return it.
1485
self.cache('charpoly', f)
1486
return f
1487
1488
def _charpoly_df(self, var = 'x'):
1489
r"""
1490
Computes the characteristic polynomial of ``self`` without divisions.
1491
1492
INPUT:
1493
1494
- ``var`` - a variable name (default: ``'x'``)
1495
1496
OUTPUT:
1497
1498
- polynomial - the characteristic polynomial of ``self``
1499
1500
EXAMPLES:
1501
1502
Here is one easy example over the integers to illustrate this::
1503
1504
sage: A = matrix(ZZ, [[1,24],[3,5]])
1505
sage: A
1506
[ 1 24]
1507
[ 3 5]
1508
sage: A._charpoly_df()
1509
x^2 - 6*x - 67
1510
1511
The second example is a matrix over a univariate polynomial ring over the
1512
rationals::
1513
1514
sage: R.<t> = QQ[]
1515
sage: A = matrix(R, [[7*t^2 - t - 9, -1/4*t - 1, -17*t^2 - t + 1], \
1516
[-t^2 + 1/4*t, t^2 + 5/7*t + 3, 1/5*t^2 + \
1517
1662], \
1518
[-2*t - 3, 2*t^2 + 6*t - 1/2, -1/6*t^2]])
1519
sage: A
1520
[ 7*t^2 - t - 9 -1/4*t - 1 -17*t^2 - t + 1]
1521
[ -t^2 + 1/4*t t^2 + 5/7*t + 3 1/5*t^2 + 1662]
1522
[ -2*t - 3 2*t^2 + 6*t - 1/2 -1/6*t^2]
1523
sage: A._charpoly_df()
1524
x^3 + (-47/6*t^2 + 2/7*t + 6)*x^2 + (79/15*t^4 - 13189/420*t^3 -
1525
1884709/560*t^2 - 279501/28*t + 807)*x - 901/30*t^6 - 423/8*t^5 +
1526
11218517/480*t^4 + 2797765/42*t^3 - 12987971/280*t^2 - 5235245/56*t + 2484
1527
1528
Thirdly, an example over a ring which is not an integral domain::
1529
1530
sage: A = matrix(ZZ.quo(12), 3, [5,8,0,10,2,1,8,7,9])
1531
sage: A
1532
[ 5 8 0]
1533
[10 2 1]
1534
[ 8 7 9]
1535
sage: A._charpoly_df()
1536
x^3 + 8*x^2 + 10*x + 1
1537
1538
TESTS::
1539
1540
sage: A = matrix(ZZ, 0, 0)
1541
sage: A
1542
[]
1543
sage: A._charpoly_df()
1544
1
1545
1546
sage: A = matrix(ZZ, 1, 1, [[23]])
1547
sage: A._charpoly_df()
1548
x - 23
1549
1550
NOTES:
1551
1552
The key feature of this implementation is that it is division-free.
1553
This means that it can be used as a generic implementation for any
1554
ring (commutative and with multiplicative identity). The algorithm
1555
is described in full detail as Algorithm 3.1 in [Se02].
1556
1557
Note that there is a missing minus sign in front of the last term in
1558
the penultimate line of Algorithm 3.1.
1559
1560
REFERENCES:
1561
1562
- [Se02] T. R. Seifullin, "Computation of determinants, adjoint
1563
matrices, and characteristic polynomials without division"
1564
1565
AUTHORS:
1566
1567
- Sebastian Pancratz (2009-06-12)
1568
"""
1569
1570
# Validate assertions
1571
#
1572
if not self.is_square():
1573
raise ValueError("self must be a square matrix")
1574
1575
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
1576
1577
# Extract parameters
1578
#
1579
cdef Matrix M = <Matrix> self
1580
n = M._ncols
1581
R = M._base_ring
1582
S = PolynomialRing(R, var)
1583
1584
# Corner cases
1585
# N.B. We already tested for M to be square, hence we do not need to
1586
# test for 0 x n or m x 0 matrices.
1587
#
1588
if n == 0:
1589
return S(1)
1590
1591
# In the notation of Algorithm 3.1,
1592
#
1593
# F Matrix over R such that F[p, t] is the coefficient of X^{t-p}
1594
# in the polynomial $F_t$;
1595
# a List of lists such that a[p, t] is a vector of length t;
1596
# A Matrix over R.
1597
#
1598
# But by looking at the algorithm, we see that in F, a and A we can
1599
# drop the second index t, reducing storage requirements.
1600
#
1601
# N.B. The documentation is still 1-based, although the code, after
1602
# having been ported from Magma to SAGE, is 0-based.
1603
#
1604
from sage.matrix.constructor import matrix
1605
1606
F = [R(0) for i in xrange(n)]
1607
cdef Matrix a = <Matrix> matrix(R, n-1, n)
1608
A = [R(0) for i in xrange(n)]
1609
1610
F[0] = - M.get_unsafe(0, 0)
1611
for t in xrange(1,n):
1612
1613
# Set a(1, t) to be M(<=t, t)
1614
#
1615
for i in xrange(t+1):
1616
a.set_unsafe(0, i, M.get_unsafe(i, t))
1617
1618
# Set A[1, t] to be the (t)th entry in a[1, t]
1619
#
1620
A[0] = M.get_unsafe(t, t)
1621
1622
for p in xrange(1, t):
1623
1624
# Set a(p, t) to the product of M[<=t, <=t] * a(p-1, t)
1625
#
1626
for i in xrange(t+1):
1627
s = R(0)
1628
for j in xrange(t+1):
1629
s = s + M.get_unsafe(i, j) * a.get_unsafe(p-1, j)
1630
a.set_unsafe(p, i, s)
1631
1632
# Set A[p, t] to be the (t)th entry in a[p, t]
1633
#
1634
A[p] = a.get_unsafe(p, t)
1635
1636
# Set A[t, t] to be M[t, <=t] * a(p-1, t)
1637
#
1638
s = R(0)
1639
for j in xrange(t+1):
1640
s = s + M.get_unsafe(t, j) * a.get_unsafe(t-1, j)
1641
A[t] = s
1642
1643
for p in xrange(t+1):
1644
s = F[p]
1645
for k in xrange(p):
1646
s = s - A[k] * F[p-k-1]
1647
F[p] = s - A[p]
1648
1649
X = S.gen(0)
1650
f = X ** n
1651
for p in xrange(n):
1652
f = f + F[p] * X ** (n-1-p)
1653
1654
return f
1655
1656
def _charpoly_over_number_field(self, var='x'):
1657
r"""
1658
Use PARI to compute the characteristic polynomial of self as a
1659
polynomial over the base ring.
1660
1661
EXAMPLES::
1662
1663
sage: x = QQ['x'].gen()
1664
sage: K.<a> = NumberField(x^2 - 2)
1665
sage: m = matrix(K, [[a-1, 2], [a, a+1]])
1666
sage: m._charpoly_over_number_field('Z')
1667
Z^2 - 2*a*Z - 2*a + 1
1668
sage: m._charpoly_over_number_field('a')(m) == 0
1669
True
1670
sage: m = matrix(K, [[0, a, 0], [-a, 0, 0], [0, 0, 0]])
1671
sage: m._charpoly_over_number_field('Z')
1672
Z^3 + 2*Z
1673
1674
The remaining tests are indirect::
1675
1676
sage: L.<b> = K.extension(x^3 - a)
1677
sage: m = matrix(L, [[b+a, 1], [a, b^2-2]])
1678
sage: m.charpoly('Z')
1679
Z^2 + (-b^2 - b - a + 2)*Z + a*b^2 - 2*b - 2*a
1680
sage: m.charpoly('a')
1681
a^2 + (-b^2 - b - a + 2)*a + a*b^2 - 2*b - 2*a
1682
sage: m.charpoly('a')(m) == 0
1683
True
1684
1685
::
1686
1687
sage: M.<c> = L.extension(x^2 - a*x + b)
1688
sage: m = matrix(M, [[a+b+c, 0, b], [0, c, 1], [a-1, b^2+1, 2]])
1689
sage: f = m.charpoly('Z'); f
1690
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
1691
sage: f(m) == 0
1692
True
1693
sage: f.base_ring() is M
1694
True
1695
"""
1696
K = self.base_ring()
1697
if not is_NumberField(K):
1698
raise ValueError, "_charpoly_over_number_field called with base ring (%s) not a number field" % K
1699
1700
paripoly = self._pari_().charpoly()
1701
return K[var](paripoly)
1702
1703
def fcp(self, var='x'):
1704
"""
1705
Return the factorization of the characteristic polynomial of self.
1706
1707
INPUT:
1708
1709
- ``var`` - (default: 'x') name of variable of charpoly
1710
1711
EXAMPLES::
1712
1713
sage: M = MatrixSpace(QQ,3,3)
1714
sage: A = M([1,9,-7,4/5,4,3,6,4,3])
1715
sage: A.fcp()
1716
x^3 - 8*x^2 + 209/5*x - 286
1717
sage: A = M([3, 0, -2, 0, -2, 0, 0, 0, 0])
1718
sage: A.fcp('T')
1719
(T - 3) * T * (T + 2)
1720
"""
1721
return self.charpoly(var).factor()
1722
1723
## def minimal_polynomial(self, var, algorithm=''):
1724
## """
1725
## Synonym for self.charpoly(...).
1726
1727
## EXAMPLES:
1728
## sage: ???
1729
## """
1730
## return self.minpoly(*args, **kwds)
1731
1732
## def minpoly(self, *args, **kwds):
1733
## """
1734
## EXAMPLES:
1735
## sage: ???
1736
## """
1737
## raise NotImplementedError
1738
1739
def denominator(self):
1740
r"""
1741
Return the least common multiple of the denominators of the
1742
elements of self.
1743
1744
If there is no denominator function for the base field, or no LCM
1745
function for the denominators, raise a TypeError.
1746
1747
EXAMPLES::
1748
1749
sage: A = MatrixSpace(QQ,2)(['1/2', '1/3', '1/5', '1/7'])
1750
sage: A.denominator()
1751
210
1752
1753
A trivial example::
1754
1755
sage: A = matrix(QQ, 0,2)
1756
sage: A.denominator()
1757
1
1758
1759
Denominators are not defined for real numbers::
1760
1761
sage: A = MatrixSpace(RealField(),2)([1,2,3,4])
1762
sage: A.denominator()
1763
Traceback (most recent call last):
1764
...
1765
TypeError: denominator not defined for elements of the base ring
1766
1767
We can even compute the denominator of matrix over the fraction
1768
field of `\ZZ[x]`.
1769
1770
::
1771
1772
sage: K.<x> = Frac(ZZ['x'])
1773
sage: A = MatrixSpace(K,2)([1/x, 2/(x+1), 1, 5/(x^3)])
1774
sage: A.denominator()
1775
x^4 + x^3
1776
1777
Here's an example involving a cyclotomic field::
1778
1779
sage: K.<z> = CyclotomicField(3)
1780
sage: M = MatrixSpace(K,3,sparse=True)
1781
sage: A = M([(1+z)/3,(2+z)/3,z/3,1,1+z,-2,1,5,-1+z])
1782
sage: print A
1783
[1/3*z + 1/3 1/3*z + 2/3 1/3*z]
1784
[ 1 z + 1 -2]
1785
[ 1 5 z - 1]
1786
sage: print A.denominator()
1787
3
1788
"""
1789
if self.nrows() == 0 or self.ncols() == 0:
1790
return ZZ(1)
1791
R = self.base_ring()
1792
x = self.list()
1793
try:
1794
d = x[0].denominator()
1795
except AttributeError:
1796
raise TypeError, "denominator not defined for elements of the base ring"
1797
try:
1798
for y in x:
1799
d = d.lcm(y.denominator())
1800
except AttributeError:
1801
raise TypeError, "lcm function not defined for elements of the base ring"
1802
return d
1803
1804
def diagonal(self):
1805
r"""
1806
Return the diagonal entries of ``self``.
1807
1808
OUTPUT:
1809
1810
A list containing the entries of the matrix that
1811
have equal row and column indices, in order of the
1812
indices. Behavior is not limited to square matrices.
1813
1814
EXAMPLES::
1815
1816
sage: A = matrix([[2,5],[3,7]]); A
1817
[2 5]
1818
[3 7]
1819
sage: A.diagonal()
1820
[2, 7]
1821
1822
Two rectangular matrices. ::
1823
1824
sage: B = matrix(3, 7, range(21)); B
1825
[ 0 1 2 3 4 5 6]
1826
[ 7 8 9 10 11 12 13]
1827
[14 15 16 17 18 19 20]
1828
sage: B.diagonal()
1829
[0, 8, 16]
1830
1831
sage: C = matrix(3, 2, range(6)); C
1832
[0 1]
1833
[2 3]
1834
[4 5]
1835
sage: C.diagonal()
1836
[0, 3]
1837
1838
Empty matrices behave properly. ::
1839
1840
sage: E = matrix(0, 5, []); E
1841
[]
1842
sage: E.diagonal()
1843
[]
1844
"""
1845
n = min(self.nrows(), self.ncols())
1846
return [self[i,i] for i in range(n)]
1847
1848
def trace(self):
1849
"""
1850
Return the trace of self, which is the sum of the diagonal entries
1851
of self.
1852
1853
INPUT:
1854
1855
1856
- ``self`` - a square matrix
1857
1858
1859
OUTPUT: element of the base ring of self
1860
1861
EXAMPLES::
1862
1863
sage: a = matrix(3,range(9)); a
1864
[0 1 2]
1865
[3 4 5]
1866
[6 7 8]
1867
sage: a.trace()
1868
12
1869
sage: a = matrix({(1,1):10, (2,1):-3, (2,2):4/3}); a
1870
[ 0 0 0]
1871
[ 0 10 0]
1872
[ 0 -3 4/3]
1873
sage: a.trace()
1874
34/3
1875
"""
1876
if self._nrows != self._ncols:
1877
raise ValueError, "self must be a square matrix"
1878
R = self._base_ring
1879
cdef Py_ssize_t i
1880
cdef object s
1881
s = R(0)
1882
for i from 0 <= i < self._nrows:
1883
s = s + self.get_unsafe(i,i)
1884
return s
1885
1886
def trace_of_product(self, Matrix other):
1887
"""
1888
Returns the trace of self * other without computing the entire product.
1889
1890
EXAMPLES::
1891
1892
sage: M = random_matrix(ZZ, 10, 20)
1893
sage: N = random_matrix(ZZ, 20, 10)
1894
sage: M.trace_of_product(N)
1895
-1629
1896
sage: (M*N).trace()
1897
-1629
1898
"""
1899
if self._nrows != other._ncols or other._nrows != self._ncols:
1900
raise ArithmeticError, "incompatible dimensions"
1901
s = self._base_ring(0)
1902
for i from 0 <= i < self._nrows:
1903
for j from 0 <= j < self._ncols:
1904
s += self.get_unsafe(i, j) * other.get_unsafe(j, i)
1905
return s
1906
1907
#####################################################################################
1908
# Generic Hessenberg Form and charpoly algorithm
1909
#####################################################################################
1910
def hessenberg_form(self):
1911
"""
1912
Return Hessenberg form of self.
1913
1914
If the base ring is merely an integral domain (and not a field),
1915
the Hessenberg form will (in general) only be defined over the
1916
fraction field of the base ring.
1917
1918
EXAMPLES::
1919
1920
sage: A = matrix(ZZ,4,[2, 1, 1, -2, 2, 2, -1, -1, -1,1,2,3,4,5,6,7])
1921
sage: h = A.hessenberg_form(); h
1922
[ 2 -7/2 -19/5 -2]
1923
[ 2 1/2 -17/5 -1]
1924
[ 0 25/4 15/2 5/2]
1925
[ 0 0 58/5 3]
1926
sage: parent(h)
1927
Full MatrixSpace of 4 by 4 dense matrices over Rational Field
1928
sage: A.hessenbergize()
1929
Traceback (most recent call last):
1930
...
1931
TypeError: Hessenbergize only possible for matrices over a field
1932
"""
1933
X = self.fetch('hessenberg_form')
1934
if not X is None:
1935
return X
1936
R = self._base_ring
1937
if not R.is_field():
1938
try:
1939
K = self._base_ring.fraction_field()
1940
H = self.change_ring(K)
1941
H.hessenbergize()
1942
except TypeError, msg:
1943
raise TypeError, "%s\nHessenberg form only possible for matrices over a field"%msg
1944
else:
1945
H = self.__copy__()
1946
H.hessenbergize()
1947
#end if
1948
self.cache('hessenberg_form', H)
1949
return H
1950
1951
def hessenbergize(self):
1952
"""
1953
Transform self to Hessenberg form.
1954
1955
The hessenberg form of a matrix `A` is a matrix that is
1956
similar to `A`, so has the same characteristic polynomial
1957
as `A`, and is upper triangular except possible for entries
1958
right below the diagonal.
1959
1960
ALGORITHM: See Henri Cohen's first book.
1961
1962
EXAMPLES::
1963
1964
sage: A = matrix(QQ,3, [2, 1, 1, -2, 2, 2, -1, -1, -1])
1965
sage: A.hessenbergize(); A
1966
[ 2 3/2 1]
1967
[ -2 3 2]
1968
[ 0 -3 -2]
1969
1970
::
1971
1972
sage: A = matrix(QQ,4, [2, 1, 1, -2, 2, 2, -1, -1, -1,1,2,3,4,5,6,7])
1973
sage: A.hessenbergize(); A
1974
[ 2 -7/2 -19/5 -2]
1975
[ 2 1/2 -17/5 -1]
1976
[ 0 25/4 15/2 5/2]
1977
[ 0 0 58/5 3]
1978
1979
You can't Hessenbergize an immutable matrix::
1980
1981
sage: A = matrix(QQ, 3, [1..9])
1982
sage: A.set_immutable()
1983
sage: A.hessenbergize()
1984
Traceback (most recent call last):
1985
...
1986
ValueError: matrix is immutable; please change a copy instead (i.e., use copy(M) to change a copy of M).
1987
"""
1988
cdef Py_ssize_t i, j, m, n, r
1989
n = self._nrows
1990
1991
tm = verbose("Computing Hessenberg Normal Form of %sx%s matrix"%(n,n))
1992
1993
if not self.is_square():
1994
raise TypeError, "self must be square"
1995
1996
if not self._base_ring.is_field():
1997
raise TypeError, "Hessenbergize only possible for matrices over a field"
1998
1999
self.check_mutability()
2000
2001
zero = self._base_ring(0)
2002
one = self._base_ring(1)
2003
for m from 1 <= m < n-1:
2004
# Search for a non-zero entry in column m-1
2005
i = -1
2006
for r from m+1 <= r < n:
2007
if self.get_unsafe(r, m-1) != zero:
2008
i = r
2009
break
2010
if i != -1:
2011
# Found a nonzero entry in column m-1 that is strictly below row m
2012
# Now set i to be the first nonzero position >= m in column m-1
2013
if self.get_unsafe(m,m-1) != zero:
2014
i = m
2015
t = self.get_unsafe(i,m-1)
2016
t_inv = None
2017
if i > m:
2018
self.swap_rows_c(i,m)
2019
# We must do the corresponding column swap to
2020
# maintain the characteristic polynomial (which is
2021
# an invariant of Hessenberg form)
2022
self.swap_columns_c(i,m)
2023
# Now the nonzero entry in position (m,m-1) is t.
2024
# Use t to clear the entries in column m-1 below m.
2025
for j from m+1 <= j < n:
2026
x = self.get_unsafe(j, m-1)
2027
if x != zero:
2028
if t_inv is None:
2029
t_inv = one / t
2030
u = x * t_inv
2031
self.add_multiple_of_row_c(j, m, -u, 0)
2032
# To maintain charpoly, do the corresponding column operation,
2033
# which doesn't mess up the matrix, since it only changes
2034
# column m, and we're only worried about column m-1 right now.
2035
# Add u*column_j to column_m.
2036
self.add_multiple_of_column_c(m, j, u, 0)
2037
verbose("Finished Hessenberg Normal Form of %sx%s matrix"%(n,n),tm)
2038
2039
2040
2041
def _charpoly_hessenberg(self, var):
2042
"""
2043
Transforms self in place to its Hessenberg form then computes and
2044
returns the coefficients of the characteristic polynomial of this
2045
matrix.
2046
2047
INPUT:
2048
2049
- ``var`` - name of the indeterminate of the charpoly
2050
2051
The characteristic polynomial is represented as a vector of ints,
2052
where the constant term of the characteristic polynomial is the 0th
2053
coefficient of the vector.
2054
2055
EXAMPLES::
2056
2057
sage: matrix(QQ,3,range(9))._charpoly_hessenberg('Z')
2058
Z^3 - 12*Z^2 - 18*Z
2059
sage: matrix(ZZ,3,range(9))._charpoly_hessenberg('Z')
2060
Z^3 - 12*Z^2 - 18*Z
2061
sage: matrix(GF(7),3,range(9))._charpoly_hessenberg('Z')
2062
Z^3 + 2*Z^2 + 3*Z
2063
sage: matrix(QQ['x'],3,range(9))._charpoly_hessenberg('Z')
2064
Z^3 - 12*Z^2 - 18*Z
2065
sage: matrix(ZZ['ZZ'],3,range(9))._charpoly_hessenberg('Z')
2066
Z^3 - 12*Z^2 - 18*Z
2067
"""
2068
if self._nrows != self._ncols:
2069
raise ArithmeticError, "charpoly not defined for non-square matrix."
2070
2071
# Replace self by its Hessenberg form
2072
# (note the entries might now live in the fraction field)
2073
cdef Matrix H
2074
H = self.hessenberg_form()
2075
2076
# We represent the intermediate polynomials that come up in
2077
# the calculations as rows of an (n+1)x(n+1) matrix, since
2078
# we've implemented basic arithmetic with such a matrix.
2079
# Please see the generic implementation of charpoly in
2080
# matrix.py to see more clearly how the following algorithm
2081
# actually works. (The implementation is clearer (but slower)
2082
# if one uses polynomials to represent polynomials instead of
2083
# using the rows of a matrix.) Also see Cohen's first GTM,
2084
# Algorithm 2.2.9.
2085
2086
cdef Py_ssize_t i, m, n,
2087
n = self._nrows
2088
2089
cdef Matrix c
2090
c = H.new_matrix(nrows=n+1,ncols=n+1) # the 0 matrix
2091
one = H._coerce_element(1)
2092
c.set_unsafe(0,0,one)
2093
2094
for m from 1 <= m <= n:
2095
# 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]
2096
# We do this by hand by setting the m-th row to c[m-1]
2097
# shifted to the right by one. We then add
2098
# -H[m-1,m-1]*c[m-1] to the resulting m-th row.
2099
for i from 1 <= i <= n:
2100
c.set_unsafe(m, i, c.get_unsafe(m-1,i-1))
2101
c.add_multiple_of_row_c(m, m-1, -H.get_unsafe(m-1, m-1), 0)
2102
t = one
2103
for i from 1 <= i < m:
2104
t = t * H.get_unsafe(m-i,m-i-1)
2105
# Set the m-th row of c to c[m] - t*H[m-i-1,m-1]*c[m-i-1]
2106
c.add_multiple_of_row_c(m, m-i-1, - t*H.get_unsafe(m-i-1,m-1), 0)
2107
2108
# The answer is now the n-th row of c.
2109
v = PyList_New(n+1) # this is really sort of v = []..."
2110
for i from 0 <= i <= n:
2111
# Finally, set v[i] = c[n,i]
2112
o = c.get_unsafe(n,i)
2113
Py_INCREF(o); PyList_SET_ITEM(v, i, o)
2114
2115
R = self._base_ring[var] # polynomial ring over the base ring
2116
return R(v)
2117
2118
#####################################################################################
2119
# Decomposition: kernel, image, decomposition
2120
#####################################################################################
2121
nullity = left_nullity
2122
2123
def left_nullity(self):
2124
"""
2125
Return the (left) nullity of this matrix, which is the dimension of
2126
the (left) kernel of this matrix acting from the right on row
2127
vectors.
2128
2129
EXAMPLES::
2130
2131
sage: M = Matrix(QQ,[[1,0,0,1],[0,1,1,0],[1,1,1,0]])
2132
sage: M.nullity()
2133
0
2134
sage: M.left_nullity()
2135
0
2136
2137
::
2138
2139
sage: A = M.transpose()
2140
sage: A.nullity()
2141
1
2142
sage: A.left_nullity()
2143
1
2144
2145
::
2146
2147
sage: M = M.change_ring(ZZ)
2148
sage: M.nullity()
2149
0
2150
sage: A = M.transpose()
2151
sage: A.nullity()
2152
1
2153
"""
2154
# Use that rank + nullity = number of rows, since matrices act
2155
# from the right on row vectors.
2156
return self.nrows() - self.rank()
2157
2158
def right_nullity(self):
2159
"""
2160
Return the right nullity of this matrix, which is the dimension of
2161
the right kernel.
2162
2163
EXAMPLES::
2164
2165
sage: A = MatrixSpace(QQ,3,2)(range(6))
2166
sage: A.right_nullity()
2167
0
2168
2169
::
2170
2171
sage: A = matrix(ZZ,3,range(9))
2172
sage: A.right_nullity()
2173
1
2174
"""
2175
return self.ncols() - self.rank()
2176
2177
######################################
2178
# Kernel Helper Functions
2179
######################################
2180
2181
def _right_kernel_matrix_over_number_field(self):
2182
r"""
2183
Returns a pair that includes a matrix of basis vectors
2184
for the right kernel of ``self``.
2185
2186
OUTPUT:
2187
2188
Returns a pair. First item is the string 'pivot-pari-numberfield'
2189
that identifies the nature of the basis vectors.
2190
2191
Second item is a matrix whose rows are a basis for the right kernel,
2192
over the number field, as computed by PARI.
2193
2194
EXAMPLES::
2195
2196
sage: Q = QuadraticField(-7)
2197
sage: a = Q.gen(0)
2198
sage: A = matrix(Q, [[ 2, 5-a, 15-a],
2199
... [2+a, a, -7 + 5*a]])
2200
sage: result = A._right_kernel_matrix_over_number_field()
2201
sage: result[0]
2202
'pivot-pari-numberfield'
2203
sage: P = result[1]; P
2204
[-a -3 1]
2205
sage: A*P.transpose() == zero_matrix(Q, 2, 1)
2206
True
2207
2208
TESTS:
2209
2210
We test some trivial cases. ::
2211
2212
sage: Q = QuadraticField(-7)
2213
sage: A = matrix(Q, 0, 2)
2214
sage: A._right_kernel_matrix_over_number_field()[1]
2215
[1 0]
2216
[0 1]
2217
sage: A = matrix(Q, 2, 0)
2218
sage: A._right_kernel_matrix_over_number_field()[1].parent()
2219
Full MatrixSpace of 0 by 0 dense matrices over Number Field in a with defining polynomial x^2 + 7
2220
sage: A = zero_matrix(Q, 4, 3)
2221
sage: A._right_kernel_matrix_over_number_field()[1]
2222
[1 0 0]
2223
[0 1 0]
2224
[0 0 1]
2225
"""
2226
tm = verbose("computing right kernel matrix over a number field for %sx%s matrix" % (self.nrows(), self.ncols()),level=1)
2227
basis = self._pari_().matker()
2228
# Coerce PARI representations into the number field
2229
R = self.base_ring()
2230
basis = [[R(x) for x in row] for row in basis]
2231
verbose("done computing right kernel matrix over a number field for %sx%s matrix" % (self.nrows(), self.ncols()),level=1,t=tm)
2232
return 'pivot-pari-numberfield', matrix_space.MatrixSpace(R, len(basis), ncols=self._ncols)(basis)
2233
2234
def _right_kernel_matrix_over_field(self, *args, **kwds):
2235
r"""
2236
Returns a pair that includes a matrix of basis vectors
2237
for the right kernel of ``self``.
2238
2239
OUTPUT:
2240
2241
Returns a pair. First item is the string 'pivot-generic'
2242
that identifies the nature of the basis vectors.
2243
2244
Second item is a matrix whose rows are a basis for the right kernel,
2245
over the field, as computed by general Python code.
2246
2247
EXAMPLES::
2248
2249
sage: C = CyclotomicField(14)
2250
sage: a = C.gen(0)
2251
sage: A = matrix(C, 3, 4, [[ 1, a, 1+a, a^3+a^5],
2252
... [ a, a^4, a+a^4, a^4+a^8],
2253
... [a^2, a^6, a^2+a^6, a^5+a^10]])
2254
sage: result = A._right_kernel_matrix_over_field()
2255
sage: result[0]
2256
'pivot-generic'
2257
sage: P = result[1]; P
2258
[ -1 -1 1 0]
2259
[-zeta14^3 -zeta14^4 0 1]
2260
sage: A*P.transpose() == zero_matrix(C, 3, 2)
2261
True
2262
2263
TESTS:
2264
2265
We test some trivial cases. ::
2266
2267
sage: C = CyclotomicField(14)
2268
sage: A = matrix(C, 0, 2)
2269
sage: A._right_kernel_matrix_over_field()[1]
2270
[1 0]
2271
[0 1]
2272
sage: A = matrix(C, 2, 0)
2273
sage: A._right_kernel_matrix_over_field()[1].parent()
2274
Full MatrixSpace of 0 by 0 dense matrices over Cyclotomic Field of order 14 and degree 6
2275
sage: A = zero_matrix(C, 4, 3)
2276
sage: A._right_kernel_matrix_over_field()[1]
2277
[1 0 0]
2278
[0 1 0]
2279
[0 0 1]
2280
"""
2281
tm = verbose("computing right kernel matrix over an arbitrary field for %sx%s matrix" % (self.nrows(), self.ncols()),level=1)
2282
E = self.echelon_form(*args, **kwds)
2283
pivots = E.pivots()
2284
pivots_set = set(pivots)
2285
R = self.base_ring()
2286
zero = R(0)
2287
one = R(1)
2288
basis = []
2289
for i in xrange(self._ncols):
2290
if not (i in pivots_set):
2291
v = [zero]*self._ncols
2292
v[i] = one
2293
for r in range(len(pivots)):
2294
v[pivots[r]] = -E[r,i]
2295
basis.append(v)
2296
tm = verbose("done computing right kernel matrix over an arbitrary field for %sx%s matrix" % (self.nrows(), self.ncols()),level=1,t=tm)
2297
return 'pivot-generic', matrix_space.MatrixSpace(R, len(basis), self._ncols)(basis)
2298
2299
def _right_kernel_matrix_over_domain(self):
2300
r"""
2301
Returns a pair that includes a matrix of basis vectors
2302
for the right kernel of ``self``.
2303
2304
OUTPUT:
2305
2306
Returns a pair. First item is the string 'computed-smith-form'
2307
that identifies the nature of the basis vectors.
2308
2309
Second item is a matrix whose rows are a basis for the right kernel,
2310
over the field, as computed by general Python code.
2311
2312
.. warning::
2313
2314
This routine uses Smith normal form, which can fail
2315
if the domain is not a principal ideal domain. Since we do
2316
not have a good test for PIDs, this is just a risk we take.
2317
See an example failure in the documentation for
2318
:meth:`right_kernel_matrix`.
2319
2320
EXAMPLES:
2321
2322
Univariate polynomials over a field form a PID. ::
2323
2324
sage: R.<y> = QQ[]
2325
sage: A = matrix(R, [[ 1, y, 1+y^2],
2326
... [y^3, y^2, 2*y^3]])
2327
sage: result = A._right_kernel_matrix_over_domain()
2328
sage: result[0]
2329
'computed-smith-form'
2330
sage: P = result[1]; P
2331
[-1 -y 1]
2332
sage: A*P.transpose() == zero_matrix(R, 2, 1)
2333
True
2334
2335
TESTS:
2336
2337
We test some trivial cases. ::
2338
2339
sage: R.<y> = QQ[]
2340
sage: A = matrix(R, 0, 2)
2341
sage: A._right_kernel_matrix_over_domain()[1]
2342
[1 0]
2343
[0 1]
2344
sage: A = matrix(R, 2, 0)
2345
sage: A._right_kernel_matrix_over_domain()[1].parent()
2346
Full MatrixSpace of 0 by 0 dense matrices over Univariate Polynomial Ring in y over Rational Field
2347
sage: A = zero_matrix(R, 4, 3)
2348
sage: A._right_kernel_matrix_over_domain()[1]
2349
[1 0 0]
2350
[0 1 0]
2351
[0 0 1]
2352
"""
2353
tm = verbose("computing right kernel matrix over a domain for %sx%s matrix" % (self.nrows(), self.ncols()),level=1)
2354
d, u, v = self.smith_form()
2355
basis = []
2356
for i in xrange(self.ncols()):
2357
if (i >= self.nrows()) or d[i][i] == 0:
2358
basis.append( v.column(i).list() )
2359
verbose("done computing right kernel matrix over a domain for %sx%s matrix" % (self.nrows(), self.ncols()),level=1,t=tm)
2360
return 'computed-smith-form', self.new_matrix(nrows=len(basis), ncols=self._ncols, entries=basis)
2361
2362
def right_kernel_matrix(self, *args, **kwds):
2363
r"""
2364
Returns a matrix whose rows form a basis
2365
for the right kernel of ``self``.
2366
2367
INPUT:
2368
2369
- ``algorithm`` - default: 'default' - a keyword that selects the
2370
algorithm employed. Allowable values are:
2371
2372
- 'default' - allows the algorithm to be chosen automatically
2373
- 'generic' - naive algorithm usable for matrices over any field
2374
- 'pari' - PARI library code for matrices over number fields
2375
or the integers
2376
- 'padic' - padic algorithm from IML library for matrices
2377
over the rationals and integers
2378
- 'pluq' - PLUQ matrix factorization for matrices mod 2
2379
2380
- ``basis`` - default: 'echelon' - a keyword that describes
2381
the format of the basis returned. Allowable values are:
2382
2383
- 'echelon': the basis matrix is in echelon form
2384
- 'pivot' : each basis vector is computed from the reduced
2385
row-echelon form of ``self`` by placing a single one in a
2386
non-pivot column and zeros in the remaining non-pivot columns.
2387
Only available for matrices over fields.
2388
- 'LLL': an LLL-reduced basis. Only available for matrices
2389
over the integers.
2390
- 'computed': no work is done to transform the basis, it is
2391
returned exactly as provided by whichever routine actually
2392
computed the basis. Request this for the least possible
2393
computation possible, but with no guarantees about the format
2394
of the basis.
2395
2396
OUTPUT:
2397
2398
A matrix ``X`` whose rows are an independent set spanning the
2399
right kernel of ``self``. So ``self*X.transpose()`` is a zero matrix.
2400
2401
The output varies depending on the choice of ``algorithm`` and the
2402
format chosen by ``basis``.
2403
2404
The results of this routine are not cached, so you can call it again
2405
with different options to get possibly different output (like the basis
2406
format). Conversely, repeated calls on the same matrix will always
2407
start from scratch.
2408
2409
.. note::
2410
2411
If you want to get the most basic description of a kernel, with a
2412
minimum of overhead, then ask for the right kernel matrix with
2413
the basis format requested as 'computed'. You are then free to
2414
work with the output for whatever purpose. For a left kernel,
2415
call this method on the transpose of your matrix.
2416
2417
For greater convenience, plus cached results, request an actual
2418
vector space or free module with :meth:`right_kernel`
2419
or :meth:`left_kernel`.
2420
2421
EXAMPLES:
2422
2423
Over the Rational Numbers:
2424
2425
Kernels are computed by the IML library in
2426
:meth:`~sage.matrix.matrix_rational_dense.Matrix_rational_dense._right_kernel_matrix`.
2427
Setting the `algorithm` keyword to 'default', 'padic' or unspecified
2428
will yield the same result, as there is no optional behavior.
2429
The 'computed' format of the basis vectors are exactly the negatives
2430
of the vectors in the 'pivot' format. ::
2431
2432
sage: A = matrix(QQ, [[1, 0, 1, -3, 1],
2433
... [-5, 1, 0, 7, -3],
2434
... [0, -1, -4, 6, -2],
2435
... [4, -1, 0, -6, 2]])
2436
sage: C = A.right_kernel_matrix(algorithm='default', basis='computed'); C
2437
[-1 2 -2 -1 0]
2438
[ 1 2 0 0 -1]
2439
sage: A*C.transpose() == zero_matrix(QQ, 4, 2)
2440
True
2441
sage: P = A.right_kernel_matrix(algorithm='padic', basis='pivot'); P
2442
[ 1 -2 2 1 0]
2443
[-1 -2 0 0 1]
2444
sage: A*P.transpose() == zero_matrix(QQ, 4, 2)
2445
True
2446
sage: C == -P
2447
True
2448
sage: E = A.right_kernel_matrix(algorithm='default', basis='echelon'); E
2449
[ 1 0 1 1/2 -1/2]
2450
[ 0 1 -1/2 -1/4 -1/4]
2451
sage: A*E.transpose() == zero_matrix(QQ, 4, 2)
2452
True
2453
2454
Since the rationals are a field, we can call the general code
2455
available for any field by using the 'generic' keyword. ::
2456
2457
sage: A = matrix(QQ, [[1, 0, 1, -3, 1],
2458
... [-5, 1, 0, 7, -3],
2459
... [0, -1, -4, 6, -2],
2460
... [4, -1, 0, -6, 2]])
2461
sage: G = A.right_kernel_matrix(algorithm='generic', basis='echelon'); G
2462
[ 1 0 1 1/2 -1/2]
2463
[ 0 1 -1/2 -1/4 -1/4]
2464
sage: A*G.transpose() == zero_matrix(QQ, 4, 2)
2465
True
2466
2467
We verify that the rational matrix code is called for both
2468
dense and sparse rational matrices, with equal result. ::
2469
2470
sage: A = matrix(QQ, [[1, 0, 1, -3, 1],
2471
... [-5, 1, 0, 7, -3],
2472
... [0, -1, -4, 6, -2],
2473
... [4, -1, 0, -6, 2]],
2474
... sparse=False)
2475
sage: B = copy(A).sparse_matrix()
2476
sage: set_verbose(1)
2477
sage: D = A.right_kernel(); D
2478
verbose ...
2479
verbose 1 (<module>) computing right kernel matrix over the rationals for 4x5 matrix
2480
...
2481
verbose 1 (<module>) done computing right kernel matrix over the rationals for 4x5 matrix
2482
...
2483
Vector space of degree 5 and dimension 2 over Rational Field
2484
Basis matrix:
2485
[ 1 0 1 1/2 -1/2]
2486
[ 0 1 -1/2 -1/4 -1/4]
2487
sage: S = B.right_kernel(); S
2488
verbose ...
2489
verbose 1 (<module>) computing right kernel matrix over the rationals for 4x5 matrix
2490
...
2491
verbose 1 (<module>) done computing right kernel matrix over the rationals for 4x5 matrix
2492
...
2493
Vector space of degree 5 and dimension 2 over Rational Field
2494
Basis matrix:
2495
[ 1 0 1 1/2 -1/2]
2496
[ 0 1 -1/2 -1/4 -1/4]
2497
sage: set_verbose(0)
2498
sage: D == S
2499
True
2500
2501
Over Number Fields:
2502
2503
Kernels are by default computed by PARI, (except for exceptions like
2504
the rationals themselves). The raw results from PARI are a pivot
2505
basis, so the `basis` keywords 'computed' and 'pivot' will return
2506
the same results. ::
2507
2508
sage: Q = QuadraticField(-7)
2509
sage: a = Q.gen(0)
2510
sage: A = matrix(Q, [[2, 5-a, 15-a, 16+4*a],
2511
... [2+a, a, -7 + 5*a, -3+3*a]])
2512
sage: C = A.right_kernel_matrix(algorithm='default', basis='computed'); C
2513
[ -a -3 1 0]
2514
[ -2 -a - 1 0 1]
2515
sage: A*C.transpose() == zero_matrix(Q, 2, 2)
2516
True
2517
sage: P = A.right_kernel_matrix(algorithm='pari', basis='pivot'); P
2518
[ -a -3 1 0]
2519
[ -2 -a - 1 0 1]
2520
sage: A*P.transpose() == zero_matrix(Q, 2, 2)
2521
True
2522
sage: E = A.right_kernel_matrix(algorithm='default', basis='echelon'); E
2523
[ 1 0 7/88*a + 3/88 -3/176*a - 39/176]
2524
[ 0 1 -1/88*a - 13/88 13/176*a - 7/176]
2525
sage: A*E.transpose() == zero_matrix(Q, 2, 2)
2526
True
2527
2528
We can bypass using PARI for number fields and use Sage's general
2529
code for matrices over any field. The basis vectors as computed
2530
are in pivot format. ::
2531
2532
sage: Q = QuadraticField(-7)
2533
sage: a = Q.gen(0)
2534
sage: A = matrix(Q, [[2, 5-a, 15-a, 16+4*a],[2+a, a, -7 + 5*a, -3+3*a]])
2535
sage: G = A.right_kernel_matrix(algorithm='generic', basis='computed'); G
2536
[ -a -3 1 0]
2537
[ -2 -a - 1 0 1]
2538
sage: A*G.transpose() == zero_matrix(Q, 2, 2)
2539
True
2540
2541
We check that number fields are handled by the right routine as part of
2542
typical right kernel computation. ::
2543
2544
sage: Q = QuadraticField(-7)
2545
sage: a = Q.gen(0)
2546
sage: A = matrix(Q, [[2, 5-a, 15-a, 16+4*a],[2+a, a, -7 + 5*a, -3+3*a]])
2547
sage: set_verbose(1)
2548
sage: A.right_kernel(algorithm='default')
2549
verbose ...
2550
verbose 1 (<module>) computing right kernel matrix over a number field for 2x4 matrix
2551
verbose 1 (<module>) done computing right kernel matrix over a number field for 2x4 matrix
2552
...
2553
Vector space of degree 4 and dimension 2 over Number Field in a with defining polynomial x^2 + 7
2554
Basis matrix:
2555
[ 1 0 7/88*a + 3/88 -3/176*a - 39/176]
2556
[ 0 1 -1/88*a - 13/88 13/176*a - 7/176]
2557
sage: set_verbose(0)
2558
2559
Over the Finite Field of Order 2:
2560
2561
Kernels are computed by the M4RI library using PLUQ matrix
2562
decomposition in the
2563
:meth:`~sage.matrix.matrix_mod2_dense.Matrix_mod2_dense._right_kernel_matrix`
2564
method. There are no options for the algorithm used. ::
2565
2566
sage: A = matrix(GF(2),[[0, 1, 1, 0, 0, 0],
2567
... [1, 0, 0, 0, 1, 1,],
2568
... [1, 0, 0, 0, 1, 1]])
2569
sage: E = A.right_kernel_matrix(algorithm='default', format='echelon'); E
2570
[1 0 0 0 0 1]
2571
[0 1 1 0 0 0]
2572
[0 0 0 1 0 0]
2573
[0 0 0 0 1 1]
2574
sage: A*E.transpose() == zero_matrix(GF(2), 3, 4)
2575
True
2576
2577
Since GF(2) is a field we can route this computation to the generic
2578
code and obtain the 'pivot' form of the basis. The ``algorithm``
2579
keywords, 'pluq', 'default' and unspecified, all have the
2580
same effect as there is no optional behavior. ::
2581
2582
sage: A = matrix(GF(2),[[0, 1, 1, 0, 0, 0],
2583
... [1, 0, 0, 0, 1, 1,],
2584
... [1, 0, 0, 0, 1, 1]])
2585
sage: P = A.right_kernel_matrix(algorithm='generic', basis='pivot'); P
2586
[0 1 1 0 0 0]
2587
[0 0 0 1 0 0]
2588
[1 0 0 0 1 0]
2589
[1 0 0 0 0 1]
2590
sage: A*P.transpose() == zero_matrix(GF(2), 3, 4)
2591
True
2592
sage: DP = A.right_kernel_matrix(algorithm='default', basis='pivot'); DP
2593
[0 1 1 0 0 0]
2594
[0 0 0 1 0 0]
2595
[1 0 0 0 1 0]
2596
[1 0 0 0 0 1]
2597
sage: A*DP.transpose() == zero_matrix(GF(2), 3, 4)
2598
True
2599
sage: A.right_kernel_matrix(algorithm='pluq', basis='echelon')
2600
[1 0 0 0 0 1]
2601
[0 1 1 0 0 0]
2602
[0 0 0 1 0 0]
2603
[0 0 0 0 1 1]
2604
2605
We test that the mod 2 code is called for matrices over GF(2). ::
2606
2607
sage: A = matrix(GF(2),[[0, 1, 1, 0, 0, 0],
2608
... [1, 0, 0, 0, 1, 1,],
2609
... [1, 0, 0, 0, 1, 1]])
2610
sage: set_verbose(1)
2611
sage: A.right_kernel(algorithm='default')
2612
verbose ...
2613
verbose 1 (<module>) computing right kernel matrix over integers mod 2 for 3x6 matrix
2614
verbose 1 (<module>) done computing right kernel matrix over integers mod 2 for 3x6 matrix
2615
...
2616
Vector space of degree 6 and dimension 4 over Finite Field of size 2
2617
Basis matrix:
2618
[1 0 0 0 0 1]
2619
[0 1 1 0 0 0]
2620
[0 0 0 1 0 0]
2621
[0 0 0 0 1 1]
2622
sage: set_verbose(0)
2623
2624
Over Arbitrary Fields:
2625
2626
For kernels over fields not listed above, totally general code
2627
will compute a set of basis vectors in the pivot format.
2628
These could be returned as a basis in echelon form. ::
2629
2630
sage: F.<a> = FiniteField(5^2)
2631
sage: A = matrix(F, 3, 4, [[ 1, a, 1+a, a^3+a^5],
2632
... [ a, a^4, a+a^4, a^4+a^8],
2633
... [a^2, a^6, a^2+a^6, a^5+a^10]])
2634
sage: P = A.right_kernel_matrix(algorithm='default', basis='pivot'); P
2635
[ 4 4 1 0]
2636
[ a + 2 3*a + 3 0 1]
2637
sage: A*P.transpose() == zero_matrix(F, 3, 2)
2638
True
2639
sage: E = A.right_kernel_matrix(algorithm='default', basis='echelon'); E
2640
[ 1 0 3*a + 4 2*a + 2]
2641
[ 0 1 2*a 3*a + 3]
2642
sage: A*E.transpose() == zero_matrix(F, 3, 2)
2643
True
2644
2645
This general code can be requested for matrices over any field
2646
with the ``algorithm`` keyword 'generic'. Normally, matrices
2647
over the rationals would be handled by specific routines from
2648
the IML library. The default format is an echelon basis, but a
2649
pivot basis may be requested, which is identical to the computed
2650
basis. ::
2651
2652
sage: A = matrix(QQ, 3, 4, [[1,3,-2,4],
2653
... [2,0,2,2],
2654
... [-1,1,-2,0]])
2655
sage: G = A.right_kernel_matrix(algorithm='generic'); G
2656
[ 1 0 -1/2 -1/2]
2657
[ 0 1 1/2 -1/2]
2658
sage: A*G.transpose() == zero_matrix(QQ, 3, 2)
2659
True
2660
sage: C = A.right_kernel_matrix(algorithm='generic', basis='computed'); C
2661
[-1 1 1 0]
2662
[-1 -1 0 1]
2663
sage: A*C.transpose() == zero_matrix(QQ, 3, 2)
2664
True
2665
2666
We test that the generic code is called for matrices over fields,
2667
lacking any more specific routine. ::
2668
2669
sage: F.<a> = FiniteField(5^2)
2670
sage: A = matrix(F, 3, 4, [[ 1, a, 1+a, a^3+a^5],
2671
... [ a, a^4, a+a^4, a^4+a^8],
2672
... [a^2, a^6, a^2+a^6, a^5+a^10]])
2673
sage: set_verbose(1)
2674
sage: A.right_kernel(algorithm='default')
2675
verbose ...
2676
verbose 1 (<module>) computing right kernel matrix over an arbitrary field for 3x4 matrix
2677
...
2678
verbose 1 (<module>) done computing right kernel matrix over an arbitrary field for 3x4 matrix
2679
...
2680
Vector space of degree 4 and dimension 2 over Finite Field in a of size 5^2
2681
Basis matrix:
2682
[ 1 0 3*a + 4 2*a + 2]
2683
[ 0 1 2*a 3*a + 3]
2684
sage: set_verbose(0)
2685
2686
Over the Integers:
2687
2688
Either the IML or PARI libraries are used to provide a set of basis
2689
vectors. The ``algorithm`` keyword can be used to select either,
2690
or when set to 'default' a heuristic will choose between the two.
2691
Results can be returned in the 'compute' format, straight out of
2692
the libraries. Unique to the integers, the basis vectors can be
2693
returned as an LLL basis. Note the similarities and differences
2694
in the results. The 'pivot' format is not available, since the
2695
integers are not a field. ::
2696
2697
sage: A = matrix(ZZ, [[8, 0, 7, 1, 3, 4, 6],
2698
... [4, 0, 3, 4, 2, 7, 7],
2699
... [1, 4, 6, 1, 2, 8, 5],
2700
... [0, 3, 1, 2, 3, 6, 2]])
2701
2702
sage: X = A.right_kernel_matrix(algorithm='default', basis='echelon'); X
2703
[ 1 12 3 14 -3 -10 1]
2704
[ 0 35 0 25 -1 -31 17]
2705
[ 0 0 7 12 -3 -1 -8]
2706
sage: A*X.transpose() == zero_matrix(ZZ, 4, 3)
2707
True
2708
2709
sage: X = A.right_kernel_matrix(algorithm='padic', basis='LLL'); X
2710
[ -3 -1 5 7 2 -3 -2]
2711
[ 3 1 2 5 -5 2 -6]
2712
[ -4 -13 2 -7 5 7 -3]
2713
sage: A*X.transpose() == zero_matrix(ZZ, 4, 3)
2714
True
2715
2716
sage: X = A.right_kernel_matrix(algorithm='pari', basis='computed'); X
2717
[ 3 1 -5 -7 -2 3 2]
2718
[ 3 1 2 5 -5 2 -6]
2719
[ 4 13 -2 7 -5 -7 3]
2720
sage: A*X.transpose() == zero_matrix(ZZ, 4, 3)
2721
True
2722
2723
sage: X = A.right_kernel_matrix(algorithm='padic', basis='computed'); X
2724
[ 265 345 -178 17 -297 0 0]
2725
[-242 -314 163 -14 271 -1 0]
2726
[ -36 -47 25 -1 40 0 -1]
2727
sage: A*X.transpose() == zero_matrix(ZZ, 4, 3)
2728
True
2729
2730
We test that the code for integer matrices is called for matrices
2731
defined over the integers, both dense and sparse, with equal result. ::
2732
2733
sage: A = matrix(ZZ, [[8, 0, 7, 1, 3, 4, 6],
2734
... [4, 0, 3, 4, 2, 7, 7],
2735
... [1, 4, 6, 1, 2, 8, 5],
2736
... [0, 3, 1, 2, 3, 6, 2]],
2737
... sparse=False)
2738
sage: B = copy(A).sparse_matrix()
2739
sage: set_verbose(1)
2740
sage: D = A.right_kernel(); D
2741
verbose ...
2742
verbose 1 (<module>) computing right kernel matrix over the integers for 4x7 matrix
2743
verbose 1 (<module>) done computing right kernel matrix over the integers for 4x7 matrix
2744
...
2745
Free module of degree 7 and rank 3 over Integer Ring
2746
Echelon basis matrix:
2747
[ 1 12 3 14 -3 -10 1]
2748
[ 0 35 0 25 -1 -31 17]
2749
[ 0 0 7 12 -3 -1 -8]
2750
sage: S = B.right_kernel(); S
2751
verbose ...
2752
verbose 1 (<module>) computing right kernel matrix over the integers for 4x7 matrix
2753
verbose 1 (<module>) done computing right kernel matrix over the integers for 4x7 matrix
2754
...
2755
Free module of degree 7 and rank 3 over Integer Ring
2756
Echelon basis matrix:
2757
[ 1 12 3 14 -3 -10 1]
2758
[ 0 35 0 25 -1 -31 17]
2759
[ 0 0 7 12 -3 -1 -8]
2760
sage: set_verbose(0)
2761
sage: D == S
2762
True
2763
2764
Over Principal Ideal Domains:
2765
2766
Kernels can be computed using Smith normal form. Only the default
2767
algorithm is available, and the 'pivot' basis format is
2768
not available. ::
2769
2770
sage: R.<y> = QQ[]
2771
sage: A = matrix(R, [[ 1, y, 1+y^2],
2772
... [y^3, y^2, 2*y^3]])
2773
sage: E = A.right_kernel_matrix(algorithm='default', basis='echelon'); E
2774
[-1 -y 1]
2775
sage: A*E.transpose() == zero_matrix(ZZ, 2, 1)
2776
True
2777
2778
It can be computationally expensive to determine if an integral
2779
domain is a principal ideal domain. The Smith normal form routine
2780
can fail for non-PIDs, as in this example. ::
2781
2782
sage: D.<x> = ZZ[]
2783
sage: A = matrix(D, 2, 2, [[x^2 - x, -x + 5],
2784
... [x^2 - 8, -x + 2]])
2785
sage: A.right_kernel_matrix()
2786
Traceback (most recent call last):
2787
...
2788
ArithmeticError: Ideal Ideal (x^2 - x, x^2 - 8) of Univariate Polynomial Ring in x over Integer Ring not principal
2789
2790
We test that the domain code is called for domains that lack any
2791
extra structure. ::
2792
2793
sage: R.<y> = QQ[]
2794
sage: A = matrix(R, [[ 1, y, 1+y^2],
2795
... [y^3, y^2, 2*y^3]])
2796
sage: set_verbose(1)
2797
sage: A.right_kernel(algorithm='default', basis='echelon')
2798
verbose ...
2799
verbose 1 (<module>) computing right kernel matrix over a domain for 2x3 matrix
2800
verbose 1 (<module>) done computing right kernel matrix over a domain for 2x3 matrix
2801
...
2802
Free module of degree 3 and rank 1 over Univariate Polynomial Ring in y over Rational Field
2803
Echelon basis matrix:
2804
[-1 -y 1]
2805
sage: set_verbose(0)
2806
2807
Trivial Cases:
2808
2809
We test two trivial cases. Any possible values for the
2810
keywords (``algorithm``, ``basis``) will return identical results. ::
2811
2812
sage: A = matrix(ZZ, 0, 2)
2813
sage: A.right_kernel_matrix()
2814
[1 0]
2815
[0 1]
2816
sage: A = matrix(FiniteField(7), 2, 0)
2817
sage: A.right_kernel_matrix().parent()
2818
Full MatrixSpace of 0 by 0 dense matrices over Finite Field of size 7
2819
2820
TESTS:
2821
2822
The "usual" quaternions are a non-commutative ring and computations
2823
of kernels over these rings are not implemented. ::
2824
2825
sage: Q.<i,j,k> = QuaternionAlgebra(-1,-1)
2826
sage: A = matrix(Q, 2, [i,j,-1,k])
2827
sage: A.right_kernel_matrix()
2828
Traceback (most recent call last):
2829
...
2830
NotImplementedError: Cannot compute a matrix kernel over Quaternion Algebra (-1, -1) with base ring Rational Field
2831
2832
We test error messages for improper choices of the 'algorithm'
2833
keyword. ::
2834
2835
sage: matrix(ZZ, 2, 2).right_kernel_matrix(algorithm='junk')
2836
Traceback (most recent call last):
2837
...
2838
ValueError: matrix kernel algorithm 'junk' not recognized
2839
sage: matrix(GF(2), 2, 2).right_kernel_matrix(algorithm='padic')
2840
Traceback (most recent call last):
2841
...
2842
ValueError: 'padic' matrix kernel algorithm only available over the rationals and the integers, not over Finite Field of size 2
2843
sage: matrix(QQ, 2, 2).right_kernel_matrix(algorithm='pari')
2844
Traceback (most recent call last):
2845
...
2846
ValueError: 'pari' matrix kernel algorithm only available over non-trivial number fields and the integers, not over Rational Field
2847
sage: matrix(Integers(6), 2, 2).right_kernel_matrix(algorithm='generic')
2848
Traceback (most recent call last):
2849
...
2850
ValueError: 'generic' matrix kernel algorithm only available over a field, not over Ring of integers modulo 6
2851
sage: matrix(QQ, 2, 2).right_kernel_matrix(algorithm='pluq')
2852
Traceback (most recent call last):
2853
...
2854
ValueError: 'pluq' matrix kernel algorithm only available over integers mod 2, not over Rational Field
2855
2856
We test error messages for improper basis format requests. ::
2857
2858
sage: matrix(ZZ, 2, 2).right_kernel_matrix(basis='junk')
2859
Traceback (most recent call last):
2860
...
2861
ValueError: matrix kernel basis format 'junk' not recognized
2862
sage: matrix(ZZ, 2, 2).right_kernel_matrix(basis='pivot')
2863
Traceback (most recent call last):
2864
...
2865
ValueError: pivot basis only available over a field, not over Integer Ring
2866
sage: matrix(QQ, 2, 2).right_kernel_matrix(basis='LLL')
2867
Traceback (most recent call last):
2868
...
2869
ValueError: LLL-reduced basis only available over the integers, not over Rational Field
2870
2871
Finally, error messages for the 'proof' keyword. ::
2872
2873
sage: matrix(ZZ, 2, 2).right_kernel_matrix(proof='junk')
2874
Traceback (most recent call last):
2875
...
2876
ValueError: 'proof' must be one of True, False or None, not junk
2877
sage: matrix(QQ, 2, 2).right_kernel_matrix(proof=True)
2878
Traceback (most recent call last):
2879
...
2880
ValueError: 'proof' flag only valid for matrices over the integers
2881
2882
AUTHOR:
2883
2884
- Rob Beezer (2011-02-05)
2885
"""
2886
R = self.base_ring()
2887
2888
# First: massage keywords
2889
# Determine algorithm to use for computation of kernel matrix
2890
algorithm = kwds.pop('algorithm', None)
2891
if algorithm is None:
2892
algorithm = 'default'
2893
elif not algorithm in ['default', 'generic', 'pari', 'padic', 'pluq']:
2894
raise ValueError("matrix kernel algorithm '%s' not recognized" % algorithm )
2895
elif algorithm == 'padic' and not (is_IntegerRing(R) or is_RationalField(R)):
2896
raise ValueError("'padic' matrix kernel algorithm only available over the rationals and the integers, not over %s" % R)
2897
elif algorithm == 'pari' and not (is_IntegerRing(R) or (is_NumberField(R) and not is_RationalField(R))):
2898
raise ValueError("'pari' matrix kernel algorithm only available over non-trivial number fields and the integers, not over %s" % R)
2899
elif algorithm == 'generic' and not R.is_field():
2900
raise ValueError("'generic' matrix kernel algorithm only available over a field, not over %s" % R)
2901
elif algorithm == 'pluq' and not isinstance(self, sage.matrix.matrix_mod2_dense.Matrix_mod2_dense):
2902
raise ValueError("'pluq' matrix kernel algorithm only available over integers mod 2, not over %s" % R)
2903
2904
# Determine the basis format of independent spanning set to return
2905
basis = kwds.pop('basis', None)
2906
if basis is None:
2907
basis = 'echelon'
2908
elif not basis in ['computed', 'echelon', 'pivot', 'LLL']:
2909
raise ValueError("matrix kernel basis format '%s' not recognized" % basis )
2910
elif basis == 'pivot' and not R.is_field():
2911
raise ValueError('pivot basis only available over a field, not over %s' % R)
2912
elif basis == 'LLL' and not is_IntegerRing(R):
2913
raise ValueError('LLL-reduced basis only available over the integers, not over %s' % R)
2914
2915
# Determine proof keyword for integer matrices
2916
proof = kwds.pop('proof', None)
2917
if not (proof in [None, True, False]):
2918
raise ValueError("'proof' must be one of True, False or None, not %s" % proof)
2919
if not (proof is None or is_IntegerRing(R)):
2920
raise ValueError("'proof' flag only valid for matrices over the integers")
2921
2922
# We could sanitize/process remaining (un-popped) keywords here and
2923
# send them to the echelon form routine in the 'generic' algorithm case
2924
# Would need to handle 'algorithm' keyword properly
2925
2926
# Second: Trivial cases over any integral domain
2927
# With zero columns the domain has dimension 0,
2928
# so only an empty basis is possible
2929
# With zero rows the codomain is just the zero vector,
2930
# thus the kernel is the whole domain, so return an identity matrix
2931
# identity_matrix constructor will fail if ring does not have a one
2932
# For all keywords the results are identical
2933
if self._ncols == 0 and R.is_integral_domain():
2934
return self.new_matrix(nrows = 0, ncols = self._ncols)
2935
if self._nrows == 0 and R.is_integral_domain():
2936
import constructor
2937
return constructor.identity_matrix(R, self._ncols)
2938
2939
# Third: generic first, if requested explicitly
2940
# then try specialized class methods, and finally
2941
# delegate to ad-hoc methods in greater generality
2942
M = None; format = ''
2943
2944
if algorithm == 'generic':
2945
format, M = self._right_kernel_matrix_over_field()
2946
2947
if M is None:
2948
try:
2949
format, M = self._right_kernel_matrix(algorithm=algorithm, proof=proof)
2950
except AttributeError:
2951
pass
2952
2953
if M is None and is_NumberField(R):
2954
format, M = self._right_kernel_matrix_over_number_field()
2955
2956
if M is None and R.is_field():
2957
format, M = self._right_kernel_matrix_over_field()
2958
2959
if M is None and R.is_integral_domain():
2960
format, M = self._right_kernel_matrix_over_domain()
2961
2962
if M is None:
2963
raise NotImplementedError("Cannot compute a matrix kernel over %s" % R)
2964
2965
# Trivial kernels give empty matrices, which sometimes mistakenly have
2966
# zero columns as well. (eg PARI?) This could be fixed at the source
2967
# with a careful study of the phenomenon. Start by commenting out
2968
# the following and running doctests in sage/matrix
2969
if M.nrows()==0 and M.ncols()!=self.ncols():
2970
M = M.new_matrix(nrows=0, ncols=self.ncols())
2971
2972
# Convert basis to requested type and return the matrix
2973
# format string leads with 'echelon', 'pivot' or 'LLL' if known
2974
# to be of that format otherwise format string leads with
2975
# 'computed' if it needs work (ie raw results)
2976
if basis == 'computed':
2977
return M
2978
elif basis == 'echelon':
2979
if not format[:7] == 'echelon':
2980
return M.echelon_form()
2981
else:
2982
return M
2983
elif basis == 'pivot':
2984
# cannot get here unless over a field
2985
if not format[:5] == 'pivot':
2986
# convert non-pivot columns to identity matrix
2987
# this is the basis immediately obvious from echelon form
2988
# so C is always invertible (when working over a field)
2989
C = M.matrix_from_columns(self.nonpivots())
2990
return C.inverse()*M
2991
else:
2992
return M
2993
elif basis == 'LLL':
2994
# cannot get here unless over integers
2995
if not format[:3] == 'LLL':
2996
return M.LLL()
2997
else:
2998
return M
2999
3000
def right_kernel(self, *args, **kwds):
3001
r"""
3002
Returns the right kernel of this matrix, as a vector space or
3003
free module. This is the set of vectors ``x`` such that ``self*x = 0``.
3004
3005
.. note::
3006
3007
For the left kernel, use :meth:`left_kernel`. The method
3008
:meth:`kernel` is exactly equal to :meth:`left_kernel`.
3009
3010
INPUT:
3011
3012
- ``algorithm`` - default: 'default' - a keyword that selects the
3013
algorithm employed. Allowable values are:
3014
3015
- 'default' - allows the algorithm to be chosen automatically
3016
- 'generic' - naive algorithm usable for matrices over any field
3017
- 'pari' - PARI library code for matrices over number fields
3018
or the integers
3019
- 'padic' - padic algorithm from IML library for matrices
3020
over the rationals and integers
3021
- 'pluq' - PLUQ matrix factorization for matrices mod 2
3022
3023
- ``basis`` - default: 'echelon' - a keyword that describes the
3024
format of the basis used to construct the left kernel.
3025
Allowable values are:
3026
3027
- 'echelon': the basis matrix is in echelon form
3028
- 'pivot' : each basis vector is computed from the reduced
3029
row-echelon form of ``self`` by placing a single one in a
3030
non-pivot column and zeros in the remaining non-pivot columns.
3031
Only available for matrices over fields.
3032
- 'LLL': an LLL-reduced basis. Only available for matrices
3033
over the integers.
3034
3035
OUTPUT:
3036
3037
A vector space or free module whose degree equals the number
3038
of columns in ``self`` and contains all the vectors ``x`` such
3039
that ``self*x = 0``.
3040
3041
If ``self`` has 0 columns, the kernel has dimension 0, while if
3042
``self`` has 0 rows the kernel is the entire ambient vector space.
3043
3044
The result is cached. Requesting the right kernel a second time,
3045
but with a different basis format, will return the cached result
3046
with the format from the first computation.
3047
3048
.. note::
3049
3050
For more detailed documentation on the selection of algorithms
3051
used and a more flexible method for computing a basis matrix
3052
for a right kernel (rather than computing a vector space), see
3053
:meth:`right_kernel_matrix`, which powers the computations for
3054
this method.
3055
3056
EXAMPLES::
3057
3058
sage: A = matrix(QQ, [[0, 0, 1, 2, 2, -5, 3],
3059
... [-1, 5, 2, 2, 1, -7, 5],
3060
... [0, 0, -2, -3, -3, 8, -5],
3061
... [-1, 5, 0, -1, -2, 1, 0]])
3062
sage: K = A.right_kernel(); K
3063
Vector space of degree 7 and dimension 4 over Rational Field
3064
Basis matrix:
3065
[ 1 0 0 0 -1 -1 -1]
3066
[ 0 1 0 0 5 5 5]
3067
[ 0 0 1 0 -1 -2 -3]
3068
[ 0 0 0 1 0 1 1]
3069
sage: A*K.basis_matrix().transpose() == zero_matrix(QQ, 4, 4)
3070
True
3071
3072
The default is basis vectors that form a matrix in echelon form.
3073
A "pivot basis" instead has a basis matrix where the columns of
3074
an identity matrix are in the locations of the non-pivot columns
3075
of the original matrix. This alternate format is available whenever
3076
the base ring is a field. ::
3077
3078
sage: A = matrix(QQ, [[0, 0, 1, 2, 2, -5, 3],
3079
... [-1, 5, 2, 2, 1, -7, 5],
3080
... [0, 0, -2, -3, -3, 8, -5],
3081
... [-1, 5, 0, -1, -2, 1, 0]])
3082
sage: A.rref()
3083
[ 1 -5 0 0 1 1 -1]
3084
[ 0 0 1 0 0 -1 1]
3085
[ 0 0 0 1 1 -2 1]
3086
[ 0 0 0 0 0 0 0]
3087
sage: A.nonpivots()
3088
(1, 4, 5, 6)
3089
sage: K = A.right_kernel(basis='pivot'); K
3090
Vector space of degree 7 and dimension 4 over Rational Field
3091
User basis matrix:
3092
[ 5 1 0 0 0 0 0]
3093
[-1 0 0 -1 1 0 0]
3094
[-1 0 1 2 0 1 0]
3095
[ 1 0 -1 -1 0 0 1]
3096
sage: A*K.basis_matrix().transpose() == zero_matrix(QQ, 4, 4)
3097
True
3098
3099
Matrices may have any field as a base ring. Number fields are
3100
computed by PARI library code, matrices over `GF(2)` are computed
3101
by the M4RI library, and matrices over the rationals are computed by
3102
the IML library. For any of these specialized cases, general-purpose
3103
code can be called instead with the keyword setting
3104
``algorithm='generic'``.
3105
3106
Over an arbitrary field, with two basis formats. Same vector space,
3107
different bases. ::
3108
3109
sage: F.<a> = FiniteField(5^2)
3110
sage: A = matrix(F, 3, 4, [[ 1, a, 1+a, a^3+a^5],
3111
... [ a, a^4, a+a^4, a^4+a^8],
3112
... [a^2, a^6, a^2+a^6, a^5+a^10]])
3113
sage: K = A.right_kernel(); K
3114
Vector space of degree 4 and dimension 2 over Finite Field in a of size 5^2
3115
Basis matrix:
3116
[ 1 0 3*a + 4 2*a + 2]
3117
[ 0 1 2*a 3*a + 3]
3118
sage: A*K.basis_matrix().transpose() == zero_matrix(F, 3, 2)
3119
True
3120
sage: B = copy(A)
3121
sage: P = B.right_kernel(basis = 'pivot'); P
3122
Vector space of degree 4 and dimension 2 over Finite Field in a of size 5^2
3123
User basis matrix:
3124
[ 4 4 1 0]
3125
[ a + 2 3*a + 3 0 1]
3126
sage: B*P.basis_matrix().transpose() == zero_matrix(F, 3, 2)
3127
True
3128
sage: K == P
3129
True
3130
3131
Over number fields, PARI is used by default, but general-purpose code
3132
can be requested. Same vector space, same bases, different code.::
3133
3134
sage: Q = QuadraticField(-7)
3135
sage: a = Q.gen(0)
3136
sage: A = matrix(Q, [[ 2, 5-a, 15-a, 16+4*a],
3137
... [2+a, a, -7 + 5*a, -3+3*a]])
3138
sage: K = A.right_kernel(algorithm='default'); K
3139
Vector space of degree 4 and dimension 2 over Number Field in a with defining polynomial x^2 + 7
3140
Basis matrix:
3141
[ 1 0 7/88*a + 3/88 -3/176*a - 39/176]
3142
[ 0 1 -1/88*a - 13/88 13/176*a - 7/176]
3143
sage: A*K.basis_matrix().transpose() == zero_matrix(Q, 2, 2)
3144
True
3145
sage: B = copy(A)
3146
sage: G = A.right_kernel(algorithm='generic'); G
3147
Vector space of degree 4 and dimension 2 over Number Field in a with defining polynomial x^2 + 7
3148
Basis matrix:
3149
[ 1 0 7/88*a + 3/88 -3/176*a - 39/176]
3150
[ 0 1 -1/88*a - 13/88 13/176*a - 7/176]
3151
sage: B*G.basis_matrix().transpose() == zero_matrix(Q, 2, 2)
3152
True
3153
sage: K == G
3154
True
3155
3156
For matrices over the integers, several options are possible.
3157
The basis can be an LLL-reduced basis or an echelon basis.
3158
The pivot basis isnot available. A heuristic will decide whether
3159
to use a p-adic algorithm from the IML library or an algorithm
3160
from the PARI library. Note how specifying the algorithm can
3161
mildly influence the LLL basis. ::
3162
3163
sage: A = matrix(ZZ, [[0, -1, -1, 2, 9, 4, -4],
3164
... [-1, 1, 0, -2, -7, -1, 6],
3165
... [2, 0, 1, 0, 1, -5, -2],
3166
... [-1, -1, -1, 3, 10, 10, -9],
3167
... [-1, 2, 0, -3, -7, 1, 6]])
3168
sage: A.right_kernel(basis='echelon')
3169
Free module of degree 7 and rank 2 over Integer Ring
3170
Echelon basis matrix:
3171
[ 1 5 -8 3 -1 -1 -1]
3172
[ 0 11 -19 5 -2 -3 -3]
3173
sage: B = copy(A)
3174
sage: B.right_kernel(basis='LLL')
3175
Free module of degree 7 and rank 2 over Integer Ring
3176
User basis matrix:
3177
[ 2 -1 3 1 0 1 1]
3178
[-5 -3 2 -5 1 -1 -1]
3179
sage: C = copy(A)
3180
sage: C.right_kernel(basis='pivot')
3181
Traceback (most recent call last):
3182
...
3183
ValueError: pivot basis only available over a field, not over Integer Ring
3184
sage: D = copy(A)
3185
sage: D.right_kernel(algorithm='pari')
3186
Free module of degree 7 and rank 2 over Integer Ring
3187
Echelon basis matrix:
3188
[ 1 5 -8 3 -1 -1 -1]
3189
[ 0 11 -19 5 -2 -3 -3]
3190
sage: E = copy(A)
3191
sage: E.right_kernel(algorithm='padic', basis='LLL')
3192
Free module of degree 7 and rank 2 over Integer Ring
3193
User basis matrix:
3194
[-2 1 -3 -1 0 -1 -1]
3195
[ 5 3 -2 5 -1 1 1]
3196
3197
Besides the integers, rings may be as general as principal ideal
3198
domains. Results are then free modules. ::
3199
3200
sage: R.<y> = QQ[]
3201
sage: A = matrix(R, [[ 1, y, 1+y^2],
3202
... [y^3, y^2, 2*y^3]])
3203
sage: K = A.right_kernel(algorithm='default', basis='echelon'); K
3204
Free module of degree 3 and rank 1 over Univariate Polynomial Ring in y over Rational Field
3205
Echelon basis matrix:
3206
[-1 -y 1]
3207
sage: A*K.basis_matrix().transpose() == zero_matrix(ZZ, 2, 1)
3208
True
3209
3210
It is possible to compute a kernel for a matrix over an integral
3211
domain which is not a PID, but usually this will fail. ::
3212
3213
sage: D.<x> = ZZ[]
3214
sage: A = matrix(D, 2, 2, [[x^2 - x, -x + 5],
3215
... [x^2 - 8, -x + 2]])
3216
sage: A.right_kernel()
3217
Traceback (most recent call last):
3218
...
3219
ArithmeticError: Ideal Ideal (x^2 - x, x^2 - 8) of Univariate Polynomial Ring in x over Integer Ring not principal
3220
3221
Matrices over non-commutative rings are not a good idea either.
3222
These are the "usual" quaternions. ::
3223
3224
sage: Q.<i,j,k> = QuaternionAlgebra(-1,-1)
3225
sage: A = matrix(Q, 2, [i,j,-1,k])
3226
sage: A.right_kernel()
3227
Traceback (most recent call last):
3228
...
3229
NotImplementedError: Cannot compute a matrix kernel over Quaternion Algebra (-1, -1) with base ring Rational Field
3230
3231
Sparse matrices, over the rationals and the integers,
3232
use the same routines as the dense versions. ::
3233
3234
sage: A = matrix(ZZ, [[0, -1, 1, 1, 2],
3235
... [1, -2, 0, 1, 3],
3236
... [-1, 2, 0, -1, -3]],
3237
... sparse=True)
3238
sage: A.right_kernel()
3239
Free module of degree 5 and rank 3 over Integer Ring
3240
Echelon basis matrix:
3241
[ 1 0 0 2 -1]
3242
[ 0 1 0 -1 1]
3243
[ 0 0 1 -3 1]
3244
sage: B = A.change_ring(QQ)
3245
sage: B.is_sparse()
3246
True
3247
sage: B.right_kernel()
3248
Vector space of degree 5 and dimension 3 over Rational Field
3249
Basis matrix:
3250
[ 1 0 0 2 -1]
3251
[ 0 1 0 -1 1]
3252
[ 0 0 1 -3 1]
3253
3254
With no columns, the kernel can only have dimension zero.
3255
With no rows, every possible vector is in the kernel. ::
3256
3257
sage: A = matrix(QQ, 2, 0)
3258
sage: A.right_kernel()
3259
Vector space of degree 0 and dimension 0 over Rational Field
3260
Basis matrix:
3261
[]
3262
sage: A = matrix(QQ, 0, 2)
3263
sage: A.right_kernel()
3264
Vector space of degree 2 and dimension 2 over Rational Field
3265
Basis matrix:
3266
[1 0]
3267
[0 1]
3268
3269
Every vector is in the kernel of a zero matrix, the
3270
dimension is the number of columns. ::
3271
3272
sage: A = zero_matrix(QQ, 10, 20)
3273
sage: A.right_kernel()
3274
Vector space of degree 20 and dimension 20 over Rational Field
3275
Basis matrix:
3276
20 x 20 dense matrix over Rational Field
3277
3278
Results are cached as the right kernel of the matrix.
3279
Subsequent requests for the right kernel will return
3280
the cached result, without regard for new values of the
3281
algorithm or format keyword. Work with a copy if you
3282
need a new right kernel, or perhaps investigate the
3283
:meth:`right_kernel_matrix` method, which does not
3284
cache its results and is more flexible. ::
3285
3286
sage: A = matrix(QQ, 3, range(9))
3287
sage: K1 = A.right_kernel(basis='echelon')
3288
sage: K1
3289
Vector space of degree 3 and dimension 1 over Rational Field
3290
Basis matrix:
3291
[ 1 -2 1]
3292
sage: K2 = A.right_kernel(basis='pivot')
3293
sage: K2
3294
Vector space of degree 3 and dimension 1 over Rational Field
3295
Basis matrix:
3296
[ 1 -2 1]
3297
sage: K1 is K2
3298
True
3299
sage: B = copy(A)
3300
sage: K3 = B.kernel(basis='pivot')
3301
sage: K3
3302
Vector space of degree 3 and dimension 1 over Rational Field
3303
User basis matrix:
3304
[ 1 -2 1]
3305
sage: K3 is K1
3306
False
3307
sage: K3 == K1
3308
True
3309
"""
3310
K = self.fetch('right_kernel')
3311
if not K is None:
3312
verbose("retrieving cached right kernel for %sx%s matrix" % (self.nrows(), self.ncols()),level=1)
3313
return K
3314
3315
R = self.base_ring()
3316
tm = verbose("computing a right kernel for %sx%s matrix over %s" % (self.nrows(), self.ncols(), R),level=1)
3317
3318
# Sanitize basis format
3319
# 'computed' is OK in right_kernel_matrix(), but not here
3320
# 'echelon' is default here (and elsewhere)
3321
# everything else gets checked in right_kernel_matrix()
3322
basis = kwds.pop('basis', None)
3323
if basis == 'computed':
3324
raise ValueError("kernel basis format 'computed' not supported for kernels (just right kernel matrices)")
3325
if basis is None:
3326
basis = 'echelon'
3327
kwds['basis'] = basis
3328
3329
# Go get the kernel matrix, this is where it all happens
3330
M = self.right_kernel_matrix(*args, **kwds)
3331
3332
ambient = R**self.ncols()
3333
if basis == 'echelon':
3334
K = ambient.submodule(M.rows(), already_echelonized=True, check=False)
3335
else:
3336
K = ambient.submodule_with_basis(M.rows(), already_echelonized=False, check=False)
3337
3338
verbose("done computing a right kernel for %sx%s matrix over %s" % (self.nrows(), self.ncols(), R),level=1, t=tm)
3339
self.cache('right_kernel', K)
3340
return K
3341
3342
def left_kernel(self, *args, **kwds):
3343
r"""
3344
Returns the left kernel of this matrix, as a vector space or free module.
3345
This is the set of vectors ``x`` such that ``x*self = 0``.
3346
3347
.. note::
3348
3349
For the right kernel, use :meth:`right_kernel`. The method
3350
:meth:`kernel` is exactly equal to :meth:`left_kernel`.
3351
3352
INPUT:
3353
3354
- ``algorithm`` - default: 'default' - a keyword that selects the
3355
algorithm employed. Allowable values are:
3356
3357
- 'default' - allows the algorithm to be chosen automatically
3358
- 'generic' - naive algorithm usable for matrices over any field
3359
- 'pari' - PARI library code for matrices over number fields
3360
or the integers
3361
- 'padic' - padic algorithm from IML library for matrices
3362
over the rationals and integers
3363
- 'pluq' - PLUQ matrix factorization for matrices mod 2
3364
3365
- ``basis`` - default: 'echelon' - a keyword that describes
3366
the format of the basis used to construct the left kernel.
3367
Allowable values are:
3368
3369
- 'echelon': the basis matrix is in echelon form
3370
- 'pivot' : each basis vector is computed from the reduced
3371
row-echelon form of ``self`` by placing a single one in a
3372
non-pivot column and zeros in the remaining non-pivot columns.
3373
Only available for matrices over fields.
3374
- 'LLL': an LLL-reduced basis. Only available for matrices
3375
over the integers.
3376
3377
OUTPUT:
3378
3379
A vector space or free module whose degree equals the number
3380
of rows in ``self`` and contains all the vectors ``x`` such
3381
that ``x*self = 0``.
3382
3383
If ``self`` has 0 rows, the kernel has dimension 0, while if ``self``
3384
has 0 columns the kernel is the entire ambient vector space.
3385
3386
The result is cached. Requesting the left kernel a second time,
3387
but with a different basis format will return the cached result
3388
with the format from the first computation.
3389
3390
.. note::
3391
3392
For much more detailed documentation of the various options see
3393
:meth:`right_kernel`, since this method just computes
3394
the right kernel of the transpose of ``self``.
3395
3396
EXAMPLES:
3397
3398
Over the rationals with a basis matrix in echelon form. ::
3399
3400
sage: A = matrix(QQ, [[1, 2, 4, -7, 4],
3401
... [1, 1, 0, 2, -1],
3402
... [1, 0, 3, -3, 1],
3403
... [0, -1, -1, 3, -2],
3404
... [0, 0, -1, 2, -1]])
3405
sage: A.left_kernel()
3406
Vector space of degree 5 and dimension 2 over Rational Field
3407
Basis matrix:
3408
[ 1 0 -1 2 -1]
3409
[ 0 1 -1 1 -4]
3410
3411
Over a finite field, with a basis matrix in "pivot" format. ::
3412
3413
sage: A = matrix(FiniteField(7), [[5, 0, 5, 2, 4],
3414
... [1, 3, 2, 3, 6],
3415
... [1, 1, 6, 5, 3],
3416
... [2, 5, 6, 0, 0]])
3417
sage: A.kernel(basis='pivot')
3418
Vector space of degree 4 and dimension 2 over Finite Field of size 7
3419
User basis matrix:
3420
[5 2 1 0]
3421
[6 3 0 1]
3422
3423
The left kernel of a zero matrix is the entire ambient vector
3424
space whose degree equals the number of rows of ``self``
3425
(i.e. everything). ::
3426
3427
sage: A = MatrixSpace(QQ, 3, 4)(0)
3428
sage: A.kernel()
3429
Vector space of degree 3 and dimension 3 over Rational Field
3430
Basis matrix:
3431
[1 0 0]
3432
[0 1 0]
3433
[0 0 1]
3434
3435
We test matrices with no rows or columns. ::
3436
3437
sage: A = matrix(QQ, 2, 0)
3438
sage: A.left_kernel()
3439
Vector space of degree 2 and dimension 2 over Rational Field
3440
Basis matrix:
3441
[1 0]
3442
[0 1]
3443
sage: A = matrix(QQ, 0, 2)
3444
sage: A.left_kernel()
3445
Vector space of degree 0 and dimension 0 over Rational Field
3446
Basis matrix:
3447
[]
3448
3449
The results are cached. Note that requesting a new format
3450
for the basis is ignored and the cached copy is returned.
3451
Work with a copy if you need a new left kernel, or perhaps
3452
investigate the :meth:`right_kernel_matrix` method on the
3453
transpose, which does not cache its results and is more
3454
flexible. ::
3455
3456
sage: A = matrix(QQ, [[1,1],[2,2]])
3457
sage: K1 = A.left_kernel()
3458
sage: K1
3459
Vector space of degree 2 and dimension 1 over Rational Field
3460
Basis matrix:
3461
[ 1 -1/2]
3462
sage: K2 = A.left_kernel()
3463
sage: K1 is K2
3464
True
3465
sage: K3 = A.left_kernel(basis='pivot')
3466
sage: K3
3467
Vector space of degree 2 and dimension 1 over Rational Field
3468
Basis matrix:
3469
[ 1 -1/2]
3470
sage: B = copy(A)
3471
sage: K3 = B.left_kernel(basis='pivot')
3472
sage: K3
3473
Vector space of degree 2 and dimension 1 over Rational Field
3474
User basis matrix:
3475
[-2 1]
3476
sage: K3 is K1
3477
False
3478
sage: K3 == K1
3479
True
3480
"""
3481
K = self.fetch('left_kernel')
3482
if not K is None:
3483
verbose("retrieving cached left kernel for %sx%s matrix" % (self.nrows(), self.ncols()),level=1)
3484
return K
3485
3486
tm = verbose("computing left kernel for %sx%s matrix" % (self.nrows(), self.ncols()),level=1)
3487
K = self.transpose().right_kernel(*args, **kwds)
3488
self.cache('left_kernel', K)
3489
verbose("done computing left kernel for %sx%s matrix" % (self.nrows(), self.ncols()),level=1,t=tm)
3490
return K
3491
3492
# .kernel() is a an alias for .left_kernel()
3493
kernel = left_kernel
3494
3495
def kernel_on(self, V, poly=None, check=True):
3496
"""
3497
Return the kernel of self restricted to the invariant subspace V.
3498
The result is a vector subspace of V, which is also a subspace
3499
of the ambient space.
3500
3501
INPUT:
3502
3503
- ``V`` - vector subspace
3504
3505
- ``check`` - (optional) default: True; whether to check that
3506
V is invariant under the action of self.
3507
3508
- ``poly`` - (optional) default: None; if not None, compute instead
3509
the kernel of poly(self) on V.
3510
3511
OUTPUT:
3512
3513
- a subspace
3514
3515
.. warning::
3516
3517
This function does *not* check that V is in fact
3518
invariant under self if check is False. With check False this
3519
function is much faster.
3520
3521
EXAMPLES::
3522
3523
sage: t = matrix(QQ, 4, [39, -10, 0, -12, 0, 2, 0, -1, 0, 1, -2, 0, 0, 2, 0, -2]); t
3524
[ 39 -10 0 -12]
3525
[ 0 2 0 -1]
3526
[ 0 1 -2 0]
3527
[ 0 2 0 -2]
3528
sage: t.fcp()
3529
(x - 39) * (x + 2) * (x^2 - 2)
3530
sage: s = (t-39)*(t^2-2)
3531
sage: V = s.kernel(); V
3532
Vector space of degree 4 and dimension 3 over Rational Field
3533
Basis matrix:
3534
[1 0 0 0]
3535
[0 1 0 0]
3536
[0 0 0 1]
3537
sage: s.restrict(V)
3538
[0 0 0]
3539
[0 0 0]
3540
[0 0 0]
3541
sage: s.kernel_on(V)
3542
Vector space of degree 4 and dimension 3 over Rational Field
3543
Basis matrix:
3544
[1 0 0 0]
3545
[0 1 0 0]
3546
[0 0 0 1]
3547
sage: k = t-39
3548
sage: k.restrict(V)
3549
[ 0 -10 -12]
3550
[ 0 -37 -1]
3551
[ 0 2 -41]
3552
sage: ker = k.kernel_on(V); ker
3553
Vector space of degree 4 and dimension 1 over Rational Field
3554
Basis matrix:
3555
[ 1 -2/7 0 -2/7]
3556
sage: ker.0 * k
3557
(0, 0, 0, 0)
3558
3559
Test that trac ticket #9425 is fixed.
3560
3561
::
3562
3563
sage: V = span([[1/7,0,0] ,[0,1,0]], ZZ); V
3564
Free module of degree 3 and rank 2 over Integer Ring
3565
Echelon basis matrix:
3566
[1/7 0 0]
3567
[ 0 1 0]
3568
sage: T = matrix(ZZ,3,[1,0,0,0,0,0,0,0,0]); T
3569
[1 0 0]
3570
[0 0 0]
3571
[0 0 0]
3572
sage: W = T.kernel_on(V); W.basis()
3573
[
3574
(0, 1, 0)
3575
]
3576
sage: W.is_submodule(V)
3577
True
3578
"""
3579
A = self.restrict(V, check=check)
3580
if not poly is None:
3581
A = poly(A)
3582
W = A.kernel()
3583
if V.is_ambient():
3584
return W
3585
else:
3586
A = V.basis_matrix()
3587
B = W.basis_matrix()
3588
C = B*A
3589
return C.row_module(base_ring=V.base_ring())
3590
3591
3592
def integer_kernel(self, ring=ZZ):
3593
"""
3594
Return the kernel of this matrix over the given ring (which should be
3595
either the base ring, or a PID whose fraction field is the base ring).
3596
3597
Assume that the base field of this matrix has a numerator and
3598
denominator functions for its elements, e.g., it is the rational
3599
numbers or a fraction field. This function computes a basis over
3600
the integers for the kernel of self.
3601
3602
If the matrix is not coercible into QQ, then the PID itself should be
3603
given as a second argument, as in the third example below.
3604
3605
EXAMPLES::
3606
3607
sage: A = MatrixSpace(QQ, 4)(range(16))
3608
sage: A.integer_kernel()
3609
Free module of degree 4 and rank 2 over Integer Ring
3610
Echelon basis matrix:
3611
[ 1 0 -3 2]
3612
[ 0 1 -2 1]
3613
3614
The integer kernel even makes sense for matrices with fractional
3615
entries::
3616
3617
sage: A = MatrixSpace(QQ, 2)(['1/2',0, 0, 0])
3618
sage: A.integer_kernel()
3619
Free module of degree 2 and rank 1 over Integer Ring
3620
Echelon basis matrix:
3621
[0 1]
3622
3623
An example over a bigger ring::
3624
3625
sage: L.<w> = NumberField(x^2 - x + 2)
3626
sage: OL = L.ring_of_integers()
3627
sage: A = matrix(L, 2, [1, w/2])
3628
sage: A.integer_kernel(OL)
3629
Free module of degree 2 and rank 1 over Maximal Order in Number Field in w with defining polynomial x^2 - x + 2
3630
Echelon basis matrix:
3631
[ -1 -w + 1]
3632
3633
"""
3634
try:
3635
A, _ = self._clear_denom()
3636
return A.kernel()
3637
except AttributeError:
3638
d = self.denominator()
3639
A = self*d
3640
M = matrix_space.MatrixSpace(ring, self.nrows(), self.ncols())(A)
3641
return M.kernel()
3642
3643
def image(self):
3644
"""
3645
Return the image of the homomorphism on rows defined by this
3646
matrix.
3647
3648
EXAMPLES::
3649
3650
sage: MS1 = MatrixSpace(ZZ,4)
3651
sage: MS2 = MatrixSpace(QQ,6)
3652
sage: A = MS1.matrix([3,4,5,6,7,3,8,10,14,5,6,7,2,2,10,9])
3653
sage: B = MS2.random_element()
3654
3655
::
3656
3657
sage: image(A)
3658
Free module of degree 4 and rank 4 over Integer Ring
3659
Echelon basis matrix:
3660
[ 1 0 0 426]
3661
[ 0 1 0 518]
3662
[ 0 0 1 293]
3663
[ 0 0 0 687]
3664
3665
::
3666
3667
sage: image(B) == B.row_module()
3668
True
3669
"""
3670
return self.row_module()
3671
3672
def _row_ambient_module(self, base_ring=None):
3673
if base_ring is None:
3674
base_ring = self.base_ring()
3675
x = self.fetch('row_ambient_module_%s'%base_ring)
3676
if not x is None:
3677
return x
3678
x = sage.modules.free_module.FreeModule(base_ring, self.ncols(), sparse=self.is_sparse())
3679
self.cache('row_ambient_module',x)
3680
return x
3681
3682
def row_module(self, base_ring=None):
3683
"""
3684
Return the free module over the base ring spanned by the rows of
3685
self.
3686
3687
EXAMPLES::
3688
3689
sage: A = MatrixSpace(IntegerRing(), 2)([1,2,3,4])
3690
sage: A.row_module()
3691
Free module of degree 2 and rank 2 over Integer Ring
3692
Echelon basis matrix:
3693
[1 0]
3694
[0 2]
3695
"""
3696
M = self._row_ambient_module(base_ring = base_ring)
3697
if (base_ring is None or base_ring == self.base_ring()) and self.fetch('in_echelon_form'):
3698
if self.rank() != self.nrows():
3699
rows = self.matrix_from_rows(range(self.rank())).rows()
3700
else:
3701
rows = self.rows()
3702
return M.span(rows, already_echelonized=True)
3703
else:
3704
return M.span(self.rows(), already_echelonized=False)
3705
3706
def row_space(self, base_ring=None):
3707
"""
3708
Return the row space of this matrix. (Synonym for
3709
self.row_module().)
3710
3711
EXAMPLES::
3712
3713
sage: t = matrix(QQ, 3, range(9)); t
3714
[0 1 2]
3715
[3 4 5]
3716
[6 7 8]
3717
sage: t.row_space()
3718
Vector space of degree 3 and dimension 2 over Rational Field
3719
Basis matrix:
3720
[ 1 0 -1]
3721
[ 0 1 2]
3722
3723
::
3724
3725
sage: m = Matrix(Integers(5),2,2,[2,2,2,2]);
3726
sage: m.row_space()
3727
Vector space of degree 2 and dimension 1 over Ring of integers modulo 5
3728
Basis matrix:
3729
[1 1]
3730
"""
3731
return self.row_module(base_ring=base_ring)
3732
3733
3734
def _column_ambient_module(self):
3735
x = self.fetch('column_ambient_module')
3736
if not x is None:
3737
return x
3738
x = sage.modules.free_module.FreeModule(self.base_ring(), self.nrows(),
3739
sparse=self.is_sparse())
3740
self.cache('column_ambient_module',x)
3741
return x
3742
3743
def column_module(self):
3744
"""
3745
Return the free module over the base ring spanned by the columns of
3746
this matrix.
3747
3748
EXAMPLES::
3749
3750
sage: t = matrix(QQ, 3, range(9)); t
3751
[0 1 2]
3752
[3 4 5]
3753
[6 7 8]
3754
sage: t.column_module()
3755
Vector space of degree 3 and dimension 2 over Rational Field
3756
Basis matrix:
3757
[ 1 0 -1]
3758
[ 0 1 2]
3759
"""
3760
return self.transpose().row_module()
3761
3762
def column_space(self):
3763
"""
3764
Return the vector space over the base ring spanned by the columns
3765
of this matrix.
3766
3767
EXAMPLES::
3768
3769
sage: M = MatrixSpace(QQ,3,3)
3770
sage: A = M([1,9,-7,4/5,4,3,6,4,3])
3771
sage: A.column_space()
3772
Vector space of degree 3 and dimension 3 over Rational Field
3773
Basis matrix:
3774
[1 0 0]
3775
[0 1 0]
3776
[0 0 1]
3777
sage: W = MatrixSpace(CC,2,2)
3778
sage: B = W([1, 2+3*I,4+5*I,9]); B
3779
[ 1.00000000000000 2.00000000000000 + 3.00000000000000*I]
3780
[4.00000000000000 + 5.00000000000000*I 9.00000000000000]
3781
sage: B.column_space()
3782
Vector space of degree 2 and dimension 2 over Complex Field with 53 bits of precision
3783
Basis matrix:
3784
[ 1.00000000000000 0.000000000000000]
3785
[0.000000000000000 1.00000000000000]
3786
"""
3787
return self.column_module()
3788
3789
3790
3791
def decomposition(self, algorithm='spin',
3792
is_diagonalizable=False, dual=False):
3793
"""
3794
Returns the decomposition of the free module on which this matrix A
3795
acts from the right (i.e., the action is x goes to x A), along with
3796
whether this matrix acts irreducibly on each factor. The factors
3797
are guaranteed to be sorted in the same way as the corresponding
3798
factors of the characteristic polynomial.
3799
3800
Let A be the matrix acting from the on the vector space V of column
3801
vectors. Assume that A is square. This function computes maximal
3802
subspaces W_1, ..., W_n corresponding to Galois conjugacy classes
3803
of eigenvalues of A. More precisely, let `f(X)` be the characteristic
3804
polynomial of A. This function computes the subspace
3805
`W_i = ker(g_(A)^n)`, where `g_i(X)` is an irreducible
3806
factor of `f(X)` and `g_i(X)` exactly divides `f(X)`. If the optional
3807
parameter is_diagonalizable is True, then we let `W_i = ker(g(A))`,
3808
since then we know that `ker(g(A)) = ker(g(A)^n)`.
3809
3810
INPUT:
3811
3812
3813
- ``self`` - a matrix
3814
3815
- ``algorithm`` - 'spin' (default): algorithm involves
3816
iterating the action of self on a vector. 'kernel': naively just
3817
compute `ker(f_i(A))` for each factor `f_i`.
3818
3819
- ``dual`` - bool (default: False): If True, also
3820
returns the corresponding decomposition of V under the action of
3821
the transpose of A. The factors are guaranteed to correspond.
3822
3823
- ``is_diagonalizable`` - if the matrix is known to
3824
be diagonalizable, set this to True, which might speed up the
3825
algorithm in some cases.
3826
3827
.. note::
3828
3829
If the base ring is not a field, the kernel algorithm is
3830
used.
3831
3832
3833
OUTPUT:
3834
3835
3836
- ``Sequence`` - list of pairs (V,t), where V is a vector
3837
spaces and t is a bool, and t is True exactly when the
3838
charpoly of self on V is irreducible.
3839
3840
3841
- (optional) list - list of pairs (W,t), where W is a vector
3842
space and t is a bool, and t is True exactly when the
3843
charpoly of the transpose of self on W is irreducible.
3844
3845
EXAMPLES::
3846
3847
sage: A = matrix(ZZ, 4, [3,4,5,6,7,3,8,10,14,5,6,7,2,2,10,9])
3848
sage: B = matrix(QQ, 6, range(36))
3849
sage: B*11
3850
[ 0 11 22 33 44 55]
3851
[ 66 77 88 99 110 121]
3852
[132 143 154 165 176 187]
3853
[198 209 220 231 242 253]
3854
[264 275 286 297 308 319]
3855
[330 341 352 363 374 385]
3856
sage: A.decomposition()
3857
[
3858
(Ambient free module of rank 4 over the principal ideal domain Integer Ring, True)
3859
]
3860
sage: B.decomposition()
3861
[
3862
(Vector space of degree 6 and dimension 2 over Rational Field
3863
Basis matrix:
3864
[ 1 0 -1 -2 -3 -4]
3865
[ 0 1 2 3 4 5], True),
3866
(Vector space of degree 6 and dimension 4 over Rational Field
3867
Basis matrix:
3868
[ 1 0 0 0 -5 4]
3869
[ 0 1 0 0 -4 3]
3870
[ 0 0 1 0 -3 2]
3871
[ 0 0 0 1 -2 1], False)
3872
]
3873
"""
3874
if algorithm == 'kernel' or not self.base_ring().is_field():
3875
return self._decomposition_using_kernels(is_diagonalizable = is_diagonalizable, dual=dual)
3876
elif algorithm == 'spin':
3877
X = self._decomposition_spin_generic(is_diagonalizable = is_diagonalizable)
3878
if dual:
3879
Y = self.transpose()._decomposition_spin_generic(is_diagonalizable = is_diagonalizable)
3880
return X, Y
3881
return X
3882
else:
3883
raise ValueError, "no algorithm '%s'"%algorithm
3884
3885
def _decomposition_spin_generic(self, is_diagonalizable=False):
3886
r"""
3887
Compute the decomposition of this matrix using the spin algorithm.
3888
3889
INPUT:
3890
3891
- ``self`` - a matrix with field entries
3892
3893
OUTPUT: a list of reduced row echelon form basis
3894
3895
AUTHORS:
3896
3897
- William Stein
3898
"""
3899
if not self.is_square():
3900
raise ValueError, "self must be a square matrix"
3901
3902
if not self.base_ring().is_field():
3903
raise TypeError, "self must be over a field."
3904
3905
if self.nrows() == 0:
3906
return decomp_seq([])
3907
3908
f = self.charpoly('x')
3909
E = decomp_seq([])
3910
3911
t = verbose('factoring the characteristic polynomial', level=2, caller_name='generic spin decomp')
3912
F = f.factor()
3913
verbose('done factoring', t=t, level=2, caller_name='generic spin decomp')
3914
3915
if len(F) == 1:
3916
V = self.base_ring()**self.nrows()
3917
return decomp_seq([(V,F[0][1]==1)])
3918
3919
V = self.base_ring()**self.nrows()
3920
v = V.random_element()
3921
num_iterates = max([0] + [f.degree() - g.degree() for g, _ in F if g.degree() > 1]) + 1
3922
3923
S = [ ]
3924
3925
F.sort()
3926
for i in range(len(F)):
3927
g, m = F[i]
3928
3929
if g.degree() == 1:
3930
# Just use kernel -- much easier.
3931
B = self.__copy__()
3932
for k from 0 <= k < self.nrows():
3933
B[k,k] += g[0]
3934
if m > 1 and not is_diagonalizable:
3935
B = B**m
3936
W = B.kernel()
3937
E.append((W, m==1))
3938
continue
3939
3940
# General case, i.e., deg(g) > 1:
3941
W = None
3942
tries = m
3943
while True:
3944
3945
# Compute the complementary factor.
3946
h = f // (g**m)
3947
v = h.list()
3948
3949
while len(S) < tries:
3950
t = verbose('%s-spinning %s-th random vector'%(num_iterates, len(S)), level=2, caller_name='generic spin decomp')
3951
S.append(self.iterates(V.random_element(), num_iterates))
3952
verbose('done spinning', level=2, t=t, caller_name='generic spin decomp')
3953
3954
for j in range(0 if W is None else W.nrows() // g.degree(), len(S)):
3955
# Compute one element of the kernel of g(A)**m.
3956
t = verbose('compute element of kernel of g(A), for g of degree %s'%g.degree(),level=2,
3957
caller_name='generic spin decomp')
3958
w = S[j].linear_combination_of_rows(h.list())
3959
t = verbose('done computing element of kernel of g(A)', t=t,level=2, caller_name='generic spin decomp')
3960
3961
# Get the rest of the kernel.
3962
t = verbose('fill out rest of kernel',level=2, caller_name='generic spin decomp')
3963
if W is None:
3964
W = self.iterates(w, g.degree())
3965
else:
3966
W = W.stack(self.iterates(w, g.degree()))
3967
t = verbose('finished filling out more of kernel',level=2, t=t, caller_name='generic spin decomp')
3968
3969
if W.rank() == m * g.degree():
3970
t = verbose('now computing row space', level=2, caller_name='generic spin decomp')
3971
W.echelonize()
3972
E.append((W.row_space(), m==1))
3973
verbose('computed row space', level=2,t=t, caller_name='generic spin decomp')
3974
break
3975
else:
3976
verbose('we have not yet generated all the kernel (rank so far=%s, target rank=%s)'%(
3977
W.rank(), m*g.degree()), level=2, caller_name='generic spin decomp')
3978
tries += 1
3979
if tries > 1000*m: # avoid an insanely long infinite loop
3980
raise RuntimeError, "likely bug in decomposition"
3981
# end if
3982
#end while
3983
#end for
3984
return E
3985
3986
def _decomposition_using_kernels(self, is_diagonalizable=False, dual=False):
3987
if not self.is_square():
3988
raise ValueError, "self must be a square matrix"
3989
3990
if self.nrows() == 0:
3991
return decomp_seq([])
3992
3993
f = self.charpoly('x')
3994
E = decomp_seq([])
3995
3996
# Idea: For optimization, could compute powers of self
3997
# up to max degree of any factor. Then get g(self)
3998
# by taking a linear combination.
3999
4000
if dual:
4001
Edual = decomp_seq([])
4002
F = f.factor()
4003
if len(F) == 1:
4004
V = sage.modules.free_module.FreeModule(
4005
self.base_ring(), self.nrows(), sparse=self.is_sparse())
4006
m = F[0][1]
4007
if dual:
4008
return decomp_seq([(V, m==1)]), decomp_seq([(V, m==1)])
4009
else:
4010
return decomp_seq([(V, m==1)])
4011
F.sort()
4012
for g, m in f.factor():
4013
t = verbose('decomposition -- Computing g(self) for an irreducible factor g of degree %s'%g.degree(),level=2)
4014
if is_diagonalizable:
4015
B = g(self)
4016
else:
4017
B = g(self)
4018
t2 = verbose('decomposition -- raising g(self) to the power %s'%m,level=2)
4019
B = B ** m
4020
verbose('done powering',t2)
4021
t = verbose('decomposition -- done computing g(self)', level=2, t=t)
4022
E.append((B.kernel(), m==1))
4023
t = verbose('decomposition -- time to compute kernel', level=2, t=t)
4024
if dual:
4025
Edual.append((B.transpose().kernel(), m==1))
4026
verbose('decomposition -- time to compute dual kernel', level=2, t=t)
4027
if dual:
4028
return E, Edual
4029
return E
4030
4031
def decomposition_of_subspace(self, M, check_restrict = True, **kwds):
4032
"""
4033
Suppose the right action of self on M leaves M invariant. Return
4034
the decomposition of M as a list of pairs (W, is_irred) where
4035
is_irred is True if the charpoly of self acting on the factor W is
4036
irreducible.
4037
4038
Additional inputs besides M are passed onto the decomposition
4039
command.
4040
4041
INPUT:
4042
4043
- `M` -- A subspace of the free module ``self`` acts on.
4044
- ``check_restrict`` -- A boolean (default: ``True``); Call restrict
4045
with or without check.
4046
- ``kwds`` -- Keywords that will be forwarded to :meth:`~.decomposition`.
4047
4048
EXAMPLES::
4049
4050
sage: t = matrix(QQ, 3, [3, 0, -2, 0, -2, 0, 0, 0, 0]); t
4051
[ 3 0 -2]
4052
[ 0 -2 0]
4053
[ 0 0 0]
4054
sage: t.fcp('X') # factored charpoly
4055
(X - 3) * X * (X + 2)
4056
sage: v = kernel(t*(t+2)); v # an invariant subspace
4057
Vector space of degree 3 and dimension 2 over Rational Field
4058
Basis matrix:
4059
[0 1 0]
4060
[0 0 1]
4061
sage: D = t.decomposition_of_subspace(v); D
4062
[
4063
(Vector space of degree 3 and dimension 1 over Rational Field
4064
Basis matrix:
4065
[0 0 1], True),
4066
(Vector space of degree 3 and dimension 1 over Rational Field
4067
Basis matrix:
4068
[0 1 0], True)
4069
]
4070
sage: t.restrict(D[0][0])
4071
[0]
4072
sage: t.restrict(D[1][0])
4073
[-2]
4074
4075
We do a decomposition over ZZ::
4076
4077
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])
4078
sage: a.decomposition_of_subspace(ZZ^6)
4079
[
4080
(Free module of degree 6 and rank 2 over Integer Ring
4081
Echelon basis matrix:
4082
[ 1 0 1 -1 1 -1]
4083
[ 0 1 0 -1 2 -1], False),
4084
(Free module of degree 6 and rank 4 over Integer Ring
4085
Echelon basis matrix:
4086
[ 1 0 -1 0 1 0]
4087
[ 0 1 0 0 0 0]
4088
[ 0 0 0 1 0 0]
4089
[ 0 0 0 0 0 1], False)
4090
]
4091
4092
TESTS::
4093
4094
sage: t = matrix(QQ, 3, [3, 0, -2, 0, -2, 0, 0, 0, 0]);
4095
sage: t.decomposition_of_subspace(v, check_restrict = False) == t.decomposition_of_subspace(v)
4096
True
4097
"""
4098
if not sage.modules.free_module.is_FreeModule(M):
4099
raise TypeError, "M must be a free module."
4100
if not self.is_square():
4101
raise ArithmeticError, "self must be a square matrix"
4102
if M.base_ring() != self.base_ring():
4103
raise ArithmeticError, "base rings must be the same, but self is over %s and module is over %s"%(
4104
self.base_ring(), M.base_ring())
4105
if M.degree() != self.ncols():
4106
raise ArithmeticError, \
4107
"M must be a subspace of an %s-dimensional space"%self.ncols()
4108
4109
time = verbose(t=0)
4110
4111
# 1. Restrict
4112
B = self.restrict(M, check = check_restrict)
4113
time0 = verbose("decompose restriction -- ", time)
4114
4115
# 2. Decompose restriction
4116
D = B.decomposition(**kwds)
4117
4118
sum_dim = sum([A.dimension() for A,_ in D])
4119
assert sum_dim == M.dimension(), \
4120
"bug in decomposition; " + \
4121
"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)
4122
4123
# 3. Lift decomposition to subspaces of ambient vector space.
4124
# Each basis vector for an element of D defines a linear
4125
# combination of the basis of W, and these linear combinations
4126
# define the corresponding subspaces of the ambient space M.
4127
4128
verbose("decomposition -- ", time0)
4129
C = M.basis_matrix()
4130
4131
D = [((W.basis_matrix() * C).row_module(self.base_ring()), is_irred) for W, is_irred in D]
4132
D = decomp_seq(D)
4133
4134
verbose(t=time)
4135
return D
4136
4137
def restrict(self, V, check=True):
4138
"""
4139
Returns the matrix that defines the action of self on the chosen
4140
basis for the invariant subspace V. If V is an ambient, returns
4141
self (not a copy of self).
4142
4143
INPUT:
4144
4145
4146
- ``V`` - vector subspace
4147
4148
- ``check`` - (optional) default: True; if False may
4149
not check that V is invariant (hence can be faster).
4150
4151
4152
OUTPUT: a matrix
4153
4154
.. warning::
4155
4156
This function returns an nxn matrix, where V has dimension
4157
n. It does *not* check that V is in fact invariant under
4158
self, unless check is True.
4159
4160
EXAMPLES::
4161
4162
sage: V = VectorSpace(QQ, 3)
4163
sage: M = MatrixSpace(QQ, 3)
4164
sage: A = M([1,2,0, 3,4,0, 0,0,0])
4165
sage: W = V.subspace([[1,0,0], [0,1,0]])
4166
sage: A.restrict(W)
4167
[1 2]
4168
[3 4]
4169
sage: A.restrict(W, check=True)
4170
[1 2]
4171
[3 4]
4172
4173
We illustrate the warning about invariance not being checked by
4174
default, by giving a non-invariant subspace. With the default
4175
check=False this function returns the 'restriction' matrix, which
4176
is meaningless as check=True reveals.
4177
4178
::
4179
4180
sage: W2 = V.subspace([[1,0,0], [0,1,1]])
4181
sage: A.restrict(W2, check=False)
4182
[1 2]
4183
[3 4]
4184
sage: A.restrict(W2, check=True)
4185
Traceback (most recent call last):
4186
...
4187
ArithmeticError: subspace is not invariant under matrix
4188
"""
4189
if not isinstance(V, sage.modules.free_module.FreeModule_generic):
4190
raise TypeError, "V must be a free module"
4191
#if V.base_ring() != self.base_ring():
4192
# 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())
4193
if V.degree() != self.nrows():
4194
raise IndexError, "degree of V (=%s) must equal number of rows of self (=%s)"%(\
4195
V.degree(), self.nrows())
4196
if V.rank() == 0 or V.degree() == 0:
4197
return self.new_matrix(nrows=0, ncols=0)
4198
4199
if not check and V.base_ring().is_field() and not V.has_user_basis():
4200
B = V.echelonized_basis_matrix()
4201
P = B.pivots()
4202
return B*self.matrix_from_columns(P)
4203
else:
4204
n = V.rank()
4205
try:
4206
# todo optimize so only involves matrix multiplies ?
4207
C = [V.coordinate_vector(b*self) for b in V.basis()]
4208
except ArithmeticError:
4209
raise ArithmeticError, "subspace is not invariant under matrix"
4210
return self.new_matrix(n, n, C, sparse=False)
4211
4212
def restrict_domain(self, V):
4213
"""
4214
Compute the matrix relative to the basis for V on the domain
4215
obtained by restricting self to V, but not changing the codomain of
4216
the matrix. This is the matrix whose rows are the images of the
4217
basis for V.
4218
4219
INPUT:
4220
4221
4222
- ``V`` - vector space (subspace of ambient space on
4223
which self acts)
4224
4225
4226
.. seealso::
4227
4228
:meth:`restrict`
4229
4230
EXAMPLES::
4231
4232
sage: V = QQ^3
4233
sage: A = matrix(QQ,3,[1,2,0, 3,4,0, 0,0,0])
4234
sage: W = V.subspace([[1,0,0], [1,2,3]])
4235
sage: A.restrict_domain(W)
4236
[1 2 0]
4237
[3 4 0]
4238
sage: W2 = V.subspace_with_basis([[1,0,0], [1,2,3]])
4239
sage: A.restrict_domain(W2)
4240
[ 1 2 0]
4241
[ 7 10 0]
4242
"""
4243
return V.basis_matrix() * self
4244
4245
def restrict_codomain(self, V):
4246
r"""
4247
Suppose that self defines a linear map from some domain to a
4248
codomain that contains `V` and that the image of self is
4249
contained in `V`. This function returns a new matrix
4250
`A` that represents this linear map but as a map to
4251
`V`, in the sense that if `x` is in the domain,
4252
then `xA` is the linear combination of the elements of the
4253
basis of `V` that equals v\*self.
4254
4255
INPUT:
4256
4257
4258
- ``V`` - vector space (space of degree
4259
``self.ncols()``) that contains the image of self.
4260
4261
4262
.. seealso::
4263
4264
:meth:`restrict`, :meth:`restrict_domain`
4265
4266
EXAMPLES::
4267
4268
sage: A = matrix(QQ,3,[1..9])
4269
sage: V = (QQ^3).span([[1,2,3], [7,8,9]]); V
4270
Vector space of degree 3 and dimension 2 over Rational Field
4271
Basis matrix:
4272
[ 1 0 -1]
4273
[ 0 1 2]
4274
sage: z = vector(QQ,[1,2,5])
4275
sage: B = A.restrict_codomain(V); B
4276
[1 2]
4277
[4 5]
4278
[7 8]
4279
sage: z*B
4280
(44, 52)
4281
sage: z*A
4282
(44, 52, 60)
4283
sage: 44*V.0 + 52*V.1
4284
(44, 52, 60)
4285
"""
4286
return V.basis_matrix().solve_left(self)
4287
4288
def maxspin(self, v):
4289
"""
4290
Computes the largest integer n such that the list of vectors
4291
`S=[v, v*A, ..., v * A^n]` are linearly independent, and
4292
returns that list.
4293
4294
INPUT:
4295
4296
4297
- ``self`` - Matrix
4298
4299
- ``v`` - Vector
4300
4301
4302
OUTPUT:
4303
4304
4305
- ``list`` - list of Vectors
4306
4307
4308
ALGORITHM: The current implementation just adds vectors to a vector
4309
space until the dimension doesn't grow. This could be optimized by
4310
directly using matrices and doing an efficient Echelon form. Also,
4311
when the base is Q, maybe we could simultaneously keep track of
4312
what is going on in the reduction modulo p, which might make things
4313
much faster.
4314
4315
EXAMPLES::
4316
4317
sage: t = matrix(QQ, 3, range(9)); t
4318
[0 1 2]
4319
[3 4 5]
4320
[6 7 8]
4321
sage: v = (QQ^3).0
4322
sage: t.maxspin(v)
4323
[(1, 0, 0), (0, 1, 2), (15, 18, 21)]
4324
sage: k = t.kernel(); k
4325
Vector space of degree 3 and dimension 1 over Rational Field
4326
Basis matrix:
4327
[ 1 -2 1]
4328
sage: t.maxspin(k.0)
4329
[(1, -2, 1)]
4330
"""
4331
if v == 0:
4332
return []
4333
if not is_FreeModuleElement(v):
4334
raise TypeError, "v must be a FreeModuleElement"
4335
VS = v.parent()
4336
V = VS.span([v])
4337
w = v
4338
S = [v]
4339
while True:
4340
w = w*self
4341
W = V + VS.span([w])
4342
if W.dimension() == V.dimension():
4343
return S
4344
V = W
4345
S.append(w)
4346
4347
4348
def wiedemann(self, i, t=0):
4349
"""
4350
Application of Wiedemann's algorithm to the i-th standard basis
4351
vector.
4352
4353
INPUT:
4354
4355
4356
- ``i`` - an integer
4357
4358
- ``t`` - an integer (default: 0) if t is nonzero, use
4359
only the first t linear recurrence relations.
4360
4361
4362
IMPLEMENTATION: This is a toy implementation.
4363
4364
EXAMPLES::
4365
4366
sage: t = matrix(QQ, 3, range(9)); t
4367
[0 1 2]
4368
[3 4 5]
4369
[6 7 8]
4370
sage: t.wiedemann(0)
4371
x^2 - 12*x - 18
4372
sage: t.charpoly()
4373
x^3 - 12*x^2 - 18*x
4374
"""
4375
i = int(i); t=int(t)
4376
if self.nrows() != self.ncols():
4377
raise ArithmeticError, "self must be a square matrix"
4378
n = self.nrows()
4379
v = sage.modules.free_module.VectorSpace(self.base_ring(), n).gen(i)
4380
tm = verbose('computing iterates...')
4381
cols = self.iterates(v, 2*n).columns()
4382
tm = verbose('computed iterates', tm)
4383
f = None
4384
# Compute the minimal polynomial of the linear recurrence
4385
# sequence corresponding to the 0-th entries of the iterates,
4386
# then the 1-th entries, etc.
4387
if t == 0:
4388
R = range(n)
4389
else:
4390
R = [t]
4391
for i in R:
4392
tm = verbose('applying berlekamp-massey')
4393
g = berlekamp_massey.berlekamp_massey(cols[i].list())
4394
verbose('berlekamp-massey done', tm)
4395
if f is None:
4396
f = g
4397
else:
4398
f = f.lcm(g)
4399
if f.degree() == n:
4400
break
4401
return f
4402
4403
# Deprecated Aug 2008 Trac #3794
4404
# Removed July 2011
4405
# def eigenspaces(self, var='a', even_if_inexact=None):
4406
4407
def _eigenspace_format(self, format):
4408
r"""
4409
Helper method to control output format for eigenspaces.
4410
4411
INPUT:
4412
4413
- ``format`` - ``None``, ``'all'`` or ``'galois'``
4414
4415
OUTPUT:
4416
4417
Any format except ``None`` is just passed through. When the
4418
format is ``None`` a choice is made about the style of the output.
4419
If there is an algebraically closed field that will contain the
4420
possible eigenvalues, then 'all" of the eigenspaces are given.
4421
4422
However if this is not the case, then only one eigenspace is output
4423
for each irreducible factor of the characteristic polynomial.
4424
4425
EXAMPLES:
4426
4427
Pass-through first. ::
4428
4429
sage: A = matrix(QQ, 2, range(4))
4430
sage: A._eigenspace_format('all') == 'all'
4431
True
4432
sage: A._eigenspace_format('galois') == 'galois'
4433
True
4434
4435
The algebraic closure of the rationals, the field of algebraic numbers,
4436
(aka ``QQbar``) is implemented, while in general the algebraic closure
4437
of a finite field is not implemented. ::
4438
4439
sage: A = matrix(QQ, 2, range(4))
4440
sage: A._eigenspace_format(None) == 'all'
4441
True
4442
sage: B = matrix(GF(13), 2, range(4))
4443
sage: B._eigenspace_format(None) == 'galois'
4444
True
4445
4446
Subrings are promoted to fraction fields and then checked for the
4447
existence of algebraic closures. ::
4448
4449
sage: A = matrix(ZZ, 2, range(4))
4450
sage: A._eigenspace_format(None) == 'all'
4451
True
4452
"""
4453
if not format in [None, 'all', 'galois']:
4454
msg = "format keyword must be None, 'all' or 'galois', not {0}"
4455
raise ValueError(msg.format(format))
4456
4457
# For subrings of implemented algebraically closed fields we
4458
# default to all eigenspaces in the absence of a format keyword
4459
# Add newly implemented algebraically closed fields to list below
4460
# and implement the determintion of the actual eigenvalues
4461
# in the eigenspace_left() routine
4462
if format is None:
4463
R = self.base_ring()
4464
from sage.rings.qqbar import QQbar
4465
try:
4466
if R.fraction_field().algebraic_closure() in [QQbar]:
4467
return 'all'
4468
else:
4469
return 'galois'
4470
except (NotImplementedError, AttributeError):
4471
return 'galois'
4472
else:
4473
return format
4474
4475
def eigenspaces_left(self, format='all', var='a', algebraic_multiplicity=False):
4476
r"""
4477
Compute the left eigenspaces of a matrix.
4478
4479
Note that ``eigenspaces_left()`` and ``left_eigenspaces()``
4480
are identical methods. Here "left" refers to the eigenvectors
4481
being placed to the left of the matrix.
4482
4483
INPUT:
4484
4485
- ``self`` - a square matrix over an exact field. For inexact
4486
matrices consult the numerical or symbolic matrix classes.
4487
4488
- ``format`` - default: ``None``
4489
4490
- ``'all'`` - attempts to create every eigenspace. This will
4491
always be possible for matrices with rational entries.
4492
- ``'galois'`` - for each irreducible factor of the characteristic
4493
polynomial, a single eigenspace will be output for a
4494
single root/eigenvalue for the irreducible factor.
4495
- ``None`` - Uses the 'all' format if the base ring is contained
4496
in an algebraically closed field which is implemented.
4497
Otherwise, uses the 'galois' format.
4498
4499
- ``var`` - default: 'a' - variable name used to
4500
represent elements of the root field of each
4501
irreducible factor of the characteristic polynomial.
4502
If var='a', then the root fields will be in terms of
4503
a0, a1, a2, ...., where the numbering runs across all
4504
the irreducible factors of the characteristic polynomial,
4505
even for linear factors.
4506
4507
- ``algebraic_multiplicity`` - default: False - whether or
4508
not to include the algebraic multiplicity of each eigenvalue
4509
in the output. See the discussion below.
4510
4511
OUTPUT:
4512
4513
If algebraic_multiplicity=False, return a list of pairs (e, V)
4514
where e is an eigenvalue of the matrix, and V is the corresponding
4515
left eigenspace. For Galois conjugates of eigenvalues, there
4516
may be just one representative eigenspace, depending on the
4517
``format`` keyword.
4518
4519
If algebraic_multiplicity=True, return a list of triples (e, V, n)
4520
where e and V are as above and n is the algebraic multiplicity of
4521
the eigenvalue.
4522
4523
.. warning::
4524
4525
Uses a somewhat naive algorithm (simply factors the
4526
characteristic polynomial and computes kernels directly
4527
over the extension field).
4528
4529
EXAMPLES:
4530
4531
We compute the left eigenspaces of a `3\times 3`
4532
rational matrix. First, we request `all` of the eigenvalues,
4533
so the results are in the field of algebraic numbers, `QQbar`.
4534
Then we request just one eigenspace per irreducible factor of
4535
the characteristic polynomial with the `galois` keyword. ::
4536
4537
sage: A = matrix(QQ,3,3,range(9)); A
4538
[0 1 2]
4539
[3 4 5]
4540
[6 7 8]
4541
sage: es = A.eigenspaces_left(format='all'); es
4542
[
4543
(0, Vector space of degree 3 and dimension 1 over Rational Field
4544
User basis matrix:
4545
[ 1 -2 1]),
4546
(-1.348469228349535?, Vector space of degree 3 and dimension 1 over Algebraic Field
4547
User basis matrix:
4548
[ 1 0.3101020514433644? -0.3797958971132713?]),
4549
(13.34846922834954?, Vector space of degree 3 and dimension 1 over Algebraic Field
4550
User basis matrix:
4551
[ 1 1.289897948556636? 1.579795897113272?])
4552
]
4553
4554
sage: es = A.eigenspaces_left(format='galois'); es
4555
[
4556
(0, Vector space of degree 3 and dimension 1 over Rational Field
4557
User basis matrix:
4558
[ 1 -2 1]),
4559
(a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18
4560
User basis matrix:
4561
[ 1 1/15*a1 + 2/5 2/15*a1 - 1/5])
4562
]
4563
sage: es = A.eigenspaces_left(format='galois', algebraic_multiplicity=True); es
4564
[
4565
(0, Vector space of degree 3 and dimension 1 over Rational Field
4566
User basis matrix:
4567
[ 1 -2 1], 1),
4568
(a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18
4569
User basis matrix:
4570
[ 1 1/15*a1 + 2/5 2/15*a1 - 1/5], 1)
4571
]
4572
sage: e, v, n = es[0]; v = v.basis()[0]
4573
sage: delta = e*v - v*A
4574
sage: abs(abs(delta)) < 1e-10
4575
True
4576
4577
The same computation, but with implicit base change to a field. ::
4578
4579
sage: A = matrix(ZZ,3,range(9)); A
4580
[0 1 2]
4581
[3 4 5]
4582
[6 7 8]
4583
sage: A.eigenspaces_left(format='galois')
4584
[
4585
(0, Vector space of degree 3 and dimension 1 over Rational Field
4586
User basis matrix:
4587
[ 1 -2 1]),
4588
(a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18
4589
User basis matrix:
4590
[ 1 1/15*a1 + 2/5 2/15*a1 - 1/5])
4591
]
4592
4593
We compute the left eigenspaces of the matrix of the Hecke operator
4594
`T_2` on level 43 modular symbols, both with all eigenvalues (the default)
4595
and with one subspace per factor. ::
4596
4597
sage: A = ModularSymbols(43).T(2).matrix(); A
4598
[ 3 0 0 0 0 0 -1]
4599
[ 0 -2 1 0 0 0 0]
4600
[ 0 -1 1 1 0 -1 0]
4601
[ 0 -1 0 -1 2 -1 1]
4602
[ 0 -1 0 1 1 -1 1]
4603
[ 0 0 -2 0 2 -2 1]
4604
[ 0 0 -1 0 1 0 -1]
4605
sage: A.base_ring()
4606
Rational Field
4607
sage: f = A.charpoly(); f
4608
x^7 + x^6 - 12*x^5 - 16*x^4 + 36*x^3 + 52*x^2 - 32*x - 48
4609
sage: factor(f)
4610
(x - 3) * (x + 2)^2 * (x^2 - 2)^2
4611
sage: A.eigenspaces_left(algebraic_multiplicity=True)
4612
[
4613
(3, Vector space of degree 7 and dimension 1 over Rational Field
4614
User basis matrix:
4615
[ 1 0 1/7 0 -1/7 0 -2/7], 1),
4616
(-2, Vector space of degree 7 and dimension 2 over Rational Field
4617
User basis matrix:
4618
[ 0 1 0 1 -1 1 -1]
4619
[ 0 0 1 0 -1 2 -1], 2),
4620
(-1.414213562373095?, Vector space of degree 7 and dimension 2 over Algebraic Field
4621
User basis matrix:
4622
[ 0 1 0 -1 0.4142135623730951? 1 -1]
4623
[ 0 0 1 0 -1 0 2.414213562373095?], 2),
4624
(1.414213562373095?, Vector space of degree 7 and dimension 2 over Algebraic Field
4625
User basis matrix:
4626
[ 0 1 0 -1 -2.414213562373095? 1 -1]
4627
[ 0 0 1 0 -1 0 -0.4142135623730951?], 2)
4628
]
4629
sage: A.eigenspaces_left(format='galois', algebraic_multiplicity=True)
4630
[
4631
(3, Vector space of degree 7 and dimension 1 over Rational Field
4632
User basis matrix:
4633
[ 1 0 1/7 0 -1/7 0 -2/7], 1),
4634
(-2, Vector space of degree 7 and dimension 2 over Rational Field
4635
User basis matrix:
4636
[ 0 1 0 1 -1 1 -1]
4637
[ 0 0 1 0 -1 2 -1], 2),
4638
(a2, Vector space of degree 7 and dimension 2 over Number Field in a2 with defining polynomial x^2 - 2
4639
User basis matrix:
4640
[ 0 1 0 -1 -a2 - 1 1 -1]
4641
[ 0 0 1 0 -1 0 -a2 + 1], 2)
4642
]
4643
4644
Next we compute the left eigenspaces over the finite field of order 11. ::
4645
4646
sage: A = ModularSymbols(43, base_ring=GF(11), sign=1).T(2).matrix(); A
4647
[ 3 9 0 0]
4648
[ 0 9 0 1]
4649
[ 0 10 9 2]
4650
[ 0 9 0 2]
4651
sage: A.base_ring()
4652
Finite Field of size 11
4653
sage: A.charpoly()
4654
x^4 + 10*x^3 + 3*x^2 + 2*x + 1
4655
sage: A.eigenspaces_left(format='galois', var = 'beta')
4656
[
4657
(9, Vector space of degree 4 and dimension 1 over Finite Field of size 11
4658
User basis matrix:
4659
[0 0 1 5]),
4660
(3, Vector space of degree 4 and dimension 1 over Finite Field of size 11
4661
User basis matrix:
4662
[1 6 0 6]),
4663
(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
4664
User basis matrix:
4665
[ 0 1 0 5*beta2 + 10])
4666
]
4667
4668
This method is only applicable to exact matrices.
4669
The "eigenmatrix" routines for matrices with double-precision
4670
floating-point entries (``RDF``, ``CDF``) are the best
4671
alternative. (Since some platforms return eigenvectors
4672
that are the negatives of those given here, this one example
4673
is not tested here.) There are also "eigenmatrix" routines for
4674
matrices with symbolic entries. ::
4675
4676
sage: A = matrix(QQ, 3, 3, range(9))
4677
sage: A.change_ring(RR).eigenspaces_left()
4678
Traceback (most recent call last):
4679
...
4680
NotImplementedError: eigenspaces cannot be computed reliably for inexact rings such as Real Field with 53 bits of precision,
4681
consult numerical or symbolic matrix classes for other options
4682
4683
sage: em = A.change_ring(RDF).eigenmatrix_left()
4684
sage: eigenvalues = em[0]; eigenvalues.dense_matrix().zero_at(2e-15)
4685
[ 13.3484692283 0.0 0.0]
4686
[ 0.0 -1.34846922835 0.0]
4687
[ 0.0 0.0 0.0]
4688
sage: eigenvectors = em[1]; eigenvectors # not tested
4689
[ 0.440242867... 0.567868371... 0.695493875...]
4690
[ 0.897878732... 0.278434036... -0.341010658...]
4691
[ 0.408248290... -0.816496580... 0.408248290...]
4692
4693
sage: x, y = var('x y')
4694
sage: S = matrix([[x, y], [y, 3*x^2]])
4695
sage: em = S.eigenmatrix_left()
4696
sage: eigenvalues = em[0]; eigenvalues
4697
[-1/2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2) + 3/2*x^2 + 1/2*x 0]
4698
[ 0 3/2*x^2 + 1/2*x + 1/2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2)]
4699
sage: eigenvectors = em[1]; eigenvectors
4700
[ 1 1/2*(3*x^2 - x - sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y]
4701
[ 1 -1/2*(x - sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2) - 3*x^2)/y]
4702
4703
A request for ``'all'`` the eigenvalues, when it is not
4704
possible, will raise an error. Using the ``'galois'``
4705
format option is more likely to be successful. ::
4706
4707
sage: F.<b> = FiniteField(11^2)
4708
sage: A = matrix(F, [[b + 1, b + 1], [10*b + 4, 5*b + 4]])
4709
sage: A.eigenspaces_left(format='all')
4710
Traceback (most recent call last):
4711
...
4712
NotImplementedError: unable to construct eigenspaces for eigenvalues outside the base field,
4713
try the keyword option: format='galois'
4714
4715
sage: A.eigenspaces_left(format='galois')
4716
[
4717
(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
4718
User basis matrix:
4719
[ 1 6*b*a0 + 3*b + 1])
4720
]
4721
4722
TESTS::
4723
4724
sage: B = matrix(QQ, 2, 3, range(6))
4725
sage: B.eigenspaces_left()
4726
Traceback (most recent call last):
4727
...
4728
TypeError: matrix must be square, not 2 x 3
4729
4730
sage: B = matrix(QQ, 4, 4, range(16))
4731
sage: B.eigenspaces_left(format='junk')
4732
Traceback (most recent call last):
4733
...
4734
ValueError: format keyword must be None, 'all' or 'galois', not junk
4735
4736
sage: B.eigenspaces_left(algebraic_multiplicity='garbage')
4737
Traceback (most recent call last):
4738
...
4739
ValueError: algebraic_multiplicity keyword must be True or False
4740
"""
4741
if not algebraic_multiplicity in [True, False]:
4742
msg = 'algebraic_multiplicity keyword must be True or False'
4743
raise ValueError(msg.format(algebraic_multiplicity))
4744
if not self.is_square():
4745
msg = 'matrix must be square, not {0} x {1}'
4746
raise TypeError(msg.format(self.nrows(), self.ncols()))
4747
if not self.base_ring().is_exact():
4748
msg = ("eigenspaces cannot be computed reliably for inexact rings such as {0},\n",
4749
"consult numerical or symbolic matrix classes for other options")
4750
raise NotImplementedError(''.join(msg).format(self.base_ring()))
4751
4752
format = self._eigenspace_format(format)
4753
4754
key = 'eigenspaces_left_' + format + '{0}'.format(var)
4755
x = self.fetch(key)
4756
if not x is None:
4757
if algebraic_multiplicity:
4758
return x
4759
else:
4760
return Sequence([(e[0],e[1]) for e in x], cr=True, check=False)
4761
4762
# Possible improvements:
4763
# algorithm for dual_eigenvector in sage/modular/hecke/module.py
4764
# use minpoly when algebraic_multiplicity=False
4765
# as of 2007-03-25 minpoly is unreliable via linbox
4766
4767
import sage.categories.homset
4768
import sage.rings.qqbar
4769
4770
G = self.fcp() # factored characteristic polynomial
4771
V = []
4772
i = -1 # variable name index, increments for each eigenvalue
4773
for h, e in G:
4774
i = i + 1
4775
if h.degree() == 1:
4776
alpha = -h[0]/h[1]
4777
F = alpha.parent()
4778
if F != self.base_ring():
4779
self = self.change_ring(F)
4780
A = self - alpha
4781
W = A.kernel()
4782
V.append((alpha, W.ambient_module().span_of_basis(W.basis()), e))
4783
else:
4784
F = h.root_field('{0}{1}'.format(var,i))
4785
alpha = F.gen(0)
4786
A = self.change_ring(F) - alpha
4787
W = A.kernel()
4788
WB = W.basis()
4789
if format == 'galois':
4790
V.append((alpha, W.ambient_module().span_of_basis(WB), e))
4791
elif format == 'all':
4792
try:
4793
alpha_conj = alpha.galois_conjugates(sage.rings.qqbar.QQbar)
4794
except (AttributeError, TypeError):
4795
msg = ("unable to construct eigenspaces for eigenvalues outside the base field,\n"
4796
"try the keyword option: format='galois'")
4797
raise NotImplementedError(''.join(msg))
4798
for ev in alpha_conj:
4799
m = sage.categories.homset.hom(alpha.parent(), ev.parent(), ev)
4800
space = (ev.parent())**self.nrows()
4801
evec_list = [(space)([m(i) for i in v]) for v in WB]
4802
V.append((ev, space.span_of_basis(evec_list, already_echelonized=True), e))
4803
V = Sequence(V, cr=True, check=False)
4804
self.cache(key, V)
4805
if algebraic_multiplicity:
4806
return V
4807
else:
4808
return Sequence([(e[0],e[1]) for e in V], cr=True, check=False)
4809
4810
left_eigenspaces = eigenspaces_left
4811
4812
def eigenspaces_right(self, format='all', var='a', algebraic_multiplicity=False):
4813
r"""
4814
Compute the right eigenspaces of a matrix.
4815
4816
Note that ``eigenspaces_right()`` and ``right_eigenspaces()``
4817
are identical methods. Here "right" refers to the eigenvectors
4818
being placed to the right of the matrix.
4819
4820
INPUT:
4821
4822
- ``self`` - a square matrix over an exact field. For inexact
4823
matrices consult the numerical or symbolic matrix classes.
4824
4825
- ``format`` - default: ``None``
4826
4827
- ``'all'`` - attempts to create every eigenspace. This will
4828
always be possible for matrices with rational entries.
4829
- ``'galois'`` - for each irreducible factor of the characteristic
4830
polynomial, a single eigenspace will be output for a
4831
single root/eigenvalue for the irreducible factor.
4832
- ``None`` - Uses the 'all' format if the base ring is contained
4833
in an algebraically closed field which is implemented.
4834
Otherwise, uses the 'galois' format.
4835
4836
- ``var`` - default: 'a' - variable name used to
4837
represent elements of the root field of each
4838
irreducible factor of the characteristic polynomial.
4839
If var='a', then the root fields will be in terms of
4840
a0, a1, a2, ...., where the numbering runs across all
4841
the irreducible factors of the characteristic polynomial,
4842
even for linear factors.
4843
4844
- ``algebraic_multiplicity`` - default: False - whether or
4845
not to include the algebraic multiplicity of each eigenvalue
4846
in the output. See the discussion below.
4847
4848
OUTPUT:
4849
4850
If algebraic_multiplicity=False, return a list of pairs (e, V)
4851
where e is an eigenvalue of the matrix, and V is the corresponding
4852
left eigenspace. For Galois conjugates of eigenvalues, there
4853
may be just one representative eigenspace, depending on the
4854
``format`` keyword.
4855
4856
If algebraic_multiplicity=True, return a list of triples (e, V, n)
4857
where e and V are as above and n is the algebraic multiplicity of
4858
the eigenvalue.
4859
4860
.. warning::
4861
4862
Uses a somewhat naive algorithm (simply factors the
4863
characteristic polynomial and computes kernels directly
4864
over the extension field).
4865
4866
EXAMPLES:
4867
4868
Right eigenspaces are computed from the left eigenspaces of the
4869
transpose of the matrix. As such, there is a greater collection
4870
of illustrative examples at the :meth:`eigenspaces_left`.
4871
4872
We compute the right eigenspaces of a `3\times 3` rational matrix. ::
4873
4874
sage: A = matrix(QQ, 3 ,3, range(9)); A
4875
[0 1 2]
4876
[3 4 5]
4877
[6 7 8]
4878
sage: A.eigenspaces_right()
4879
[
4880
(0, Vector space of degree 3 and dimension 1 over Rational Field
4881
User basis matrix:
4882
[ 1 -2 1]),
4883
(-1.348469228349535?, Vector space of degree 3 and dimension 1 over Algebraic Field
4884
User basis matrix:
4885
[ 1 0.1303061543300932? -0.7393876913398137?]),
4886
(13.34846922834954?, Vector space of degree 3 and dimension 1 over Algebraic Field
4887
User basis matrix:
4888
[ 1 3.069693845669907? 5.139387691339814?])
4889
]
4890
sage: es = A.eigenspaces_right(format='galois'); es
4891
[
4892
(0, Vector space of degree 3 and dimension 1 over Rational Field
4893
User basis matrix:
4894
[ 1 -2 1]),
4895
(a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18
4896
User basis matrix:
4897
[ 1 1/5*a1 + 2/5 2/5*a1 - 1/5])
4898
]
4899
sage: es = A.eigenspaces_right(format='galois', algebraic_multiplicity=True); es
4900
[
4901
(0, Vector space of degree 3 and dimension 1 over Rational Field
4902
User basis matrix:
4903
[ 1 -2 1], 1),
4904
(a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18
4905
User basis matrix:
4906
[ 1 1/5*a1 + 2/5 2/5*a1 - 1/5], 1)
4907
]
4908
sage: e, v, n = es[0]; v = v.basis()[0]
4909
sage: delta = v*e - A*v
4910
sage: abs(abs(delta)) < 1e-10
4911
True
4912
4913
The same computation, but with implicit base change to a field::
4914
4915
sage: A = matrix(ZZ, 3, range(9)); A
4916
[0 1 2]
4917
[3 4 5]
4918
[6 7 8]
4919
sage: A.eigenspaces_right(format='galois')
4920
[
4921
(0, Vector space of degree 3 and dimension 1 over Rational Field
4922
User basis matrix:
4923
[ 1 -2 1]),
4924
(a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18
4925
User basis matrix:
4926
[ 1 1/5*a1 + 2/5 2/5*a1 - 1/5])
4927
]
4928
4929
This method is only applicable to exact matrices.
4930
The "eigenmatrix" routines for matrices with double-precision
4931
floating-point entries (``RDF``, ``CDF``) are the best
4932
alternative. (Since some platforms return eigenvectors
4933
that are the negatives of those given here, this one example
4934
is not tested here.) There are also "eigenmatrix" routines for
4935
matrices with symbolic entries. ::
4936
4937
sage: B = matrix(RR, 3, 3, range(9))
4938
sage: B.eigenspaces_right()
4939
Traceback (most recent call last):
4940
...
4941
NotImplementedError: eigenspaces cannot be computed reliably for inexact rings such as Real Field with 53 bits of precision,
4942
consult numerical or symbolic matrix classes for other options
4943
4944
sage: em = B.change_ring(RDF).eigenmatrix_right()
4945
sage: eigenvalues = em[0]; eigenvalues.dense_matrix().zero_at(1e-15)
4946
[ 13.3484692283 0.0 0.0]
4947
[ 0.0 -1.34846922835 0.0]
4948
[ 0.0 0.0 0.0]
4949
sage: eigenvectors = em[1]; eigenvectors # not tested
4950
[ 0.164763817... 0.799699663... 0.408248290...]
4951
[ 0.505774475... 0.104205787... -0.816496580...]
4952
[ 0.846785134... -0.591288087... 0.408248290...]
4953
4954
sage: x, y = var('x y')
4955
sage: S = matrix([[x, y], [y, 3*x^2]])
4956
sage: em = S.eigenmatrix_right()
4957
sage: eigenvalues = em[0]; eigenvalues
4958
[-1/2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2) + 3/2*x^2 + 1/2*x 0]
4959
[ 0 3/2*x^2 + 1/2*x + 1/2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2)]
4960
sage: eigenvectors = em[1]; eigenvectors
4961
[ 1 1]
4962
[ 1/2*(3*x^2 - x - sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y -1/2*(x - sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2) - 3*x^2)/y]
4963
4964
TESTS::
4965
4966
sage: B = matrix(QQ, 2, 3, range(6))
4967
sage: B.eigenspaces_right()
4968
Traceback (most recent call last):
4969
...
4970
TypeError: matrix must be square, not 2 x 3
4971
4972
sage: B = matrix(QQ, 4, 4, range(16))
4973
sage: B.eigenspaces_right(format='junk')
4974
Traceback (most recent call last):
4975
...
4976
ValueError: format keyword must be None, 'all' or 'galois', not junk
4977
4978
sage: B.eigenspaces_right(algebraic_multiplicity='garbage')
4979
Traceback (most recent call last):
4980
...
4981
ValueError: algebraic_multiplicity keyword must be True or False
4982
"""
4983
if not algebraic_multiplicity in [True, False]:
4984
msg = 'algebraic_multiplicity keyword must be True or False'
4985
raise ValueError(msg.format(algebraic_multiplicity))
4986
if not self.is_square():
4987
msg = 'matrix must be square, not {0} x {1}'
4988
raise TypeError(msg.format(self.nrows(), self.ncols()))
4989
if not self.base_ring().is_exact():
4990
msg = ("eigenspaces cannot be computed reliably for inexact rings such as {0},\n",
4991
"consult numerical or symbolic matrix classes for other options")
4992
raise NotImplementedError(''.join(msg).format(self.base_ring()))
4993
4994
format = self._eigenspace_format(format)
4995
4996
key = 'eigenspaces_right_' + format + '{0}'.format(var)
4997
x = self.fetch(key)
4998
if not x is None:
4999
if algebraic_multiplicity:
5000
return x
5001
else:
5002
return Sequence([(e[0],e[1]) for e in x], cr=True, check=False)
5003
5004
V = self.transpose().eigenspaces_left(format=format, var=var, algebraic_multiplicity=True)
5005
5006
self.cache(key, V)
5007
if algebraic_multiplicity:
5008
return V
5009
else:
5010
return Sequence([(e[0],e[1]) for e in V], cr=True, check=False)
5011
5012
right_eigenspaces = eigenspaces_right
5013
5014
def eigenvalues(self,extend=True):
5015
r"""
5016
Return a sequence of the eigenvalues of a matrix, with
5017
multiplicity. If the eigenvalues are roots of polynomials in QQ,
5018
then QQbar elements are returned that represent each separate
5019
root.
5020
5021
If the option extend is set to False, only eigenvalues in the base
5022
ring are considered.
5023
5024
EXAMPLES::
5025
5026
sage: a = matrix(QQ, 4, range(16)); a
5027
[ 0 1 2 3]
5028
[ 4 5 6 7]
5029
[ 8 9 10 11]
5030
[12 13 14 15]
5031
sage: sorted(a.eigenvalues(), reverse=True)
5032
[32.46424919657298?, 0, 0, -2.464249196572981?]
5033
5034
::
5035
5036
sage: a=matrix([(1, 9, -1, -1), (-2, 0, -10, 2), (-1, 0, 15, -2), (0, 1, 0, -1)])
5037
sage: a.eigenvalues()
5038
[-0.9386318578049146?, 15.50655435353258?, 0.2160387521361705? - 4.713151979747493?*I, 0.2160387521361705? + 4.713151979747493?*I]
5039
5040
A symmetric matrix a+a.transpose() should have real eigenvalues
5041
5042
::
5043
5044
sage: b=a+a.transpose()
5045
sage: ev = b.eigenvalues(); ev
5046
[-8.35066086057957?, -1.107247901349379?, 5.718651326708515?, 33.73925743522043?]
5047
5048
The eigenvalues are elements of QQbar, so they really represent
5049
exact roots of polynomials, not just approximations.
5050
5051
::
5052
5053
sage: e = ev[0]; e
5054
-8.35066086057957?
5055
sage: p = e.minpoly(); p
5056
x^4 - 30*x^3 - 171*x^2 + 1460*x + 1784
5057
sage: p(e) == 0
5058
True
5059
5060
To perform computations on the eigenvalue as an element of a number
5061
field, you can always convert back to a number field element.
5062
5063
::
5064
5065
sage: e.as_number_field_element()
5066
(Number Field in a with defining polynomial y^4 - 2*y^3 - 507*y^2 + 4988*y - 8744,
5067
-a + 8,
5068
Ring morphism:
5069
From: Number Field in a with defining polynomial y^4 - 2*y^3 - 507*y^2 + 4988*y - 8744
5070
To: Algebraic Real Field
5071
Defn: a |--> 16.35066086057957?)
5072
5073
5074
Notice the effect of the extend option.
5075
5076
::
5077
5078
sage: M=matrix(QQ,[[0,-1,0],[1,0,0],[0,0,2]])
5079
sage: M.eigenvalues()
5080
[2, -1*I, 1*I]
5081
sage: M.eigenvalues(extend=False)
5082
[2]
5083
5084
"""
5085
x = self.fetch('eigenvalues')
5086
if not x is None:
5087
if not extend:
5088
x1=Sequence([])
5089
for i in x:
5090
if i in self.base_ring():
5091
x1.append(i)
5092
x=x1
5093
return x
5094
5095
if not self.base_ring().is_exact():
5096
from warnings import warn
5097
warn("Using generic algorithm for an inexact ring, which will probably give incorrect results due to numerical precision issues.")
5098
5099
from sage.rings.qqbar import QQbar
5100
G = self.fcp() # factored charpoly of self.
5101
V = []
5102
i=0
5103
for h, e in G:
5104
if h.degree() == 1:
5105
alpha = [-h[0]/h[1]]
5106
V.extend(alpha*e)
5107
else:
5108
if extend:
5109
F = h.root_field('%s%s'%('a',i))
5110
try:
5111
alpha = F.gen(0).galois_conjugates(QQbar)
5112
except AttributeError, TypeError:
5113
raise NotImplementedError, "eigenvalues() is not implemented for matrices with eigenvalues that are not in the fraction field of the base ring or in QQbar"
5114
V.extend(alpha*e)
5115
i+=1
5116
V = Sequence(V)
5117
if extend:
5118
self.cache('eigenvalues', V)
5119
if not extend:
5120
V1=Sequence([])
5121
for i in V:
5122
if i in self.base_ring():
5123
V1.append(i)
5124
V=V1
5125
return V
5126
5127
5128
5129
def eigenvectors_left(self,extend=True):
5130
r"""
5131
Compute the left eigenvectors of a matrix.
5132
5133
For each distinct eigenvalue, returns a list of the form (e,V,n)
5134
where e is the eigenvalue, V is a list of eigenvectors forming a
5135
basis for the corresponding left eigenspace, and n is the algebraic
5136
multiplicity of the eigenvalue.
5137
5138
If the option extend is set to False, then only the eigenvalues that
5139
live in the base ring are considered.
5140
5141
EXAMPLES: We compute the left eigenvectors of a `3\times 3`
5142
rational matrix.
5143
5144
::
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: es = A.eigenvectors_left(); es
5151
[(0, [
5152
(1, -2, 1)
5153
], 1),
5154
(-1.348469228349535?, [(1, 0.3101020514433644?, -0.3797958971132713?)], 1),
5155
(13.34846922834954?, [(1, 1.289897948556636?, 1.579795897113272?)], 1)]
5156
sage: eval, [evec], mult = es[0]
5157
sage: delta = eval*evec - evec*A
5158
sage: abs(abs(delta)) < 1e-10
5159
True
5160
5161
Notice the difference between considering ring extensions or not.
5162
5163
::
5164
5165
sage: M=matrix(QQ,[[0,-1,0],[1,0,0],[0,0,2]])
5166
sage: M.eigenvectors_left()
5167
[(2, [
5168
(0, 0, 1)
5169
], 1), (-1*I, [(1, -1*I, 0)], 1), (1*I, [(1, 1*I, 0)], 1)]
5170
sage: M.eigenvectors_left(extend=False)
5171
[(2, [
5172
(0, 0, 1)
5173
], 1)]
5174
5175
"""
5176
x = self.fetch('eigenvectors_left')
5177
if not x is None:
5178
return x
5179
5180
if not self.base_ring().is_exact():
5181
from warnings import warn
5182
warn("Using generic algorithm for an inexact ring, which may result in garbage from numerical precision issues.")
5183
5184
V = []
5185
from sage.rings.qqbar import QQbar
5186
from sage.categories.homset import hom
5187
eigenspaces = self.eigenspaces_left(format='galois', algebraic_multiplicity=True)
5188
evec_list=[]
5189
n = self._nrows
5190
evec_eval_list = []
5191
F = self.base_ring().fraction_field()
5192
for ev in eigenspaces:
5193
eigval = ev[0]
5194
eigbasis = ev[1].basis()
5195
eigmult = ev[2]
5196
if eigval in self.base_ring() or extend:
5197
if eigval.parent().fraction_field() == F:
5198
evec_eval_list.append((eigval, eigbasis, eigmult))
5199
else:
5200
try:
5201
eigval_conj = eigval.galois_conjugates(QQbar)
5202
except AttributeError, TypeError:
5203
raise NotImplementedError, "eigenvectors are not implemented for matrices with eigenvalues that are not in the fraction field of the base ring or in QQbar"
5204
5205
for e in eigval_conj:
5206
m = hom(eigval.parent(), e.parent(), e)
5207
space = (e.parent())**n
5208
evec_list = [(space)([m(i) for i in v]) for v in eigbasis]
5209
evec_eval_list.append( (e, evec_list, eigmult))
5210
5211
return evec_eval_list
5212
5213
left_eigenvectors = eigenvectors_left
5214
5215
def eigenvectors_right(self, extend=True):
5216
r"""
5217
Compute the right eigenvectors of a matrix.
5218
5219
For each distinct eigenvalue, returns a list of the form (e,V,n)
5220
where e is the eigenvalue, V is a list of eigenvectors forming a
5221
basis for the corresponding right eigenspace, and n is the
5222
algebraic multiplicity of the eigenvalue. If ``extend = True``
5223
(the default), this will return eigenspaces over the algebraic
5224
closure of the base field where this is implemented; otherwise
5225
it will restrict to eigenvalues in the base field.
5226
5227
EXAMPLES: We compute the right eigenvectors of a
5228
`3\times 3` rational matrix.
5229
5230
::
5231
5232
sage: A = matrix(QQ,3,3,range(9)); A
5233
[0 1 2]
5234
[3 4 5]
5235
[6 7 8]
5236
sage: es = A.eigenvectors_right(); es
5237
[(0, [
5238
(1, -2, 1)
5239
], 1),
5240
(-1.348469228349535?, [(1, 0.1303061543300932?, -0.7393876913398137?)], 1),
5241
(13.34846922834954?, [(1, 3.069693845669907?, 5.139387691339814?)], 1)]
5242
sage: A.eigenvectors_right(extend=False)
5243
[(0, [
5244
(1, -2, 1)
5245
], 1)]
5246
sage: eval, [evec], mult = es[0]
5247
sage: delta = eval*evec - A*evec
5248
sage: abs(abs(delta)) < 1e-10
5249
True
5250
"""
5251
return self.transpose().eigenvectors_left(extend=extend)
5252
5253
right_eigenvectors = eigenvectors_right
5254
5255
def eigenmatrix_left(self):
5256
r"""
5257
Return matrices D and P, where D is a diagonal matrix of
5258
eigenvalues and P is the corresponding matrix where the rows are
5259
corresponding eigenvectors (or zero vectors) so that P\*self =
5260
D\*P.
5261
5262
EXAMPLES::
5263
5264
sage: A = matrix(QQ,3,3,range(9)); A
5265
[0 1 2]
5266
[3 4 5]
5267
[6 7 8]
5268
sage: D, P = A.eigenmatrix_left()
5269
sage: D
5270
[ 0 0 0]
5271
[ 0 -1.348469228349535? 0]
5272
[ 0 0 13.34846922834954?]
5273
sage: P
5274
[ 1 -2 1]
5275
[ 1 0.3101020514433644? -0.3797958971132713?]
5276
[ 1 1.289897948556636? 1.579795897113272?]
5277
sage: P*A == D*P
5278
True
5279
5280
Because P is invertible, A is diagonalizable.
5281
5282
::
5283
5284
sage: A == (~P)*D*P
5285
True
5286
5287
The matrix P may contain zero rows corresponding to eigenvalues for
5288
which the algebraic multiplicity is greater than the geometric
5289
multiplicity. In these cases, the matrix is not diagonalizable.
5290
5291
::
5292
5293
sage: A = jordan_block(2,3); A
5294
[2 1 0]
5295
[0 2 1]
5296
[0 0 2]
5297
sage: A = jordan_block(2,3)
5298
sage: D, P = A.eigenmatrix_left()
5299
sage: D
5300
[2 0 0]
5301
[0 2 0]
5302
[0 0 2]
5303
sage: P
5304
[0 0 1]
5305
[0 0 0]
5306
[0 0 0]
5307
sage: P*A == D*P
5308
True
5309
5310
TESTS:
5311
5312
For matrices with floating point entries, some platforms will
5313
return eigenvectors that are negatives of those returned by the
5314
majority of platforms. This test accounts for that possibility.
5315
Running this test independently, without adjusting the eigenvectors
5316
could indicate this situation on your hardware. ::
5317
5318
sage: A = matrix(QQ, 3, 3, range(9))
5319
sage: em = A.change_ring(RDF).eigenmatrix_left()
5320
sage: evalues = em[0]; evalues.dense_matrix().zero_at(2e-15)
5321
[ 13.3484692283 0.0 0.0]
5322
[ 0.0 -1.34846922835 0.0]
5323
[ 0.0 0.0 0.0]
5324
sage: evectors = em[1];
5325
sage: for i in range(3):
5326
... scale = evectors[i,0].sign()
5327
... evectors.rescale_row(i, scale)
5328
sage: evectors
5329
[ 0.440242867... 0.567868371... 0.695493875...]
5330
[ 0.897878732... 0.278434036... -0.341010658...]
5331
[ 0.408248290... -0.816496580... 0.408248290...]
5332
"""
5333
from sage.misc.flatten import flatten
5334
evecs = self.eigenvectors_left()
5335
D = sage.matrix.constructor.diagonal_matrix(flatten([[e[0]]*e[2] for e in evecs]))
5336
rows = []
5337
for e in evecs:
5338
rows.extend(e[1]+[e[1][0].parent().zero_vector()]*(e[2]-len(e[1])))
5339
P = sage.matrix.constructor.matrix(rows)
5340
return D,P
5341
5342
left_eigenmatrix = eigenmatrix_left
5343
5344
def eigenmatrix_right(self):
5345
r"""
5346
Return matrices D and P, where D is a diagonal matrix of
5347
eigenvalues and P is the corresponding matrix where the columns are
5348
corresponding eigenvectors (or zero vectors) so that self\*P =
5349
P\*D.
5350
5351
EXAMPLES::
5352
5353
sage: A = matrix(QQ,3,3,range(9)); A
5354
[0 1 2]
5355
[3 4 5]
5356
[6 7 8]
5357
sage: D, P = A.eigenmatrix_right()
5358
sage: D
5359
[ 0 0 0]
5360
[ 0 -1.348469228349535? 0]
5361
[ 0 0 13.34846922834954?]
5362
sage: P
5363
[ 1 1 1]
5364
[ -2 0.1303061543300932? 3.069693845669907?]
5365
[ 1 -0.7393876913398137? 5.139387691339814?]
5366
sage: A*P == P*D
5367
True
5368
5369
Because P is invertible, A is diagonalizable.
5370
5371
::
5372
5373
sage: A == P*D*(~P)
5374
True
5375
5376
The matrix P may contain zero columns corresponding to eigenvalues
5377
for which the algebraic multiplicity is greater than the geometric
5378
multiplicity. In these cases, the matrix is not diagonalizable.
5379
5380
::
5381
5382
sage: A = jordan_block(2,3); A
5383
[2 1 0]
5384
[0 2 1]
5385
[0 0 2]
5386
sage: A = jordan_block(2,3)
5387
sage: D, P = A.eigenmatrix_right()
5388
sage: D
5389
[2 0 0]
5390
[0 2 0]
5391
[0 0 2]
5392
sage: P
5393
[1 0 0]
5394
[0 0 0]
5395
[0 0 0]
5396
sage: A*P == P*D
5397
True
5398
5399
TESTS:
5400
5401
For matrices with floating point entries, some platforms will
5402
return eigenvectors that are negatives of those returned by the
5403
majority of platforms. This test accounts for that possibility.
5404
Running this test independently, without adjusting the eigenvectors
5405
could indicate this situation on your hardware. ::
5406
5407
sage: B = matrix(QQ, 3, 3, range(9))
5408
sage: em = B.change_ring(RDF).eigenmatrix_right()
5409
sage: evalues = em[0]; evalues.dense_matrix().zero_at(2e-15)
5410
[ 13.3484692283 0.0 0.0]
5411
[ 0.0 -1.34846922835 0.0]
5412
[ 0.0 0.0 0.0]
5413
sage: evectors = em[1];
5414
sage: for i in range(3):
5415
... scale = evectors[0,i].sign()
5416
... evectors.rescale_col(i, scale)
5417
sage: evectors
5418
[ 0.164763817... 0.799699663... 0.408248290...]
5419
[ 0.505774475... 0.104205787... -0.816496580...]
5420
[ 0.846785134... -0.591288087... 0.408248290...]
5421
"""
5422
D,P=self.transpose().eigenmatrix_left()
5423
return D,P.transpose()
5424
5425
right_eigenmatrix = eigenmatrix_right
5426
5427
5428
5429
#####################################################################################
5430
# Generic Echelon Form
5431
###################################################################################
5432
5433
5434
def rref(self, *args, **kwds):
5435
"""
5436
Return the reduced row echelon form of the matrix, considered
5437
as a matrix over a field.
5438
5439
If the matrix is over a ring, then an equivalent matrix is
5440
constructed over the fraction field, and then row reduced.
5441
5442
All arguments are passed on to :meth:``echelon_form``.
5443
5444
.. note::
5445
5446
Because the matrix is viewed as a matrix over a field,
5447
every leading coefficient of the returned matrix will be
5448
one and will be the only nonzero entry in its column.
5449
5450
EXAMPLES::
5451
5452
sage: A=matrix(3,range(9)); A
5453
[0 1 2]
5454
[3 4 5]
5455
[6 7 8]
5456
sage: A.rref()
5457
[ 1 0 -1]
5458
[ 0 1 2]
5459
[ 0 0 0]
5460
5461
5462
Note that there is a difference between :meth:`rref` and
5463
:meth:`echelon_form` when the matrix is not over a field (in
5464
this case, the integers instead of the rational numbers)::
5465
5466
sage: A.base_ring()
5467
Integer Ring
5468
sage: A.echelon_form()
5469
[ 3 0 -3]
5470
[ 0 1 2]
5471
[ 0 0 0]
5472
5473
sage: B=random_matrix(QQ,3,num_bound=10); B
5474
[ -4 -3 6]
5475
[ 5 -5 9/2]
5476
[3/2 -4 -7]
5477
sage: B.rref()
5478
[1 0 0]
5479
[0 1 0]
5480
[0 0 1]
5481
5482
In this case, since ``B`` is a matrix over a field (the
5483
rational numbers), :meth:`rref` and :meth:`echelon_form` are
5484
exactly the same::
5485
5486
sage: B.echelon_form()
5487
[1 0 0]
5488
[0 1 0]
5489
[0 0 1]
5490
sage: B.echelon_form() is B.rref()
5491
True
5492
5493
Since :meth:`echelon_form` is not implemented for every ring,
5494
sometimes behavior varies, as here::
5495
5496
sage: R.<x>=ZZ[]
5497
sage: C = matrix(3,[2,x,x^2,x+1,3-x,-1,3,2,1])
5498
sage: C.rref()
5499
[1 0 0]
5500
[0 1 0]
5501
[0 0 1]
5502
sage: C.base_ring()
5503
Univariate Polynomial Ring in x over Integer Ring
5504
sage: C.echelon_form()
5505
Traceback (most recent call last):
5506
...
5507
NotImplementedError: Ideal Ideal (2, x + 1) of Univariate Polynomial Ring in x over Integer Ring not principal
5508
Echelon form not implemented over 'Univariate Polynomial Ring in x over Integer Ring'.
5509
sage: C = matrix(3,[2,x,x^2,x+1,3-x,-1,3,2,1/2])
5510
sage: C.echelon_form()
5511
[ 2 x x^2]
5512
[ 0 1 15*x^2 - 3/2*x - 31/2]
5513
[ 0 0 5/2*x^3 - 15/4*x^2 - 9/4*x + 7/2]
5514
sage: C.rref()
5515
[1 0 0]
5516
[0 1 0]
5517
[0 0 1]
5518
sage: C = matrix(3,[2,x,x^2,x+1,3-x,-1/x,3,2,1/2])
5519
sage: C.echelon_form()
5520
[1 0 0]
5521
[0 1 0]
5522
[0 0 1]
5523
"""
5524
R=self.base_ring()
5525
if R.is_field():
5526
return self.echelon_form()
5527
else:
5528
F=R.fraction_field()
5529
return self.change_ring(F).echelon_form()
5530
5531
def _echelonize_ring(self, **kwds):
5532
r"""
5533
Echelonize self in place, where the base ring of self is assumed to
5534
be a ring (not a field).
5535
5536
Right now this *only* works over ZZ and some principal ideal domains;
5537
otherwise a ``NotImplementedError`` is raised. In the special case of
5538
sparse matrices over ZZ it makes them dense, gets the echelon form of
5539
the dense matrix, then sets self equal to the result.
5540
5541
EXAMPLES::
5542
5543
sage: a = matrix(ZZ, 3, 4, [1..12], sparse=True); a
5544
[ 1 2 3 4]
5545
[ 5 6 7 8]
5546
[ 9 10 11 12]
5547
sage: a._echelonize_ring()
5548
sage: a
5549
[ 1 2 3 4]
5550
[ 0 4 8 12]
5551
[ 0 0 0 0]
5552
5553
sage: L.<w> = NumberField(x^2 - x + 2)
5554
sage: OL = L.ring_of_integers()
5555
sage: m = matrix(OL, 2, 2, [1,2,3,4+w])
5556
sage: m.echelon_form()
5557
[ 1 2]
5558
[ 0 w - 2]
5559
sage: E, T = m.echelon_form(transformation=True); E,T
5560
(
5561
[ 1 2] [ 1 0]
5562
[ 0 w - 2], [-3 1]
5563
)
5564
sage: E == T*m
5565
True
5566
5567
TESTS:
5568
5569
Check that http://trac.sagemath.org/sage_trac/ticket/11558 is fixed::
5570
5571
sage: matrix(ZZ, [[1,2],[4,6]], sparse=False).echelon_form(transformation=True)
5572
(
5573
[1 0] [-3 1]
5574
[0 2], [ 4 -1]
5575
)
5576
sage: matrix(ZZ, [[1,2],[4,6]], sparse=True).echelon_form(transformation=True)
5577
(
5578
[1 0] [-3 1]
5579
[0 2], [ 4 -1]
5580
)
5581
"""
5582
self.check_mutability()
5583
cdef Matrix d, a
5584
cdef Py_ssize_t r, c
5585
cdef bint transformation = kwds.has_key('transformation') and kwds['transformation']
5586
if self._base_ring == ZZ:
5587
if kwds.has_key('include_zero_rows') and not kwds['include_zero_rows']:
5588
raise ValueError, "cannot echelonize in place and delete zero rows"
5589
if transformation:
5590
d, a = self.dense_matrix().echelon_form(**kwds)
5591
else:
5592
d = self.dense_matrix().echelon_form(**kwds)
5593
for c from 0 <= c < self.ncols():
5594
for r from 0 <= r < self.nrows():
5595
self.set_unsafe(r, c, d.get_unsafe(r,c))
5596
self.clear_cache()
5597
self.cache('pivots', d.pivots())
5598
self.cache('in_echelon_form', True)
5599
else:
5600
try:
5601
a, d, p = self._echelon_form_PID()
5602
except TypeError, msg:
5603
raise NotImplementedError, "%s\nechelon form over %s not yet implemented"%(msg, self.base_ring())
5604
5605
for c from 0 <= c < self.ncols():
5606
for r from 0 <= r < self.nrows():
5607
self.set_unsafe(r, c, d.get_unsafe(r,c))
5608
self.clear_cache()
5609
self.cache('pivots', tuple(p))
5610
self.cache('in_echelon_form', True)
5611
if transformation:
5612
return a
5613
else:
5614
return
5615
5616
def echelonize(self, algorithm="default", cutoff=0, **kwds):
5617
r"""
5618
Transform ``self`` into a matrix in echelon form over the same
5619
base ring as self.
5620
5621
.. note::
5622
5623
This row reduction does not use division if the
5624
matrix is not over a field (e.g., if the matrix is over
5625
the integers). If you want to calculate the echelon form
5626
using division, then use :meth:`rref`, which assumes that
5627
the matrix entries are in a field (specifically, the field
5628
of fractions of the base ring of the matrix).
5629
5630
INPUT:
5631
5632
- ``algorithm`` -- string. Which algorithm to use. Choices are
5633
5634
- ``'default'``: Let Sage choose an algorithm (default).
5635
5636
- ``'classical'``: Gauss elimination.
5637
5638
- ``'strassen'``: use a Strassen divide and conquer
5639
algorithm (if available)
5640
5641
- ``cutoff`` -- integer. Only used if the Strassen algorithm
5642
is selected.
5643
5644
- ``transformation`` -- boolean. Whether to also return the
5645
transformation matrix. Some matrix backends do not provide
5646
this information, in which case this option is ignored.
5647
5648
OUTPUT:
5649
5650
The matrix ``self`` is put into echelon form. Nothing is
5651
returned unless the keyword option ``transformation=True`` is
5652
specified, in which case the transformation matrix is
5653
returned.
5654
5655
EXAMPLES::
5656
5657
sage: a = matrix(QQ,3,range(9)); a
5658
[0 1 2]
5659
[3 4 5]
5660
[6 7 8]
5661
sage: a.echelonize()
5662
sage: a
5663
[ 1 0 -1]
5664
[ 0 1 2]
5665
[ 0 0 0]
5666
5667
An immutable matrix cannot be transformed into echelon form. Use
5668
``self.echelon_form()`` instead::
5669
5670
sage: a = matrix(QQ,3,range(9)); a.set_immutable()
5671
sage: a.echelonize()
5672
Traceback (most recent call last):
5673
...
5674
ValueError: matrix is immutable; please change a copy instead
5675
(i.e., use copy(M) to change a copy of M).
5676
sage: a.echelon_form()
5677
[ 1 0 -1]
5678
[ 0 1 2]
5679
[ 0 0 0]
5680
5681
Echelon form over the integers is what is also classically often
5682
known as Hermite normal form::
5683
5684
sage: a = matrix(ZZ,3,range(9))
5685
sage: a.echelonize(); a
5686
[ 3 0 -3]
5687
[ 0 1 2]
5688
[ 0 0 0]
5689
5690
We compute an echelon form both over a domain and fraction field::
5691
5692
sage: R.<x,y> = QQ[]
5693
sage: a = matrix(R, 2, [x,y,x,y])
5694
sage: a.echelon_form() # not very useful? -- why two copies of the same row?
5695
[x y]
5696
[x y]
5697
5698
::
5699
5700
sage: b = a.change_ring(R.fraction_field())
5701
sage: b.echelon_form() # potentially useful
5702
[ 1 y/x]
5703
[ 0 0]
5704
5705
Echelon form is not defined over arbitrary rings::
5706
5707
sage: a = matrix(Integers(9),3,range(9))
5708
sage: a.echelon_form()
5709
Traceback (most recent call last):
5710
...
5711
NotImplementedError: Echelon form not implemented over 'Ring of integers modulo 9'.
5712
5713
Involving a sparse matrix::
5714
5715
sage: m = matrix(3,[1, 1, 1, 1, 0, 2, 1, 2, 0], sparse=True); m
5716
[1 1 1]
5717
[1 0 2]
5718
[1 2 0]
5719
sage: m.echelon_form()
5720
[ 1 0 2]
5721
[ 0 1 -1]
5722
[ 0 0 0]
5723
sage: m.echelonize(); m
5724
[ 1 0 2]
5725
[ 0 1 -1]
5726
[ 0 0 0]
5727
5728
The transformation matrix is optionally returned::
5729
5730
sage: m_original = m
5731
sage: transformation_matrix = m.echelonize(transformation=True)
5732
sage: m == transformation_matrix * m_original
5733
True
5734
"""
5735
self.check_mutability()
5736
5737
if algorithm == 'default':
5738
if self._will_use_strassen_echelon():
5739
algorithm = 'strassen'
5740
else:
5741
algorithm = 'classical'
5742
try:
5743
if self.base_ring().is_field():
5744
if algorithm == 'classical':
5745
self._echelon_in_place_classical()
5746
elif algorithm == 'strassen':
5747
self._echelon_strassen(cutoff)
5748
else:
5749
raise ValueError, "Unknown algorithm '%s'"%algorithm
5750
else:
5751
if not (algorithm in ['classical', 'strassen']):
5752
kwds['algorithm'] = algorithm
5753
return self._echelonize_ring(**kwds)
5754
except ArithmeticError, msg:
5755
raise NotImplementedError, "%s\nEchelon form not implemented over '%s'."%(msg,self.base_ring())
5756
5757
def echelon_form(self, algorithm="default", cutoff=0, **kwds):
5758
"""
5759
Return the echelon form of self.
5760
5761
.. note::
5762
5763
This row reduction does not use division if the
5764
matrix is not over a field (e.g., if the matrix is over
5765
the integers). If you want to calculate the echelon form
5766
using division, then use :meth:`rref`, which assumes that
5767
the matrix entries are in a field (specifically, the field
5768
of fractions of the base ring of the matrix).
5769
5770
INPUT:
5771
5772
- ``algorithm`` -- string. Which algorithm to use. Choices are
5773
5774
- ``'default'``: Let Sage choose an algorithm (default).
5775
5776
- ``'classical'``: Gauss elimination.
5777
5778
- ``'strassen'``: use a Strassen divide and conquer
5779
algorithm (if available)
5780
5781
- ``cutoff`` -- integer. Only used if the Strassen algorithm is selected.
5782
5783
- ``transformation`` -- boolean. Whether to also return the
5784
transformation matrix. Some matrix backends do not provide
5785
this information, in which case this option is ignored.
5786
5787
OUTPUT:
5788
5789
The reduced row echelon form of ``self``, as an immutable
5790
matrix. Note that self is *not* changed by this command. Use
5791
:meth:`echelonize` to change ``self`` in place.
5792
5793
If the optional parameter ``transformation=True`` is
5794
specified, the output consists of a pair `(E,T)` of matrices
5795
where `E` is the echelon form of ``self`` and `T` is the
5796
transformation matrix.
5797
5798
EXAMPLES::
5799
5800
sage: MS = MatrixSpace(GF(19),2,3)
5801
sage: C = MS.matrix([1,2,3,4,5,6])
5802
sage: C.rank()
5803
2
5804
sage: C.nullity()
5805
0
5806
sage: C.echelon_form()
5807
[ 1 0 18]
5808
[ 0 1 2]
5809
5810
The matrix library used for `\ZZ/p`-matrices does not return
5811
the transformation matrix, so the ``transformation`` option is
5812
ignored::
5813
5814
sage: C.echelon_form(transformation=True)
5815
[ 1 0 18]
5816
[ 0 1 2]
5817
5818
sage: D = matrix(ZZ, 2, 3, [1,2,3,4,5,6])
5819
sage: D.echelon_form(transformation=True)
5820
(
5821
[1 2 3] [ 1 0]
5822
[0 3 6], [ 4 -1]
5823
)
5824
sage: E, T = D.echelon_form(transformation=True)
5825
sage: T*D == E
5826
True
5827
"""
5828
cdef bint transformation = (kwds.has_key('transformation') and kwds['transformation'])
5829
x = self.fetch('echelon_form')
5830
if x is not None:
5831
if not transformation:
5832
return x
5833
y = self.fetch('echelon_transformation')
5834
if y:
5835
return (x, y)
5836
5837
E = self.__copy__()
5838
if algorithm == 'default':
5839
v = E.echelonize(cutoff=cutoff, **kwds)
5840
else:
5841
v = E.echelonize(algorithm = algorithm, cutoff=cutoff, **kwds)
5842
E.set_immutable() # so we can cache the echelon form.
5843
self.cache('echelon_form', E)
5844
if v is not None:
5845
self.cache('echelon_transformation', v)
5846
self.cache('pivots', E.pivots())
5847
if transformation and v is not None:
5848
return (E, v)
5849
else:
5850
return E
5851
5852
def _echelon_classical(self):
5853
"""
5854
Return the echelon form of self.
5855
"""
5856
E = self.fetch('echelon_classical')
5857
if not E is None:
5858
return E
5859
E = self.__copy__()
5860
E._echelon_in_place_classical()
5861
self.cache('echelon_classical', E)
5862
return E
5863
5864
def _echelon_in_place_classical(self):
5865
"""
5866
Transform self into echelon form and set the pivots of self.
5867
5868
EXAMPLES::
5869
5870
sage: t = matrix(QQ, 3, range(9)); t
5871
[0 1 2]
5872
[3 4 5]
5873
[6 7 8]
5874
sage: E = t._echelon_in_place_classical(); t
5875
[ 1 0 -1]
5876
[ 0 1 2]
5877
[ 0 0 0]
5878
"""
5879
tm = verbose('generic in-place Gauss elimination on %s x %s matrix'%(self._nrows, self._ncols))
5880
cdef Py_ssize_t start_row, c, r, nr, nc, i
5881
if self.fetch('in_echelon_form'):
5882
return
5883
5884
self.check_mutability()
5885
cdef Matrix A
5886
5887
nr = self._nrows
5888
nc = self._ncols
5889
A = self
5890
5891
start_row = 0
5892
pivots = []
5893
5894
for c from 0 <= c < nc:
5895
sig_check()
5896
for r from start_row <= r < nr:
5897
if A.get_unsafe(r, c):
5898
pivots.append(c)
5899
a_inverse = ~A.get_unsafe(r,c)
5900
A.rescale_row(r, a_inverse, c)
5901
A.swap_rows(r, start_row)
5902
for i from 0 <= i < nr:
5903
if i != start_row:
5904
if A.get_unsafe(i,c):
5905
minus_b = -A.get_unsafe(i, c)
5906
A.add_multiple_of_row(i, start_row, minus_b, c)
5907
start_row = start_row + 1
5908
break
5909
self.cache('pivots', tuple(pivots))
5910
self.cache('in_echelon_form', True)
5911
self.cache('echelon_form', self)
5912
verbose('done with gauss echelon form', tm)
5913
5914
def extended_echelon_form(self, subdivide=False, **kwds):
5915
r"""
5916
Returns the echelon form of ``self`` augmented with an identity matrix.
5917
5918
INPUT:
5919
5920
- ``subdivide`` - default: ``False`` - determines if the
5921
returned matrix is subdivided. See the description of the
5922
(output) below for details.
5923
- ``kwds`` - additional keywords that can be passed to
5924
the method that computes the echelon form.
5925
5926
OUTPUT:
5927
5928
If `A` is an `m\times n` matrix, add the `m` columns of an
5929
`m\times m` identity matrix to the right of ``self``. Then
5930
row-reduce this `m\times(n+m)` matrix. This matrix is returned
5931
as an immutable matrix.
5932
5933
If ``subdivide`` is ``True`` then the returned matrix has a single
5934
division among the columns and a single division among the rows.
5935
The column subdivision has `n` columns to the left and `m`
5936
columns to the right. The row division separates the non-zero rows
5937
from the zero rows, when restricted to the first `n` columns.
5938
5939
For a nonsingular matrix the final `m` columns of the extended
5940
echelon form are the inverse of ``self``. For a matrix of
5941
any size, the final `m` columns provide a matrix that transforms
5942
``self`` to echelon form when it multiplies ``self`` from the left.
5943
When the base ring is a field, the uniqueness of reduced row-echelon
5944
form implies that this transformation matrix can be taken as the
5945
coefficients giving a
5946
canonical set of linear combinations of the rows of ``self`` that
5947
yield reduced row-echelon form.
5948
5949
When subdivided as described above, and again over a field, the
5950
parts of the subdivision in the upper-left corner and lower-right
5951
corner satisfy several interesting relationships with the row space,
5952
column space, left kernel and right kernel of ``self``. See the
5953
examples below.
5954
5955
.. note::
5956
5957
This method returns an echelon form. If the base ring
5958
is not a field, no atttempt is made to move to the fraction field.
5959
See an example below where the base ring is changed manually.
5960
5961
EXAMPLES:
5962
5963
The four relationships at the end of this example hold in general. ::
5964
5965
sage: A = matrix(QQ, [[2, -1, 7, -1, 0, -3],
5966
... [-1, 1, -5, 3, 4, 4],
5967
... [2, -1, 7, 0, 2, -2],
5968
... [2, 0, 4, 3, 6, 1],
5969
... [2, -1, 7, 0, 2, -2]])
5970
sage: E = A.extended_echelon_form(subdivide=True); E
5971
[ 1 0 2 0 0 -1| 0 -1 0 1 -1]
5972
[ 0 1 -3 0 -2 0| 0 -2 0 2 -3]
5973
[ 0 0 0 1 2 1| 0 2/3 0 -1/3 2/3]
5974
[-----------------------------+------------------------]
5975
[ 0 0 0 0 0 0| 1 2/3 0 -1/3 -1/3]
5976
[ 0 0 0 0 0 0| 0 0 1 0 -1]
5977
sage: J = E.matrix_from_columns(range(6,11)); J
5978
[ 0 -1 0 1 -1]
5979
[ 0 -2 0 2 -3]
5980
[ 0 2/3 0 -1/3 2/3]
5981
[ 1 2/3 0 -1/3 -1/3]
5982
[ 0 0 1 0 -1]
5983
sage: J*A == A.rref()
5984
True
5985
sage: C = E.subdivision(0,0); C
5986
[ 1 0 2 0 0 -1]
5987
[ 0 1 -3 0 -2 0]
5988
[ 0 0 0 1 2 1]
5989
sage: L = E.subdivision(1,1); L
5990
[ 1 2/3 0 -1/3 -1/3]
5991
[ 0 0 1 0 -1]
5992
sage: A.right_kernel() == C.right_kernel()
5993
True
5994
sage: A.row_space() == C.row_space()
5995
True
5996
sage: A.column_space() == L.right_kernel()
5997
True
5998
sage: A.left_kernel() == L.row_space()
5999
True
6000
6001
For a nonsingular matrix, the right half of the extended
6002
echelon form is the inverse matrix. ::
6003
6004
sage: B = matrix(QQ, [[1,3,4], [1,4,4], [0,-2,-1]])
6005
sage: E = B.extended_echelon_form()
6006
sage: J = E.matrix_from_columns(range(3,6)); J
6007
[-4 5 4]
6008
[-1 1 0]
6009
[ 2 -2 -1]
6010
sage: J == B.inverse()
6011
True
6012
6013
The result is in echelon form, so if the base ring is
6014
not a field, the leading entry of each row may not be 1.
6015
But you can easily change to the fraction field if necessary. ::
6016
6017
sage: A = matrix(ZZ, [[16, 20, 4, 5, -4, 13, 5],
6018
... [10, 13, 3, -3, 7, 11, 6],
6019
... [-12, -15, -3, -3, 2, -10, -4],
6020
... [10, 13, 3, 3, -1, 9, 4],
6021
... [4, 5, 1, 8, -10, 1, -1]])
6022
sage: E = A.extended_echelon_form(subdivide=True); E
6023
[ 2 0 -2 2 -9 -3 -4| 0 4 -3 -9 4]
6024
[ 0 1 1 2 0 1 1| 0 1 2 1 1]
6025
[ 0 0 0 3 -4 -1 -1| 0 3 1 -3 3]
6026
[--------------------+--------------]
6027
[ 0 0 0 0 0 0 0| 1 6 3 -6 5]
6028
[ 0 0 0 0 0 0 0| 0 7 2 -7 6]
6029
sage: J = E.matrix_from_columns(range(7,12)); J
6030
[ 0 4 -3 -9 4]
6031
[ 0 1 2 1 1]
6032
[ 0 3 1 -3 3]
6033
[ 1 6 3 -6 5]
6034
[ 0 7 2 -7 6]
6035
sage: J*A == A.echelon_form()
6036
True
6037
sage: B = A.change_ring(QQ)
6038
sage: B.extended_echelon_form(subdivide=True)
6039
[ 1 0 -1 0 -19/6 -7/6 -5/3| 0 0 -89/42 -5/2 1/7]
6040
[ 0 1 1 0 8/3 5/3 5/3| 0 0 34/21 2 -1/7]
6041
[ 0 0 0 1 -4/3 -1/3 -1/3| 0 0 1/21 0 1/7]
6042
[------------------------------------------------+----------------------------------]
6043
[ 0 0 0 0 0 0 0| 1 0 9/7 0 -1/7]
6044
[ 0 0 0 0 0 0 0| 0 1 2/7 -1 6/7]
6045
6046
Subdivided, or not, the result is immutable, so make a
6047
copy if you want to make changes. ::
6048
6049
sage: A = matrix(FiniteField(7), [[2,0,3], [5,5,3], [5,6,5]])
6050
sage: E = A.extended_echelon_form()
6051
sage: E.is_mutable()
6052
False
6053
sage: F = A.extended_echelon_form(subdivide=True)
6054
sage: F
6055
[1 0 0|0 4 6]
6056
[0 1 0|4 2 2]
6057
[0 0 1|5 2 3]
6058
[-----+-----]
6059
sage: F.is_mutable()
6060
False
6061
sage: G = copy(F)
6062
sage: G.subdivide([],[]); G
6063
[1 0 0 0 4 6]
6064
[0 1 0 4 2 2]
6065
[0 0 1 5 2 3]
6066
6067
If you want to determine exactly which algorithm is
6068
used to compute the echelon form, you can add additional
6069
keywords to pass on to the ``echelon_form()`` routine
6070
employed on the augmented matrix. Sending the flag
6071
``include_zero_rows`` is a bit silly, since the
6072
extended echelon form will never have any zero rows. ::
6073
6074
sage: A = matrix(ZZ, [[1,2], [5,0], [5,9]])
6075
sage: E = A.extended_echelon_form(algorithm='padic', include_zero_rows=False)
6076
sage: E
6077
[ 1 0 36 1 -8]
6078
[ 0 1 5 0 -1]
6079
[ 0 0 45 1 -10]
6080
6081
TESTS:
6082
6083
The ``subdivide`` keyword is checked. ::
6084
6085
sage: A = matrix(QQ, 2, range(4))
6086
sage: A.extended_echelon_form(subdivide='junk')
6087
Traceback (most recent call last):
6088
...
6089
TypeError: subdivide must be True or False, not junk
6090
6091
AUTHOR:
6092
6093
- Rob Beezer (2011-02-02)
6094
"""
6095
if not subdivide in [True, False]:
6096
raise TypeError("subdivide must be True or False, not %s" % subdivide)
6097
R = self.base_ring()
6098
import constructor
6099
ident = constructor.identity_matrix(R, self.nrows())
6100
E = self.augment(ident)
6101
extended = E.echelon_form(**kwds)
6102
if subdivide:
6103
from copy import copy
6104
extended = copy(extended)
6105
# pivots of E are cached from echelon form computation
6106
rank = len([c for c in E.pivots() if c < self.ncols()])
6107
extended.subdivide(rank, self.ncols())
6108
extended.set_immutable()
6109
return extended
6110
6111
def weak_popov_form(self, ascend=True):
6112
"""
6113
This function computes a weak Popov form of a matrix over a rational
6114
function field `k(x)`, for `k` a field.
6115
6116
INPUT:
6117
6118
- `ascend` - if True, rows of output matrix `W` are sorted so
6119
degree (= the maximum of the degrees of the elements in
6120
the row) increases monotonically, and otherwise degrees decrease.
6121
6122
OUTPUT:
6123
6124
A 3-tuple `(W,N,d)` consisting of:
6125
6126
1. `W` - a matrix over `k(x)` giving a weak the Popov form of self
6127
2. `N` - a matrix over `k[x]` representing row operations used to
6128
transform `self` to `W`
6129
3. `d` - degree of respective columns of W; the degree of a column is
6130
the maximum of the degree of its elements
6131
6132
`N` is invertible over `k(x)`. These matrices satisfy the relation
6133
`N*self = W`.
6134
6135
EXAMPLES:
6136
6137
The routine expects matrices over the rational function field, but
6138
other examples below show how one can provide matrices over the ring
6139
of polynomials (whose quotient field is the rational function field).
6140
6141
::
6142
6143
sage: R.<t> = GF(3)['t']
6144
sage: K = FractionField(R)
6145
sage: M = matrix([[(t-1)^2/t],[(t-1)]])
6146
sage: M.weak_popov_form()
6147
(
6148
[ 0] [ t 2*t + 1]
6149
[(2*t + 1)/t], [ 1 2], [-Infinity, 0]
6150
)
6151
6152
If `self` is an `n x 1` matrix with at least one non-zero entry, `W` has
6153
a single non-zero entry and that entry is a scalar multiple of the
6154
greatest-common-divisor of the entries of `self`.
6155
6156
::
6157
6158
sage: M1 = matrix([[t*(t-1)*(t+1)],[t*(t-2)*(t+2)],[t]])
6159
sage: output1 = M1.weak_popov_form()
6160
sage: output1
6161
(
6162
[0] [ 1 0 2*t^2 + 1]
6163
[0] [ 0 1 2*t^2 + 1]
6164
[t], [ 0 0 1], [-Infinity, -Infinity, 1]
6165
)
6166
6167
We check that the output is the same for a matrix `M` if its entries are
6168
rational functions intead of polynomials. We also check that the type of
6169
the output follows the documentation. See #9063
6170
6171
::
6172
6173
sage: M2 = M1.change_ring(K)
6174
sage: output2 = M2.weak_popov_form()
6175
sage: output1 == output2
6176
True
6177
sage: output1[0].base_ring() is K
6178
True
6179
sage: output2[0].base_ring() is K
6180
True
6181
sage: output1[1].base_ring() is R
6182
True
6183
sage: output2[1].base_ring() is R
6184
True
6185
6186
The following is the first half of example 5 in [H] *except* that we
6187
have transposed `self`; [H] uses column operations and we use row.
6188
6189
::
6190
6191
sage: R.<t> = QQ['t']
6192
sage: M = matrix([[t^3 - t,t^2 - 2],[0,t]]).transpose()
6193
sage: M.weak_popov_form()
6194
(
6195
[ t -t^2] [ 1 -t]
6196
[t^2 - 2 t], [ 0 1], [2, 2]
6197
)
6198
6199
The next example demonstrates what happens when `self` is a zero matrix.
6200
6201
::
6202
6203
sage: R.<t> = GF(5)['t']
6204
sage: K = FractionField(R)
6205
sage: M = matrix([[K(0),K(0)],[K(0),K(0)]])
6206
sage: M.weak_popov_form()
6207
(
6208
[0 0] [1 0]
6209
[0 0], [0 1], [-Infinity, -Infinity]
6210
)
6211
6212
In the following example, `self` has more rows than columns.
6213
6214
::
6215
6216
sage: R.<t> = QQ['t']
6217
sage: M = matrix([[t,t,t],[0,0,t]], ascend=False)
6218
sage: M.weak_popov_form()
6219
(
6220
[t t t] [1 0]
6221
[0 0 t], [0 1], [1, 1]
6222
)
6223
6224
The next example shows that M must be a matrix with
6225
coefficients in a rational function field `k(t)`.
6226
6227
::
6228
6229
sage: M = matrix([[1,0],[1,1]])
6230
sage: M.weak_popov_form()
6231
Traceback (most recent call last):
6232
...
6233
TypeError: the coefficients of M must lie in a univariate
6234
polynomial ring
6235
6236
6237
NOTES:
6238
6239
- For consistency with LLL and other algorithms in sage, we have opted
6240
for row operations; however, references such as [H] transpose and use
6241
column operations.
6242
6243
- There are multiple weak Popov forms of a matrix, so one may want to
6244
extend this code to produce a Popov form (see section 1.2 of [V]). The
6245
latter is canonical, but more work to produce.
6246
6247
REFERENCES:
6248
6249
.. [H] F. Hess, "Computing Riemann-Roch spaces in algebraic function
6250
fields and related topics," J. Symbolic Comput. 33 (2002), no. 4,
6251
425--445.
6252
6253
.. [MS] T. Mulders, A. Storjohann, "On lattice reduction for polynomial
6254
matrices," J. Symbolic Comput. 35 (2003), no. 4, 377--401
6255
6256
.. [V] G. Villard, "Computing Popov and Hermite forms of polynomial
6257
matrices", ISSAC '96: Proceedings of the 1996 international symposium
6258
on Symbolic and algebraic computation, 250--258.
6259
6260
"""
6261
import sage.matrix.matrix_misc
6262
return sage.matrix.matrix_misc.weak_popov_form(self)
6263
6264
#####################################################################################
6265
# Windowed Strassen Matrix Multiplication and Echelon
6266
# Precise algorithms invented and implemented by David Harvey and Robert Bradshaw
6267
# at William Stein's MSRI 2006 Summer Workshop on Modular Forms.
6268
#####################################################################################
6269
def _multiply_strassen(self, Matrix right, int cutoff=0):
6270
"""
6271
Multiply self by the matrix right using a Strassen-based
6272
asymptotically fast arithmetic algorithm.
6273
6274
ALGORITHM: Custom algorithm for arbitrary size matrices designed by
6275
David Harvey and Robert Bradshaw, based on Strassen's algorithm.
6276
6277
INPUT:
6278
6279
6280
- ``cutoff`` - integer (default: 0 - let class
6281
decide).
6282
6283
6284
EXAMPLES::
6285
6286
sage: a = matrix(ZZ,4,range(16))
6287
sage: a._multiply_strassen(a,2)
6288
[ 56 62 68 74]
6289
[152 174 196 218]
6290
[248 286 324 362]
6291
[344 398 452 506]
6292
"""
6293
if self._ncols != right._nrows:
6294
raise ArithmeticError, "Number of columns of self must equal number of rows of right."
6295
if not self._base_ring is right.base_ring():
6296
raise TypeError, "Base rings must be the same."
6297
6298
if cutoff == 0:
6299
cutoff = self._strassen_default_cutoff(right)
6300
6301
if cutoff <= 0:
6302
raise ValueError, "cutoff must be at least 1"
6303
6304
output = self.new_matrix(self._nrows, right._ncols)
6305
# The following used to be a little faster, but meanwhile
6306
# the previous line is faster.
6307
#if self.is_sparse():
6308
# output = self.matrix_space(self._nrows, right._ncols, sparse = True)(0)
6309
#else:
6310
# output = self.matrix_space(self._nrows, right._ncols, sparse = False).zero_matrix().__copy__()
6311
6312
self_window = self.matrix_window()
6313
right_window = right.matrix_window()
6314
output_window = output.matrix_window()
6315
6316
6317
import strassen
6318
strassen.strassen_window_multiply(output_window, self_window, right_window, cutoff)
6319
return output
6320
6321
def _echelon_strassen(self, int cutoff=0):
6322
"""
6323
In place Strassen echelon of self, and sets the pivots.
6324
6325
ALGORITHM: Custom algorithm for arbitrary size matrices designed by
6326
David Harvey and Robert Bradshaw, based on Strassen's algorithm.
6327
6328
EXAMPLES::
6329
6330
sage: A = matrix(QQ, 4, range(16))
6331
sage: A._echelon_strassen(2)
6332
sage: A
6333
[ 1 0 -1 -2]
6334
[ 0 1 2 3]
6335
[ 0 0 0 0]
6336
[ 0 0 0 0]
6337
"""
6338
tm = verbose('strassen echelon of %s x %s matrix'%(self._nrows, self._ncols))
6339
6340
self.check_mutability()
6341
6342
if not self._base_ring.is_field():
6343
raise ValueError, "Echelon form not defined over this base ring."
6344
6345
if cutoff == 0:
6346
cutoff = self._strassen_default_echelon_cutoff()
6347
6348
if cutoff < 1:
6349
raise ValueError, "cutoff must be at least 1"
6350
6351
if self._nrows < cutoff or self._ncols < cutoff:
6352
self._echelon_in_place_classical()
6353
return
6354
6355
import strassen
6356
pivots = strassen.strassen_echelon(self.matrix_window(), cutoff)
6357
self._set_pivots(pivots)
6358
verbose('done with strassen', tm)
6359
6360
cpdef matrix_window(self, Py_ssize_t row=0, Py_ssize_t col=0,
6361
Py_ssize_t nrows=-1, Py_ssize_t ncols=-1,
6362
bint check=1):
6363
"""
6364
Return the requested matrix window.
6365
6366
EXAMPLES::
6367
6368
sage: A = matrix(QQ, 3, range(9))
6369
sage: A.matrix_window(1,1, 2, 1)
6370
Matrix window of size 2 x 1 at (1,1):
6371
[0 1 2]
6372
[3 4 5]
6373
[6 7 8]
6374
6375
We test the optional check flag.
6376
6377
::
6378
6379
sage: matrix([1]).matrix_window(0,1,1,1, check=False)
6380
Matrix window of size 1 x 1 at (0,1):
6381
[1]
6382
sage: matrix([1]).matrix_window(0,1,1,1)
6383
Traceback (most recent call last):
6384
...
6385
IndexError: matrix window index out of range
6386
6387
Another test of bounds checking::
6388
6389
sage: matrix([1]).matrix_window(1,1,1,1)
6390
Traceback (most recent call last):
6391
...
6392
IndexError: matrix window index out of range
6393
"""
6394
import matrix_window
6395
if nrows == -1:
6396
nrows = self._nrows - row
6397
if ncols == -1:
6398
ncols = self._ncols - col
6399
if check and (row < 0 or col < 0 or row + nrows > self._nrows or \
6400
col + ncols > self._ncols):
6401
raise IndexError, "matrix window index out of range"
6402
return matrix_window.MatrixWindow(self, row, col, nrows, ncols)
6403
6404
def set_block(self, row, col, block):
6405
"""
6406
Sets the sub-matrix of self, with upper left corner given by row,
6407
col to block.
6408
6409
EXAMPLES::
6410
6411
sage: A = matrix(QQ, 3, 3, range(9))/2
6412
sage: B = matrix(ZZ, 2, 1, [100,200])
6413
sage: A.set_block(0, 1, B)
6414
sage: A
6415
[ 0 100 1]
6416
[3/2 200 5/2]
6417
[ 3 7/2 4]
6418
6419
We test that an exception is raised when the block is out of
6420
bounds::
6421
6422
sage: matrix([1]).set_block(0,1,matrix([1]))
6423
Traceback (most recent call last):
6424
...
6425
IndexError: matrix window index out of range
6426
"""
6427
self.check_mutability()
6428
if block.base_ring() is not self.base_ring():
6429
block = block.change_ring(self.base_ring())
6430
window = self.matrix_window(row, col, block.nrows(), block.ncols(), check=True)
6431
window.set(block.matrix_window())
6432
6433
def subdivide(self, row_lines=None, col_lines=None):
6434
"""
6435
Divides self into logical submatrices which can then be queried and
6436
extracted. If a subdivision already exists, this method forgets the
6437
previous subdivision and flushes the cache.
6438
6439
INPUT:
6440
6441
6442
- ``row_lines`` - None, an integer, or a list of
6443
integers
6444
6445
- ``col_lines`` - None, an integer, or a list of
6446
integers
6447
6448
6449
OUTPUT: changes self
6450
6451
.. note::
6452
6453
One may also pass a tuple into the first argument which
6454
will be interpreted as (row_lines, col_lines)
6455
6456
EXAMPLES::
6457
6458
sage: M = matrix(5, 5, prime_range(100))
6459
sage: M.subdivide(2,3); M
6460
[ 2 3 5| 7 11]
6461
[13 17 19|23 29]
6462
[--------+-----]
6463
[31 37 41|43 47]
6464
[53 59 61|67 71]
6465
[73 79 83|89 97]
6466
sage: M.subdivision(0,0)
6467
[ 2 3 5]
6468
[13 17 19]
6469
sage: M.subdivision(1,0)
6470
[31 37 41]
6471
[53 59 61]
6472
[73 79 83]
6473
sage: M.subdivision_entry(1,0,0,0)
6474
31
6475
sage: M.subdivisions()
6476
([2], [3])
6477
sage: M.subdivide(None, [1,3]); M
6478
[ 2| 3 5| 7 11]
6479
[13|17 19|23 29]
6480
[31|37 41|43 47]
6481
[53|59 61|67 71]
6482
[73|79 83|89 97]
6483
6484
Degenerate cases work too.
6485
6486
::
6487
6488
sage: M.subdivide([2,5], [0,1,3]); M
6489
[| 2| 3 5| 7 11]
6490
[|13|17 19|23 29]
6491
[+--+-----+-----]
6492
[|31|37 41|43 47]
6493
[|53|59 61|67 71]
6494
[|73|79 83|89 97]
6495
[+--+-----+-----]
6496
sage: M.subdivision(0,0)
6497
[]
6498
sage: M.subdivision(0,1)
6499
[ 2]
6500
[13]
6501
sage: M.subdivide([2,2,3], [0,0,1,1]); M
6502
[|| 2|| 3 5 7 11]
6503
[||13||17 19 23 29]
6504
[++--++-----------]
6505
[++--++-----------]
6506
[||31||37 41 43 47]
6507
[++--++-----------]
6508
[||53||59 61 67 71]
6509
[||73||79 83 89 97]
6510
sage: M.subdivision(0,0)
6511
[]
6512
sage: M.subdivision(2,4)
6513
[37 41 43 47]
6514
6515
AUTHORS:
6516
6517
- Robert Bradshaw (2007-06-14)
6518
"""
6519
6520
self.check_mutability()
6521
if col_lines is None and row_lines is not None and isinstance(row_lines, tuple):
6522
tmp = row_lines
6523
row_lines, col_lines = tmp
6524
if row_lines is None:
6525
row_lines = []
6526
elif not isinstance(row_lines, list):
6527
row_lines = [row_lines]
6528
if col_lines is None:
6529
col_lines = []
6530
elif not isinstance(col_lines, list):
6531
col_lines = [col_lines]
6532
row_lines = [0] + [int(ZZ(x)) for x in row_lines] + [self._nrows]
6533
col_lines = [0] + [int(ZZ(x)) for x in col_lines] + [self._ncols]
6534
if self._subdivisions is not None:
6535
self.clear_cache()
6536
self._subdivisions = (row_lines, col_lines)
6537
6538
def subdivision(self, i, j):
6539
"""
6540
Returns an immutable copy of the (i,j)th submatrix of self,
6541
according to a previously set subdivision.
6542
6543
Before a subdivision is set, the only valid arguments are (0,0)
6544
which returns self.
6545
6546
EXAMPLE::
6547
6548
sage: M = matrix(3, 4, range(12))
6549
sage: M.subdivide(1,2); M
6550
[ 0 1| 2 3]
6551
[-----+-----]
6552
[ 4 5| 6 7]
6553
[ 8 9|10 11]
6554
sage: M.subdivision(0,0)
6555
[0 1]
6556
sage: M.subdivision(0,1)
6557
[2 3]
6558
sage: M.subdivision(1,0)
6559
[4 5]
6560
[8 9]
6561
6562
It handles size-zero subdivisions as well.
6563
6564
::
6565
6566
sage: M = matrix(3, 4, range(12))
6567
sage: M.subdivide([0],[0,2,2,4]); M
6568
[+-----++-----+]
6569
[| 0 1|| 2 3|]
6570
[| 4 5|| 6 7|]
6571
[| 8 9||10 11|]
6572
sage: M.subdivision(0,0)
6573
[]
6574
sage: M.subdivision(1,1)
6575
[0 1]
6576
[4 5]
6577
[8 9]
6578
sage: M.subdivision(1,2)
6579
[]
6580
sage: M.subdivision(1,0)
6581
[]
6582
sage: M.subdivision(0,1)
6583
[]
6584
"""
6585
if self._subdivisions is None:
6586
self._subdivisions = ([0, self._nrows], [0, self._ncols])
6587
key = "subdivision %s %s"%(i,j)
6588
sd = self.fetch(key)
6589
if sd is None:
6590
sd = self[self._subdivisions[0][i]:self._subdivisions[0][i+1],
6591
self._subdivisions[1][j]:self._subdivisions[1][j+1]]
6592
sd.set_immutable()
6593
self.cache(key, sd)
6594
return sd
6595
6596
def subdivision_entry(self, i, j, x, y):
6597
"""
6598
Returns the x,y entry of the i,j submatrix of self.
6599
6600
EXAMPLES::
6601
6602
sage: M = matrix(5, 5, range(25))
6603
sage: M.subdivide(3,3); M
6604
[ 0 1 2| 3 4]
6605
[ 5 6 7| 8 9]
6606
[10 11 12|13 14]
6607
[--------+-----]
6608
[15 16 17|18 19]
6609
[20 21 22|23 24]
6610
sage: M.subdivision_entry(0,0,1,2)
6611
7
6612
sage: M.subdivision(0,0)[1,2]
6613
7
6614
sage: M.subdivision_entry(0,1,0,0)
6615
3
6616
sage: M.subdivision_entry(1,0,0,0)
6617
15
6618
sage: M.subdivision_entry(1,1,1,1)
6619
24
6620
6621
Even though this entry exists in the matrix, the index is invalid
6622
for the submatrix.
6623
6624
::
6625
6626
sage: M.subdivision_entry(0,0,4,0)
6627
Traceback (most recent call last):
6628
...
6629
IndexError: Submatrix 0,0 has no entry 4,0
6630
"""
6631
if self._subdivisions is None:
6632
if not i and not j:
6633
return self[x,y]
6634
else:
6635
raise IndexError, "No such submatrix %s, %s"%(i,j)
6636
if x >= self._subdivisions[0][i+1]-self._subdivisions[0][i] or \
6637
y >= self._subdivisions[1][j+1]-self._subdivisions[1][j]:
6638
raise IndexError, "Submatrix %s,%s has no entry %s,%s"%(i,j, x, y)
6639
return self[self._subdivisions[0][i] + x , self._subdivisions[1][j] + y]
6640
6641
def _subdivide_on_augment(self, left, right):
6642
r"""
6643
Helper method to manage subdivisions when augmenting a matrix.
6644
6645
INPUT:
6646
6647
- ``left``, ``right`` - two matrices, such that if ``left`` is
6648
augmented by placing ``right`` on the right side of ``left``,
6649
then the result is ``self``. It is the responsibility of the
6650
calling routine to ensure this condition holds.
6651
6652
OUTPUT:
6653
6654
``None``. A new subdivision is created between ``left`` and
6655
``right`` for ``self``. If possible, row subdivisions are
6656
preserved in ``self``, but if the two sets of row subdivisions
6657
are incompatible, they are removed.
6658
6659
EXAMPLE::
6660
6661
sage: A = matrix(QQ, 3, 4, range(12))
6662
sage: B = matrix(QQ, 3, 6, range(18))
6663
sage: C = A.augment(B)
6664
sage: C._subdivide_on_augment(A, B)
6665
sage: C
6666
[ 0 1 2 3| 0 1 2 3 4 5]
6667
[ 4 5 6 7| 6 7 8 9 10 11]
6668
[ 8 9 10 11|12 13 14 15 16 17]
6669
6670
More descriptive, but indirect, doctests are at
6671
:meth:`sage.matrix.matrix1.Matrix.augment`.
6672
"""
6673
left_rows, left_cols = left.subdivisions()
6674
right_rows, right_cols = right.subdivisions()
6675
if left_rows == right_rows:
6676
self_rows = left_rows
6677
else:
6678
self_rows = None
6679
nc = left.ncols()
6680
self_cols = left_cols + [nc]
6681
for col in right_cols:
6682
self_cols.append(col+nc)
6683
self.subdivide(self_rows, self_cols)
6684
return None
6685
6686
def _subdivide_on_stack(self, top, bottom):
6687
r"""
6688
Helper method to manage subdivisions when stacking a matrix.
6689
6690
INPUT:
6691
6692
- ``top``, ``bottom`` - two matrices, such that if ``top`` is
6693
stacked by placing ``top`` above ``bottom``, then the result
6694
is ``self``. It is the responsibility of the calling routine
6695
to ensure this condition holds.
6696
6697
OUTPUT:
6698
6699
``None``. A new subdivision is created between ``top`` and
6700
``bottom`` for ``self``. If possible, column subdivisions are
6701
preserved in ``self``, but if the two sets of solumn subdivisions
6702
are incompatible, they are removed.
6703
6704
EXAMPLE::
6705
6706
sage: A = matrix(QQ, 3, 2, range(6))
6707
sage: B = matrix(QQ, 4, 2, range(8))
6708
sage: C = A.stack(B)
6709
sage: C._subdivide_on_stack(A, B)
6710
sage: C
6711
[0 1]
6712
[2 3]
6713
[4 5]
6714
[---]
6715
[0 1]
6716
[2 3]
6717
[4 5]
6718
[6 7]
6719
6720
More descriptive, but indirect, doctests are at
6721
:meth:`sage.matrix.matrix1.Matrix.augment`.
6722
"""
6723
top_rows, top_cols = top.subdivisions()
6724
bottom_rows, bottom_cols = bottom.subdivisions()
6725
if top_cols == bottom_cols:
6726
self_cols = top_cols
6727
else:
6728
self_cols = None
6729
nr = top.nrows()
6730
self_rows = top_rows + [nr]
6731
for row in bottom_rows:
6732
self_rows.append(row+nr)
6733
self.subdivide(self_rows, self_cols)
6734
return None
6735
6736
def subdivisions(self):
6737
"""
6738
Returns the current subdivision of self.
6739
6740
EXAMPLES::
6741
6742
sage: M = matrix(5, 5, range(25))
6743
sage: M.subdivisions()
6744
([], [])
6745
sage: M.subdivide(2,3)
6746
sage: M.subdivisions()
6747
([2], [3])
6748
sage: N = M.parent()(1)
6749
sage: N.subdivide(M.subdivisions()); N
6750
[1 0 0|0 0]
6751
[0 1 0|0 0]
6752
[-----+---]
6753
[0 0 1|0 0]
6754
[0 0 0|1 0]
6755
[0 0 0|0 1]
6756
"""
6757
if self._subdivisions is None:
6758
return ([], [])
6759
else:
6760
return (self._subdivisions[0][1:-1], self._subdivisions[1][1:-1])
6761
6762
# 'get_subdivisions' is kept for backwards compatibility: see #4983.
6763
get_subdivisions = subdivisions
6764
6765
def tensor_product(self, A, subdivide=True):
6766
r"""
6767
Returns the tensor product of two matrices.
6768
6769
INPUT:
6770
6771
- ``A`` - a matrix
6772
- ``subdivide`` - default: True - whether or not to return
6773
natural subdivisions with the matrix
6774
6775
OUTPUT:
6776
6777
Replace each element of ``self`` by a copy of ``A``, but first
6778
create a scalar multiple of ``A`` by the element it replaces.
6779
So if ``self`` is an `m\times n` matrix and ``A`` is a
6780
`p\times q` matrix, then the tensor product is an `mp\times nq`
6781
matrix. By default, the matrix will be subdivided into
6782
submatrices of size `p\times q`.
6783
6784
EXAMPLES::
6785
6786
sage: M1=Matrix(QQ,[[-1,0],[-1/2,-1]])
6787
sage: M2=Matrix(ZZ,[[1,-1,2],[-2,4,8]])
6788
sage: M1.tensor_product(M2)
6789
[ -1 1 -2| 0 0 0]
6790
[ 2 -4 -8| 0 0 0]
6791
[--------------+--------------]
6792
[-1/2 1/2 -1| -1 1 -2]
6793
[ 1 -2 -4| 2 -4 -8]
6794
sage: M2.tensor_product(M1)
6795
[ -1 0| 1 0| -2 0]
6796
[-1/2 -1| 1/2 1| -1 -2]
6797
[---------+---------+---------]
6798
[ 2 0| -4 0| -8 0]
6799
[ 1 2| -2 -4| -4 -8]
6800
6801
Subdivisions can be optionally suppressed. ::
6802
6803
sage: M1.tensor_product(M2, subdivide=False)
6804
[ -1 1 -2 0 0 0]
6805
[ 2 -4 -8 0 0 0]
6806
[-1/2 1/2 -1 -1 1 -2]
6807
[ 1 -2 -4 2 -4 -8]
6808
6809
Different base rings are handled sensibly. ::
6810
6811
sage: A = matrix(ZZ, 2, 3, range(6))
6812
sage: B = matrix(FiniteField(23), 3, 4, range(12))
6813
sage: C = matrix(FiniteField(29), 4, 5, range(20))
6814
sage: D = A.tensor_product(B)
6815
sage: D.parent()
6816
Full MatrixSpace of 6 by 12 dense matrices over Finite Field of size 23
6817
sage: E = C.tensor_product(B)
6818
Traceback (most recent call last):
6819
...
6820
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'
6821
6822
The input is checked to be sure it is a matrix. ::
6823
6824
sage: A = matrix(QQ, 2, range(4))
6825
sage: A.tensor_product('junk')
6826
Traceback (most recent call last):
6827
...
6828
TypeError: tensor product requires a second matrix, not junk
6829
"""
6830
if not isinstance(A, Matrix):
6831
raise TypeError('tensor product requires a second matrix, not {0}'.format(A))
6832
return sage.matrix.constructor.block_matrix(self.nrows(),self.ncols(),[x*A for x in self.list()], subdivide=subdivide)
6833
6834
def randomize(self, density=1, nonzero=False, *args, **kwds):
6835
"""
6836
Randomize density proportion of the entries of this matrix, leaving
6837
the rest unchanged.
6838
6839
.. note::
6840
6841
We actually choose at random ``density`` proportion of entries of
6842
the matrix and set them to random elements. It's possible that the
6843
same position can be chosen multiple times, especially for a very
6844
small matrix.
6845
6846
INPUT:
6847
6848
- ``density`` - ``float`` (default: 1); rough measure of the
6849
proportion of nonzero entries in the random matrix
6850
- ``nonzero`` - Bool (default: ``False``); whether the new entries
6851
have to be non-zero
6852
- ``*args, **kwds`` - Remaining parameters may be passed to the
6853
``random_element`` function of the base ring
6854
6855
EXAMPLES:
6856
6857
We construct the zero matrix over a polynomial ring.
6858
6859
::
6860
6861
sage: a = matrix(QQ['x'], 3); a
6862
[0 0 0]
6863
[0 0 0]
6864
[0 0 0]
6865
6866
We then randomize roughly half the entries::
6867
6868
sage: a.randomize(0.5)
6869
sage: a
6870
[ 1/2*x^2 - x - 12 1/2*x^2 - 1/95*x - 1/2 0]
6871
[-5/2*x^2 + 2/3*x - 1/4 0 0]
6872
[ -x^2 + 2/3*x 0 0]
6873
6874
Now we randomize all the entries of the resulting matrix::
6875
6876
sage: a.randomize()
6877
sage: a
6878
[ 1/3*x^2 - x + 1 -x^2 + 1 x^2 - x]
6879
[ -1/14*x^2 - x - 1/4 -4*x - 1/5 -1/4*x^2 - 1/2*x + 4]
6880
[ 1/9*x^2 + 5/2*x - 3 -x^2 + 3/2*x + 1 -2/7*x^2 - x - 1/2]
6881
6882
We create the zero matrix over the integers::
6883
6884
sage: a = matrix(ZZ, 2); a
6885
[0 0]
6886
[0 0]
6887
6888
Then we randomize it; the x and y parameters, which determine the
6889
size of the random elements, are passed onto the ZZ random_element
6890
method.
6891
6892
::
6893
6894
sage: a.randomize(x=-2^64, y=2^64)
6895
sage: a
6896
[-12401200298100116246 1709403521783430739]
6897
[ -4417091203680573707 17094769731745295000]
6898
"""
6899
randint = current_randstate().python_random().randint
6900
6901
density = float(density)
6902
if density <= 0:
6903
return
6904
if density > 1:
6905
density = 1
6906
6907
self.check_mutability()
6908
self.clear_cache()
6909
6910
R = self.base_ring()
6911
6912
cdef Py_ssize_t i, j, num
6913
6914
if nonzero:
6915
if density >= 1:
6916
for i from 0 <= i < self._nrows:
6917
for j from 0 <= j < self._ncols:
6918
self.set_unsafe(i, j, R._random_nonzero_element(*args,\
6919
**kwds))
6920
else:
6921
num = int(self._nrows * self._ncols * density)
6922
for i from 0 <= i < num:
6923
self.set_unsafe(randint(0, self._nrows - 1),
6924
randint(0, self._ncols - 1),
6925
R._random_nonzero_element(*args, **kwds))
6926
else:
6927
if density >= 1:
6928
for i from 0 <= i < self._nrows:
6929
for j from 0 <= j < self._ncols:
6930
self.set_unsafe(i, j, R.random_element(*args, **kwds))
6931
else:
6932
num = int(self._nrows * self._ncols * density)
6933
for i from 0 <= i < num:
6934
self.set_unsafe(randint(0, self._nrows - 1),
6935
randint(0, self._ncols - 1),
6936
R.random_element(*args, **kwds))
6937
6938
def is_one(self):
6939
"""
6940
Return True if this matrix is the identity matrix.
6941
6942
EXAMPLES::
6943
6944
sage: m = matrix(QQ,2,range(4))
6945
sage: m.is_one()
6946
False
6947
sage: m = matrix(QQ,2,[5,0,0,5])
6948
sage: m.is_one()
6949
False
6950
sage: m = matrix(QQ,2,[1,0,0,1])
6951
sage: m.is_one()
6952
True
6953
sage: m = matrix(QQ,2,[1,1,1,1])
6954
sage: m.is_one()
6955
False
6956
"""
6957
return self.is_scalar(1)
6958
6959
def is_scalar(self, a = None):
6960
"""
6961
Return True if this matrix is a scalar matrix.
6962
6963
INPUT
6964
6965
- base_ring element a, which is chosen as self[0][0] if
6966
a = None
6967
6968
OUTPUT
6969
6970
- whether self is a scalar matrix (in fact the scalar matrix
6971
aI if a is input)
6972
6973
EXAMPLES::
6974
6975
sage: m = matrix(QQ,2,range(4))
6976
sage: m.is_scalar(5)
6977
False
6978
sage: m = matrix(QQ,2,[5,0,0,5])
6979
sage: m.is_scalar(5)
6980
True
6981
sage: m = matrix(QQ,2,[1,0,0,1])
6982
sage: m.is_scalar(1)
6983
True
6984
sage: m = matrix(QQ,2,[1,1,1,1])
6985
sage: m.is_scalar(1)
6986
False
6987
"""
6988
if not self.is_square():
6989
return False
6990
cdef Py_ssize_t i, j
6991
if a is None:
6992
if self._nrows == 0:
6993
return True
6994
a = self.get_unsafe(0,0)
6995
else:
6996
a = self.base_ring()(a)
6997
zero = self.base_ring()(0)
6998
for i from 0 <= i < self._nrows:
6999
for j from 0 <= j < self._ncols:
7000
if i != j:
7001
if self.get_unsafe(i,j) != zero:
7002
return False
7003
else:
7004
if self.get_unsafe(i, i) != a:
7005
return False
7006
return True
7007
7008
7009
def is_unitary(self):
7010
r"""
7011
Returns ``True`` if the columns of the matrix are an orthonormal basis.
7012
7013
For a matrix with real entries this determines if a matrix is
7014
"orthogonal" and for a matrix with complex entries this determines
7015
if the matrix is "unitary."
7016
7017
OUTPUT:
7018
7019
``True`` if the matrix is square and its conjugate-transpose is
7020
its inverse, and ``False`` otherwise. In other words, a matrix
7021
is orthogonal or unitary if the product of its conjugate-transpose
7022
times the matrix is the identity matrix.
7023
7024
For numerical matrices a specialized routine available
7025
over ``RDF`` and ``CDF`` is a good choice.
7026
7027
EXAMPLES::
7028
7029
sage: A = matrix(QQbar, [[(1/sqrt(5))*(1+i), (1/sqrt(55))*(3+2*I), (1/sqrt(22))*(2+2*I)],
7030
... [(1/sqrt(5))*(1-i), (1/sqrt(55))*(2+2*I), (1/sqrt(22))*(-3+I)],
7031
... [ (1/sqrt(5))*I, (1/sqrt(55))*(3-5*I), (1/sqrt(22))*(-2)]])
7032
sage: A.is_unitary()
7033
True
7034
7035
A permutation matrix is always orthogonal. ::
7036
7037
sage: sigma = Permutation([1,3,4,5,2])
7038
sage: P = sigma.to_matrix(); P
7039
[1 0 0 0 0]
7040
[0 0 0 0 1]
7041
[0 1 0 0 0]
7042
[0 0 1 0 0]
7043
[0 0 0 1 0]
7044
sage: P.is_unitary()
7045
True
7046
7047
A square matrix far from unitary. ::
7048
7049
sage: A = matrix(QQ, 4, range(16))
7050
sage: A.is_unitary()
7051
False
7052
7053
Rectangular matrices are never unitary. ::
7054
7055
sage: A = matrix(QQbar, 3, 4)
7056
sage: A.is_unitary()
7057
False
7058
"""
7059
import sage.matrix.constructor
7060
if not self.is_square():
7061
return False
7062
P = self.conjugate().transpose()*self
7063
return P.is_scalar(1)
7064
7065
def is_bistochastic(self, normalized = True):
7066
r"""
7067
Returns ``True`` if this matrix is bistochastic.
7068
7069
A matrix is said to be bistochastic if both the sums of the
7070
entries of each row and the sum of the entries of each column
7071
are equal to 1.
7072
7073
INPUT:
7074
7075
- ``normalized`` -- if set to ``True`` (default), checks that
7076
the sums are equal to 1. When set to ``False``, checks that
7077
the row sums and column sums are all equal to some constant
7078
possibly different from 1.
7079
7080
EXAMPLES:
7081
7082
The identity matrix is clearly bistochastic::
7083
7084
sage: Matrix(5,5,1).is_bistochastic()
7085
True
7086
7087
The same matrix, multiplied by 2, is not bistochastic anymore,
7088
though is verifies the constraints of ``normalized == False``::
7089
7090
sage: (2 * Matrix(5,5,1)).is_bistochastic()
7091
False
7092
sage: (2 * Matrix(5,5,1)).is_bistochastic(normalized = False)
7093
True
7094
"""
7095
7096
row_sums = map(sum, self.rows())
7097
col_sums = map(sum, self.columns())
7098
7099
return self.is_square() and\
7100
col_sums[0] == row_sums[0] and\
7101
row_sums == col_sums and\
7102
row_sums == len(row_sums) * [col_sums[0]] and\
7103
((not normalized) or col_sums[0] == self.base_ring()(1))
7104
7105
def is_normal(self):
7106
r"""
7107
Returns ``True`` if the matrix commutes with its conjugate-transpose.
7108
7109
OUTPUT:
7110
7111
``True`` if the matrix is square and commutes with its
7112
conjugate-transpose, and ``False`` otherwise.
7113
7114
Normal matrices are precisely those that can be diagonalized
7115
by a unitary matrix.
7116
7117
This routine is for matrices over exact rings and so may not
7118
work properly for matrices over ``RR`` or ``CC``. For matrices with
7119
approximate entries, the rings of double-precision floating-point
7120
numbers, ``RDF`` and ``CDF``, are a better choice since the
7121
:meth:`sage.matrix.matrix_double_dense.Matrix_double_dense.is_normal`
7122
method has a tolerance parameter. This provides control over
7123
allowing for minor discrepancies between entries when checking
7124
equality.
7125
7126
The result is cached.
7127
7128
EXAMPLES:
7129
7130
Hermitian matrices are normal. ::
7131
7132
sage: A = matrix(QQ, 5, range(25)) + I*matrix(QQ, 5, range(0, 50, 2))
7133
sage: B = A*A.conjugate_transpose()
7134
sage: B.is_hermitian()
7135
True
7136
sage: B.is_normal()
7137
True
7138
7139
Circulant matrices are normal. ::
7140
7141
sage: G = graphs.CirculantGraph(20, [3, 7])
7142
sage: D = digraphs.Circuit(20)
7143
sage: A = 3*D.adjacency_matrix() - 5*G.adjacency_matrix()
7144
sage: A.is_normal()
7145
True
7146
7147
Skew-symmetric matrices are normal. ::
7148
7149
sage: A = matrix(QQ, 5, range(25))
7150
sage: B = A - A.transpose()
7151
sage: B.is_skew_symmetric()
7152
True
7153
sage: B.is_normal()
7154
True
7155
7156
A small matrix that does not fit into any of the usual categories
7157
of normal matrices. ::
7158
7159
sage: A = matrix(ZZ, [[1, -1],
7160
... [1, 1]])
7161
sage: A.is_normal()
7162
True
7163
sage: not A.is_hermitian() and not A.is_skew_symmetric()
7164
True
7165
7166
Sage has several fields besides the entire complex numbers
7167
where conjugation is non-trivial. ::
7168
7169
sage: F.<b> = QuadraticField(-7)
7170
sage: C = matrix(F, [[-2*b - 3, 7*b - 6, -b + 3],
7171
... [-2*b - 3, -3*b + 2, -2*b],
7172
... [ b + 1, 0, -2]])
7173
sage: C = C*C.conjugate_transpose()
7174
sage: C.is_normal()
7175
True
7176
7177
A matrix that is nearly normal, but for a non-real
7178
diagonal entry. ::
7179
7180
sage: A = matrix(QQbar, [[ 2, 2-I, 1+4*I],
7181
... [ 2+I, 3+I, 2-6*I],
7182
... [1-4*I, 2+6*I, 5]])
7183
sage: A.is_normal()
7184
False
7185
sage: A[1,1] = 132
7186
sage: A.is_normal()
7187
True
7188
7189
Rectangular matrices are never normal. ::
7190
7191
sage: A = matrix(QQbar, 3, 4)
7192
sage: A.is_normal()
7193
False
7194
7195
A square, empty matrix is trivially normal. ::
7196
7197
sage: A = matrix(QQ, 0, 0)
7198
sage: A.is_normal()
7199
True
7200
7201
AUTHOR:
7202
7203
- Rob Beezer (2011-03-31)
7204
"""
7205
key = 'normal'
7206
n = self.fetch(key)
7207
if not n is None:
7208
return n
7209
if not self.is_square():
7210
self.cache(key, False)
7211
return False
7212
if self._nrows == 0:
7213
self.cache(key, True)
7214
return True
7215
7216
CT = self.conjugate_transpose()
7217
cdef Matrix left = self*CT
7218
cdef Matrix right = CT*self
7219
7220
cdef Py_ssize_t i,j
7221
normal = True
7222
# two products are Hermitian, need only check lower triangle
7223
for i from 0 <= i < self._nrows:
7224
for j from 0 <= j <= i:
7225
if left.get_unsafe(i,j) != right.get_unsafe(i,j):
7226
normal = False
7227
break
7228
if not normal:
7229
break
7230
self.cache(key, normal)
7231
return normal
7232
7233
def as_sum_of_permutations(self):
7234
r"""
7235
Returns the current matrix as a sum of permutation matrices
7236
7237
According to the Birkhoff-von Neumann Theorem, any bistochastic matrix
7238
can be written as a positive sum of permutation matrices, which also
7239
means that the polytope of bistochastic matrices is integer.
7240
7241
As a non-bistochastic matrix can obviously not be written as a sum of
7242
permutations, this theorem is an equivalence.
7243
7244
This function, given a bistochastic matrix, returns the corresponding
7245
decomposition.
7246
7247
.. SEEALSO:
7248
7249
- :meth:`bistochastic_as_sum_of_permutations <sage.combinat.permutation.bistochastic_as_sum_of_permutations>`
7250
-- for more information on this method.
7251
7252
EXAMPLE:
7253
7254
We create a bistochastic matrix from a convex sum of permutations, then
7255
try to deduce the decomposition from the matrix ::
7256
7257
sage: L = []
7258
sage: L.append((9,Permutation([4, 1, 3, 5, 2])))
7259
sage: L.append((6,Permutation([5, 3, 4, 1, 2])))
7260
sage: L.append((3,Permutation([3, 1, 4, 2, 5])))
7261
sage: L.append((2,Permutation([1, 4, 2, 3, 5])))
7262
sage: M = sum([c * p.to_matrix() for (c,p) in L])
7263
sage: decomp = sage.combinat.permutation.bistochastic_as_sum_of_permutations(M)
7264
sage: print decomp
7265
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]]
7266
7267
An exception is raised when the matrix is not bistochastic::
7268
7269
sage: M = Matrix([[2,3],[2,2]])
7270
sage: decomp = sage.combinat.permutation.bistochastic_as_sum_of_permutations(M)
7271
Traceback (most recent call last):
7272
...
7273
ValueError: The matrix is not bistochastic
7274
"""
7275
7276
from sage.combinat.permutation import bistochastic_as_sum_of_permutations
7277
return bistochastic_as_sum_of_permutations(self)
7278
7279
7280
def visualize_structure(self, filename=None, maxsize=512):
7281
"""
7282
Write a PNG image to 'filename' which visualizes self by putting
7283
black pixels in those positions which have nonzero entries.
7284
7285
White pixels are put at positions with zero entries. If 'maxsize'
7286
is given, then the maximal dimension in either x or y direction is
7287
set to 'maxsize' depending on which is bigger. If the image is
7288
scaled, the darkness of the pixel reflects how many of the
7289
represented entries are nonzero. So if e.g. one image pixel
7290
actually represents a 2x2 submatrix, the dot is darker the more of
7291
the four values are nonzero.
7292
7293
INPUT:
7294
7295
7296
- ``filename`` - either a path or None in which case a
7297
filename in the current directory is chosen automatically
7298
(default:None)
7299
7300
7301
maxsize - maximal dimension in either x or y direction of the
7302
resulting image. If None or a maxsize larger than
7303
max(self.nrows(),self.ncols()) is given the image will have the
7304
same pixelsize as the matrix dimensions (default: 512)
7305
7306
EXAMPLE::
7307
7308
sage: M = random_matrix(CC, 4)
7309
sage: M.visualize_structure(SAGE_TMP + "matrix.png")
7310
"""
7311
import gd
7312
import os
7313
7314
cdef int x, y, _x, _y, v, bi, bisq
7315
cdef int ir,ic
7316
cdef float b, fct
7317
7318
mr, mc = self.nrows(), self.ncols()
7319
7320
if maxsize is None:
7321
7322
ir = mc
7323
ic = mr
7324
b = 1.0
7325
7326
elif max(mr,mc) > maxsize:
7327
7328
maxsize = float(maxsize)
7329
ir = int(mc * maxsize/max(mr,mc))
7330
ic = int(mr * maxsize/max(mr,mc))
7331
b = max(mr,mc)/maxsize
7332
7333
else:
7334
7335
ir = mc
7336
ic = mr
7337
b = 1.0
7338
7339
bi = round(b)
7340
bisq = bi*bi
7341
fct = 255.0/bisq
7342
7343
im = gd.image((ir,ic),1)
7344
white = im.colorExact((255,255,255))
7345
im.fill((0,0),white)
7346
7347
# these speed things up a bit
7348
colorExact = im.colorExact
7349
setPixel = im.setPixel
7350
7351
for x from 0 <= x < ic:
7352
for y from 0 <= y < ir:
7353
v = bisq
7354
for _x from 0 <= _x < bi:
7355
for _y from 0 <= _y < bi:
7356
if not self.get_unsafe(<int>(x*b + _x), <int>(y*b + _y)).is_zero():
7357
v-=1 #increase darkness
7358
7359
v = round(v*fct)
7360
val = colorExact((v,v,v))
7361
setPixel((y,x), val)
7362
7363
if filename is None:
7364
filename = graphics_filename()
7365
7366
im.writePng(filename)
7367
7368
def density(self):
7369
"""
7370
Return the density of the matrix.
7371
7372
By density we understand the ratio of the number of nonzero
7373
positions and the self.nrows() \* self.ncols(), i.e. the number of
7374
possible nonzero positions.
7375
7376
EXAMPLE:
7377
7378
First, note that the density parameter does not ensure the density
7379
of a matrix, it is only an upper bound.
7380
7381
::
7382
7383
sage: A = random_matrix(GF(127),200,200,density=0.3)
7384
sage: A.density()
7385
5211/20000
7386
7387
::
7388
7389
sage: A = matrix(QQ,3,3,[0,1,2,3,0,0,6,7,8])
7390
sage: A.density()
7391
2/3
7392
7393
::
7394
7395
sage: a = matrix([[],[],[],[]])
7396
sage: a.density()
7397
0
7398
"""
7399
cdef int x,y,k
7400
k = 0
7401
nr = self.nrows()
7402
nc = self.ncols()
7403
if nc == 0 or nr == 0:
7404
return 0
7405
for x from 0 <= x < nr:
7406
for y from 0 <= y < nc:
7407
if not self.get_unsafe(x,y).is_zero():
7408
k+=1
7409
return QQ(k)/QQ(nr*nc)
7410
7411
7412
def inverse(self):
7413
"""
7414
Returns the inverse of self, without changing self.
7415
7416
Note that one can use the Python inverse operator to obtain the
7417
inverse as well.
7418
7419
EXAMPLES::
7420
7421
sage: m = matrix([[1,2],[3,4]])
7422
sage: m^(-1)
7423
[ -2 1]
7424
[ 3/2 -1/2]
7425
sage: m.inverse()
7426
[ -2 1]
7427
[ 3/2 -1/2]
7428
sage: ~m
7429
[ -2 1]
7430
[ 3/2 -1/2]
7431
7432
::
7433
7434
sage: m = matrix([[1,2],[3,4]], sparse=True)
7435
sage: m^(-1)
7436
[ -2 1]
7437
[ 3/2 -1/2]
7438
sage: m.inverse()
7439
[ -2 1]
7440
[ 3/2 -1/2]
7441
sage: ~m
7442
[ -2 1]
7443
[ 3/2 -1/2]
7444
sage: m.I
7445
[ -2 1]
7446
[ 3/2 -1/2]
7447
7448
TESTS::
7449
7450
sage: matrix().inverse()
7451
[]
7452
"""
7453
return self.__invert__()
7454
7455
def adjoint(self):
7456
"""
7457
Returns the adjoint matrix of self (matrix of cofactors).
7458
7459
OUTPUT:
7460
7461
- ``N`` - the adjoint matrix, such that
7462
N \* M = M \* N = M.parent(M.det())
7463
7464
ALGORITHM:
7465
7466
Use PARI whenever the method ``self._adjoint`` is included to do so
7467
in an inheriting class. Otherwise, use a generic division-free
7468
algorithm to compute the characteristic polynomial and hence the
7469
adjoint.
7470
7471
The result is cached.
7472
7473
EXAMPLES::
7474
7475
sage: M = Matrix(ZZ,2,2,[5,2,3,4]) ; M
7476
[5 2]
7477
[3 4]
7478
sage: N = M.adjoint() ; N
7479
[ 4 -2]
7480
[-3 5]
7481
sage: M * N
7482
[14 0]
7483
[ 0 14]
7484
sage: N * M
7485
[14 0]
7486
[ 0 14]
7487
sage: M = Matrix(QQ,2,2,[5/3,2/56,33/13,41/10]) ; M
7488
[ 5/3 1/28]
7489
[33/13 41/10]
7490
sage: N = M.adjoint() ; N
7491
[ 41/10 -1/28]
7492
[-33/13 5/3]
7493
sage: M * N
7494
[7363/1092 0]
7495
[ 0 7363/1092]
7496
7497
AUTHORS:
7498
7499
- Unknown: No author specified in the file from 2009-06-25
7500
- Sebastian Pancratz (2009-06-25): Reflecting the change that
7501
``_adjoint`` is now implemented in this class
7502
"""
7503
7504
if self._nrows != self._ncols:
7505
raise ValueError, "self must be a square matrix"
7506
7507
X = self.fetch('adjoint')
7508
if not X is None:
7509
return X
7510
7511
X = self._adjoint()
7512
self.cache('adjoint', X)
7513
return X
7514
7515
def _adjoint(self):
7516
r"""
7517
Returns the adjoint of self.
7518
7519
OUTPUT:
7520
7521
- matrix - the adjoint of self
7522
7523
EXAMPLES:
7524
7525
Here is one example to illustrate this::
7526
7527
sage: A = matrix(ZZ, [[1,24],[3,5]])
7528
sage: A
7529
[ 1 24]
7530
[ 3 5]
7531
sage: A._adjoint()
7532
[ 5 -24]
7533
[ -3 1]
7534
7535
Secondly, here is an example over a polynomial ring::
7536
7537
sage: R.<t> = QQ[]
7538
sage: A = matrix(R, [[-2*t^2 + t + 3/2, 7*t^2 + 1/2*t - 1, \
7539
-6*t^2 + t - 2/11], \
7540
[-7/3*t^2 - 1/2*t - 1/15, -2*t^2 + 19/8*t, \
7541
-10*t^2 + 2*t + 1/2], \
7542
[6*t^2 - 1/2, -1/7*t^2 + 9/4*t, -t^2 - 4*t \
7543
- 1/10]])
7544
sage: A
7545
[ -2*t^2 + t + 3/2 7*t^2 + 1/2*t - 1 -6*t^2 + t - 2/11]
7546
[-7/3*t^2 - 1/2*t - 1/15 -2*t^2 + 19/8*t -10*t^2 + 2*t + 1/2]
7547
[ 6*t^2 - 1/2 -1/7*t^2 + 9/4*t -t^2 - 4*t - 1/10]
7548
sage: A._adjoint()
7549
[ 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]
7550
[ -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]
7551
[ 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]
7552
7553
Finally, an example over a general ring, that is to say, as of
7554
version 4.0.2, SAGE does not even determine that ``S`` in the following
7555
example is an integral domain::
7556
7557
sage: R.<a,b> = QQ[]
7558
sage: S.<x,y> = R.quo((b^3))
7559
sage: A = matrix(S, [[x*y^2,2*x],[2,x^10*y]])
7560
sage: A
7561
[ x*y^2 2*x]
7562
[ 2 x^10*y]
7563
sage: A.det()
7564
-4*x
7565
sage: A.charpoly('T')
7566
T^2 + (-x^10*y - x*y^2)*T - 4*x
7567
sage: A.adjoint()
7568
[x^10*y -2*x]
7569
[ -2 x*y^2]
7570
sage: A.adjoint() * A
7571
[-4*x 0]
7572
[ 0 -4*x]
7573
7574
TESTS::
7575
7576
sage: A = matrix(ZZ, 0, 0)
7577
sage: A
7578
[]
7579
sage: A._adjoint()
7580
[]
7581
sage: A = matrix(ZZ, [[2]])
7582
sage: A
7583
[2]
7584
sage: A._adjoint()
7585
[1]
7586
7587
NOTES:
7588
7589
The key feature of this implementation is that it is division-free.
7590
This means that it can be used as a generic implementation for any
7591
ring (commutative and with multiplicative identity). The algorithm
7592
is described in full detail as Algorithm 3.1 in [Se02].
7593
7594
Note that this method does not utilise a lookup if the adjoint has
7595
already been computed previously, and it does not cache the result.
7596
This is all left to the method `adjoint`.
7597
7598
REFERENCES:
7599
7600
- [Se02] T. R. Seifullin, "Computation of determinants, adjoint
7601
matrices, and characteristic polynomials without division"
7602
7603
AUTHORS:
7604
7605
- Sebastian Pancratz (2009-06-12): Initial version
7606
"""
7607
7608
# Validate assertions
7609
#
7610
if self._nrows != self._ncols:
7611
raise ValueError("self must be a square matrix")
7612
7613
# Corner cases
7614
# N.B. We already tested for the matrix to be square, hence we do not
7615
# need to test for 0 x n or m x 0 matrices.
7616
#
7617
if self._ncols == 0:
7618
return self.copy()
7619
7620
# Extract parameters
7621
#
7622
n = self._ncols
7623
R = self._base_ring
7624
MS = self._parent
7625
7626
f = self.charpoly()
7627
7628
# Let A denote the adjoint of M, which we want to compute, and
7629
# N denote a copy of M used to store powers of M.
7630
#
7631
A = f[1] * MS.identity_matrix()
7632
N = R(1) * MS.identity_matrix()
7633
for i in range(1, n):
7634
# Set N to be M^i
7635
#
7636
N = N * self
7637
A = A + f[i+1] * N
7638
if not (n % 2):
7639
A = - A
7640
7641
return A
7642
7643
def QR(self, full=True):
7644
r"""
7645
Returns a factorization of ``self`` as a unitary matrix
7646
and an upper-triangular matrix.
7647
7648
INPUT:
7649
7650
- ``full`` - default: ``True`` - if ``True`` then the
7651
returned matrices have dimensions as described below.
7652
If ``False`` the ``R`` matrix has no zero rows and the
7653
columns of ``Q`` are a basis for the column space of
7654
``self``.
7655
7656
OUTPUT:
7657
7658
If ``self`` is an `m\times n` matrix and ``full=True`` then this
7659
method returns a pair of matrices: `Q` is an `m\times m` unitary
7660
matrix (meaning its inverse is its conjugate-transpose) and `R`
7661
is an `m\times n` upper-triangular matrix with non-negative entries
7662
on the diagonal. For a matrix of full rank this factorization is
7663
unique (due to the restriction to positive entries on the diagonal).
7664
7665
If ``full=False`` then `Q` has `m` rows and the columns form an
7666
orthonormal basis for the column space of ``self``. So, in particular,
7667
the conjugate-transpose of `Q` times `Q` will be an identity matrix.
7668
The matrix `R` will still be upper-triangular but will also have full
7669
rank, in particular it will lack the zero rows present in a full
7670
factorization of a rank-deficient matrix.
7671
7672
The results obtained when ``full=True`` are cached,
7673
hence `Q` and `R` are immutable matrices in this case.
7674
7675
.. note::
7676
7677
This is an exact computation, so limited to exact rings.
7678
Also the base ring needs to have a fraction field implemented
7679
in Sage and this field must contain square roots. One example
7680
is the field of algebraic numbers, ``QQbar``, as used in the
7681
examples below. If you need numerical results, convert the
7682
base ring to the field of complex double numbers, ``CDF``,
7683
which will use a faster routine that is careful about
7684
numerical subtleties.
7685
7686
ALGORITHM:
7687
7688
"Modified Gram-Schmidt," Algorithm 8.1 of [TREFETHEN-BAU]_.
7689
7690
EXAMPLES:
7691
7692
For a nonsingular matrix, the QR decomposition is unique. ::
7693
7694
sage: A = matrix(QQbar, [[-2, 0, -4, -1, -1],
7695
... [-2, 1, -6, -3, -1],
7696
... [1, 1, 7, 4, 5],
7697
... [3, 0, 8, 3, 3],
7698
... [-1, 1, -6, -6, 5]])
7699
sage: Q, R = A.QR()
7700
sage: Q
7701
[ -0.4588314677411235? -0.1260506983326509? 0.3812120831224489? -0.394573711338418? -0.687440062597?]
7702
[ -0.4588314677411235? 0.4726901187474409? -0.05198346588033394? 0.717294125164660? -0.220962877263?]
7703
[ 0.2294157338705618? 0.6617661662464172? 0.6619227988762521? -0.180872093737548? 0.1964114464561?]
7704
[ 0.6882472016116853? 0.1890760474989764? -0.2044682991293135? 0.096630296654307? -0.662888631790?]
7705
[ -0.2294157338705618? 0.5357154679137663? -0.609939332995919? -0.536422031427112? 0.0245514308070?]
7706
sage: R
7707
[ 4.358898943540674? -0.4588314677411235? 13.07669683062202? 6.194224814505168? 2.982404540317303?]
7708
[ 0 1.670171752907625? 0.5987408170800917? -1.292019657909672? 6.207996892883057?]
7709
[ 0 0 5.444401659866974? 5.468660610611130? -0.682716185228386?]
7710
[ 0 0 0 1.027626039419836? -3.61930014968662?]
7711
[ 0 0 0 0 0.02455143080702?]
7712
sage: Q.conjugate_transpose()*Q
7713
[1.000000000000000? 0.?e-18 0.?e-17 0.?e-15 0.?e-12]
7714
[ 0.?e-18 1.000000000000000? 0.?e-16 0.?e-15 0.?e-12]
7715
[ 0.?e-17 0.?e-16 1.000000000000000? 0.?e-15 0.?e-12]
7716
[ 0.?e-15 0.?e-15 0.?e-15 1.000000000000000? 0.?e-12]
7717
[ 0.?e-12 0.?e-12 0.?e-12 0.?e-12 1.000000000000?]
7718
sage: Q*R == A
7719
True
7720
7721
7722
An example with complex numbers in ``QQbar``, the field of algebraic
7723
numbers. ::
7724
7725
sage: A = matrix(QQbar, [[-8, 4*I + 1, -I + 2, 2*I + 1],
7726
... [1, -2*I - 1, -I + 3, -I + 1],
7727
... [I + 7, 2*I + 1, -2*I + 7, -I + 1],
7728
... [I + 2, 0, I + 12, -1]])
7729
sage: Q, R = A.QR()
7730
sage: Q
7731
[ -0.7302967433402215? 0.2070566455055649? + 0.5383472783144687?*I 0.2463049809998642? - 0.0764456358723292?*I 0.2381617683194332? - 0.1036596032779695?*I]
7732
[ 0.0912870929175277? -0.2070566455055649? - 0.3778783780476559?*I 0.3786559533863032? - 0.1952221495524667?*I 0.701244450214469? - 0.364371165098660?*I]
7733
[ 0.6390096504226938? + 0.0912870929175277?*I 0.1708217325420910? + 0.6677576817554466?*I -0.03411475806452072? + 0.04090198741767143?*I 0.3140171085506763? - 0.0825191718705412?*I]
7734
[ 0.1825741858350554? + 0.0912870929175277?*I -0.03623491296347385? + 0.0724698259269477?*I 0.8632284069415110? + 0.06322839976356195?*I -0.4499694867611521? - 0.0116119181208918?*I]
7735
sage: R
7736
[ 10.95445115010333? 0.?e-18 - 1.917028951268082?*I 5.385938482134133? - 2.190890230020665?*I -0.2738612787525831? - 2.190890230020665?*I]
7737
[ 0 4.829596256417300? + 0.?e-17*I -0.869637911123373? - 5.864879483945125?*I 0.993871898426712? - 0.3054085521207082?*I]
7738
[ 0 0 12.00160760935814? + 0.?e-16*I -0.2709533402297273? + 0.4420629644486323?*I]
7739
[ 0 0 0 1.942963944258992? + 0.?e-16*I]
7740
sage: Q.conjugate_transpose()*Q
7741
[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]
7742
[ 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]
7743
[ 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]
7744
[ 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]
7745
sage: Q*R - A
7746
[ 0.?e-17 0.?e-17 + 0.?e-17*I 0.?e-16 + 0.?e-16*I 0.?e-16 + 0.?e-16*I]
7747
[ 0.?e-18 0.?e-17 + 0.?e-17*I 0.?e-16 + 0.?e-16*I 0.?e-15 + 0.?e-15*I]
7748
[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]
7749
[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]
7750
7751
A rank-deficient rectangular matrix, with both values of the ``full`` keyword. ::
7752
7753
sage: A = matrix(QQbar, [[2, -3, 3],
7754
... [-1, 1, -1],
7755
... [-1, 3, -3],
7756
... [-5, 1, -1]])
7757
sage: Q, R = A.QR()
7758
sage: Q
7759
[ 0.3592106040535498? -0.5693261797050169? 0.7239227659930268? 0.1509015305256380?]
7760
[ -0.1796053020267749? 0.1445907757980996? 0 0.9730546968377341?]
7761
[ -0.1796053020267749? 0.7048800320157352? 0.672213996993525? -0.1378927778941174?]
7762
[ -0.8980265101338745? -0.3976246334447737? 0.1551263069985058? -0.10667177157846818?]
7763
sage: R
7764
[ 5.567764362830022? -2.694079530401624? 2.694079530401624?]
7765
[ 0 3.569584777515583? -3.569584777515583?]
7766
[ 0 0 0]
7767
[ 0 0 0]
7768
sage: Q.conjugate_transpose()*Q
7769
[ 1 0.?e-18 0.?e-18 0.?e-18]
7770
[ 0.?e-18 1 0.?e-18 0.?e-18]
7771
[ 0.?e-18 0.?e-18 1.000000000000000? 0.?e-18]
7772
[ 0.?e-18 0.?e-18 0.?e-18 1.000000000000000?]
7773
7774
sage: Q, R = A.QR(full=False)
7775
sage: Q
7776
[ 0.3592106040535498? -0.5693261797050169?]
7777
[-0.1796053020267749? 0.1445907757980996?]
7778
[-0.1796053020267749? 0.7048800320157352?]
7779
[-0.8980265101338745? -0.3976246334447737?]
7780
sage: R
7781
[ 5.567764362830022? -2.694079530401624? 2.694079530401624?]
7782
[ 0 3.569584777515583? -3.569584777515583?]
7783
sage: Q.conjugate_transpose()*Q
7784
[ 1 0.?e-18]
7785
[0.?e-18 1]
7786
7787
Another rank-deficient rectangular matrix, with complex entries,
7788
as a reduced decomposition. ::
7789
7790
sage: A = matrix(QQbar, [[-3*I - 3, I - 3, -12*I + 1, -2],
7791
... [-I - 1, -2, 5*I - 1, -I - 2],
7792
... [-4*I - 4, I - 5, -7*I, -I - 4]])
7793
sage: Q, R = A.QR(full=False)
7794
sage: Q
7795
[ -0.4160251471689219? - 0.4160251471689219?*I 0.5370861555295747? + 0.1790287185098583?*I]
7796
[ -0.1386750490563073? - 0.1386750490563073?*I -0.7519206177414046? - 0.2506402059138015?*I]
7797
[ -0.5547001962252291? - 0.5547001962252291?*I -0.2148344622118299? - 0.07161148740394329?*I]
7798
sage: R
7799
[ 7.211102550927979? 3.328201177351375? - 5.269651864139676?*I 7.904477796209515? + 8.45917799243475?*I 4.021576422632911? - 2.634825932069838?*I]
7800
[ 0 1.074172311059150? -1.611258466588724? - 9.13046464400277?*I 1.611258466588724? + 0.5370861555295747?*I]
7801
sage: Q.conjugate_transpose()*Q
7802
[1.000000000000000? + 0.?e-18*I 0.?e-18 + 0.?e-18*I]
7803
[ 0.?e-17 + 0.?e-17*I 1.000000000000000? + 0.?e-17*I]
7804
sage: Q*R-A
7805
[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]
7806
[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]
7807
[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]
7808
7809
Results of full decompositions are cached and thus returned
7810
immutable. ::
7811
7812
sage: A = random_matrix(QQbar, 2, 2)
7813
sage: Q, R = A.QR()
7814
sage: Q.is_mutable()
7815
False
7816
sage: R.is_mutable()
7817
False
7818
7819
Trivial cases return trivial results of the correct size,
7820
and we check `Q` itself in one case. ::
7821
7822
sage: A = zero_matrix(QQbar, 0, 10)
7823
sage: Q, R = A.QR()
7824
sage: Q.nrows(), Q.ncols()
7825
(0, 0)
7826
sage: R.nrows(), R.ncols()
7827
(0, 10)
7828
sage: A = zero_matrix(QQbar, 3, 0)
7829
sage: Q, R = A.QR()
7830
sage: Q.nrows(), Q.ncols()
7831
(3, 3)
7832
sage: R.nrows(), R.ncols()
7833
(3, 0)
7834
sage: Q
7835
[1 0 0]
7836
[0 1 0]
7837
[0 0 1]
7838
7839
TESTS:
7840
7841
Inexact rings are caught and ``CDF`` suggested. ::
7842
7843
sage: A = matrix(RealField(100), 2, range(4))
7844
sage: A.QR()
7845
Traceback (most recent call last):
7846
...
7847
NotImplementedError: QR decomposition is implemented over exact rings, try CDF for numerical results, not Real Field with 100 bits of precision
7848
7849
Without a fraction field, we cannot hope to run the algorithm. ::
7850
7851
sage: A = matrix(Integers(6), 2, range(4))
7852
sage: A.QR()
7853
Traceback (most recent call last):
7854
...
7855
ValueError: QR decomposition needs a fraction field of Ring of integers modulo 6
7856
7857
The biggest obstacle is making unit vectors, thus requiring square
7858
roots, though some small cases pass through. ::
7859
7860
sage: A = matrix(ZZ, 3, range(9))
7861
sage: A.QR()
7862
Traceback (most recent call last):
7863
...
7864
TypeError: QR decomposition unable to compute square roots in Rational Field
7865
7866
sage: A = matrix(ZZ, 2, range(4))
7867
sage: Q, R = A.QR()
7868
sage: Q
7869
[0 1]
7870
[1 0]
7871
sage: R
7872
[2 3]
7873
[0 1]
7874
7875
REFERENCES:
7876
7877
.. [TREFETHEN-BAU] Trefethen, Lloyd N., Bau, David, III
7878
"Numerical Linear Algebra"
7879
SIAM, Philadelphia, 1997.
7880
7881
AUTHOR:
7882
7883
- Rob Beezer (2011-02-17)
7884
"""
7885
from sage.modules.free_module_element import zero_vector
7886
from sage.matrix.constructor import zero_matrix, matrix
7887
from sage.functions.other import sqrt
7888
7889
if full:
7890
QR = self.fetch('QR_factors')
7891
if QR is not None:
7892
return QR
7893
R = self.base_ring()
7894
if not R.is_exact():
7895
raise NotImplementedError('QR decomposition is implemented over exact rings, try CDF for numerical results, not %s' % R)
7896
try:
7897
F = R.fraction_field()
7898
except:
7899
raise ValueError("QR decomposition needs a fraction field of %s" % R)
7900
m = self.nrows()
7901
n = self.ncols()
7902
7903
R = zero_matrix(F, m, n)
7904
V = self.columns(copy=True)
7905
Q = []
7906
row = 0 # row of R being filled
7907
for i in range(n):
7908
v = V[i]
7909
hip = v.hermitian_inner_product(v)
7910
if hip != 0:
7911
try:
7912
scale = sqrt(hip)
7913
q = (1/scale)*v
7914
Q.append(q)
7915
R[row,i] = scale
7916
for j in range(i+1, n):
7917
R[row,j] = q.hermitian_inner_product(V[j])
7918
V[j] = V[j] - R[row,j]*q
7919
row = row + 1
7920
except TypeError:
7921
raise TypeError('QR decomposition unable to compute square roots in %s' % F)
7922
# complete to full orthonormal basis, or reduce to truncated R
7923
if full:
7924
Qt = matrix(Q) # as rows here
7925
if Qt.nrows() == 0:
7926
Qt = zero_matrix(F, 0, m)
7927
orthogonal = Qt.right_kernel().basis_matrix().transpose()
7928
Qperp, _ = orthogonal.QR(full=False)
7929
Q = Q + Qperp.columns()
7930
else:
7931
R = R[0:len(Q), 0:n]
7932
Q = matrix(Q).transpose()
7933
# Adjust rows of Q if empty
7934
if Q.ncols() == 0:
7935
Q = zero_matrix(F, m, 0)
7936
QR = (Q, R)
7937
if full:
7938
Q.set_immutable()
7939
R.set_immutable()
7940
self.cache('QR_factors', QR)
7941
return QR
7942
7943
def _gram_schmidt_noscale(self):
7944
r"""
7945
Performs Gram-Schmidt orthogonalization, with no scaling to unit vectors.
7946
7947
INPUT:
7948
7949
- ``self`` - is a matrix whose columns are to be orthogonalized.
7950
The base ring of the matrix needs to have its fraction field
7951
implemented.
7952
7953
OUTPUT:
7954
7955
Two matrices, ``Q`` and ``R`` such that if ``A`` represents ``self``:
7956
7957
- ``A = Q*R``
7958
- The columns of ``Q`` are an orthogonal set which spans the
7959
column space of ``A``.
7960
- The conjugate-transpose of ``Q`` times ``Q`` is a diagonal matrix.
7961
- ``R`` is a full-rank matrix, that has all entries below the
7962
main diagonal equal to zero.
7963
7964
This is basically a "reduced" QR decomposition of ``self`` with
7965
the distinction that the orthogonal column vectors of ``Q`` have
7966
not been scaled to unit vectors, avoiding the need to take square
7967
roots.
7968
7969
EXAMPLES:
7970
7971
A rectangular matrix whose columns have full-rank. Notice that the
7972
routine computes in the fraction field, requiring the column space
7973
check to step up to ``QQ``. ::
7974
7975
sage: A = matrix(ZZ, [[-1, -3, 0, -1],
7976
... [ 1, 2, -1, 2],
7977
... [-3, -6, 4, -7]])
7978
sage: Q,R = A._gram_schmidt_noscale()
7979
sage: Q
7980
[ -1 -10/11 0]
7981
[ 1 -1/11 3/10]
7982
[ -3 3/11 1/10]
7983
sage: R
7984
[ 1 23/11 -13/11 24/11]
7985
[ 0 1 13/10 -13/10]
7986
[ 0 0 1 -1]
7987
sage: Q*R == A
7988
True
7989
sage: Q.transpose()*Q
7990
[ 11 0 0]
7991
[ 0 10/11 0]
7992
[ 0 0 1/10]
7993
sage: A.change_ring(QQ).column_space() == Q.column_space()
7994
True
7995
7996
A matrix over a subfield of the complex numbers, with four
7997
columns but rank 3, so the orthogonal set has just 3 vectors
7998
as well. Orthogonality comes from the Hermitian inner product
7999
so we need to check with the conjugate-transpose. This
8000
example verifies that the bug on #10791 is fixed. ::
8001
8002
sage: F.<a> = QuadraticField(-5)
8003
sage: A = matrix(F, [[ 1, a - 3, a - 2, a + 1],
8004
... [ a, 2*a + 1, 3*a + 1, 1],
8005
... [a + 1, a - 6, 2*a - 5, 1],
8006
... [ 2*a, a, 3*a, -3],
8007
... [ 1, a - 1, a, a - 1]])
8008
sage: A.rank()
8009
3
8010
sage: Q, R = A._gram_schmidt_noscale()
8011
sage: Q
8012
[ 1 25/33*a - 38/11 641/1163*a + 453/1163]
8013
[ a 17/11*a + 73/33 322/1163*a + 1566/1163]
8014
[ a + 1 10/33*a - 173/33 -784/1163*a + 1614/1163]
8015
[ 2*a 1/11*a + 80/33 196/1163*a - 1234/1163]
8016
[ 1 25/33*a - 16/11 855/1163*a - 1717/1163]
8017
sage: R
8018
[ 1 8/33*a + 5/11 8/33*a + 16/11 2/11*a + 1/33]
8019
[ 0 1 1 -107/1163*a - 78/1163]
8020
[ 0 0 0 1]
8021
sage: Q*R == A
8022
True
8023
sage: Q.transpose().conjugate()*Q
8024
[ 33 0 0]
8025
[ 0 2326/33 0]
8026
[ 0 0 16532/1163]
8027
sage: Q.column_space() == A.column_space()
8028
True
8029
8030
Some trivial cases. ::
8031
8032
sage: A = matrix(ZZ, 3, 0)
8033
sage: Q, R = A._gram_schmidt_noscale()
8034
sage: Q.parent()
8035
Full MatrixSpace of 3 by 0 dense matrices over Rational Field
8036
sage: R.parent()
8037
Full MatrixSpace of 0 by 0 dense matrices over Rational Field
8038
sage: Q*R == A
8039
True
8040
8041
sage: A = matrix(ZZ, 0, 3)
8042
sage: Q, R = A._gram_schmidt_noscale()
8043
sage: Q.parent()
8044
Full MatrixSpace of 0 by 0 dense matrices over Rational Field
8045
sage: R.parent()
8046
Full MatrixSpace of 0 by 3 dense matrices over Rational Field
8047
sage: Q*R == A
8048
True
8049
8050
TESTS:
8051
8052
Without a fraction field, we cannot hope to proceed. ::
8053
8054
sage: A = matrix(Integers(6), 2, range(4))
8055
sage: A._gram_schmidt_noscale()
8056
Traceback (most recent call last):
8057
...
8058
TypeError: Gram-Schmidt orthogonalization requires a base ring with a fraction field, not Ring of integers modulo 6
8059
8060
AUTHORS:
8061
8062
- William Stein (2007-11-18)
8063
- Rob Beezer (2011-02-25)
8064
"""
8065
import sage.matrix.constructor
8066
R = self.base_ring()
8067
try:
8068
F = R.fraction_field()
8069
except TypeError:
8070
raise TypeError("Gram-Schmidt orthogonalization requires a base ring with a fraction field, not %s" % R)
8071
n = self.ncols()
8072
B = self.columns()
8073
zero = F(0)
8074
Bstar = []
8075
R = sage.matrix.constructor.zero_matrix(F, n)
8076
nnz = 0 # number non-zero rows in R, or number of nonzero vectors in Bstar
8077
for i in range(n):
8078
ortho = B[i]
8079
for j in range(nnz):
8080
R[j,i] = Bstar[j].hermitian_inner_product(B[i])/Bstar[j].hermitian_inner_product(Bstar[j])
8081
ortho = ortho - R[j,i]*Bstar[j]
8082
if ortho.hermitian_inner_product(ortho) != zero:
8083
Bstar.append(ortho)
8084
R[nnz, i] = 1
8085
nnz = nnz + 1
8086
R = R[0:nnz]
8087
if Bstar == []:
8088
Q = sage.matrix.constructor.matrix(F, 0, self.nrows()).transpose()
8089
else:
8090
Q = sage.matrix.constructor.matrix(F, Bstar).transpose()
8091
return Q, R
8092
8093
def gram_schmidt(self, orthonormal=False):
8094
r"""
8095
Performs Gram-Schmidt orthogonalization on the rows of the matrix,
8096
returning a new matrix and a matrix accomplishing the transformation.
8097
8098
INPUT:
8099
8100
- ``self`` - a matrix whose rows are to be orthogonalized.
8101
- ``orthonormal`` - default: ``False`` - if ``True`` the
8102
returned orthogonal vectors are unit vectors. This keyword
8103
is ignored if the matrix is over ``RDF`` or ``CDF`` and the
8104
results are always orthonormal.
8105
8106
OUTPUT:
8107
8108
A pair of matrices, ``G`` and ``M`` such that if ``A``
8109
represents ``self``, where the parenthetical properties occur
8110
when ``orthonormal = True``:
8111
8112
- ``A = M*G``
8113
- The rows of ``G`` are an orthogonal (resp. orthonormal)
8114
set of vectors.
8115
- ``G`` times the conjugate-transpose of ``G`` is a diagonal
8116
(resp. identity) matrix.
8117
- The row space of ``G`` equals the row space of ``A``.
8118
- ``M`` is a full-rank matrix with zeros above the diagonal.
8119
8120
For exact rings, any zero vectors produced (when the original
8121
vectors are linearly dependent) are not output, thus the
8122
orthonormal set is linearly independent, and thus a basis for the
8123
row space of the original matrix.
8124
8125
Any notion of a Gram-Schmidt procedure requires that the base
8126
ring of the matrix has a fraction field implemented. In order
8127
to arrive at an orthonormal set, it must be possible to construct
8128
square roots of the elements of the base field. In Sage, your
8129
best option is the field of algebraic numbers, ``QQbar``, which
8130
properly contains the rationals and number fields.
8131
8132
If you have an approximate numerical matrix, then this routine
8133
requires that your base field be the real and complex
8134
double-precision floating point numbers, ``RDF`` and ``CDF``.
8135
In this case, the matrix is treated as having full rank, as no
8136
attempt is made to recognize linear dependence with approximate
8137
calculations.
8138
8139
EXAMPLES:
8140
8141
Inexact Rings, Numerical Matrices:
8142
8143
First, the inexact rings, ``CDF`` and ``RDF``. ::
8144
8145
sage: A = matrix(CDF, [[ 0.6454 + 0.7491*I, -0.8662 + 0.1489*I, 0.7656 - 0.00344*I],
8146
... [-0.2913 + 0.8057*I, 0.8321 + 0.8170*I, -0.6744 + 0.9248*I],
8147
... [ 0.2554 + 0.3517*I, -0.4454 - 0.1715*I, 0.8325 - 0.6282*I]])
8148
sage: G, M = A.gram_schmidt()
8149
sage: G.round(6) # random signs
8150
[-0.422243 - 0.490087*I 0.566698 - 0.097416*I -0.500882 + 0.002251*I]
8151
[-0.057002 - 0.495035*I -0.35059 - 0.625323*I 0.255514 - 0.415284*I]
8152
[ 0.394105 - 0.421778*I -0.392266 - 0.039345*I -0.352905 + 0.62195*I]
8153
sage: M.round(6) # random
8154
[ -1.528503 0.0 0.0]
8155
[ 0.459974 - 0.40061*I -1.741233 0.0]
8156
[-0.934304 + 0.148868*I 0.54833 + 0.073202*I -0.550725]
8157
sage: (A - M*G).zero_at(10^-12)
8158
[0.0 0.0 0.0]
8159
[0.0 0.0 0.0]
8160
[0.0 0.0 0.0]
8161
sage: (G*G.conjugate_transpose()).zero_at(10^-12)
8162
[1.0 0.0 0.0]
8163
[0.0 1.0 0.0]
8164
[0.0 0.0 1.0]
8165
8166
8167
A rectangular matrix. Note that the ``orthonormal`` keyword
8168
is ignored in these cases. ::
8169
8170
sage: A = matrix(RDF, [[-0.978325, -0.751994, 0.925305, -0.200512, 0.420458],
8171
... [-0.474877, -0.983403, 0.089836, 0.132218, 0.672965]])
8172
sage: G, M = A.gram_schmidt(orthonormal=False)
8173
sage: G.round(6).zero_at(10^-6)
8174
[-0.607223 -0.466745 0.574315 -0.124453 0.260968]
8175
[ 0.123203 -0.617909 -0.530578 0.289773 0.487368]
8176
sage: M.round(6).zero_at(10^-6)
8177
[1.611147 0.0]
8178
[0.958116 0.867778]
8179
sage: (A-M*G).zero_at(10^-12)
8180
[0.0 0.0 0.0 0.0 0.0]
8181
[0.0 0.0 0.0 0.0 0.0]
8182
sage: (G*G.transpose()).round(6).zero_at(10^-6)
8183
[1.0 0.0]
8184
[0.0 1.0]
8185
8186
Even though a set of vectors may be linearly dependent, no effort
8187
is made to decide when a zero vector is really the result of a
8188
relation of linear dependence. So in this regard, input matrices
8189
are treated as being of full rank. Try one of the base rings that
8190
provide exact results if you need exact results. ::
8191
8192
sage: entries = [[1,1,2], [2,1,3], [3,1,4]]
8193
sage: A = matrix(QQ, entries)
8194
sage: A.rank()
8195
2
8196
sage: B = matrix(RDF, entries)
8197
sage: G, M = B.gram_schmidt()
8198
sage: G.round(6) # random signs
8199
[-0.408248 -0.408248 -0.816497]
8200
[ 0.707107 -0.707107 -0.0]
8201
[ -0.57735 -0.57735 0.57735]
8202
sage: M.round(10) # random
8203
[-2.4494897428 0.0 0.0]
8204
[-3.6742346142 0.7071067812 0.0]
8205
[-4.8989794856 1.4142135624 0.0]
8206
sage: (A - M*G).zero_at(1e-14)
8207
[0.0 0.0 0.0]
8208
[0.0 0.0 0.0]
8209
[0.0 0.0 0.0]
8210
sage: (G*G.transpose()).zero_at(1e-14)
8211
[1.0 0.0 0.0]
8212
[0.0 1.0 0.0]
8213
[0.0 0.0 1.0]
8214
8215
Exact Rings, Orthonormalization:
8216
8217
To scale a vector to unit length requires taking
8218
a square root, which often takes us outside the base ring.
8219
For the integers and the rationals, the field of algebraic numbers
8220
(``QQbar``) is big enough to contain what we need, but the price
8221
is that the computations are very slow, hence mostly of value
8222
for small cases or instruction. Now we need to use the
8223
``orthonormal`` keyword. ::
8224
8225
sage: A = matrix(QQbar, [[6, -8, 1],
8226
... [4, 1, 3],
8227
... [6, 3, 3],
8228
... [7, 1, -5],
8229
... [7, -3, 5]])
8230
sage: G, M = A.gram_schmidt(orthonormal=True)
8231
sage: G
8232
[ 0.5970223141259934? -0.7960297521679913? 0.09950371902099891?]
8233
[ 0.6063218341690895? 0.5289635311888953? 0.5937772444966257?]
8234
[ 0.5252981913594170? 0.2941669871612735? -0.798453250866314?]
8235
sage: M
8236
[ 10.04987562112089? 0 0]
8237
[ 1.890570661398980? 4.735582601355131? 0]
8238
[ 1.492555785314984? 7.006153332071100? 1.638930357041381?]
8239
[ 2.885607851608969? 1.804330147889395? 7.963520581008761?]
8240
[ 7.064764050490923? 5.626248468100069? -1.197679876299471?]
8241
sage: M*G-A
8242
[0 0 0]
8243
[0 0 0]
8244
[0 0 0]
8245
[0 0 0]
8246
[0 0 0]
8247
sage: (G*G.transpose()-identity_matrix(3)).norm() < 10^-10
8248
True
8249
sage: G.row_space() == A.row_space()
8250
True
8251
8252
Starting with complex numbers with rational real and imaginary parts.
8253
Note the use of the conjugate-transpose when checking the
8254
orthonormality. ::
8255
8256
sage: A = matrix(QQbar, [[ -2, -I - 1, 4*I + 2, -1],
8257
... [-4*I, -2*I + 17, 0, 9*I + 1],
8258
... [ 1, -2*I - 6, -I + 11, -5*I + 1]])
8259
sage: G, M = A.gram_schmidt(orthonormal=True)
8260
sage: (M*G-A).norm() < 10^-10
8261
True
8262
sage: id3 = G*G.conjugate().transpose()
8263
sage: (id3 - identity_matrix(3)).norm() < 10^-10
8264
True
8265
sage: G.row_space() == A.row_space()
8266
True
8267
8268
A square matrix with small rank. The zero vectors produced as a
8269
result of linear dependence get eliminated, so the rows of ``G``
8270
are a basis for the row space of ``A``. ::
8271
8272
sage: A = matrix(QQbar, [[2, -6, 3, 8],
8273
... [1, -3, 2, 5],
8274
... [0, 0, 2, 4],
8275
... [2, -6, 3, 8]])
8276
sage: A.change_ring(QQ).rank()
8277
2
8278
sage: G, M = A.gram_schmidt(orthonormal=True)
8279
sage: G
8280
[ 0.1881441736767195? -0.5644325210301583? 0.2822162605150792? 0.7525766947068779?]
8281
[-0.2502818123591464? 0.750845437077439? 0.3688363550555841? 0.4873908977520218?]
8282
sage: M
8283
[10.630145812734649? 0]
8284
[ 6.208757731331742? 0.6718090752798139?]
8285
[ 3.574739299857670? 2.687236301119256?]
8286
[10.630145812734649? 0]
8287
sage: M*G-A
8288
[0 0 0 0]
8289
[0 0 0 0]
8290
[0 0 0 0]
8291
[0 0 0 0]
8292
sage: (G*G.transpose()-identity_matrix(2)).norm() < 10^-10
8293
True
8294
sage: G.row_space() == A.row_space()
8295
True
8296
8297
Exact Rings, Orthogonalization:
8298
8299
If we forego scaling orthogonal vectors to unit vectors, we
8300
can apply Gram-Schmidt to a much greater variety of rings.
8301
Use the ``orthonormal=False`` keyword (or assume it as the default).
8302
Note that now the orthogonality check creates a diagonal matrix
8303
whose diagonal entries are the squares of the lengths of the
8304
vectors.
8305
8306
First, in the rationals, without involving ``QQbar``. ::
8307
8308
sage: A = matrix(QQ, [[-1, 3, 2, 2],
8309
... [-1, 0, -1, 0],
8310
... [-1, -2, -3, -1],
8311
... [ 1, 1, 2, 0]])
8312
sage: A.rank()
8313
3
8314
sage: G, M = A.gram_schmidt()
8315
sage: G
8316
[ -1 3 2 2]
8317
[-19/18 1/6 -8/9 1/9]
8318
[ 2/35 -4/35 -2/35 9/35]
8319
sage: M
8320
[ 1 0 0]
8321
[ -1/18 1 0]
8322
[-13/18 59/35 1]
8323
[ 1/3 -48/35 -2]
8324
sage: M*G-A
8325
[0 0 0 0]
8326
[0 0 0 0]
8327
[0 0 0 0]
8328
[0 0 0 0]
8329
sage: G*G.transpose()
8330
[ 18 0 0]
8331
[ 0 35/18 0]
8332
[ 0 0 3/35]
8333
sage: G.row_space() == A.row_space()
8334
True
8335
8336
A complex subfield of the complex numbers. ::
8337
8338
sage: C.<z> = CyclotomicField(5)
8339
sage: A = matrix(C, [[ -z^3 - 2*z, -z^3 - 1, 2*z^3 - 2*z^2 + 2*z, 1],
8340
... [ z^3 - 2*z^2 + 1, -z^3 + 2*z^2 - z - 1, -1, z^2 + z],
8341
... [-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]])
8342
sage: G, M = A.gram_schmidt(orthonormal=False)
8343
sage: G
8344
[ -z^3 - 2*z -z^3 - 1 2*z^3 - 2*z^2 + 2*z 1]
8345
[ 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]
8346
[-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]
8347
sage: M
8348
[ 1 0 0]
8349
[ 14/139*z^3 + 47/139*z^2 + 145/139*z + 95/139 1 0]
8350
[ -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]
8351
sage: M*G - A
8352
[0 0 0 0]
8353
[0 0 0 0]
8354
[0 0 0 0]
8355
sage: G*G.conjugate().transpose()
8356
[ 15*z^3 + 15*z^2 + 28 0 0]
8357
[ 0 463/139*z^3 + 463/139*z^2 + 1971/139 0]
8358
[ 0 0 230983/19841*z^3 + 230983/19841*z^2 + 1003433/39682]
8359
sage: G.row_space() == A.row_space()
8360
True
8361
8362
A slightly edited legacy example. ::
8363
8364
sage: A = matrix(ZZ, 3, [-1, 2, 5, -11, 1, 1, 1, -1, -3]); A
8365
[ -1 2 5]
8366
[-11 1 1]
8367
[ 1 -1 -3]
8368
sage: G, mu = A.gram_schmidt()
8369
sage: G
8370
[ -1 2 5]
8371
[ -52/5 -1/5 -2]
8372
[ 2/187 36/187 -14/187]
8373
sage: mu
8374
[ 1 0 0]
8375
[ 3/5 1 0]
8376
[ -3/5 -7/187 1]
8377
sage: G.row(0) * G.row(1)
8378
0
8379
sage: G.row(0) * G.row(2)
8380
0
8381
sage: G.row(1) * G.row(2)
8382
0
8383
8384
The relation between mu and A is as follows. ::
8385
8386
sage: mu*G == A
8387
True
8388
"""
8389
import sage.rings.real_double
8390
import sage.rings.complex_double
8391
R = self.base_ring()
8392
if R in [sage.rings.real_double.RDF, sage.rings.complex_double.CDF]:
8393
Q, R = self.transpose().QR()
8394
m = R.nrows(); n = R.ncols()
8395
if m > n:
8396
Q = Q[0:m, 0:n]
8397
R = R[0:n, 0:n]
8398
elif R.is_exact():
8399
if orthonormal:
8400
Q, R = self.transpose().QR(full=False)
8401
else:
8402
Q, R = self.transpose()._gram_schmidt_noscale()
8403
else:
8404
raise NotImplementedError("Gram-Scmidt orthogonalization not implemented for matrices over inexact rings, except for RDF and CDF")
8405
return Q.transpose(), R.transpose()
8406
8407
def jordan_form(self, base_ring=None, sparse=False, subdivide=True, transformation=False):
8408
r"""
8409
Compute the Jordan normal form of this square matrix `A`, if it exists.
8410
8411
This computation is performed in a naive way using the ranks of powers
8412
of `A-xI`, where `x` is an eigenvalue of the matrix `A`. If desired,
8413
a transformation matrix `P` can be returned, which is such that the
8414
Jordan canonical form is given by `P^{-1} A P`.
8415
8416
INPUT:
8417
8418
- ``base_ring`` - Ring in which to compute the Jordan form.
8419
8420
- ``sparse`` - (default ``False``) If ``sparse=True``, return a sparse
8421
matrix.
8422
8423
- ``subdivide`` - (default ``True``) If ``subdivide=True``, the
8424
subdivisions for the Jordan blocks in the matrix are shown.
8425
8426
- ``transformation`` - (default ``False``) If ``transformation=True``,
8427
computes also the transformation matrix.
8428
8429
NOTES:
8430
8431
Currently, the Jordan normal form is not computed over inexact rings
8432
in any but the trivial cases when the matrix is either `0 \times 0`
8433
or `1 \times 1`.
8434
8435
In the case of exact rings, this method does not compute any
8436
generalized form of the Jordan normal form, but is only able to
8437
compute the result if the characteristic polynomial of the matrix
8438
splits over the specific base ring.
8439
8440
Note that the base ring must be a field or a ring with an implemented
8441
fraction field.
8442
8443
EXAMPLES::
8444
8445
sage: a = matrix(ZZ,4,[1, 0, 0, 0, 0, 1, 0, 0, 1, \
8446
-1, 1, 0, 1, -1, 1, 2]); a
8447
[ 1 0 0 0]
8448
[ 0 1 0 0]
8449
[ 1 -1 1 0]
8450
[ 1 -1 1 2]
8451
sage: a.jordan_form()
8452
[2|0 0|0]
8453
[-+---+-]
8454
[0|1 1|0]
8455
[0|0 1|0]
8456
[-+---+-]
8457
[0|0 0|1]
8458
sage: a.jordan_form(subdivide=False)
8459
[2 0 0 0]
8460
[0 1 1 0]
8461
[0 0 1 0]
8462
[0 0 0 1]
8463
sage: b = matrix(ZZ,3,range(9)); b
8464
[0 1 2]
8465
[3 4 5]
8466
[6 7 8]
8467
sage: b.jordan_form()
8468
Traceback (most recent call last):
8469
...
8470
RuntimeError: Some eigenvalue does not exist in Rational Field.
8471
sage: b.jordan_form(RealField(15))
8472
Traceback (most recent call last):
8473
...
8474
ValueError: Jordan normal form not implemented over inexact rings.
8475
8476
If you need the transformation matrix as well as the Jordan form of
8477
``self``, then pass the option ``transformation=True``.
8478
8479
::
8480
8481
sage: m = matrix([[5,4,2,1],[0,1,-1,-1],[-1,-1,3,0],[1,1,-1,2]]); m
8482
[ 5 4 2 1]
8483
[ 0 1 -1 -1]
8484
[-1 -1 3 0]
8485
[ 1 1 -1 2]
8486
sage: jf, p = m.jordan_form(transformation=True)
8487
sage: jf
8488
[2|0|0 0]
8489
[-+-+---]
8490
[0|1|0 0]
8491
[-+-+---]
8492
[0|0|4 1]
8493
[0|0|0 4]
8494
sage: ~p * m * p
8495
[2 0 0 0]
8496
[0 1 0 0]
8497
[0 0 4 1]
8498
[0 0 0 4]
8499
8500
Note that for matrices over inexact rings and associated numerical
8501
stability problems, we do not attempt to compute the Jordan normal
8502
form.
8503
8504
::
8505
8506
sage: b = matrix(ZZ,3,3,range(9))
8507
sage: jf, p = b.jordan_form(RealField(15), transformation=True)
8508
Traceback (most recent call last):
8509
...
8510
ValueError: Jordan normal form not implemented over inexact rings.
8511
8512
TESTS::
8513
8514
sage: c = matrix(ZZ, 3, [1]*9); c
8515
[1 1 1]
8516
[1 1 1]
8517
[1 1 1]
8518
sage: c.jordan_form(subdivide=False)
8519
[3 0 0]
8520
[0 0 0]
8521
[0 0 0]
8522
8523
::
8524
8525
sage: evals = [(i,i) for i in range(1,6)]
8526
sage: n = sum(range(1,6))
8527
sage: jf = block_diagonal_matrix([jordan_block(ev,size) for ev,size in evals])
8528
sage: p = random_matrix(ZZ,n,n)
8529
sage: while p.rank() != n: p = random_matrix(ZZ,n,n)
8530
sage: m = p * jf * ~p
8531
sage: mjf, mp = m.jordan_form(transformation=True)
8532
sage: mjf == jf
8533
True
8534
sage: m = diagonal_matrix([1,1,0,0])
8535
sage: jf,P = m.jordan_form(transformation=True)
8536
sage: jf == ~P*m*P
8537
True
8538
8539
We verify that the bug from trac ticket #6942 is fixed::
8540
8541
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]])
8542
sage: J, T = M.jordan_form(transformation=True)
8543
sage: J
8544
[1 1|0 0|0 0|0]
8545
[0 1|0 0|0 0|0]
8546
[---+---+---+-]
8547
[0 0|1 1|0 0|0]
8548
[0 0|0 1|0 0|0]
8549
[---+---+---+-]
8550
[0 0|0 0|1 1|0]
8551
[0 0|0 0|0 1|0]
8552
[---+---+---+-]
8553
[0 0|0 0|0 0|1]
8554
sage: M * T == T * J
8555
True
8556
sage: T.rank()
8557
7
8558
sage: M.rank()
8559
7
8560
8561
We verify that the bug from trac ticket #6932 is fixed::
8562
8563
sage: M=Matrix(1,1,[1])
8564
sage: M.jordan_form(transformation=True)
8565
([1], [1])
8566
8567
We now go through three `10 \times 10` matrices to exhibit cases where
8568
there are multiple blocks of the same size::
8569
8570
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
8571
[ 15 37/3 -16 -104/3 -29 -7/3 0 2/3 -29/3 -1/3]
8572
[ 2 9 -1 -6 -6 0 0 0 -2 0]
8573
[ 24 74/3 -41 -208/3 -58 -23/3 0 4/3 -58/3 -2/3]
8574
[ -6 -19 3 21 19 0 0 0 6 0]
8575
[ 2 6 3 -6 -3 1 0 0 -2 0]
8576
[ -96 -296/3 176 832/3 232 101/3 0 -16/3 232/3 8/3]
8577
[ -4 -2/3 21 16/3 4 14/3 3 -1/3 4/3 -25/3]
8578
[ 20 26/3 -66 -199/3 -42 -41/3 0 13/3 -55/3 -2/3]
8579
[ 18 57 -9 -54 -57 0 0 0 -15 0]
8580
[ 0 0 0 0 0 0 0 0 0 3]
8581
sage: J, T = A.jordan_form(transformation=True); J
8582
[3 1 0|0 0 0|0 0 0|0]
8583
[0 3 1|0 0 0|0 0 0|0]
8584
[0 0 3|0 0 0|0 0 0|0]
8585
[-----+-----+-----+-]
8586
[0 0 0|3 1 0|0 0 0|0]
8587
[0 0 0|0 3 1|0 0 0|0]
8588
[0 0 0|0 0 3|0 0 0|0]
8589
[-----+-----+-----+-]
8590
[0 0 0|0 0 0|3 1 0|0]
8591
[0 0 0|0 0 0|0 3 1|0]
8592
[0 0 0|0 0 0|0 0 3|0]
8593
[-----+-----+-----+-]
8594
[0 0 0|0 0 0|0 0 0|3]
8595
sage: T * J * T**(-1) == A
8596
True
8597
sage: T.rank()
8598
10
8599
8600
::
8601
8602
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
8603
[ 15 37/3 -16 -14/3 -29 -7/3 0 2/3 1/3 44/3]
8604
[ 2 9 -1 0 -6 0 0 0 0 3]
8605
[ 24 74/3 -41 -28/3 -58 -23/3 0 4/3 2/3 88/3]
8606
[ -6 -19 3 3 19 0 0 0 0 -9]
8607
[ 2 6 3 0 -3 1 0 0 0 3]
8608
[ -96 -296/3 176 112/3 232 101/3 0 -16/3 -8/3 -352/3]
8609
[ -4 -2/3 21 16/3 4 14/3 3 -1/3 4/3 -25/3]
8610
[ 20 26/3 -66 -28/3 -42 -41/3 0 13/3 2/3 82/3]
8611
[ 18 57 -9 0 -57 0 0 0 3 28]
8612
[ 0 0 0 0 0 0 0 0 0 3]
8613
sage: J, T = A.jordan_form(transformation=True); J
8614
[3 1 0|0 0 0|0 0|0 0]
8615
[0 3 1|0 0 0|0 0|0 0]
8616
[0 0 3|0 0 0|0 0|0 0]
8617
[-----+-----+---+---]
8618
[0 0 0|3 1 0|0 0|0 0]
8619
[0 0 0|0 3 1|0 0|0 0]
8620
[0 0 0|0 0 3|0 0|0 0]
8621
[-----+-----+---+---]
8622
[0 0 0|0 0 0|3 1|0 0]
8623
[0 0 0|0 0 0|0 3|0 0]
8624
[-----+-----+---+---]
8625
[0 0 0|0 0 0|0 0|3 1]
8626
[0 0 0|0 0 0|0 0|0 3]
8627
sage: T * J * T**(-1) == A
8628
True
8629
sage: T.rank()
8630
10
8631
8632
::
8633
8634
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
8635
[ 15 37/3 -16 -104/3 -29 -7/3 35 2/3 -29/3 -1/3]
8636
[ 2 9 -1 -6 -6 0 7 0 -2 0]
8637
[ 24 74/3 -29 -208/3 -58 -14/3 70 4/3 -58/3 -2/3]
8638
[ -6 -19 3 21 19 0 -21 0 6 0]
8639
[ 2 6 -1 -6 -3 0 7 0 -2 0]
8640
[ -96 -296/3 128 832/3 232 65/3 -279 -16/3 232/3 8/3]
8641
[ 0 0 0 0 0 0 3 0 0 0]
8642
[ 20 26/3 -30 -199/3 -42 -14/3 70 13/3 -55/3 -2/3]
8643
[ 18 57 -9 -54 -57 0 63 0 -15 0]
8644
[ 0 0 0 0 0 0 0 0 0 3]
8645
sage: J, T = A.jordan_form(transformation=True); J
8646
[3 1 0|0 0|0 0|0 0|0]
8647
[0 3 1|0 0|0 0|0 0|0]
8648
[0 0 3|0 0|0 0|0 0|0]
8649
[-----+---+---+---+-]
8650
[0 0 0|3 1|0 0|0 0|0]
8651
[0 0 0|0 3|0 0|0 0|0]
8652
[-----+---+---+---+-]
8653
[0 0 0|0 0|3 1|0 0|0]
8654
[0 0 0|0 0|0 3|0 0|0]
8655
[-----+---+---+---+-]
8656
[0 0 0|0 0|0 0|3 1|0]
8657
[0 0 0|0 0|0 0|0 3|0]
8658
[-----+---+---+---+-]
8659
[0 0 0|0 0|0 0|0 0|3]
8660
sage: T * J * T**(-1) == A
8661
True
8662
sage: T.rank()
8663
10
8664
8665
Verify that we smoothly move to QQ from ZZ (:trac:`12693`), i.e.
8666
we work in the vector space over the field::
8667
8668
sage: M = matrix(((2,2,2),(0,0,0),(-2,-2,-2)))
8669
sage: J, P = M.jordan_form(transformation=True)
8670
sage: J; P
8671
[0 1|0]
8672
[0 0|0]
8673
[---+-]
8674
[0 0|0]
8675
[ 2 1 0]
8676
[ 0 0 1]
8677
[-2 0 -1]
8678
sage: J - ~P * M * P
8679
[0 0 0]
8680
[0 0 0]
8681
[0 0 0]
8682
sage: parent(M)
8683
Full MatrixSpace of 3 by 3 dense matrices over Integer Ring
8684
sage: parent(J) == parent(P) == MatrixSpace(QQ, 3)
8685
True
8686
sage: M.jordan_form(transformation=True) == (M/1).jordan_form(transformation=True)
8687
True
8688
8689
TESTS:
8690
8691
The base ring for the matrix needs to have a fraction field
8692
and it needs to be implemented. ::
8693
8694
sage: A = matrix(Integers(6), 2, 2, range(4))
8695
sage: A.jordan_form()
8696
Traceback (most recent call last):
8697
...
8698
ValueError: Matrix entries must be from a field, not Ring of integers modulo 6
8699
"""
8700
from sage.matrix.constructor import block_diagonal_matrix, jordan_block, diagonal_matrix
8701
from sage.combinat.partition import Partition
8702
8703
if self.ncols() != self.nrows():
8704
raise ValueError, "Jordan normal form not implemented for non-square matrices."
8705
8706
# Set ``n`` to the number of rows and handle trivial cases, regardless
8707
# of the underlying ring.
8708
n = self.nrows()
8709
if n == 0:
8710
if not transformation:
8711
return self
8712
else:
8713
return self, self
8714
elif n == 1:
8715
if not transformation:
8716
return self
8717
else:
8718
return self, self.parent().identity_matrix()
8719
8720
if (base_ring is None and not self.base_ring().is_exact()) or \
8721
(not base_ring is None and not base_ring.is_exact()):
8722
raise ValueError("Jordan normal form not implemented over inexact rings.")
8723
8724
if base_ring is None:
8725
A = self
8726
base_ring = self.base_ring()
8727
8728
# make sure we're working with a field..
8729
if not base_ring.is_field():
8730
try:
8731
base_field = base_ring.fraction_field()
8732
except (NotImplementedError, TypeError, AttributeError):
8733
raise ValueError("Matrix entries must be from a field, not {0}".
8734
format(base_ring))
8735
A = self.change_ring(base_field)
8736
8737
# Compute the eigenvalues of the matrix, with multiplicities. Here,
8738
# ``evals`` is a list of pairs, each first entry a root and each
8739
# second entry the corresponding multiplicity.
8740
evals = A.charpoly().roots()
8741
if sum([mult for (_,mult) in evals]) < n:
8742
raise RuntimeError("Some eigenvalue does not exist in %s." %(A.base_ring()))
8743
8744
# Compute the block information. Here, ``blocks`` is a list of pairs,
8745
# each first entry a root and each second entry the size of a block.
8746
# Note that in general there is more than one block per eigenvalue!
8747
blocks = []
8748
for eval, mult in evals:
8749
if mult == 1:
8750
blocks.append((eval,1))
8751
else:
8752
B = A - diagonal_matrix([eval]*n, sparse=sparse)
8753
C = B
8754
ranks = [n, C.rank()]
8755
i = 0
8756
while ranks[i] > ranks[i+1] and ranks[i+1] > n-mult:
8757
C = B*C
8758
ranks.append(C.rank())
8759
i = i+1
8760
diagram = [ranks[i]-ranks[i+1] for i in xrange(len(ranks)-1)]
8761
blocks.extend([(eval, i) \
8762
for i in Partition(diagram).conjugate()])
8763
8764
# ``J`` is the matrix in Jordan canonical form. Note that the blocks
8765
# are ordered firstly by the eigenvalues, in the same order as obeyed
8766
# by ``.roots()``, and secondly by size from greatest to smallest.
8767
J = block_diagonal_matrix([jordan_block(eval, size, sparse=sparse) \
8768
for (eval, size) in blocks], subdivide=subdivide)
8769
8770
if transformation:
8771
from itertools import groupby
8772
8773
# ``jordan_chains`` is a dictionary with keys the eigenvalues.
8774
# For every eigenvalue, we consider all Jordan blocks and find
8775
# a Jordan chain for each, adding the chain (a sequence of
8776
# vectors) to the entry for the eigenvalue (which is a list).
8777
jordan_chains = {}
8778
for eval,_ in evals:
8779
jordan_chains[eval] = []
8780
8781
# Let B be the matrix `A - eval Id`.
8782
B = A - eval
8783
8784
block_sizes = [size for e,size in blocks if e == eval]
8785
block_size_pairs = [(val,len(list(c))) \
8786
for val,c in groupby(block_sizes)]
8787
8788
# Y is a list of vectors, spanning everything that we have
8789
# covered by the Jordan chains we developed so far.
8790
Y = []
8791
8792
for l,count in block_size_pairs:
8793
8794
# There are ``count`` Jordan blocks of size ``l``
8795
# associated to this eigenvalue.
8796
8797
# We want to find elements in `\ker B^l - \ker B^{l-1}`.
8798
Vlarge = (B**l).right_kernel().basis()
8799
Vsmall = (B**(l-1)).right_kernel().basis()
8800
8801
for i in range(count):
8802
# Let v be any vector in `\ker B^l` not in the kernel
8803
# of `\ker B^{l-1}` which is also not in the span(Y),
8804
# and start a chain from there.
8805
v = _jordan_form_vector_in_difference(Vlarge, Vsmall+Y)
8806
chain = [v]
8807
for i in range(l-1):
8808
chain.append(B*chain[-1])
8809
chain.reverse()
8810
Y.extend(chain)
8811
jordan_chains[eval].append(chain)
8812
8813
# Now ``jordan_chains`` has all the columns of the transformation
8814
# matrix; we just need to put them in the right order.
8815
jordan_basis = []
8816
for eval,size in blocks:
8817
# Find a block with the right size
8818
for index,chain in enumerate(jordan_chains[eval]):
8819
if len(chain)==size:
8820
jordan_basis += jordan_chains[eval].pop(index)
8821
break
8822
8823
transformation_matrix = (A.parent()(jordan_basis)).transpose()
8824
8825
if transformation:
8826
return J, transformation_matrix
8827
else:
8828
return J
8829
8830
def is_diagonalizable(self, base_field=None):
8831
r"""
8832
Determines if the matrix is similar to a diagonal matrix.
8833
8834
INPUT:
8835
8836
- ``base_field`` - a new field to use for entries
8837
of the matrix.
8838
8839
OUTPUT:
8840
8841
If ``self`` is the matrix `A`, then it is diagonalizable
8842
if there is an invertible matrix `S` and a diagonal matrix
8843
`D` such that
8844
8845
.. math::
8846
8847
S^{-1}AS = D
8848
8849
This routine returns ``True`` if ``self`` is diagonalizable.
8850
The diagonal entries of the matrix `D` are the eigenvalues
8851
of `A`. It may be necessary to "increase" the base field to
8852
contain all of the eigenvalues. Over the rationals, the field
8853
of algebraic integers, :mod:`sage.rings.qqbar` is a good choice.
8854
8855
To obtain the matrices `S` and `D` use the :meth:`jordan_form`
8856
method with the ``transformation=True`` keyword.
8857
8858
ALGORITHM:
8859
8860
For each eigenvalue, this routine checks that the algebraic
8861
multiplicity (number of occurences as a root of the characteristic
8862
polynomial) is equal to the geometric multiplicity (dimension
8863
of the eigenspace), which is sufficient to ensure a basis of
8864
eigenvectors for the columns of `S`.
8865
8866
EXAMPLES:
8867
8868
A matrix that is diagonalizable over the rationals, as evidenced
8869
by its Jordan form. ::
8870
8871
sage: A = matrix(QQ, [[-7, 16, 12, 0, 6],
8872
... [-9, 15, 0, 12, -27],
8873
... [ 9, -8, 11, -12, 51],
8874
... [ 3, -4, 0, -1, 9],
8875
... [-1, 0, -4, 4, -12]])
8876
sage: A.jordan_form(subdivide=False)
8877
[ 2 0 0 0 0]
8878
[ 0 3 0 0 0]
8879
[ 0 0 3 0 0]
8880
[ 0 0 0 -1 0]
8881
[ 0 0 0 0 -1]
8882
sage: A.is_diagonalizable()
8883
True
8884
8885
A matrix that is not diagonalizable over the rationals, as evidenced
8886
by its Jordan form. ::
8887
8888
sage: A = matrix(QQ, [[-3, -14, 2, -1, 15],
8889
... [4, 6, -2, 3, -8],
8890
... [-2, -14, 0, 0, 10],
8891
... [3, 13, -2, 0, -11],
8892
... [-1, 6, 1, -3, 1]])
8893
sage: A.jordan_form(subdivide=False)
8894
[-1 1 0 0 0]
8895
[ 0 -1 0 0 0]
8896
[ 0 0 2 1 0]
8897
[ 0 0 0 2 1]
8898
[ 0 0 0 0 2]
8899
sage: A.is_diagonalizable()
8900
False
8901
8902
If any eigenvalue of a matrix is outside the base ring, then
8903
this routine raises an error. However, the ring can be
8904
"expanded" to contain the eigenvalues. ::
8905
8906
sage: A = matrix(QQ, [[1, 0, 1, 1, -1],
8907
... [0, 1, 0, 4, 8],
8908
... [2, 1, 3, 5, 1],
8909
... [2, -1, 1, 0, -2],
8910
... [0, -1, -1, -5, -8]])
8911
8912
sage: [e in QQ for e in A.eigenvalues()]
8913
[False, False, False, False, False]
8914
sage: A.is_diagonalizable()
8915
Traceback (most recent call last):
8916
...
8917
RuntimeError: an eigenvalue of the matrix is not contained in Rational Field
8918
8919
sage: [e in QQbar for e in A.eigenvalues()]
8920
[True, True, True, True, True]
8921
sage: A.is_diagonalizable(base_field=QQbar)
8922
True
8923
8924
Other exact fields may be employed, though it will not always
8925
be possible to expand their base fields to contain all
8926
the eigenvalues. ::
8927
8928
sage: F.<b> = FiniteField(5^2)
8929
sage: A = matrix(F, [[ 4, 3*b + 2, 3*b + 1, 3*b + 4],
8930
... [2*b + 1, 4*b, 0, 2],
8931
... [ 4*b, b + 2, 2*b + 3, 3],
8932
... [ 2*b, 3*b, 4*b + 4, 3*b + 3]])
8933
sage: A.jordan_form()
8934
[ 4 1| 0 0]
8935
[ 0 4| 0 0]
8936
[---------------+---------------]
8937
[ 0 0|2*b + 1 1]
8938
[ 0 0| 0 2*b + 1]
8939
sage: A.is_diagonalizable()
8940
False
8941
8942
sage: F.<c> = QuadraticField(-7)
8943
sage: A = matrix(F, [[ c + 3, 2*c - 2, -2*c + 2, c - 1],
8944
... [2*c + 10, 13*c + 15, -13*c - 17, 11*c + 31],
8945
... [2*c + 10, 14*c + 10, -14*c - 12, 12*c + 30],
8946
... [ 0, 2*c - 2, -2*c + 2, 2*c + 2]])
8947
sage: A.jordan_form(subdivide=False)
8948
[ 4 0 0 0]
8949
[ 0 -2 0 0]
8950
[ 0 0 c + 3 0]
8951
[ 0 0 0 c + 3]
8952
sage: A.is_diagonalizable()
8953
True
8954
8955
A trivial matrix is diagonalizable, trivially. ::
8956
8957
sage: A = matrix(QQ, 0, 0)
8958
sage: A.is_diagonalizable()
8959
True
8960
8961
A matrix must be square to be diagonalizable. ::
8962
8963
sage: A = matrix(QQ, 3, 4)
8964
sage: A.is_diagonalizable()
8965
False
8966
8967
The matrix must have entries from a field,
8968
and it must be an exact field. ::
8969
8970
sage: A = matrix(ZZ, 4, range(16))
8971
sage: A.is_diagonalizable()
8972
Traceback (most recent call last):
8973
...
8974
ValueError: matrix entries must be from a field, not Integer Ring
8975
8976
sage: A = matrix(RDF, 4, range(16))
8977
sage: A.is_diagonalizable()
8978
Traceback (most recent call last):
8979
...
8980
ValueError: base field must be exact, not Real Double Field
8981
8982
AUTHOR:
8983
8984
- Rob Beezer (2011-04-01)
8985
"""
8986
if not self.is_square():
8987
return False
8988
if not base_field is None:
8989
self = self.change_ring(base_field)
8990
if not self.base_ring().is_exact():
8991
raise ValueError('base field must be exact, not {0}'.format(self.base_ring()))
8992
if not self.base_ring().is_field():
8993
raise ValueError('matrix entries must be from a field, not {0}'.format(self.base_ring()))
8994
8995
evals = self.charpoly().roots()
8996
if sum([mult for (_,mult) in evals]) < self._nrows:
8997
raise RuntimeError('an eigenvalue of the matrix is not contained in {0}'.format(self.base_ring()))
8998
8999
# Obtaining a generic minimal polynomial requires much more
9000
# computation with kernels and their dimensions than the following.
9001
# However, if a derived class has a fast minimal polynomial routine
9002
# then overriding this by checking for repeated factors might be faster.
9003
9004
# check equality of algebraic multiplicity and geometric multiplicity
9005
for e, am in evals:
9006
gm = (self - e).right_kernel().dimension()
9007
if am != gm:
9008
return False
9009
return True
9010
9011
def is_similar(self, other, transformation=False):
9012
r"""
9013
Returns true if ``self`` and ``other`` are similar,
9014
i.e. related by a change-of-basis matrix.
9015
9016
INPUT:
9017
9018
- ``other`` - a matrix, which should be square, and of the same size
9019
as ``self``, where the entries of the matrix have a fraction field
9020
equal to that of ``self``. Inexact rings are not supported.
9021
9022
- ``transformation`` - default: ``False`` - if ``True``, the output
9023
will include the change-of-basis matrix. See below for an exact
9024
description.
9025
9026
OUTPUT:
9027
9028
Two matrices, $A$ and $B$ are similar if there is an invertible
9029
matrix $S$ such that $A=S^{-1}BS$. $S$ can be interpreted as a
9030
change-of-basis matrix if $A$ and $B$ are viewed as matrix
9031
representations of the same linear transformation.
9032
9033
When ``transformation=False`` this method will return ``True`` if
9034
such a matrix $S$ exists, otherwise it will return ``False``. When
9035
``transformation=True`` the method returns a pair. The first part
9036
of the pair is ``True`` or ``False`` depending on if the matrices
9037
are similar and the second part is the change-of-basis matrix, or
9038
``None`` should it not exist.
9039
9040
When the transformation matrix is requested, it will satisfy
9041
``self = S.inverse()*other*S``.
9042
9043
If the base rings for any of the matrices is the integers, the
9044
rationals, or the field of algebraic numbers (``QQbar``), then the
9045
matrices are converted to have ``QQbar`` as their base ring prior
9046
to checking the equality of the base rings.
9047
9048
It is possible for this routine to fail over most fields, even when
9049
the matrices are similar. However, since the field of algebraic
9050
numbers is algebraically closed, the routine will always produce
9051
a result for matrices with rational entries.
9052
9053
EXAMPLES:
9054
9055
The two matrices in this example were constructed to be similar.
9056
The computations happen in the field of algebraic numbers, but we
9057
are able to convert the change-of-basis matrix back to the rationals
9058
(which may not always be possible). ::
9059
9060
sage: A = matrix(ZZ, [[-5, 2, -11],
9061
... [-6, 7, -42],
9062
... [0, 1, -6]])
9063
sage: B = matrix(ZZ, [[ 1, 12, 3],
9064
... [-1, -6, -1],
9065
... [ 0, 6, 1]])
9066
sage: A.is_similar(B)
9067
True
9068
sage: _, T = A.is_similar(B, transformation=True)
9069
sage: T
9070
[ 1.0000000000000? + 0.?e-13*I 0.?e-13 + 0.?e-13*I 0.?e-13 + 0.?e-13*I]
9071
[-0.6666666666667? + 0.?e-13*I 0.16666666666667? + 0.?e-14*I -0.8333333333334? + 0.?e-13*I]
9072
[ 0.6666666666667? + 0.?e-13*I 0.?e-13 + 0.?e-13*I -0.333333333334? + 0.?e-13*I]
9073
sage: T.change_ring(QQ)
9074
[ 1 0 0]
9075
[-2/3 1/6 -5/6]
9076
[ 2/3 0 -1/3]
9077
sage: A == T.inverse()*B*T
9078
True
9079
9080
Other exact fields are supported. ::
9081
9082
sage: F.<a> = FiniteField(7^2)
9083
sage: A = matrix(F,[[2*a + 5, 6*a + 6, a + 3],
9084
... [ a + 3, 2*a + 2, 4*a + 2],
9085
... [2*a + 6, 5*a + 5, 3*a]])
9086
sage: B = matrix(F,[[5*a + 5, 6*a + 4, a + 1],
9087
... [ a + 5, 4*a + 3, 3*a + 3],
9088
... [3*a + 5, a + 4, 5*a + 6]])
9089
sage: A.is_similar(B)
9090
True
9091
sage: B.is_similar(A)
9092
True
9093
sage: _, T = A.is_similar(B, transformation=True)
9094
sage: T
9095
[ 1 0 0]
9096
[6*a + 1 4*a + 3 4*a + 2]
9097
[6*a + 3 3*a + 5 3*a + 6]
9098
sage: A == T.inverse()*B*T
9099
True
9100
9101
Two matrices with different sets of eigenvalues, so they
9102
cannot possibly be similar. ::
9103
9104
sage: A = matrix(QQ, [[ 2, 3, -3, -6],
9105
... [ 0, 1, -2, -8],
9106
... [-3, -3, 4, 3],
9107
... [-1, -2, 2, 6]])
9108
sage: B = matrix(QQ, [[ 1, 1, 2, 4],
9109
... [-1, 2, -3, -7],
9110
... [-2, 3, -4, -7],
9111
... [ 0, -1, 0, 0]])
9112
sage: A.eigenvalues() == B.eigenvalues()
9113
False
9114
sage: A.is_similar(B, transformation=True)
9115
(False, None)
9116
9117
Similarity is an equivalence relation, so this routine computes
9118
a representative of the equivalence class for each matrix, the
9119
Jordan form, as provided by :meth:`jordan_form`. The matrices
9120
below have identical eigenvalues (as evidenced by equal
9121
characteristic polynomials), but slightly different Jordan forms,
9122
and hence are not similar.
9123
9124
sage: A = matrix(QQ, [[ 19, -7, -29],
9125
... [-16, 11, 30],
9126
... [ 15, -7, -25]])
9127
sage: B = matrix(QQ, [[-38, -63, 42],
9128
... [ 14, 25, -14],
9129
... [-14, -21, 18]])
9130
sage: A.charpoly() == B.charpoly()
9131
True
9132
sage: A.jordan_form()
9133
[-3| 0 0]
9134
[--+-----]
9135
[ 0| 4 1]
9136
[ 0| 0 4]
9137
sage: B.jordan_form()
9138
[-3| 0| 0]
9139
[--+--+--]
9140
[ 0| 4| 0]
9141
[--+--+--]
9142
[ 0| 0| 4]
9143
sage: A.is_similar(B)
9144
False
9145
9146
Obtaining the Jordan form requires computing the eigenvalues of
9147
the matrix, which may not lie in the field used for entries of
9148
the matrix. So the routine first checks the characteristic
9149
polynomials - if they are unequal, then the matrices cannot be
9150
similar. However, when the characteristic polynomials are equal,
9151
we must examine the Jordan form. In this case, the method may fail,
9152
EVEN when the matrices are similar. This is not the case for
9153
matrices over the integers, rationals or algebraic numbers,
9154
since the computations are done in the algebraically closed
9155
field of algebraic numbers.
9156
9157
Here is an example where the similarity is obvious, but the
9158
routine fails to compute a result. ::
9159
9160
sage: F.<a> = FiniteField(7^2)
9161
sage: C = matrix(F,[[ a + 2, 5*a + 4],
9162
... [6*a + 6, 6*a + 4]])
9163
sage: S = matrix(ZZ, [[0, 1],
9164
... [1, 0]])
9165
sage: D = S.inverse()*C*S
9166
sage: C.is_similar(D)
9167
Traceback (most recent call last):
9168
...
9169
ValueError: unable to compute Jordan canonical form for a matrix
9170
sage: C.jordan_form()
9171
Traceback (most recent call last):
9172
...
9173
RuntimeError: Some eigenvalue does not exist in Finite Field in a of size 7^2.
9174
9175
Inexact rings and fields are also not supported. ::
9176
9177
sage: A = matrix(CDF, 2, 2, range(4))
9178
sage: B = copy(A)
9179
sage: A.is_similar(B)
9180
Traceback (most recent call last):
9181
...
9182
ValueError: unable to compute Jordan canonical form for a matrix
9183
9184
Rectangular matrices and mismatched sizes return quickly. ::
9185
9186
sage: A = matrix(3, 2, range(6))
9187
sage: B = copy(A)
9188
sage: A.is_similar(B)
9189
False
9190
sage: A = matrix(2, 2, range(4))
9191
sage: B = matrix(3, 3, range(9))
9192
sage: A.is_similar(B, transformation=True)
9193
(False, None)
9194
9195
If the fraction fields of the entries are unequal, it is an error,
9196
except in the case when the rationals gets promoted to the
9197
algebraic numbers. ::
9198
9199
sage: A = matrix(ZZ, 2, 2, range(4))
9200
sage: B = matrix(GF(2), 2, 2, range(4))
9201
sage: A.is_similar(B, transformation=True)
9202
Traceback (most recent call last):
9203
...
9204
TypeError: matrices need to have entries with identical fraction fields, not Algebraic Field and Finite Field of size 2
9205
sage: A = matrix(ZZ, 2, 2, range(4))
9206
sage: B = matrix(QQbar, 2, 2, range(4))
9207
sage: A.is_similar(B)
9208
True
9209
9210
Inputs are checked. ::
9211
9212
sage: A = matrix(ZZ, 2, 2, range(4))
9213
sage: A.is_similar('garbage')
9214
Traceback (most recent call last):
9215
...
9216
TypeError: similarity requires a matrix as an argument, not garbage
9217
sage: B = copy(A)
9218
sage: A.is_similar(B, transformation='junk')
9219
Traceback (most recent call last):
9220
...
9221
ValueError: transformation keyword must be True or False, not junk
9222
"""
9223
import sage.matrix.matrix
9224
import sage.rings.qqbar
9225
if not sage.matrix.matrix.is_Matrix(other):
9226
raise TypeError('similarity requires a matrix as an argument, not {0}'.format(other))
9227
if transformation not in [True, False]:
9228
raise ValueError('transformation keyword must be True or False, not {0}'.format(transformation))
9229
# easy false situations
9230
if not self.is_square() or not other.is_square():
9231
if transformation:
9232
return (False, None)
9233
else:
9234
return False
9235
if self.nrows() != other.nrows():
9236
if transformation:
9237
return (False, None)
9238
else:
9239
return False
9240
# convert to fraction fields for base rings
9241
A = self.matrix_over_field()
9242
B = other.matrix_over_field()
9243
# move rationals to algebraically closed algebraic numbers
9244
if A.base_ring() == QQ:
9245
A = A.change_ring(sage.rings.qqbar.QQbar)
9246
if B.base_ring() == QQ:
9247
B = B.change_ring(sage.rings.qqbar.QQbar)
9248
# require identical base fields
9249
if A.base_ring() != B.base_ring():
9250
raise TypeError('matrices need to have entries with identical fraction fields, not {0} and {1}'.format(A.base_ring(), B.base_ring()))
9251
# unequal characteristic polynomials implies not similar
9252
# and avoids any problems with eigenvalues not in the base field
9253
if A.charpoly() != B.charpoly():
9254
if transformation:
9255
return (False, None)
9256
else:
9257
return False
9258
# now more precisely compare Jordan form, and optionally get transformations
9259
try:
9260
if transformation:
9261
JA, SA = A.jordan_form(transformation=True)
9262
else:
9263
JA = A.jordan_form(transformation=False)
9264
except:
9265
raise ValueError('unable to compute Jordan canonical form for a matrix')
9266
try:
9267
if transformation:
9268
JB, SB = B.jordan_form(transformation=True)
9269
else:
9270
JB = B.jordan_form(transformation=False)
9271
except:
9272
raise ValueError('unable to compute Jordan canonical form for a matrix')
9273
similar = (JA == JB)
9274
transform = None
9275
if similar and transformation:
9276
transform = SB*SA.inverse()
9277
if transformation:
9278
return (similar, transform)
9279
else:
9280
return similar
9281
9282
def symplectic_form(self):
9283
r"""
9284
Find a symplectic form for self if self is an anti-symmetric,
9285
alternating matrix defined over a field.
9286
9287
Returns a pair (F, C) such that the rows of C form a symplectic
9288
basis for self and F = C \* self \* C.transpose().
9289
9290
Raises a ValueError if not over a field, or self is not
9291
anti-symmetric, or self is not alternating.
9292
9293
Anti-symmetric means that `M = -M^t`. Alternating means
9294
that the diagonal of `M` is identically zero.
9295
9296
A symplectic basis is a basis of the form
9297
`e_1, \ldots, e_j, f_1, \ldots f_j, z_1, \dots, z_k`
9298
such that
9299
9300
- `z_i M v^t` = 0 for all vectors `v`
9301
9302
- `e_i M {e_j}^t = 0` for all `i, j`
9303
9304
- `f_i M {f_j}^t = 0` for all `i, j`
9305
9306
- `e_i M {f_i}^t = 1` for all `i`
9307
9308
- `e_i M {f_j}^t = 0` for all `i` not equal
9309
`j`.
9310
9311
See the example for a pictorial description of such a basis.
9312
9313
EXAMPLES::
9314
9315
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
9316
[ 0 -1/2 -2 1/2 2 0 -2 1]
9317
[ 1/2 0 -1 -3 0 2 5/2 -3]
9318
[ 2 1 0 3/2 -1 0 -1 -2]
9319
[-1/2 3 -3/2 0 1 3/2 -1/2 -1/2]
9320
[ -2 0 1 -1 0 0 1 -1]
9321
[ 0 -2 0 -3/2 0 0 1/2 -2]
9322
[ 2 -5/2 1 1/2 -1 -1/2 0 -1]
9323
[ -1 3 2 1/2 1 2 1 0]
9324
sage: F, C = E.symplectic_form(); F
9325
[ 0 0 0 0 1 0 0 0]
9326
[ 0 0 0 0 0 1 0 0]
9327
[ 0 0 0 0 0 0 1 0]
9328
[ 0 0 0 0 0 0 0 1]
9329
[-1 0 0 0 0 0 0 0]
9330
[ 0 -1 0 0 0 0 0 0]
9331
[ 0 0 -1 0 0 0 0 0]
9332
[ 0 0 0 -1 0 0 0 0]
9333
sage: F == C * E * C.transpose()
9334
True
9335
"""
9336
import sage.matrix.symplectic_basis
9337
return sage.matrix.symplectic_basis.symplectic_basis_over_field(self)
9338
9339
def cholesky_decomposition(self):
9340
r"""
9341
Return the Cholesky decomposition of ``self``.
9342
9343
.. WARNING::
9344
9345
``cholesky_decomposition()`` is deprecated,
9346
please use :meth:`cholesky` instead.
9347
9348
The computed decomposition is cached and returned on
9349
subsequent calls. Methods such as :meth:`solve_left` may also
9350
take advantage of the cached decomposition depending on the
9351
exact implementation.
9352
9353
INPUT:
9354
9355
The input matrix must be:
9356
9357
- real, symmetric, and positive definite; or
9358
9359
- complex, Hermitian, and positive definite.
9360
9361
If not, a ``ValueError`` exception will be raised.
9362
9363
OUTPUT:
9364
9365
An immutable lower triangular matrix `L` such that `L L^t` equals ``self``.
9366
9367
ALGORITHM:
9368
9369
Calls the method ``_cholesky_decomposition_``, which by
9370
default uses a standard recursion.
9371
9372
.. warning::
9373
9374
This implementation uses a standard recursion that is not known to
9375
be numerically stable.
9376
9377
.. warning::
9378
9379
It is potentially expensive to ensure that the input is
9380
positive definite. Therefore this is not checked and it
9381
is possible that the output matrix is *not* a valid
9382
Cholesky decomposition of ``self``. An example of this is
9383
given in the tests below.
9384
9385
EXAMPLES:
9386
9387
Here is an example over the real double field; internally, this uses SciPy::
9388
9389
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 ])
9390
sage: m = r * r.transpose(); m
9391
[ 1.0 1.0 1.0 1.0 1.0]
9392
[ 1.0 5.0 31.0 121.0 341.0]
9393
[ 1.0 31.0 341.0 1555.0 4681.0]
9394
[ 1.0 121.0 1555.0 7381.0 22621.0]
9395
[ 1.0 341.0 4681.0 22621.0 69905.0]
9396
sage: L = m.cholesky_decomposition(); L
9397
doctest:...: DeprecationWarning: (Since Sage Version 5.1)
9398
cholesky_decomposition() is deprecated; please use cholesky() instead.
9399
[ 1.0 0.0 0.0 0.0 0.0]
9400
[ 1.0 2.0 0.0 0.0 0.0]
9401
[ 1.0 15.0 10.7238052948 0.0 0.0]
9402
[ 1.0 60.0 60.9858144589 7.79297342371 0.0]
9403
[ 1.0 170.0 198.623524155 39.3665667796 1.72309958068]
9404
sage: L.parent()
9405
Full MatrixSpace of 5 by 5 dense matrices over Real Double Field
9406
sage: L*L.transpose()
9407
[ 1.0 1.0 1.0 1.0 1.0]
9408
[ 1.0 5.0 31.0 121.0 341.0]
9409
[ 1.0 31.0 341.0 1555.0 4681.0]
9410
[ 1.0 121.0 1555.0 7381.0 22621.0]
9411
[ 1.0 341.0 4681.0 22621.0 69905.0]
9412
sage: ( L*L.transpose() - m ).norm(1) < 2^-30
9413
True
9414
9415
The result is immutable::
9416
9417
sage: L[0,0] = 0
9418
Traceback (most recent call last):
9419
...
9420
ValueError: matrix is immutable; please change a copy instead (i.e., use copy(M) to change a copy of M).
9421
9422
Here is an example over a higher precision real field::
9423
9424
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 ])
9425
sage: m = r * r.transpose()
9426
sage: L = m.cholesky_decomposition()
9427
sage: L.parent()
9428
Full MatrixSpace of 5 by 5 dense matrices over Real Field with 100 bits of precision
9429
sage: ( L*L.transpose() - m ).norm(1) < 2^-50
9430
True
9431
9432
Here is a Hermitian example::
9433
9434
sage: r = matrix(CDF, 2, 2, [ 1, -2*I, 2*I, 6 ]); r
9435
[ 1.0 -2.0*I]
9436
[ 2.0*I 6.0]
9437
sage: r.eigenvalues()
9438
[0.298437881284, 6.70156211872]
9439
sage: ( r - r.conjugate().transpose() ).norm(1) < 1e-30
9440
True
9441
sage: L = r.cholesky_decomposition(); L
9442
[ 1.0 0.0]
9443
[ 2.0*I 1.41421356237]
9444
sage: ( r - L*L.conjugate().transpose() ).norm(1) < 1e-30
9445
True
9446
sage: L.parent()
9447
Full MatrixSpace of 2 by 2 dense matrices over Complex Double Field
9448
9449
TESTS:
9450
9451
The following examples are not positive definite::
9452
9453
sage: m = -identity_matrix(3).change_ring(RDF)
9454
sage: m.cholesky_decomposition()
9455
Traceback (most recent call last):
9456
...
9457
ValueError: The input matrix was not symmetric and positive definite
9458
9459
sage: m = -identity_matrix(2).change_ring(RealField(100))
9460
sage: m.cholesky_decomposition()
9461
Traceback (most recent call last):
9462
...
9463
ValueError: The input matrix was not symmetric and positive definite
9464
9465
Here is a large example over a higher precision complex field::
9466
9467
sage: r = MatrixSpace(ComplexField(100), 6, 6).random_element()
9468
sage: m = r * r.conjugate().transpose()
9469
sage: m.change_ring(CDF) # for display purposes
9470
[ 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]
9471
[ 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]
9472
[-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]
9473
[ 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]
9474
[ 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]
9475
[ -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]
9476
sage: eigs = m.change_ring(CDF).eigenvalues() # again for display purposes
9477
sage: all(abs(imag(e)) < 1.3e-15 for e in eigs)
9478
True
9479
sage: [real(e) for e in eigs]
9480
[12.1121838768, 5.17714373118, 0.183583821657, 0.798520682956, 2.03399202232, 3.81092266261]
9481
9482
sage: ( m - m.conjugate().transpose() ).norm(1) < 1e-50
9483
True
9484
sage: L = m.cholesky_decomposition(); L.change_ring(CDF)
9485
[ 2.00870926089 0.0 0.0 0.0 0.0 0.0]
9486
[ 0.825730396261 - 0.599366189511*I 2.03802923221 0.0 0.0 0.0 0.0]
9487
[ -0.137091748475 + 0.195438618996*I 0.20761467212 - 0.145606613292*I 1.38750721467 0.0 0.0 0.0]
9488
[ 0.321609099528 + 0.898225453828*I -0.477666770113 + 0.0346666053769*I -0.416429223553 - 0.094835914364*I 1.65839194165 0.0 0.0]
9489
[ 0.576980839012 - 1.17091282993*I 0.232362216253 - 0.318581071175*I 0.880672963687 - 0.692440838276*I -0.920603548686 + 0.566479149373*I 0.992988116915 0.0]
9490
[ -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]
9491
sage: ( m - L*L.conjugate().transpose() ).norm(1) < 1e-20
9492
True
9493
sage: L.parent()
9494
Full MatrixSpace of 6 by 6 dense matrices over Complex Field with 100 bits of precision
9495
sage: L[0,0] = 0
9496
Traceback (most recent call last):
9497
...
9498
ValueError: matrix is immutable; please change a copy instead (i.e., use copy(M) to change a copy of M).
9499
9500
Here is an example that returns an incorrect answer, because the input is *not* positive definite::
9501
9502
sage: r = matrix(CDF, 2, 2, [ 1, -2*I, 2*I, 0 ]); r
9503
[ 1.0 -2.0*I]
9504
[ 2.0*I 0.0]
9505
sage: r.eigenvalues()
9506
[2.56155281281, -1.56155281281]
9507
sage: ( r - r.conjugate().transpose() ).norm(1) < 1e-30
9508
True
9509
sage: L = r.cholesky_decomposition(); L
9510
[ 1.0 0.0]
9511
[2.0*I 2.0*I]
9512
sage: L*L.conjugate().transpose()
9513
[ 1.0 -2.0*I]
9514
[ 2.0*I 8.0]
9515
9516
This test verifies that the caching of the two variants
9517
of the Cholesky decomposition have been cleanly separated.
9518
It can be safely removed as part of removing this method
9519
at the end of the deprecation period.
9520
(From :trac:`13045`.) ::
9521
9522
sage: r = matrix(CDF, 2, 2, [ 0, -2*I, 2*I, 0 ]); r
9523
[ 0.0 -2.0*I]
9524
[ 2.0*I 0.0]
9525
sage: r.cholesky_decomposition()
9526
[ 0.0 0.0]
9527
[NaN + NaN*I NaN + NaN*I]
9528
sage: r.cholesky()
9529
Traceback (most recent call last):
9530
...
9531
ValueError: matrix is not positive definite
9532
sage: r[0,0] = 0 # clears cache
9533
sage: r.cholesky()
9534
Traceback (most recent call last):
9535
...
9536
ValueError: matrix is not positive definite
9537
sage: r.cholesky_decomposition()
9538
[ 0.0 0.0]
9539
[NaN + NaN*I NaN + NaN*I]
9540
"""
9541
# deprecation added 2012-05-27
9542
from sage.misc.misc import deprecation
9543
deprecation("cholesky_decomposition() is deprecated; please use cholesky() instead.", "Sage Version 5.1")
9544
assert self._nrows == self._ncols, "Can only Cholesky decompose square matrices"
9545
if self._nrows == 0:
9546
return self.__copy__()
9547
return self._cholesky_decomposition_()
9548
9549
def _cholesky_decomposition_(self):
9550
r"""
9551
Return the Cholesky decomposition of ``self``; see ``cholesky_decomposition``.
9552
9553
This generic implementation uses a standard recursion.
9554
"""
9555
L = self.fetch('cholesky_broken')
9556
if L is None:
9557
A = self.__copy__()
9558
L = A.parent()(0)
9559
n = self.nrows()
9560
for k in range(0, n-1 + 1):
9561
try:
9562
L[k, k] = A[k, k].sqrt()
9563
except TypeError:
9564
raise ValueError, "The input matrix was not symmetric and positive definite"
9565
9566
for s in range(k+1, n):
9567
L[s, k] = A[s, k] / L[k, k]
9568
for j in range(k+1, n):
9569
for i in range(j, n):
9570
A[i, j] -= L[i, k]*L[j, k].conjugate()
9571
L.set_immutable()
9572
self.cache('cholesky_broken', L)
9573
return L
9574
9575
def cholesky(self):
9576
r"""
9577
Returns the Cholesky decomposition of a symmetric or Hermitian matrix.
9578
9579
INPUT:
9580
9581
A square matrix that is real, symmetric and positive definite.
9582
Or a square matrix that is complex, Hermitian and positive
9583
definite. Generally, the base ring for the entries of the
9584
matrix needs to be a subfield of the algebraic numbers
9585
(``QQbar``). Examples include the rational numbers (``QQ``),
9586
some number fields, and real algebraic numbers and the
9587
algebraic numbers themselves.
9588
9589
OUTPUT:
9590
9591
For a matrix `A` the routine returns a lower triangular
9592
matrix `L` such that,
9593
9594
.. math::
9595
9596
A = LL^\ast
9597
9598
where `L^\ast` is the conjugate-transpose in the complex case,
9599
and just the transpose in the real case. If the matrix
9600
fails to be positive definite (perhaps because it is not
9601
symmetric or Hermitian), then a ``ValueError`` results.
9602
9603
ALGORITHM:
9604
9605
Whether or not the matrix is positive definite is checked
9606
first in every case. This is accomplished with an
9607
indefinite factorization (see :meth:`indefinite_factorization`)
9608
which caches its result. This algorithm is of an order `n^3/3`.
9609
If the matrix is positive definite, this computation always
9610
succeeds, using just field operations. The transistion to a
9611
Cholesky decomposition "only" requires computing square roots
9612
of the positive (real) entries of the diagonal matrix produced in
9613
the indefinite factorization. Hence, there is no real penalty
9614
in the positive definite check (here, or prior to calling this
9615
routine), but a field extension with square roots may not be
9616
implemented in all reasonable cases.
9617
9618
EXAMPLES:
9619
9620
This simple example has a result with entries that remain
9621
in the field of rational numbers. ::
9622
9623
sage: A = matrix(QQ, [[ 4, -2, 4, 2],
9624
... [-2, 10, -2, -7],
9625
... [ 4, -2, 8, 4],
9626
... [ 2, -7, 4, 7]])
9627
sage: A.is_symmetric()
9628
True
9629
sage: L = A.cholesky()
9630
sage: L
9631
[ 2 0 0 0]
9632
[-1 3 0 0]
9633
[ 2 0 2 0]
9634
[ 1 -2 1 1]
9635
sage: L.parent()
9636
Full MatrixSpace of 4 by 4 dense matrices over Rational Field
9637
sage: L*L.transpose() == A
9638
True
9639
9640
This seemingly simple example requires first moving to
9641
the rational numbers for field operations, and then square
9642
roots necessitate that the result has entries in the field
9643
of algebraic numbers. ::
9644
9645
sage: A = matrix(ZZ, [[ 78, -30, -37, -2],
9646
... [-30, 102, 179, -18],
9647
... [-37, 179, 326, -38],
9648
... [ -2, -18, -38, 15]])
9649
sage: A.is_symmetric()
9650
True
9651
sage: L = A.cholesky()
9652
sage: L
9653
[ 8.83176086632785? 0 0 0]
9654
[ -3.396831102433787? 9.51112708681461? 0 0]
9655
[ -4.189425026335004? 17.32383862241232? 2.886751345948129? 0]
9656
[-0.2264554068289192? -1.973397116652010? -1.649572197684645? 2.886751345948129?]
9657
sage: L.parent()
9658
Full MatrixSpace of 4 by 4 dense matrices over Algebraic Field
9659
sage: L*L.transpose() == A
9660
True
9661
9662
Some subfields of the complex numbers, such as this number
9663
field of complex numbers with rational real and imaginary parts,
9664
allow for this computation. ::
9665
9666
sage: C.<I> = QuadraticField(-1)
9667
sage: A = matrix(C, [[ 23, 17*I + 3, 24*I + 25, 21*I],
9668
... [ -17*I + 3, 38, -69*I + 89, 7*I + 15],
9669
... [-24*I + 25, 69*I + 89, 976, 24*I + 6],
9670
... [ -21*I, -7*I + 15, -24*I + 6, 28]])
9671
sage: A.is_hermitian()
9672
True
9673
sage: L = A.cholesky()
9674
sage: L
9675
[ 4.79...? 0 0 0]
9676
[ 0.62...? - 3.54...?*I 5.00...? 0 0]
9677
[ 5.21...? - 5.00...?*I 13.58...? + 10.72...?*I 24.98...? 0]
9678
[ -4.37...?*I -0.10...? - 0.85...?*I -0.21...? + 0.37...?*I 2.81...?]
9679
sage: L.parent()
9680
Full MatrixSpace of 4 by 4 dense matrices over Algebraic Field
9681
sage: (L*L.conjugate_transpose() - A.change_ring(QQbar)).norm() < 10^-10
9682
True
9683
9684
The field of algebraic numbers is an ideal setting for this
9685
computation. ::
9686
9687
sage: A = matrix(QQbar, [[ 2, 4 + 2*I, 6 - 4*I],
9688
... [ -2*I + 4, 11, 10 - 12*I],
9689
... [ 4*I + 6, 10 + 12*I, 37]])
9690
sage: A.is_hermitian()
9691
True
9692
sage: L = A.cholesky()
9693
sage: L
9694
[ 1.414213562373095? 0 0]
9695
[2.828427124746190? - 1.414213562373095?*I 1 0]
9696
[4.242640687119285? + 2.828427124746190?*I -2*I + 2 1.732050807568878?]
9697
sage: L.parent()
9698
Full MatrixSpace of 3 by 3 dense matrices over Algebraic Field
9699
sage: (L*L.conjugate_transpose() - A.change_ring(QQbar)).norm() < 10^-10
9700
True
9701
9702
9703
Results are cached, hence immutable. Use the ``copy`` function
9704
if you need to make a change. ::
9705
9706
sage: A = matrix(QQ, [[ 4, -2, 4, 2],
9707
... [-2, 10, -2, -7],
9708
... [ 4, -2, 8, 4],
9709
... [ 2, -7, 4, 7]])
9710
sage: L = A.cholesky()
9711
sage: L.is_immutable()
9712
True
9713
9714
sage: from copy import copy
9715
sage: LC = copy(L)
9716
sage: LC[0,0] = 1000
9717
sage: LC
9718
[1000 0 0 0]
9719
[ -1 3 0 0]
9720
[ 2 0 2 0]
9721
[ 1 -2 1 1]
9722
9723
There are a variety of situations which will prevent the computation of a Cholesky decomposition.
9724
9725
The base ring must be exact. For numerical work, create a
9726
matrix with a base ring of ``RDF`` or ``CDF`` and use the
9727
:meth:`~sage.matrix.matrix_double_dense.Matrix_double_dense.cholesky`
9728
method for matrices of that type. ::
9729
9730
sage: F = RealField(100)
9731
sage: A = matrix(F, [[1.0, 3.0], [3.0, -6.0]])
9732
sage: A.cholesky()
9733
Traceback (most recent call last):
9734
...
9735
TypeError: base ring of the matrix must be exact, not Real Field with 100 bits of precision
9736
9737
The base ring may not have a fraction field. ::
9738
9739
sage: A = matrix(Integers(6), [[2, 0], [0, 4]])
9740
sage: A.cholesky()
9741
Traceback (most recent call last):
9742
...
9743
ValueError: unable to check positive definiteness because
9744
Unable to create the fraction field of Ring of integers modulo 6
9745
9746
The base field may not have elements that are comparable to zero. ::
9747
9748
sage: F.<a> = FiniteField(5^4)
9749
sage: A = matrix(F, [[2+a^3, 3], [3, 3]])
9750
sage: A.cholesky()
9751
Traceback (most recent call last):
9752
...
9753
ValueError: unable to check positive definiteness because
9754
cannot convert computations from Finite Field in a of size 5^4 into real numbers
9755
9756
The algebraic closure of the fraction field of the base ring may not be implemented. ::
9757
9758
sage: F = Integers(7)
9759
sage: A = matrix(F, [[4, 0], [0, 3]])
9760
sage: A.cholesky()
9761
Traceback (most recent call last):
9762
...
9763
TypeError: base field needs an algebraic closure with square roots,
9764
not Ring of integers modulo 7
9765
9766
The matrix may not be positive definite. ::
9767
9768
sage: C.<I> = QuadraticField(-1)
9769
sage: B = matrix(C, [[ 2, 4 - 2*I, 2 + 2*I],
9770
... [4 + 2*I, 8, 10*I],
9771
... [2 - 2*I, -10*I, -3]])
9772
sage: B.is_positive_definite()
9773
False
9774
sage: B.cholesky()
9775
Traceback (most recent call last):
9776
...
9777
ValueError: matrix is not positive definite,
9778
so cannot compute Cholesky decomposition
9779
9780
The matrix could be positive semi-definite, and thus
9781
lack a Cholesky decomposition. ::
9782
9783
sage: A = matrix(QQ, [[21, 15, 12, -3],
9784
... [15, 12, 9, 12],
9785
... [12, 9, 7, 3],
9786
... [-3, 12, 3, 8]])
9787
sage: A.is_positive_definite()
9788
False
9789
sage: [A[:i,:i].determinant() for i in range(1,A.nrows()+1)]
9790
[21, 27, 0, 0]
9791
sage: A.cholesky()
9792
Traceback (most recent call last):
9793
...
9794
ValueError: matrix is not positive definite,
9795
so cannot compute Cholesky decomposition
9796
9797
Even in light of the above, you can sometimes get lucky
9798
and arrive at a situation where a particular matrix has
9799
a Cholesky decomposition when the general characteristics
9800
of the matrix suggest this routine would fail. In this
9801
example, the indefinite factorization produces a
9802
diagonal matrix whose elements from the finite field
9803
convert naturally to positive integers and are also
9804
perfect squares. ::
9805
9806
sage: F.<a> = FiniteField(5^3)
9807
sage: A = matrix(F, [[ 4, 2*a^2 + 3, 4*a + 1],
9808
... [ 2*a^2 + 3, 2*a + 2, 4*a^2 + 4*a + 4],
9809
... [ 4*a + 1, 4*a^2 + 4*a + 4, a^2 + 4*a]])
9810
sage: A.is_symmetric()
9811
True
9812
sage: L = A.cholesky()
9813
sage: L
9814
[ 3 0 0]
9815
[ 4*a^2 + 1 1 0]
9816
[ 3*a + 2 a^2 + 2*a + 3 3]
9817
sage: L*L.transpose() == A
9818
True
9819
9820
TESTS:
9821
9822
This verifies that :trac:`11274` is resolved. ::
9823
9824
sage: E = matrix(QQ, [[2, 1], [1, 1]])
9825
sage: E.is_symmetric()
9826
True
9827
sage: E.eigenvalues()
9828
[0.38...?, 2.61...?]
9829
sage: E.det()
9830
1
9831
sage: E.cholesky()
9832
[ 1.414213562373095? 0]
9833
[0.7071067811865475? 0.7071067811865475?]
9834
9835
AUTHOR:
9836
9837
- Rob Beezer (2012-05-27)
9838
"""
9839
from copy import copy
9840
C = self.fetch('cholesky')
9841
if C is None:
9842
if not self.is_square():
9843
msg = "matrix must be square, not {0} x {1}"
9844
raise ValueError(msg.format(self.nrows(), self.ncols()))
9845
if not self.base_ring().is_exact():
9846
msg = 'base ring of the matrix must be exact, not {0}'
9847
raise TypeError(msg.format(self.base_ring()))
9848
try:
9849
posdef = self.is_positive_definite()
9850
except (ValueError, TypeError) as e:
9851
msg = "unable to check positive definiteness because {0}"
9852
raise ValueError(msg.format(e))
9853
if not posdef:
9854
msg = "matrix is not positive definite, so cannot compute Cholesky decomposition"
9855
raise ValueError(msg)
9856
# the successful positive definite check will cache a Hermitian
9857
# or symmetric indefinite factorization, as appropriate
9858
factors = self.fetch('indefinite_factorization_hermitian')
9859
if factors is None:
9860
factors = self.fetch('indefinite_factorization_symmetric')
9861
L = factors[0]
9862
d = factors[1]
9863
F = L.base_ring() # field really
9864
splits = [] # square roots of diagonal entries
9865
for x in d:
9866
try:
9867
sqrt = F(x.sqrt())
9868
except (TypeError, ValueError):
9869
try:
9870
F = F.algebraic_closure()
9871
except (NotImplementedError, AttributeError):
9872
msg = "base field needs an algebraic closure with square roots, not {0}"
9873
raise TypeError(msg.format(F))
9874
# try again
9875
sqrt = F(x.sqrt())
9876
splits.append(sqrt)
9877
# move square root of the diagonal matrix
9878
# into the lower triangular matrix
9879
# We need a copy, to break immutability
9880
# and the field may have changed as well
9881
C = copy(L)
9882
if F != C.base_ring():
9883
C = C.change_ring(F)
9884
for c in range(C.ncols()):
9885
C.rescale_col(c, splits[c])
9886
C.set_immutable()
9887
self.cache('cholesky', C)
9888
return C
9889
9890
def LU(self, pivot=None, format='plu'):
9891
r"""
9892
Finds a decomposition into a lower-triangular matrix and
9893
an upper-triangular matrix.
9894
9895
INPUT:
9896
9897
- ``pivot`` - pivoting strategy
9898
9899
- 'auto' (default) - see if the matrix entries are
9900
ordered (i.e. if they have an absolute value method),
9901
and if so, use a the partial pivoting strategy.
9902
Otherwise, fall back to the nonzero strategy. This
9903
is the best choice for general routines that may
9904
call this for matrix entries of a variety of types.
9905
9906
- 'partial' - each column is examined for
9907
the element with the largest absolute value and the
9908
row containing this element is swapped into place.
9909
9910
- 'nonzero' - the first nonzero element in a column
9911
is located and the row with this element is used.
9912
9913
- ``format`` - contents of output, see more discussion
9914
below about output.
9915
9916
- 'plu' (default) - a triple; matrices P, L and U
9917
such that A = P*L*U.
9918
9919
- 'compact' - a pair; row permutation as a tuple, and the
9920
matrices L and U combined into one matrix.
9921
9922
OUTPUT:
9923
9924
Suppose that `A` is an `m\times n` matrix, then an LU
9925
decomposition is a lower-triangular `m\times m` matrix
9926
`L` with every diagonal element equal to 1, and an
9927
upper-triangular `m\times n` matrix, `U` such that the
9928
product `LU`, after a permutation of the rows, is then
9929
equal to `A`. For the 'plu' format the permutation is
9930
returned as an `m\times m` permutation matrix `P` such
9931
that
9932
9933
.. math::
9934
9935
A = PLU
9936
9937
It is more common to place the permutation matrix just
9938
to the left of `A`. If you desire this version, then
9939
use the inverse of `P` which is computed most efficiently
9940
as its transpose.
9941
9942
If the 'partial' pivoting strategy is used, then the
9943
non-diagonal entries of `L` will be less than or equal
9944
to 1 in absolute value. The 'nonzero' pivot strategy may
9945
be faster, but the growth of data structures for elements of
9946
the decomposition might counteract the advantage.
9947
9948
By necessity, returned matrices have a base ring equal
9949
to the fraction field of the base ring of the original matrix.
9950
9951
In the 'compact' format, the first returned value is a
9952
tuple that is a permutation of the rows of `LU` that yields
9953
`A`. See the doctest for how you might employ this
9954
permutation. Then the matrices `L` and `U` are merged
9955
into one matrix -- remove the diagonal of ones in `L`
9956
and the remaining nonzero entries can replace the
9957
entries of `U` beneath the diagonal.
9958
9959
The results are cached, only in the compact format, separately
9960
for each pivot strategy called. Repeated requests for the
9961
'plu' format will require just a small amount of overhead
9962
in each call to bust out the compact format to the three
9963
matrices. Since only the compact format is cached, the
9964
components of the compact format are immutable, while the
9965
components of the 'plu' format are regenerated, and hence
9966
are mutable.
9967
9968
Notice that while `U` is similar to row-echelon form and the
9969
rows of `U` span the row space of `A`, the rows of `U` are not
9970
generally linearly independent. Nor are the pivot columns
9971
(or rank) immediately obvious. However for rings without
9972
specialized echelon form routines, this method is about
9973
twice as fast as the generic echelon form routine since
9974
it only acts "below the diagonal", as would be predicted
9975
from a theoretical analysis of the algorithms.
9976
9977
.. note::
9978
9979
This is an exact computation, so limited to exact
9980
rings. If you need numerical results, convert the
9981
base ring to the field of real double numbers,
9982
``RDF`` or the field of complex double numbers,
9983
``CDF``, which will use a faster routine that
9984
is careful about numerical subtleties.
9985
9986
ALGORITHM:
9987
9988
"Gaussian Elimination with Partial Pivoting,"
9989
Algorithm 21.1 of [TREFETHEN-BAU]_.
9990
9991
EXAMPLES:
9992
9993
Notice the difference in the `L` matrix as a result of different
9994
pivoting strategies. With partial pivoting, every entry of `L`
9995
has absolute value 1 or less. ::
9996
9997
sage: A = matrix(QQ, [[1, -1, 0, 2, 4, 7, -1],
9998
... [2, -1, 0, 6, 4, 8, -2],
9999
... [2, 0, 1, 4, 2, 6, 0],
10000
... [1, 0, -1, 8, -1, -1, -3],
10001
... [1, 1, 2, -2, -1, 1, 3]])
10002
sage: P, L, U = A.LU(pivot='partial')
10003
sage: P
10004
[0 0 0 0 1]
10005
[1 0 0 0 0]
10006
[0 0 0 1 0]
10007
[0 0 1 0 0]
10008
[0 1 0 0 0]
10009
sage: L
10010
[ 1 0 0 0 0]
10011
[ 1/2 1 0 0 0]
10012
[ 1/2 1/3 1 0 0]
10013
[ 1 2/3 1/5 1 0]
10014
[ 1/2 -1/3 -2/5 0 1]
10015
sage: U
10016
[ 2 -1 0 6 4 8 -2]
10017
[ 0 3/2 2 -5 -3 -3 4]
10018
[ 0 0 -5/3 20/3 -2 -4 -10/3]
10019
[ 0 0 0 0 2/5 4/5 0]
10020
[ 0 0 0 0 1/5 2/5 0]
10021
sage: A == P*L*U
10022
True
10023
sage: P, L, U = A.LU(pivot='nonzero')
10024
sage: P
10025
[1 0 0 0 0]
10026
[0 1 0 0 0]
10027
[0 0 1 0 0]
10028
[0 0 0 1 0]
10029
[0 0 0 0 1]
10030
sage: L
10031
[ 1 0 0 0 0]
10032
[ 2 1 0 0 0]
10033
[ 2 2 1 0 0]
10034
[ 1 1 -1 1 0]
10035
[ 1 2 2 0 1]
10036
sage: U
10037
[ 1 -1 0 2 4 7 -1]
10038
[ 0 1 0 2 -4 -6 0]
10039
[ 0 0 1 -4 2 4 2]
10040
[ 0 0 0 0 1 2 0]
10041
[ 0 0 0 0 -1 -2 0]
10042
sage: A == P*L*U
10043
True
10044
10045
An example of the compact format. ::
10046
10047
sage: B = matrix(QQ, [[ 1, 3, 5, 5],
10048
... [ 1, 4, 7, 8],
10049
... [-1, -4, -6, -6],
10050
... [ 0, -2, -5, -8],
10051
... [-2, -6, -6, -2]])
10052
sage: perm, M = B.LU(format='compact')
10053
sage: perm
10054
(4, 3, 0, 1, 2)
10055
sage: M
10056
[ -2 -6 -6 -2]
10057
[ 0 -2 -5 -8]
10058
[-1/2 0 2 4]
10059
[-1/2 -1/2 3/4 0]
10060
[ 1/2 1/2 -1/4 0]
10061
10062
We can easily illustrate the relationships between
10063
the two formats with a square matrix. ::
10064
10065
sage: C = matrix(QQ, [[-2, 3, -2, -5],
10066
... [ 1, -2, 1, 3],
10067
... [-4, 7, -3, -8],
10068
... [-3, 8, -1, -5]])
10069
sage: P, L, U = C.LU(format='plu')
10070
sage: perm, M = C.LU(format='compact')
10071
sage: (L - identity_matrix(4)) + U == M
10072
True
10073
sage: p = [perm[i]+1 for i in range(len(perm))]
10074
sage: PP = Permutation(p).to_matrix()
10075
sage: PP == P
10076
True
10077
10078
For a nonsingular matrix, and the 'nonzero' pivot
10079
strategy there is no need to permute rows, so the
10080
permutation matrix will be the identity. Furthermore,
10081
it can be shown that then the `L` and `U` matrices
10082
are uniquely determined by requiring `L` to have ones
10083
on the diagonal. ::
10084
10085
sage: D = matrix(QQ, [[ 1, 0, 2, 0, -2, -1],
10086
... [ 3, -2, 3, -1, 0, 6],
10087
... [-4, 2, -3, 1, -1, -8],
10088
... [-2, 2, -3, 2, 1, 0],
10089
... [ 0, -1, -1, 0, 2, 5],
10090
... [-1, 2, -4, -1, 5, -3]])
10091
sage: P, L, U = D.LU(pivot='nonzero')
10092
sage: P
10093
[1 0 0 0 0 0]
10094
[0 1 0 0 0 0]
10095
[0 0 1 0 0 0]
10096
[0 0 0 1 0 0]
10097
[0 0 0 0 1 0]
10098
[0 0 0 0 0 1]
10099
sage: L
10100
[ 1 0 0 0 0 0]
10101
[ 3 1 0 0 0 0]
10102
[ -4 -1 1 0 0 0]
10103
[ -2 -1 -1 1 0 0]
10104
[ 0 1/2 1/4 1/2 1 0]
10105
[ -1 -1 -5/2 -2 -6 1]
10106
sage: U
10107
[ 1 0 2 0 -2 -1]
10108
[ 0 -2 -3 -1 6 9]
10109
[ 0 0 2 0 -3 -3]
10110
[ 0 0 0 1 0 4]
10111
[ 0 0 0 0 -1/4 -3/4]
10112
[ 0 0 0 0 0 1]
10113
sage: D == L*U
10114
True
10115
10116
The base ring of the matrix may be any field, or a ring
10117
which has a fraction field implemented in Sage. The ring
10118
needs to be exact (there is a numerical LU decomposition
10119
for matrices over ``RDF`` and ``CDF``). Matrices returned
10120
are over the original field, or the fraction field of the
10121
ring. If the field is not ordered (i.e. the absolute value
10122
function is not implemented), then the pivot strategy needs
10123
to be 'nonzero'. ::
10124
10125
sage: A = matrix(RealField(100), 3, 3, range(9))
10126
sage: P, L, U = A.LU()
10127
Traceback (most recent call last):
10128
...
10129
TypeError: base ring of the matrix must be exact, not Real Field with 100 bits of precision
10130
10131
sage: A = matrix(Integers(6), 3, 2, range(6))
10132
sage: A.LU()
10133
Traceback (most recent call last):
10134
...
10135
TypeError: base ring of the matrix needs a field of fractions, not Ring of integers modulo 6
10136
10137
sage: R.<y> = PolynomialRing(QQ, 'y')
10138
sage: B = matrix(R, [[y+1, y^2+y], [y^2, y^3]])
10139
sage: P, L, U = B.LU(pivot='partial')
10140
Traceback (most recent call last):
10141
...
10142
TypeError: cannot take absolute value of matrix entries, try 'pivot=nonzero'
10143
sage: P, L, U = B.LU(pivot='nonzero')
10144
sage: P
10145
[1 0]
10146
[0 1]
10147
sage: L
10148
[ 1 0]
10149
[y^2/(y + 1) 1]
10150
sage: U
10151
[ y + 1 y^2 + y]
10152
[ 0 0]
10153
sage: L.base_ring()
10154
Fraction Field of Univariate Polynomial Ring in y over Rational Field
10155
sage: B == P*L*U
10156
True
10157
10158
sage: F.<a> = FiniteField(5^2)
10159
sage: C = matrix(F, [[a + 3, 4*a + 4, 2, 4*a + 2],
10160
... [3, 2*a + 4, 2*a + 4, 2*a + 1],
10161
... [3*a + 1, a + 3, 2*a + 4, 4*a + 3],
10162
... [a, 3, 3*a + 1, a]])
10163
sage: P, L, U = C.LU(pivot='nonzero')
10164
sage: P
10165
[1 0 0 0]
10166
[0 1 0 0]
10167
[0 0 1 0]
10168
[0 0 0 1]
10169
sage: L
10170
[ 1 0 0 0]
10171
[3*a + 3 1 0 0]
10172
[ 2*a 4*a + 2 1 0]
10173
[2*a + 3 2 2*a + 4 1]
10174
sage: U
10175
[ a + 3 4*a + 4 2 4*a + 2]
10176
[ 0 a + 1 a + 3 2*a + 4]
10177
[ 0 0 1 4*a + 2]
10178
[ 0 0 0 0]
10179
sage: L.base_ring()
10180
Finite Field in a of size 5^2
10181
sage: C == P*L*U
10182
True
10183
10184
With no pivoting strategy given (i.e. ``pivot=None``)
10185
the routine will try to use partial pivoting, but then
10186
fall back to the nonzero strategy. For the nonsingular
10187
matrix below, we see evidence of pivoting when viewed
10188
over the rationals, and no pivoting over the integers
10189
mod 29. ::
10190
10191
sage: entries = [3, 20, 11, 7, 16, 28, 5, 15, 21, 23, 22, 18, 8, 23, 15, 2]
10192
sage: A = matrix(Integers(29), 4, 4, entries)
10193
sage: perm, _ = A.LU(format='compact'); perm
10194
(0, 1, 2, 3)
10195
sage: B = matrix(QQ, 4, 4, entries)
10196
sage: perm, _ = B.LU(format='compact'); perm
10197
(2, 0, 1, 3)
10198
10199
The `U` matrix is only guaranteed to be upper-triangular.
10200
The rows are not necessarily linearly independent, nor are
10201
the pivots columns or rank in evidence. ::
10202
10203
sage: A = matrix(QQ, [[ 1, -4, 1, 0, -2, 1, 3, 3, 2],
10204
... [-1, 4, 0, -4, 0, -4, 5, -7, -7],
10205
... [ 0, 0, 1, -4, -1, -3, 6, -5, -6],
10206
... [-2, 8, -1, -4, 2, -4, 1, -8, -7],
10207
... [ 1, -4, 2, -4, -3, 2, 5, 6, 4]])
10208
sage: P, L, U = A.LU()
10209
sage: U
10210
[ -2 8 -1 -4 2 -4 1 -8 -7]
10211
[ 0 0 1/2 -2 -1 -2 9/2 -3 -7/2]
10212
[ 0 0 3/2 -6 -2 0 11/2 2 1/2]
10213
[ 0 0 0 0 -1/3 -1 5/3 -5/3 -5/3]
10214
[ 0 0 0 0 1/3 -3 7/3 -19/3 -19/3]
10215
sage: A.rref()
10216
[ 1 -4 0 4 0 0 -1 -1 -1]
10217
[ 0 0 1 -4 0 0 1 0 -1]
10218
[ 0 0 0 0 1 0 -2 -1 -1]
10219
[ 0 0 0 0 0 1 -1 2 2]
10220
[ 0 0 0 0 0 0 0 0 0]
10221
sage: A.pivots()
10222
(0, 2, 4, 5)
10223
10224
TESTS:
10225
10226
Unknown keywords are caught. ::
10227
10228
sage: A = matrix(ZZ, 2, range(4))
10229
sage: A.LU(pivot='junk')
10230
Traceback (most recent call last):
10231
...
10232
ValueError: pivot strategy must be None, 'partial' or 'nonzero', not junk
10233
sage: A.LU(format='garbage')
10234
Traceback (most recent call last):
10235
...
10236
ValueError: format must be 'plu' or 'compact', not garbage
10237
10238
Components of the 'compact' format are immutable, while
10239
components of the 'plu' format are not. ::
10240
10241
sage: A = matrix(ZZ, 2, range(4))
10242
sage: perm, M = A.LU(format='compact')
10243
sage: perm[0] = 25
10244
Traceback (most recent call last):
10245
...
10246
TypeError: 'tuple' object does not support item assignment
10247
sage: M.is_immutable()
10248
True
10249
sage: P, L, U = A.LU(format='plu')
10250
sage: all([A.is_mutable() for A in [P, L, U]])
10251
True
10252
10253
Partial pivoting is based on the absolute values of entries
10254
of a column. Trac #12208 shows that the return value of the
10255
absolute value must be handled carefully. This tests that
10256
situation in the case of cylotomic fields. ::
10257
10258
sage: C = SymmetricGroup(5).character_table()
10259
sage: C.base_ring()
10260
Cyclotomic Field of order 1 and degree 1
10261
sage: P, L, U = C.LU(pivot='partial')
10262
sage: C == P*L*U
10263
True
10264
10265
AUTHOR:
10266
10267
- Rob Beezer (2011-04-26)
10268
"""
10269
if not pivot in [None, 'partial', 'nonzero']:
10270
msg = "pivot strategy must be None, 'partial' or 'nonzero', not {0}"
10271
raise ValueError(msg.format(pivot))
10272
if not format in ['compact', 'plu']:
10273
msg = "format must be 'plu' or 'compact', not {0}"
10274
raise ValueError(msg.format(format))
10275
10276
# exact rings only, must have fraction field
10277
R = self.base_ring()
10278
if not R.is_exact():
10279
msg = 'base ring of the matrix must be exact, not {0}'
10280
raise TypeError(msg.format(R))
10281
if not R.is_field():
10282
try:
10283
F = R.fraction_field()
10284
except:
10285
msg = 'base ring of the matrix needs a field of fractions, not {0}'
10286
raise TypeError(msg.format(R))
10287
else:
10288
F = R
10289
10290
# 'nonzero' strategy passes through untouched
10291
# 'partial' survives iff field has absolute value
10292
# None will use 'partial' iff possible, else fallback to nonzero
10293
if pivot in [None, 'partial']:
10294
try:
10295
abs(F.an_element())
10296
pivot = 'partial'
10297
except:
10298
if pivot == 'partial':
10299
msg = "cannot take absolute value of matrix entries, try 'pivot=nonzero'"
10300
raise TypeError(msg)
10301
pivot = 'nonzero'
10302
partial = (pivot == 'partial')
10303
10304
cdef Py_ssize_t m, n, d, i, j, k, p, max_location
10305
cdef Matrix M
10306
10307
# can now access cache, else compute
10308
# the compact version of LU decomposition
10309
key = 'LU_' + pivot
10310
compact = self.fetch(key)
10311
if compact is None:
10312
if F == R:
10313
M = self.__copy__()
10314
else:
10315
M = self.change_ring(F)
10316
m, n = M._nrows, M._ncols
10317
d = min(m, n)
10318
perm = range(m)
10319
zero = F(0)
10320
for k in range(d):
10321
max_location = -1
10322
if partial:
10323
# abs() necessary to convert zero to the
10324
# correct type for comparisons (Trac #12208)
10325
max_entry = abs(zero)
10326
for i in range(k,m):
10327
entry = abs(M.get_unsafe(i,k))
10328
if entry > max_entry:
10329
max_location = i
10330
max_entry = entry
10331
else:
10332
for i in range(k,m):
10333
if M.get_unsafe(i,k) != zero:
10334
max_location = i
10335
break
10336
if max_location != -1:
10337
perm[k], perm[max_location] = perm[max_location], perm[k]
10338
M.swap_rows(k, max_location)
10339
for j in range(k+1, m):
10340
scale = -M.get_unsafe(j,k)/M.get_unsafe(k,k)
10341
M.set_unsafe(j,k, -scale)
10342
for p in range(k+1,n):
10343
M.set_unsafe(j,p, M.get_unsafe(j,p) + scale*M.get_unsafe(k,p))
10344
perm = tuple(perm)
10345
M.set_immutable()
10346
compact = (perm, M)
10347
self.cache(key, compact)
10348
10349
if format == 'compact':
10350
return compact
10351
elif format == 'plu':
10352
import sage.matrix.constructor
10353
import sage.combinat.permutation
10354
perm = compact[0]
10355
M = compact[1].__copy__()
10356
F = M.base_ring()
10357
m, n = M._nrows, M._ncols
10358
d = min(m, n)
10359
zero = F(0)
10360
perm = [perm[i]+1 for i in range(m)]
10361
P = sage.combinat.permutation.Permutation(perm).to_matrix()
10362
L = sage.matrix.constructor.identity_matrix(F, m)
10363
for i in range(1, m):
10364
for k in range(min(i,d)):
10365
L[i,k] = M[i,k]
10366
M[i,k] = zero
10367
return P, L, M
10368
10369
def _indefinite_factorization(self, algorithm, check=True):
10370
r"""
10371
Utility function to decomposes a symmetric or
10372
Hermitian matrix into a lower triangular matrix
10373
and tuple of elements for the diagonal of a diagonal matrix.
10374
10375
INPUT:
10376
10377
- ``self`` - a matrix that is symmetric or Hermitian,
10378
over a ring that has a fraction field implemented.
10379
10380
- ``algorithm`` - ``'symmetric'`` or ``'hermitian'``,
10381
according to the corresponding property of the matrix.
10382
10383
- ``check`` - default: ``True`` - if ``True`` then
10384
performs the check that the matrix is consistent with the
10385
``algorithm`` keyword.
10386
10387
OUTPUT:
10388
10389
Given a square matrix ``A``, the routine returns a
10390
pair: a matrix ``L`` and a list ``d``.
10391
10392
``L`` is a unit lower-triangular matrix. ``d`` is
10393
the entries of a diagonal matrix. Suppose this diagonal
10394
matrix is ``D``. Then, for a symmetric matrix, these items
10395
are related as:
10396
10397
.. math::
10398
10399
A = LDL^T
10400
10401
For a Hermitian matrix, the transpose can be replaced by
10402
the conjugate-transpose.
10403
10404
If any leading principal submatrix is singular, then the
10405
computation cannot be performed and a ``ValueError`` results.
10406
10407
Results are cached, and hence are immutable. Caching
10408
eliminates redundant computations across
10409
:meth:`indefinite_factorization_`, :meth:`is_positive_definite`
10410
and :meth:`cholesky_decomposition`.
10411
10412
EXAMPLES:
10413
10414
A simple symmetric matrix. ::
10415
10416
sage: A = matrix(QQ, [[ 4, -2, 4, 2],
10417
... [-2, 10, -2, -7],
10418
... [ 4, -2, 8, 4],
10419
... [ 2, -7, 4, 7]])
10420
sage: A.is_symmetric()
10421
True
10422
sage: L, d = A._indefinite_factorization('symmetric')
10423
sage: L
10424
[ 1 0 0 0]
10425
[-1/2 1 0 0]
10426
[ 1 0 1 0]
10427
[ 1/2 -2/3 1/2 1]
10428
sage: d
10429
(4, 9, 4, 1)
10430
sage: A == L*diagonal_matrix(QQ, d)*L.transpose()
10431
True
10432
10433
A Hermitian matrix. ::
10434
10435
sage: x = var('x')
10436
sage: C.<I> = NumberField(x^2 + 1)
10437
sage: A = matrix(C, [[ 23, 17*I + 3, 24*I + 25, 21*I],
10438
... [ -17*I + 3, 38, -69*I + 89, 7*I + 15],
10439
... [-24*I + 25, 69*I + 89, 976, 24*I + 6],
10440
... [ -21*I, -7*I + 15, -24*I + 6, 28]])
10441
sage: A.is_hermitian()
10442
True
10443
sage: L, d = A._indefinite_factorization('hermitian')
10444
sage: L
10445
[ 1 0 0 0]
10446
[ -17/23*I + 3/23 1 0 0]
10447
[ -24/23*I + 25/23 617/288*I + 391/144 1 0]
10448
[ -21/23*I -49/288*I - 1/48 1336/89885*I - 773/89885 1]
10449
sage: d
10450
(23, 576/23, 89885/144, 142130/17977)
10451
sage: A == L*diagonal_matrix(C, d)*L.conjugate_transpose()
10452
True
10453
10454
A matrix may have a singular submatrix in the upper-left
10455
corner ("a leading principal submatrix") which will unavoidably
10456
lead to division by zero. This is the only situation when this
10457
algorithm fails. ::
10458
10459
sage: A = matrix(QQ, [[4, 6, 1], [6, 9, 5], [1, 5, 2]])
10460
sage: B = A[0:2, 0:2]; B.determinant()
10461
0
10462
sage: A._indefinite_factorization('symmetric')
10463
Traceback (most recent call last):
10464
...
10465
ValueError: 2x2 leading principal submatrix is singular,
10466
so cannot create indefinite factorization
10467
10468
TESTS:
10469
10470
The matrix must be square. ::
10471
10472
sage: A = matrix(QQ, 3, 2, range(6))
10473
sage: A._indefinite_factorization('symmetric')
10474
Traceback (most recent call last):
10475
...
10476
ValueError: matrix must be square, not 3 x 2
10477
10478
The lone argument must describe the matrix. ::
10479
10480
sage: A = matrix(QQ, [[1, 5], [5, 8]])
10481
sage: A._indefinite_factorization('junk')
10482
Traceback (most recent call last):
10483
...
10484
ValueError: 'algorithm' must be 'symmetric' or 'hermitian',
10485
not junk
10486
10487
The matrix must contain entries from an exact ring. ::
10488
10489
sage: F = RealField(100)
10490
sage: A = matrix(F, [[1.0, 3.0], [3.0, -6.0]])
10491
sage: A._indefinite_factorization('symmetric')
10492
Traceback (most recent call last):
10493
...
10494
TypeError: entries of the matrix must be in an exact ring,
10495
not Real Field with 100 bits of precision
10496
10497
The base ring must have a fraction field. ::
10498
10499
sage: A = matrix(Integers(6), [[1, 5], [5, 8]])
10500
sage: A._indefinite_factorization('symmetric')
10501
Traceback (most recent call last):
10502
...
10503
TypeError: Unable to create the fraction field of
10504
Ring of integers modulo 6
10505
10506
When ``check`` is ``True`` (the default), the matrix is
10507
checked to see if it conforms with the ``algorithm``
10508
keyword. ::
10509
10510
sage: A = matrix(QQ, 4, 4, range(16))
10511
sage: A._indefinite_factorization('symmetric', check=True)
10512
Traceback (most recent call last):
10513
...
10514
ValueError: matrix is not symmetric (maybe try the 'hermitian' keyword)
10515
10516
sage: A = matrix([[3, 2+3*I], [5+6*I, 12]])
10517
sage: A._indefinite_factorization('hermitian', check=True)
10518
Traceback (most recent call last):
10519
...
10520
ValueError: matrix is not hermitian
10521
10522
Results are cached and hence immutable, according
10523
to the ``algorithm``. ::
10524
10525
sage: A = matrix(QQ, [[ 4, -2, 4, 2],
10526
... [-2, 10, -2, -7],
10527
... [ 4, -2, 8, 4],
10528
... [ 2, -7, 4, 7]])
10529
sage: Ls, ds = A._indefinite_factorization('symmetric')
10530
sage: Lh, dh = A._indefinite_factorization('hermitian')
10531
sage: Ls.is_immutable(), Lh.is_immutable()
10532
(True, True)
10533
sage: isinstance(ds, tuple), isinstance(dh, tuple)
10534
(True, True)
10535
10536
AUTHOR:
10537
10538
- Rob Beezer (2012-05-24)
10539
"""
10540
# Implementation note: L begins as a copy of self.
10541
# Entries below the diagonal are replaced as the loops proceed.
10542
# Entries above the diagonal are used to store entries of D*L^T,
10543
# which halves the number of multiplications needed otherwise.
10544
# The list d_inv holds reciprocals of the diagonal entries
10545
# So, below the diagonal, the main computation is:
10546
# A_ij = A_ij - (1/d_j)*sum(d_k*L_ik*L_jk, 0 <= k < j)
10547
10548
cdef Py_ssize_t m, i, j, k
10549
cdef Matrix L
10550
10551
if not algorithm in ['symmetric', 'hermitian']:
10552
msg = "'algorithm' must be 'symmetric' or 'hermitian', not {0}"
10553
raise ValueError(msg.format(algorithm))
10554
cache_string = 'indefinite_factorization_' + algorithm
10555
factors = self.fetch(cache_string)
10556
if factors is None:
10557
R = self.base_ring()
10558
if not self.is_square():
10559
msg = "matrix must be square, not {0} x {1}"
10560
raise ValueError(msg.format(self.nrows(), self.ncols()))
10561
if not algorithm in ['symmetric', 'hermitian']:
10562
msg = "'algorithm' must be 'symmetric' or 'hermitian', not {0}"
10563
raise ValueError(msg.format(algorithm))
10564
if not R.is_exact():
10565
msg = "entries of the matrix must be in an exact ring, not {0}"
10566
raise TypeError(msg.format(R))
10567
try:
10568
F = R.fraction_field()
10569
except (NotImplementedError, TypeError):
10570
msg = 'Unable to create the fraction field of {0}'
10571
raise TypeError(msg.format(R))
10572
if check and algorithm == 'symmetric':
10573
if not self.is_symmetric():
10574
msg = "matrix is not symmetric (maybe try the 'hermitian' keyword)"
10575
raise ValueError(msg)
10576
if check and algorithm == 'hermitian':
10577
if not self.is_hermitian():
10578
raise ValueError('matrix is not hermitian')
10579
conjugate = (algorithm == 'hermitian')
10580
# we need a copy no matter what, so we
10581
# (potentially) change to fraction field at the same time
10582
L = self.change_ring(F)
10583
m = L._nrows
10584
zero = F(0)
10585
one = F(1)
10586
d = []
10587
d_inv = []
10588
for i in range(m):
10589
for j in range(i+1):
10590
t = L.get_unsafe(i, j)
10591
if conjugate:
10592
for k in range(j):
10593
t -= L.get_unsafe(k,i)*L.get_unsafe(j,k).conjugate()
10594
else:
10595
for k in range(j):
10596
t -= L.get_unsafe(k,i)*L.get_unsafe(j,k)
10597
if i == j:
10598
if t == zero:
10599
msg = "{0}x{0} leading principal submatrix is singular, so cannot create indefinite factorization"
10600
raise ValueError(msg.format(i+1))
10601
d.append(t)
10602
d_inv.append(one/t)
10603
L.set_unsafe(i, i, one)
10604
else:
10605
L.set_unsafe(j, i, t)
10606
L.set_unsafe(i, j, (d_inv[j] * t))
10607
# Triangularize output matrix
10608
for i in range(m):
10609
for j in range(i+1, m):
10610
L.set_unsafe(i, j, zero)
10611
L.set_immutable()
10612
d = tuple(d)
10613
factors = (L, d)
10614
self.cache(cache_string, factors)
10615
return factors
10616
10617
def indefinite_factorization(self, algorithm='symmetric', check=True):
10618
r"""
10619
Decomposes a symmetric or Hermitian matrix into a
10620
lower triangular matrix and a diagonal matrix.
10621
10622
INPUT:
10623
10624
- ``self`` - a square matrix over a ring. The base ring
10625
must have an implemented fraction field.
10626
10627
- ``algorithm`` - default: ``'symmetric'``. Either
10628
``'symmetric'`` or ``'hermitian'``, according to if
10629
the input matrix is symmetric or hermitian.
10630
10631
- ``check`` - default: ``True`` - if ``True`` then
10632
performs the check that the matrix is consistent with the
10633
``algorithm`` keyword.
10634
10635
OUTPUT:
10636
10637
A lower triangular matrix `L` with each diagonal element
10638
equal to `1` and a vector of entries that form a
10639
diagonal matrix `D`. The vector of diagonal entries
10640
can be easily used to form the matrix, as demonstrated
10641
below in the examples.
10642
10643
For a symmetric matrix, `A`, these will be related by
10644
10645
.. math::
10646
10647
A = LDL^T
10648
10649
If `A` is Hermitian matrix, then the transpose of `L`
10650
should be replaced by the conjugate-transpose of `L`.
10651
10652
If any leading principal submatrix (a square submatrix
10653
in the upper-left corner) is singular then this method will
10654
fail with a ``ValueError``.
10655
10656
ALGORITHM:
10657
10658
The algorithm employed only uses field operations,
10659
but the compuation of each diagonal entry has the potential
10660
for division by zero. The number of operations is of order
10661
`n^3/3`, which is half the count for an LU decomposition.
10662
This makes it an appropriate candidate for solving systems
10663
with symmetric (or Hermitian) coefficient matrices.
10664
10665
EXAMPLES:
10666
10667
There is no requirement that a matrix be positive definite, as
10668
indicated by the negative entries in the resulting diagonal
10669
matrix. The default is that the input matrix is symmetric. ::
10670
10671
sage: A = matrix(QQ, [[ 3, -6, 9, 6, -9],
10672
... [-6, 11, -16, -11, 17],
10673
... [ 9, -16, 28, 16, -40],
10674
... [ 6, -11, 16, 9, -19],
10675
... [-9, 17, -40, -19, 68]])
10676
sage: A.is_symmetric()
10677
True
10678
sage: L, d = A.indefinite_factorization()
10679
sage: D = diagonal_matrix(d)
10680
sage: L
10681
[ 1 0 0 0 0]
10682
[-2 1 0 0 0]
10683
[ 3 -2 1 0 0]
10684
[ 2 -1 0 1 0]
10685
[-3 1 -3 1 1]
10686
sage: D
10687
[ 3 0 0 0 0]
10688
[ 0 -1 0 0 0]
10689
[ 0 0 5 0 0]
10690
[ 0 0 0 -2 0]
10691
[ 0 0 0 0 -1]
10692
sage: A == L*D*L.transpose()
10693
True
10694
10695
Optionally, Hermitian matrices can be factored
10696
and the result has a similar property (but not
10697
identical). Here, the field is all complex numbers
10698
with rational real and imaginary parts. As theory
10699
predicts, the diagonal entries will be real numbers. ::
10700
10701
sage: C.<I> = QuadraticField(-1)
10702
sage: B = matrix(C, [[ 2, 4 - 2*I, 2 + 2*I],
10703
... [4 + 2*I, 8, 10*I],
10704
... [2 - 2*I, -10*I, -3]])
10705
sage: B.is_hermitian()
10706
True
10707
sage: L, d = B.indefinite_factorization(algorithm='hermitian')
10708
sage: D = diagonal_matrix(d)
10709
sage: L
10710
[ 1 0 0]
10711
[ I + 2 1 0]
10712
[ -I + 1 2*I + 1 1]
10713
sage: D
10714
[ 2 0 0]
10715
[ 0 -2 0]
10716
[ 0 0 3]
10717
sage: B == L*D*L.conjugate_transpose()
10718
True
10719
10720
If a leading principal submatrix is zero this algorithm
10721
will fail. This will never happen with a positive definite
10722
matrix. ::
10723
10724
sage: A = matrix(QQ, [[21, 15, 12, -2],
10725
... [15, 12, 9, 6],
10726
... [12, 9, 7, 3],
10727
... [-2, 6, 3, 8]])
10728
sage: A.is_symmetric()
10729
True
10730
sage: A[0:3,0:3].det() == 0
10731
True
10732
sage: A.indefinite_factorization()
10733
Traceback (most recent call last):
10734
...
10735
ValueError: 3x3 leading principal submatrix is singular,
10736
so cannot create indefinite factorization
10737
10738
This algorithm only depends on field operations, so
10739
outside of the singular submatrix situation, any matrix
10740
may be factored. This provides a reasonable alternative
10741
to the Cholesky decomposition. ::
10742
10743
sage: F.<a> = FiniteField(5^3)
10744
sage: A = matrix(F,
10745
... [[ a^2 + 2*a, 4*a^2 + 3*a + 4, 3*a^2 + a, 2*a^2 + 2*a + 1],
10746
... [4*a^2 + 3*a + 4, 4*a^2 + 2, 3*a, 2*a^2 + 4*a + 2],
10747
... [ 3*a^2 + a, 3*a, 3*a^2 + 2, 3*a^2 + 2*a + 3],
10748
... [2*a^2 + 2*a + 1, 2*a^2 + 4*a + 2, 3*a^2 + 2*a + 3, 3*a^2 + 2*a + 4]])
10749
sage: A.is_symmetric()
10750
True
10751
sage: L, d = A.indefinite_factorization()
10752
sage: D = diagonal_matrix(d)
10753
sage: L
10754
[ 1 0 0 0]
10755
[4*a^2 + 4*a + 3 1 0 0]
10756
[ 3 4*a^2 + a + 2 1 0]
10757
[ 4*a^2 + 4 2*a^2 + 3*a + 3 2*a^2 + 3*a + 1 1]
10758
sage: D
10759
[ a^2 + 2*a 0 0 0]
10760
[ 0 2*a^2 + 2*a + 4 0 0]
10761
[ 0 0 3*a^2 + 4*a + 3 0]
10762
[ 0 0 0 a^2 + 3*a]
10763
sage: A == L*D*L.transpose()
10764
True
10765
10766
AUTHOR:
10767
10768
- Rob Beezer (2012-05-24)
10769
"""
10770
from sage.modules.free_module_element import vector
10771
L, d = self._indefinite_factorization(algorithm, check=check)
10772
return L, vector(L.base_ring(), d)
10773
10774
def is_positive_definite(self):
10775
r"""
10776
Determines if a real or symmetric matrix is positive definite.
10777
10778
A square matrix `A` is postive definite if it is
10779
symmetric with real entries or Hermitan with complex entries,
10780
and for every non-zero vector `\vec{x}`
10781
10782
.. math::
10783
10784
\vec{x}^\ast A\vec{x} > 0
10785
10786
Here `\vec{x}^\ast` is the conjugate-transpose, which can be
10787
simplified to just the transpose in the real case.
10788
10789
ALGORITHM:
10790
10791
A matrix is positive definite if and only if the
10792
diagonal entries from the indefinite factorization
10793
are all positive (see :meth:`indefinite_factorization`).
10794
So this algorithm is of order ``n^3/3`` and may be applied
10795
to matrices with elements of any ring that has a fraction
10796
field contained within the reals or complexes.
10797
10798
INPUT:
10799
10800
Any square matrix.
10801
10802
OUTPUT:
10803
10804
This routine will return ``True`` if the matrix is square,
10805
symmetric or Hermitian, and meets the condition above
10806
for the quadratic form.
10807
10808
The base ring for the elements of the matrix needs to
10809
have a fraction field implemented and the computations
10810
that result from the indefinite factorization must be
10811
convertable to real numbers that are comparable to zero.
10812
10813
EXAMPLES:
10814
10815
A real symmetric matrix that is positive definite,
10816
as evidenced by the positive entries for the diagonal
10817
matrix of the indefinite factorization and the postive
10818
determinants of the leading principal submatrices. ::
10819
10820
sage: A = matrix(QQ, [[ 4, -2, 4, 2],
10821
... [-2, 10, -2, -7],
10822
... [ 4, -2, 8, 4],
10823
... [ 2, -7, 4, 7]])
10824
sage: A.is_positive_definite()
10825
True
10826
sage: _, d = A.indefinite_factorization(algorithm='symmetric')
10827
sage: d
10828
(4, 9, 4, 1)
10829
sage: [A[:i,:i].determinant() for i in range(1,A.nrows()+1)]
10830
[4, 36, 144, 144]
10831
10832
A real symmetric matrix which is not positive definite, along
10833
with a vector that makes the quadratic form negative. ::
10834
10835
sage: A = matrix(QQ, [[ 3, -6, 9, 6, -9],
10836
... [-6, 11, -16, -11, 17],
10837
... [ 9, -16, 28, 16, -40],
10838
... [ 6, -11, 16, 9, -19],
10839
... [-9, 17, -40, -19, 68]])
10840
sage: A.is_positive_definite()
10841
False
10842
sage: _, d = A.indefinite_factorization(algorithm='symmetric')
10843
sage: d
10844
(3, -1, 5, -2, -1)
10845
sage: [A[:i,:i].determinant() for i in range(1,A.nrows()+1)]
10846
[3, -3, -15, 30, -30]
10847
sage: u = vector(QQ, [2, 2, 0, 1, 0])
10848
sage: u.row()*A*u
10849
(-3)
10850
10851
A real symmetric matrix with a singular leading
10852
principal submatrix, that is therefore not positive definite.
10853
The vector ``u`` makes the quadratic form zero. ::
10854
10855
sage: A = matrix(QQ, [[21, 15, 12, -2],
10856
... [15, 12, 9, 6],
10857
... [12, 9, 7, 3],
10858
... [-2, 6, 3, 8]])
10859
sage: A.is_positive_definite()
10860
False
10861
sage: [A[:i,:i].determinant() for i in range(1,A.nrows()+1)]
10862
[21, 27, 0, -75]
10863
sage: u = vector(QQ, [1,1,-3,0])
10864
sage: u.row()*A*u
10865
(0)
10866
10867
An Hermitian matrix that is positive definite. ::
10868
10869
sage: C.<I> = NumberField(x^2 + 1)
10870
sage: A = matrix(C, [[ 23, 17*I + 3, 24*I + 25, 21*I],
10871
... [ -17*I + 3, 38, -69*I + 89, 7*I + 15],
10872
... [-24*I + 25, 69*I + 89, 976, 24*I + 6],
10873
... [ -21*I, -7*I + 15, -24*I + 6, 28]])
10874
sage: A.is_positive_definite()
10875
True
10876
sage: _, d = A.indefinite_factorization(algorithm='hermitian')
10877
sage: d
10878
(23, 576/23, 89885/144, 142130/17977)
10879
sage: [A[:i,:i].determinant() for i in range(1,A.nrows()+1)]
10880
[23, 576, 359540, 2842600]
10881
10882
An Hermitian matrix that is not positive definite.
10883
The vector ``u`` makes the quadratic form negative. ::
10884
10885
sage: C.<I> = QuadraticField(-1)
10886
sage: B = matrix(C, [[ 2, 4 - 2*I, 2 + 2*I],
10887
... [4 + 2*I, 8, 10*I],
10888
... [2 - 2*I, -10*I, -3]])
10889
sage: B.is_positive_definite()
10890
False
10891
sage: _, d = B.indefinite_factorization(algorithm='hermitian')
10892
sage: d
10893
(2, -2, 3)
10894
sage: [B[:i,:i].determinant() for i in range(1,B.nrows()+1)]
10895
[2, -4, -12]
10896
sage: u = vector(C, [-5 + 10*I, 4 - 3*I, 0])
10897
sage: u.row().conjugate()*B*u
10898
(-50)
10899
10900
A positive definite matrix over an algebraically closed field. ::
10901
10902
sage: A = matrix(QQbar, [[ 2, 4 + 2*I, 6 - 4*I],
10903
... [ -2*I + 4, 11, 10 - 12*I],
10904
... [ 4*I + 6, 10 + 12*I, 37]])
10905
sage: A.is_positive_definite()
10906
True
10907
sage: [A[:i,:i].determinant() for i in range(1,A.nrows()+1)]
10908
[2, 2, 6]
10909
10910
TESTS:
10911
10912
If the base ring lacks a ``conjugate`` method, it
10913
will be assumed to not be Hermitian and thus symmetric.
10914
If the base ring does not make sense as a subfield of
10915
the reals, then this routine will fail since comparison
10916
to zero is meaningless. ::
10917
10918
sage: F.<a> = FiniteField(5^3)
10919
sage: a.conjugate()
10920
Traceback (most recent call last):
10921
...
10922
AttributeError: 'sage.rings.finite_rings.element_givaro.FiniteField_givaroElement'
10923
object has no attribute 'conjugate'
10924
sage: A = matrix(F,
10925
... [[ a^2 + 2*a, 4*a^2 + 3*a + 4, 3*a^2 + a, 2*a^2 + 2*a + 1],
10926
... [4*a^2 + 3*a + 4, 4*a^2 + 2, 3*a, 2*a^2 + 4*a + 2],
10927
... [ 3*a^2 + a, 3*a, 3*a^2 + 2, 3*a^2 + 2*a + 3],
10928
... [2*a^2 + 2*a + 1, 2*a^2 + 4*a + 2, 3*a^2 + 2*a + 3, 3*a^2 + 2*a + 4]])
10929
sage: A.is_positive_definite()
10930
Traceback (most recent call last):
10931
...
10932
TypeError: cannot convert computations from
10933
Finite Field in a of size 5^3 into real numbers
10934
10935
AUTHOR:
10936
10937
- Rob Beezer (2012-05-24)
10938
"""
10939
from sage.rings.all import RR
10940
# check to see if the Hermitian routine is usable
10941
# otherwise we will assume the symmetric case
10942
imaginary = True
10943
a = self.base_ring().an_element()
10944
try:
10945
a.conjugate()
10946
except AttributeError:
10947
imaginary = False
10948
if imaginary:
10949
if not self.is_hermitian():
10950
return False
10951
else:
10952
if not self.is_symmetric():
10953
return False
10954
try:
10955
if imaginary:
10956
_, d = self._indefinite_factorization('hermitian', check=False)
10957
else:
10958
_, d = self._indefinite_factorization('symmetric', check=False)
10959
except ValueError as e:
10960
# a zero singular leading principal submatrix is one
10961
# indicator that the matrix is not positive definite
10962
if str(e).find('leading principal submatrix is singular') != -1:
10963
return False
10964
else:
10965
raise ValueError(e)
10966
# Now have diagonal entries (hopefully real) and so can
10967
# test with a generator (which will short-circuit)
10968
# positive definite iff all entries of d are positive
10969
try:
10970
posdef = all( RR(x) > 0 for x in d )
10971
except TypeError:
10972
universe = Sequence(d).universe()
10973
msg = "cannot convert computations from {0} into real numbers"
10974
raise TypeError(msg.format(universe))
10975
return posdef
10976
10977
def hadamard_bound(self):
10978
r"""
10979
Return an int n such that the absolute value of the determinant of
10980
this matrix is at most `10^n`.
10981
10982
This is got using both the row norms and the column norms.
10983
10984
This function only makes sense when the base field can be coerced
10985
to the real double field RDF or the MPFR Real Field with 53-bits
10986
precision.
10987
10988
EXAMPLES::
10989
10990
sage: a = matrix(ZZ, 3, [1,2,5,7,-3,4,2,1,123])
10991
sage: a.hadamard_bound()
10992
4
10993
sage: a.det()
10994
-2014
10995
sage: 10^4
10996
10000
10997
10998
In this example the Hadamard bound has to be computed
10999
(automatically) using MPFR instead of doubles, since doubles
11000
overflow::
11001
11002
sage: a = matrix(ZZ, 2, [2^10000,3^10000,2^50,3^19292])
11003
sage: a.hadamard_bound()
11004
12215
11005
sage: len(str(a.det()))
11006
12215
11007
"""
11008
from sage.rings.all import RDF, RealField
11009
try:
11010
A = self.change_ring(RDF)
11011
m1 = A._hadamard_row_bound()
11012
A = A.transpose()
11013
m2 = A._hadamard_row_bound()
11014
return min(m1, m2)
11015
except (OverflowError, TypeError):
11016
# Try using MPFR, which handles large numbers much better, but is slower.
11017
import misc
11018
R = RealField(53, rnd='RNDU')
11019
A = self.change_ring(R)
11020
m1 = misc.hadamard_row_bound_mpfr(A)
11021
A = A.transpose()
11022
m2 = misc.hadamard_row_bound_mpfr(A)
11023
return min(m1, m2)
11024
11025
def find(self,f, indices=False):
11026
r"""
11027
Find elements in this matrix satisfying the constraints in the
11028
function `f`. The function is evaluated on each element of
11029
the matrix .
11030
11031
INPUT:
11032
11033
11034
- ``f`` - a function that is evaluated on each
11035
element of this matrix.
11036
11037
- ``indices`` - whether or not to return the indices
11038
and elements of this matrix that satisfy the function.
11039
11040
11041
OUTPUT: If ``indices`` is not specified, return a
11042
matrix with 1 where `f` is satisfied and 0 where it is not.
11043
If ``indices`` is specified, return a dictionary with
11044
containing the elements of this matrix satisfying `f`.
11045
11046
EXAMPLES::
11047
11048
sage: M = matrix(4,3,[1, -1/2, -1, 1, -1, -1/2, -1, 0, 0, 2, 0, 1])
11049
sage: M.find(lambda entry:entry==0)
11050
[0 0 0]
11051
[0 0 0]
11052
[0 1 1]
11053
[0 1 0]
11054
11055
::
11056
11057
sage: M.find(lambda u:u<0)
11058
[0 1 1]
11059
[0 1 1]
11060
[1 0 0]
11061
[0 0 0]
11062
11063
::
11064
11065
sage: M = matrix(4,3,[1, -1/2, -1, 1, -1, -1/2, -1, 0, 0, 2, 0, 1])
11066
sage: len(M.find(lambda u:u<1 and u>-1,indices=True))
11067
5
11068
11069
::
11070
11071
sage: M.find(lambda u:u!=1/2)
11072
[1 1 1]
11073
[1 1 1]
11074
[1 1 1]
11075
[1 1 1]
11076
11077
::
11078
11079
sage: M.find(lambda u:u>1.2)
11080
[0 0 0]
11081
[0 0 0]
11082
[0 0 0]
11083
[1 0 0]
11084
11085
::
11086
11087
sage: sorted(M.find(lambda u:u!=0,indices=True).keys()) == M.nonzero_positions()
11088
True
11089
"""
11090
11091
cdef Py_ssize_t size,i,j
11092
cdef object M
11093
11094
if indices is False:
11095
L = self._list()
11096
size = PyList_GET_SIZE(L)
11097
M = PyList_New(0)
11098
11099
for i from 0 <= i < size:
11100
PyList_Append(M,<object>f(<object>PyList_GET_ITEM(L,i)))
11101
11102
return matrix_space.MatrixSpace(IntegerModRing(2),
11103
nrows=self._nrows,ncols=self._ncols).matrix(M)
11104
11105
else:
11106
# return matrix along with indices in a dictionary
11107
d = {}
11108
for i from 0 <= i < self._nrows:
11109
for j from 0 <= j < self._ncols:
11110
if f(self.get_unsafe(i,j)):
11111
d[(i,j)] = self.get_unsafe(i,j)
11112
11113
return d
11114
11115
def conjugate(self):
11116
r"""
11117
Return the conjugate of self, i.e. the matrix whose entries are the
11118
conjugates of the entries of self.
11119
11120
EXAMPLES::
11121
11122
sage: A = matrix(CDF, [[1+I,1],[0,2*I]])
11123
sage: A.conjugate()
11124
[1.0 - 1.0*I 1.0]
11125
[ 0.0 -2.0*I]
11126
11127
A matrix over a not-totally-real number field::
11128
11129
sage: K.<j> = NumberField(x^2+5)
11130
sage: M = matrix(K, [[1+j,1], [0,2*j]])
11131
sage: M.conjugate()
11132
[-j + 1 1]
11133
[ 0 -2*j]
11134
11135
There is a shortcut for the conjugate::
11136
11137
sage: M.C
11138
[-j + 1 1]
11139
[ 0 -2*j]
11140
11141
There is also a shortcut for the conjugate transpose, or "Hermitian transpose"::
11142
11143
sage: M.H
11144
[-j + 1 0]
11145
[ 1 -2*j]
11146
11147
Conjugates work (trivially) for matrices over rings that embed
11148
canonically into the real numbers::
11149
11150
sage: M = random_matrix(ZZ, 2)
11151
sage: M == M.conjugate()
11152
True
11153
sage: M = random_matrix(QQ, 3)
11154
sage: M == M.conjugate()
11155
True
11156
sage: M = random_matrix(RR, 2)
11157
sage: M == M.conjugate()
11158
True
11159
"""
11160
return self.new_matrix(self.nrows(), self.ncols(), [z.conjugate() for z in self.list()])
11161
11162
def conjugate_transpose(self):
11163
r"""
11164
Returns the transpose of ``self`` after each entry has been converted to its complex conjugate.
11165
11166
.. note::
11167
This function is sometimes known as the "adjoint" of a matrix,
11168
though there is substantial variation and some confusion with
11169
the use of that term.
11170
11171
OUTPUT:
11172
11173
A matrix formed by taking the complex conjugate of every entry
11174
of ``self`` and then transposing the resulting matrix.
11175
11176
Complex conjugation is implemented for many subfields
11177
of the complex numbers. See the examples below, or more
11178
at :meth:`~conjugate`.
11179
11180
EXAMPLES::
11181
11182
sage: M = matrix(SR, 2, 2, [[2-I, 3+4*I], [9-6*I, 5*I]])
11183
sage: M.base_ring()
11184
Symbolic Ring
11185
sage: M.conjugate_transpose()
11186
[ I + 2 6*I + 9]
11187
[-4*I + 3 -5*I]
11188
11189
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])
11190
sage: P.base_ring()
11191
Complex Field with 53 bits of precision
11192
sage: P.conjugate_transpose()
11193
[ 0.950... + 0.630...*I 0.940... - 0.230...*I 0.520... + 0.410...*I]
11194
[ 0.840... - 0.130...*I 0.230... - 0.590...*I -0.500... - 0.900...*I]
11195
11196
There is also a shortcut for the conjugate transpose, or "Hermitian transpose"::
11197
11198
sage: M.H
11199
[ I + 2 6*I + 9]
11200
[-4*I + 3 -5*I]
11201
11202
Matrices over base rings that can be embedded in the
11203
real numbers will behave as expected. ::
11204
11205
sage: P = random_matrix(QQ, 3, 4)
11206
sage: P.conjugate_transpose() == P.transpose()
11207
True
11208
11209
The conjugate of a matrix is formed by taking conjugates of
11210
all the entries. Some specialized subfields of the complex numbers
11211
are implemented in Sage and complex conjugation can be applied.
11212
(Matrices over quadratic number fields are another
11213
class of examples.) ::
11214
11215
sage: C = CyclotomicField(5)
11216
sage: a = C.gen(); a
11217
zeta5
11218
sage: CC(a)
11219
0.309016994374947 + 0.951056516295154*I
11220
sage: M = matrix(C, 1, 2, [a^2, a+a^3])
11221
sage: M.conjugate_transpose()
11222
[ zeta5^3]
11223
[-zeta5^3 - zeta5 - 1]
11224
11225
Conjugation does not make sense over rings not containing complex numbers. ::
11226
11227
sage: N = matrix(GF(5), 2, [0,1,2,3])
11228
sage: N.conjugate_transpose()
11229
Traceback (most recent call last):
11230
...
11231
AttributeError: 'sage.rings.finite_rings.integer_mod.IntegerMod_int' object has no attribute 'conjugate'
11232
11233
AUTHOR:
11234
11235
Rob Beezer (2010-12-13)
11236
"""
11237
# limited testing on a 1000 x 1000 matrix over CC:
11238
# transpose is fast, conjugate is slow
11239
# so perhaps direct speed improvements to the conjugate() method
11240
return self.conjugate().transpose()
11241
11242
def norm(self, p=2):
11243
r"""
11244
Return the p-norm of this matrix, where `p` can be 1, 2,
11245
`\inf`, or the Frobenius norm.
11246
11247
INPUT:
11248
11249
11250
- ``self`` - a matrix whose entries are coercible into
11251
CDF
11252
11253
- ``p`` - one of the following options:
11254
11255
- ``1`` - the largest column-sum norm
11256
11257
- ``2 (default)`` - the Euclidean norm
11258
11259
- ``Infinity`` - the largest row-sum norm
11260
11261
- ``'frob'`` - the Frobenius (sum of squares) norm
11262
11263
11264
OUTPUT: RDF number
11265
11266
.. SEEALSO::
11267
11268
- :func:`sage.misc.functional.norm`
11269
11270
EXAMPLES::
11271
11272
sage: A = matrix(ZZ, [[1,2,4,3],[-1,0,3,-10]])
11273
sage: A.norm(1)
11274
13.0
11275
sage: A.norm(Infinity)
11276
14.0
11277
sage: B = random_matrix(QQ, 20, 21)
11278
sage: B.norm(Infinity) == (B.transpose()).norm(1)
11279
True
11280
11281
::
11282
11283
sage: Id = identity_matrix(12)
11284
sage: Id.norm(2)
11285
1.0
11286
sage: A = matrix(RR, 2, 2, [13,-4,-4,7])
11287
sage: A.norm()
11288
15.0
11289
11290
Norms of numerical matrices over high-precision reals are computed by this routine.
11291
Faster routines for double precision entries from `RDF` or `CDF` are provided by
11292
the :class:`~sage.matrix.matrix_double_dense.Matrix_double_dense` class. ::
11293
11294
sage: A = matrix(CC, 2, 3, [3*I,4,1-I,1,2,0])
11295
sage: A.norm('frob')
11296
5.65685424949
11297
sage: A.norm(2)
11298
5.47068444321
11299
sage: A.norm(1)
11300
6.0
11301
sage: A.norm(Infinity)
11302
8.41421356237
11303
sage: a = matrix([[],[],[],[]])
11304
sage: a.norm()
11305
0.0
11306
sage: a.norm(Infinity) == a.norm(1)
11307
True
11308
"""
11309
11310
if self._nrows == 0 or self._ncols == 0:
11311
return RDF(0)
11312
11313
# 2-norm:
11314
if p == 2:
11315
A = self.change_ring(CDF)
11316
A = A.conjugate().transpose() * A
11317
U, S, V = A.SVD()
11318
return max(S.list()).real().sqrt()
11319
11320
A = self.apply_map(abs).change_ring(RDF)
11321
11322
# 1-norm: largest column-sum
11323
if p == 1:
11324
A = A.transpose()
11325
return max([sum(i) for i in list(A)])
11326
11327
# Infinity norm: largest row-sum
11328
if p == sage.rings.infinity.Infinity:
11329
return max([sum(i) for i in list(A)])
11330
11331
# Frobenius norm: square root of sum of squares of entries of self
11332
if p == 'frob':
11333
return sum([i**2 for i in A.list()]).sqrt()
11334
11335
def _numerical_approx(self,prec=None,digits=None):
11336
r"""
11337
Return a numerical approximation of ``self`` as either
11338
a real or complex number with at least the requested number of bits
11339
or digits of precision.
11340
11341
INPUT:
11342
11343
11344
- ``prec`` - an integer: the number of bits of
11345
precision
11346
11347
- ``digits`` - an integer: digits of precision
11348
11349
11350
OUTPUT: A matrix coerced to a real or complex field with prec bits
11351
of precision.
11352
11353
EXAMPLES::
11354
11355
sage: d = matrix([[3, 0],[0,sqrt(2)]]) ;
11356
sage: b = matrix([[1, -1], [2, 2]]) ; e = b * d * b.inverse();e
11357
[ 1/2*sqrt(2) + 3/2 -1/4*sqrt(2) + 3/4]
11358
[ -sqrt(2) + 3 1/2*sqrt(2) + 3/2]
11359
11360
::
11361
11362
sage: e.numerical_approx(53)
11363
[ 2.20710678118655 0.396446609406726]
11364
[ 1.58578643762690 2.20710678118655]
11365
11366
::
11367
11368
sage: e.numerical_approx(20)
11369
[ 2.2071 0.39645]
11370
[ 1.5858 2.2071]
11371
11372
::
11373
11374
sage: (e-I).numerical_approx(20)
11375
[2.2071 - 1.0000*I 0.39645]
11376
[ 1.5858 2.2071 - 1.0000*I]
11377
11378
::
11379
11380
sage: M=matrix(QQ,4,[i/(i+1) for i in range(12)]);M
11381
[ 0 1/2 2/3]
11382
[ 3/4 4/5 5/6]
11383
[ 6/7 7/8 8/9]
11384
[ 9/10 10/11 11/12]
11385
11386
::
11387
11388
sage: M.numerical_approx()
11389
[0.000000000000000 0.500000000000000 0.666666666666667]
11390
[0.750000000000000 0.800000000000000 0.833333333333333]
11391
[0.857142857142857 0.875000000000000 0.888888888888889]
11392
[0.900000000000000 0.909090909090909 0.916666666666667]
11393
11394
::
11395
11396
sage: matrix(SR, 2, 2, range(4)).n()
11397
[0.000000000000000 1.00000000000000]
11398
[ 2.00000000000000 3.00000000000000]
11399
11400
::
11401
11402
sage: numerical_approx(M)
11403
[0.000000000000000 0.500000000000000 0.666666666666667]
11404
[0.750000000000000 0.800000000000000 0.833333333333333]
11405
[0.857142857142857 0.875000000000000 0.888888888888889]
11406
[0.900000000000000 0.909090909090909 0.916666666666667]
11407
11408
"""
11409
11410
if prec is None:
11411
if digits is None:
11412
prec = 53
11413
else:
11414
prec = int(digits * 3.4) + 2
11415
11416
try:
11417
return self.change_ring(sage.rings.real_mpfr.RealField(prec))
11418
except TypeError:
11419
# try to return a complex result
11420
return self.change_ring(sage.rings.complex_field.ComplexField(prec))
11421
11422
#This line is added so the doctest are visible
11423
numerical_approx=_numerical_approx
11424
n=_numerical_approx
11425
N=_numerical_approx
11426
11427
def plot(self, *args, **kwds):
11428
"""
11429
A plot of this matrix.
11430
11431
Each (ith, jth) matrix element is given a different color value
11432
depending on its relative size compared to the other elements in
11433
the matrix.
11434
11435
The tick marks drawn on the frame axes denote the (ith, jth)
11436
element of the matrix.
11437
11438
This method just calls ``matrix_plot``.
11439
``*args`` and ``**kwds`` are passed to
11440
``matrix_plot``.
11441
11442
EXAMPLES:
11443
11444
A matrix over ZZ colored with different grey levels::
11445
11446
sage: A = matrix([[1,3,5,1],[2,4,5,6],[1,3,5,7]])
11447
sage: A.plot()
11448
11449
Here we make a random matrix over RR and use cmap='hsv' to color
11450
the matrix elements different RGB colors (see documentation for
11451
``matrix_plot`` for more information on cmaps)::
11452
11453
sage: A = random_matrix(RDF, 50)
11454
sage: plot(A, cmap='hsv')
11455
11456
Another random plot, but over GF(389)::
11457
11458
sage: A = random_matrix(GF(389), 10)
11459
sage: A.plot(cmap='Oranges')
11460
"""
11461
from sage.plot.plot import matrix_plot
11462
return matrix_plot(self, *args, **kwds)
11463
11464
#added this to make doctests visible to users
11465
numerical_approx=_numerical_approx
11466
11467
def derivative(self, *args):
11468
"""
11469
Derivative with respect to variables supplied in args.
11470
11471
Multiple variables and iteration counts may be supplied; see
11472
documentation for the global derivative() function for more
11473
details.
11474
11475
EXAMPLES::
11476
11477
sage: v = vector([1,x,x^2])
11478
sage: v.derivative(x)
11479
(0, 1, 2*x)
11480
sage: type(v.derivative(x)) == type(v)
11481
True
11482
sage: v = vector([1,x,x^2], sparse=True)
11483
sage: v.derivative(x)
11484
(0, 1, 2*x)
11485
sage: type(v.derivative(x)) == type(v)
11486
True
11487
sage: v.derivative(x,x)
11488
(0, 0, 2)
11489
"""
11490
return multi_derivative(self, args)
11491
11492
def exp(self):
11493
r"""
11494
Calculate the exponential of this matrix X, which is the matrix
11495
11496
.. math::
11497
11498
e^X = \sum_{k=0}^{\infty} \frac{X^k}{k!}.
11499
11500
This function depends on maxima's matrix exponentiation
11501
function, which does not deal well with floating point
11502
numbers. If the matrix has floating point numbers, they will
11503
be rounded automatically to rational numbers during the
11504
computation. If you want approximations to the exponential
11505
that are calculated numerically, you may get better results by
11506
first converting your matrix to RDF or CDF, as shown in the
11507
last example.
11508
11509
EXAMPLES::
11510
11511
sage: a=matrix([[1,2],[3,4]])
11512
sage: a.exp()
11513
[-1/22*((sqrt(33) - 11)*e^sqrt(33) - sqrt(33) - 11)*e^(-1/2*sqrt(33) + 5/2) 2/33*(sqrt(33)*e^sqrt(33) - sqrt(33))*e^(-1/2*sqrt(33) + 5/2)]
11514
[ 1/11*(sqrt(33)*e^sqrt(33) - sqrt(33))*e^(-1/2*sqrt(33) + 5/2) 1/22*((sqrt(33) + 11)*e^sqrt(33) - sqrt(33) + 11)*e^(-1/2*sqrt(33) + 5/2)]
11515
sage: type(a.exp())
11516
<type 'sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense'>
11517
11518
sage: a=matrix([[1/2,2/3],[3/4,4/5]])
11519
sage: a.exp()
11520
[-1/418*((3*sqrt(209) - 209)*e^(1/10*sqrt(209)) - 3*sqrt(209) - 209)*e^(-1/20*sqrt(209) + 13/20) 20/627*(sqrt(209)*e^(1/10*sqrt(209)) - sqrt(209))*e^(-1/20*sqrt(209) + 13/20)]
11521
[ 15/418*(sqrt(209)*e^(1/10*sqrt(209)) - sqrt(209))*e^(-1/20*sqrt(209) + 13/20) 1/418*((3*sqrt(209) + 209)*e^(1/10*sqrt(209)) - 3*sqrt(209) + 209)*e^(-1/20*sqrt(209) + 13/20)]
11522
11523
sage: a=matrix(RR,[[1,pi.n()],[1e2,1e-2]])
11524
sage: a.exp()
11525
[ 1/11882424341266*((11*sqrt(227345670387496707609) + 5941212170633)*e^(3/1275529100*sqrt(227345670387496707609)) - 11*sqrt(227345670387496707609) + 5941212170633)*e^(-3/2551058200*sqrt(227345670387496707609) + 101/200) 445243650/75781890129165569203*(sqrt(227345670387496707609)*e^(3/1275529100*sqrt(227345670387496707609)) - sqrt(227345670387496707609))*e^(-3/2551058200*sqrt(227345670387496707609) + 101/200)]
11526
[ 10000/53470909535697*(sqrt(227345670387496707609)*e^(3/1275529100*sqrt(227345670387496707609)) - sqrt(227345670387496707609))*e^(-3/2551058200*sqrt(227345670387496707609) + 101/200) -1/11882424341266*((11*sqrt(227345670387496707609) - 5941212170633)*e^(3/1275529100*sqrt(227345670387496707609)) - 11*sqrt(227345670387496707609) - 5941212170633)*e^(-3/2551058200*sqrt(227345670387496707609) + 101/200)]
11527
sage: a.change_ring(RDF).exp()
11528
[42748127.3153 7368259.24416]
11529
[234538976.138 40426191.4516]
11530
"""
11531
from sage.symbolic.ring import SR
11532
return self.change_ring(SR).exp()
11533
11534
def elementary_divisors(self):
11535
r"""
11536
If self is a matrix over a principal ideal domain R, return
11537
elements `d_i` for `1 \le i \le k = \min(r,s)`
11538
where `r` and `s` are the number of rows and
11539
columns of self, such that the cokernel of self is isomorphic to
11540
11541
.. math::
11542
11543
R/(d_1) \oplus R/(d_2) \oplus R/(d_k)
11544
11545
with `d_i \mid d_{i+1}` for all `i`. These are
11546
the diagonal entries of the Smith form of self (see
11547
:meth:`smith_form()`).
11548
11549
EXAMPLES::
11550
11551
sage: OE = EquationOrder(x^2 - x + 2, 'w')
11552
sage: w = OE.ring_generators()[0]
11553
sage: m = Matrix([ [1, w],[w,7]])
11554
sage: m.elementary_divisors()
11555
[1, -w + 9]
11556
11557
.. seealso::
11558
11559
:meth:`smith_form`
11560
"""
11561
d, u, v = self.smith_form()
11562
r = min(self.nrows(), self.ncols())
11563
return [d[i,i] for i in xrange(r)]
11564
11565
def smith_form(self):
11566
r"""
11567
If self is a matrix over a principal ideal domain R, return
11568
matrices D, U, V over R such that D = U \* self \* V, U and V have
11569
unit determinant, and D is diagonal with diagonal entries the
11570
ordered elementary divisors of self, ordered so that
11571
`D_{i} \mid D_{i+1}`. Note that U and V are not uniquely
11572
defined in general, and D is defined only up to units.
11573
11574
INPUT:
11575
11576
11577
- ``self`` - a matrix over an integral domain. If the
11578
base ring is not a PID, the routine might work, or else it will
11579
fail having found an example of a non-principal ideal. Note that we
11580
do not call any methods to check whether or not the base ring is a
11581
PID, since this might be quite expensive (e.g. for rings of
11582
integers of number fields of large degree).
11583
11584
11585
ALGORITHM: Lifted wholesale from
11586
http://en.wikipedia.org/wiki/Smith_normal_form
11587
11588
.. seealso::
11589
11590
:meth:`elementary_divisors`
11591
11592
AUTHORS:
11593
11594
- David Loeffler (2008-12-05)
11595
11596
EXAMPLES:
11597
11598
An example over the ring of integers of a number field (of class
11599
number 1)::
11600
11601
sage: OE = NumberField(x^2 - x + 2,'w').ring_of_integers()
11602
sage: w = OE.ring_generators()[0]
11603
sage: m = Matrix([ [1, w],[w,7]])
11604
sage: d, u, v = m.smith_form()
11605
sage: (d, u, v)
11606
(
11607
[ 1 0] [ 1 0] [ 1 -w]
11608
[ 0 -w + 9], [-w 1], [ 0 1]
11609
)
11610
sage: u * m * v == d
11611
True
11612
sage: u.base_ring() == v.base_ring() == d.base_ring() == OE
11613
True
11614
sage: u.det().is_unit() and v.det().is_unit()
11615
True
11616
11617
An example over the polynomial ring QQ[x]::
11618
11619
sage: R.<x> = QQ[]; m=x*matrix(R,2,2,1) - matrix(R, 2,2,[3,-4,1,-1]); m.smith_form()
11620
(
11621
[ 1 0] [ 0 -1] [ 1 x + 1]
11622
[ 0 x^2 - 2*x + 1], [ 1 x - 3], [ 0 1]
11623
)
11624
11625
An example over a field::
11626
11627
sage: m = matrix( GF(17), 3, 3, [11,5,1,3,6,8,1,16,0]); d,u,v = m.smith_form()
11628
sage: d
11629
[1 0 0]
11630
[0 1 0]
11631
[0 0 0]
11632
sage: u*m*v == d
11633
True
11634
11635
Some examples over non-PID's work anyway::
11636
11637
sage: R = EquationOrder(x^2 + 5, 's') # class number 2
11638
sage: s = R.ring_generators()[0]
11639
sage: A = matrix(R, 2, 2, [s-1,-s,-s,2*s+1])
11640
sage: D, U, V = A.smith_form()
11641
sage: D, U, V
11642
(
11643
[ 1 0] [ 4 s + 4] [ 1 -5*s + 6]
11644
[ 0 -s - 6], [ s s - 1], [ 0 1]
11645
)
11646
sage: D == U*A*V
11647
True
11648
11649
Others don't, but they fail quite constructively::
11650
11651
sage: matrix(R,2,2,[s-1,-s-2,-2*s,-s-2]).smith_form()
11652
Traceback (most recent call last):
11653
...
11654
ArithmeticError: Ideal Fractional ideal (2, s + 1) not principal
11655
11656
Empty matrices are handled safely::
11657
11658
sage: m = MatrixSpace(OE, 2,0)(0); d,u,v=m.smith_form(); u*m*v == d
11659
True
11660
sage: m = MatrixSpace(OE, 0,2)(0); d,u,v=m.smith_form(); u*m*v == d
11661
True
11662
sage: m = MatrixSpace(OE, 0,0)(0); d,u,v=m.smith_form(); u*m*v == d
11663
True
11664
11665
Some pathological cases that crashed earlier versions::
11666
11667
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
11668
True
11669
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
11670
True
11671
"""
11672
R = self.base_ring()
11673
left_mat = self.new_matrix(self.nrows(), self.nrows(), 1)
11674
right_mat = self.new_matrix(self.ncols(), self.ncols(), 1)
11675
if self == 0 or (self.nrows() <= 1 and self.ncols() <= 1):
11676
return self.__copy__(), left_mat, right_mat
11677
11678
# data type checks on R
11679
if not R.is_integral_domain() or not R.is_noetherian():
11680
raise TypeError, "Smith form only defined over Noetherian integral domains"
11681
if not R.is_exact():
11682
raise NotImplementedError, "Smith form over non-exact rings not implemented at present"
11683
11684
# first clear the first row and column
11685
u,t,v = _smith_onestep(self)
11686
11687
# now recurse: t now has a nonzero entry at 0,0 and zero entries in the rest
11688
# of the 0th row and column, so we apply smith_form to the smaller submatrix
11689
mm = t.submatrix(1,1)
11690
dd, uu, vv = mm.smith_form()
11691
mone = self.new_matrix(1, 1, [1])
11692
d = dd.new_matrix(1,1,[t[0,0]]).block_sum(dd)
11693
u = uu.new_matrix(1,1,[1]).block_sum(uu) * u
11694
v = v * vv.new_matrix(1,1,[1]).block_sum(vv)
11695
dp, up, vp = _smith_diag(d)
11696
return dp,up*u,v*vp
11697
11698
def hermite_form(self, include_zero_rows=True, transformation=False):
11699
"""
11700
Return the Hermite form of self, if it is defined.
11701
11702
INPUT:
11703
11704
- ``include_zero_rows`` -- bool (default: True); if False
11705
the zero rows in the output matrix are deleted.
11706
11707
- ``transformation`` -- bool (default: False) a matrix U such that U*self == H.
11708
11709
OUTPUT:
11710
11711
- matrix H
11712
- (optional) transformation matrix U such that U*self == H, possibly with zero
11713
rows deleted...
11714
11715
11716
EXAMPLES::
11717
11718
sage: M = FunctionField(GF(7),'x').maximal_order()
11719
sage: K.<x> = FunctionField(GF(7)); M = K.maximal_order()
11720
sage: A = matrix(M, 2, 3, [x, 1, 2*x, x, 1+x, 2])
11721
sage: A.hermite_form()
11722
[ x 1 2*x]
11723
[ 0 x 5*x + 2]
11724
sage: A.hermite_form(transformation=True)
11725
(
11726
[ x 1 2*x] [1 0]
11727
[ 0 x 5*x + 2], [6 1]
11728
)
11729
sage: A = matrix(M, 2, 3, [x, 1, 2*x, 2*x, 2, 4*x])
11730
sage: A.hermite_form(transformation=True, include_zero_rows=False)
11731
([ x 1 2*x], [1 0])
11732
sage: H, U = A.hermite_form(transformation=True, include_zero_rows=True); H, U
11733
(
11734
[ x 1 2*x] [1 0]
11735
[ 0 0 0], [5 1]
11736
)
11737
sage: U*A == H
11738
True
11739
sage: H, U = A.hermite_form(transformation=True, include_zero_rows=False)
11740
sage: U*A
11741
[ x 1 2*x]
11742
sage: U*A == H
11743
True
11744
"""
11745
left, H, pivots = self._echelon_form_PID()
11746
if not include_zero_rows:
11747
i = H.nrows() - 1
11748
while H.row(i) == 0:
11749
i -= 1
11750
H = H[:i+1]
11751
if transformation:
11752
left = left[:i+1]
11753
if transformation:
11754
return H, left
11755
else:
11756
return H
11757
11758
def _echelon_form_PID(self):
11759
r"""
11760
Return a triple (left, a, pivots) where left*self == a and a is row
11761
echelon form (which in this case we define to mean Hermite normal
11762
form).
11763
11764
When ideals of the base ring have a "small_residue" method (as is the
11765
case for number field ideals), we use this to reduce entries above each
11766
column pivot.
11767
11768
AUTHOR:
11769
11770
- David Loeffler (2009-06-01)
11771
11772
- Moritz Minzlaff (2011-03-17): corrected code for matrices of one row;
11773
this fixed trac 9053
11774
11775
EXAMPLES::
11776
11777
sage: L.<a> = NumberField(x^3 - 2)
11778
sage: OL = L.ring_of_integers()
11779
11780
We check some degenerate cases::
11781
11782
sage: m = matrix(OL, 0, 0, []); r,s,p = m._echelon_form_PID();
11783
sage: (r,s,p)
11784
([], [], [])
11785
sage: r * m == s and r.det() == 1
11786
True
11787
sage: m = matrix(OL, 0, 1, []); r,s,p = m._echelon_form_PID();
11788
sage: (r,s,p)
11789
([], [], [])
11790
sage: r * m == s and r.det() == 1
11791
True
11792
sage: m = matrix(OL, 1, 0, []); r,s,p = m._echelon_form_PID();
11793
sage: (r,s,p)
11794
([1], [], [])
11795
sage: r * m == s and r.det() == 1
11796
True
11797
11798
A 2x2 matrix::
11799
11800
sage: m = matrix(OL, 2, 2, [1,0, a, 2]);
11801
sage: r,s,p = m._echelon_form_PID(); (r,s,p)
11802
(
11803
[ 1 0] [1 0]
11804
[-a 1], [0 2], [0, 1]
11805
)
11806
sage: r * m == s and r.det() == 1
11807
True
11808
11809
A larger example::
11810
11811
sage: m = matrix(OL, 3, 5, [a^2 - 3*a - 1, a^2 - 3*a + 1, a^2 + 1,
11812
... -a^2 + 2, -3*a^2 - a - 1, -6*a - 1, a^2 - 3*a - 1,
11813
... 2*a^2 + a + 5, -2*a^2 + 5*a + 1, -a^2 + 13*a - 3,
11814
... -2*a^2 + 4*a - 2, -2*a^2 + 1, 2*a, a^2 - 6, 3*a^2 - a ])
11815
sage: r,s,p = m._echelon_form_PID()
11816
sage: s[2]
11817
(0, 0, -3*a^2 - 18*a + 34, -68*a^2 + 134*a - 53, -111*a^2 + 275*a - 90)
11818
sage: r * m == s and r.det() == 1
11819
True
11820
11821
We verify that trac 9053 is resolved::
11822
11823
sage: R.<x> = GF(7)[]
11824
sage: A = R^3
11825
sage: L = A.span([x*A.0 + (x^3 + 1)*A.1, x*A.2])
11826
sage: M = A.span([x*L.0])
11827
sage: M.0 in L
11828
True
11829
11830
"""
11831
if self.ncols() == 0:
11832
return self.new_matrix(self.nrows(), self.nrows(), 1), self, []
11833
11834
if self.nrows() == 0:
11835
return self.new_matrix(self.nrows(), self.nrows(), 1), self, []
11836
11837
if self.nrows() == 1:
11838
if self.is_zero():
11839
return self.new_matrix(self.nrows(), self.nrows(), 1), self, []
11840
else:
11841
return self.new_matrix(self.nrows(), self.nrows(), 1), self, [
11842
self.nonzero_positions_in_row(0)[0] ]
11843
11844
R = self.base_ring()
11845
11846
# data type checks on R
11847
if not R.is_integral_domain():
11848
raise TypeError, ( "Generic echelon form only defined over "
11849
"integral domains" )
11850
if not R.is_exact():
11851
raise NotImplementedError, ( "Echelon form over generic non-exact "
11852
"rings not implemented at present" )
11853
11854
left_mat, a = _generic_clear_column(self)
11855
assert left_mat * self == a
11856
11857
if a[0,0] != 0:
11858
aa = a.submatrix(1, 1)
11859
s, t, pivs = aa._echelon_form_PID()
11860
left_mat = s.new_matrix(1,1,[1]).block_sum(s) * left_mat
11861
a = left_mat * self
11862
pivs = [0] + [x + 1 for x in pivs]
11863
11864
else:
11865
aa = a.submatrix(0, 1)
11866
s, t, pivs = aa._echelon_form_PID()
11867
left_mat = s * left_mat
11868
a = left_mat * self
11869
pivs = [x+1 for x in pivs]
11870
11871
11872
try:
11873
for i in xrange(1, len(pivs)):
11874
y = a[i][pivs[i]]
11875
I = R.ideal(y)
11876
s = a[0][pivs[i]]
11877
t = I.small_residue(s)
11878
v = R( (s-t) / y)
11879
11880
left_mat.add_multiple_of_row(0, i, -v)
11881
a.add_multiple_of_row(0, i, -v)
11882
assert left_mat * self == a
11883
except AttributeError: # on I.small_residue
11884
pass
11885
11886
return left_mat, a, pivs
11887
11888
def _zigzag_form(self, basis=True):
11889
r"""
11890
Helper method for computation of ZigZag form.
11891
11892
INPUT:
11893
11894
- ``self`` - a square matrix over an exact field.
11895
11896
- ``basis`` - default; ``True`` - controls whether or not to
11897
compute a change-of-basis matrix (also called a transformation
11898
matrix).
11899
11900
OUTPUT:
11901
11902
See the documentation for the :meth:`zigzag_form` method for a
11903
description of ZigZag form and notes on the algorithm employed.
11904
11905
When ``basis=True`` four items are returned. The first is a matrix
11906
whose columns form a basis so that a matrix representation of ``self``
11907
relative to this basis will be the ZigZag form. More precisely, if
11908
`A` is the matrix, `U` is the change-of-basis matrix and `Z` is
11909
the ZigZag form, then
11910
11911
.. math::
11912
11913
U^{-1}*A*U = Z
11914
11915
The second item returned is the ZigZag form of the matrix. The
11916
third item is a list of lists, where each list is the coefficients
11917
of the polynomial associated with a companion matrix in the form.
11918
Finally, the fourth item is a list of the entries in the upper-left
11919
corner of each off-diagonal block, which will be a zero or a one.
11920
The length of the list of corner entries will be one less than the
11921
length of list of polynomials.
11922
11923
When ``basis=False`` only three items are returned. These are
11924
just as above, but without the change-of-basis matrix.
11925
11926
The compuation of the change-of-basis matrix has not been optimized.
11927
As a helper method, no error checking is performed on the inputs -
11928
that should be performed by the calling method.
11929
11930
ALGORITHM:
11931
11932
ZigZag form, and its computation, are due to Arne Storjohann
11933
and are described in [STORJOHANN-THESIS]_ and
11934
[STORJOHANN-ISACC98]_, where the former is more
11935
representative of the code here.
11936
11937
EXAMPLE:
11938
11939
sage: A = matrix(QQ, [[-68, 69, -27, -11, -65, 9, -181, -32],
11940
... [-52, 52, -27, -8, -52, -16, -133, -14],
11941
... [ 92, -97, 47, 14, 90, 32, 241, 18],
11942
... [139, -144, 60, 18, 148, -10, 362, 77],
11943
... [ 40, -41, 12, 6, 45, -24, 105, 42],
11944
... [-46, 48, -20, -7, -47, 0, -122, -22],
11945
... [-26, 27, -13, -4, -29, -6, -66, -14],
11946
... [-33, 34, -13, -5, -35, 7, -87, -23]])
11947
sage: Z, polys, corners = A._zigzag_form(basis=False)
11948
sage: Z
11949
[ 0 0 0 40 1 0 0 0]
11950
[ 1 0 0 52 0 0 0 0]
11951
[ 0 1 0 18 0 0 0 0]
11952
[ 0 0 1 -1 0 0 0 0]
11953
[ 0 0 0 0 0 1 0 0]
11954
[ 0 0 0 0 -25 10 0 0]
11955
[ 0 0 0 0 1 0 0 -4]
11956
[ 0 0 0 0 0 0 1 -4]
11957
sage: polys
11958
[[-40, -52, -18, 1, 1], [25, -10, 1], [4, 4, 1]]
11959
sage: corners
11960
[1, 1]
11961
sage: len(polys) == len(corners) + 1
11962
True
11963
11964
sage: U, X, polys, corners = A._zigzag_form()
11965
sage: 38416*U
11966
[ 38416 -2612288 -8797264 -47943168 83753660284 -16775074316 1574993574 -12141218334]
11967
[ 0 -1997632 -7222208 -38108672 66323477868 -13362573684 3694412232 -12414630592]
11968
[ 0 3534272 12523616 66920672 -116699384082 23442252424 -4176610942 18012693216]
11969
[ 0 5339824 18631760 100842000 -175585304193 35191011843 -3619613634 22708786576]
11970
[ 0 1536640 5301408 28812000 -50432310506 10071675864 79884994 5258177064]
11971
[ 0 -1767136 -6261808 -33460336 58377759731 -11719115889 1849749314 -8725304756]
11972
[ 0 -998816 -3611104 -19054336 33189768208 -6681286842 1651135654 -5815174372]
11973
[ 0 -1267728 -4456256 -23933168 41831027339 -8380482791 785625330 -5536675718]
11974
sage: X == Z
11975
True
11976
sage: U.inverse()*A*U == X
11977
True
11978
11979
AUTHOR:
11980
11981
- Rob Beezer (2011-06-09)
11982
"""
11983
import sage.matrix.constructor
11984
cdef Py_ssize_t n, s, c, i, j, k
11985
11986
n = self._ncols
11987
R = self.base_ring()
11988
zero = R(0)
11989
one = R(1)
11990
cdef Matrix Z
11991
Z = self.__copy__()
11992
polys = [] # coefficients for polynomials of companion matrices
11993
corners = [] # zero or one in corner of off-diagonal blocks
11994
if basis:
11995
U = sage.matrix.constructor.identity_matrix(R, n) # transformation matrix
11996
# parity switch, True iff working on transpose
11997
# if False, mimic row operations only on U
11998
# if True, mimic column operations only on U
11999
trans = False
12000
s = 0 # index of top row of current block
12001
c = 0 # index of current row of current block
12002
while s < n:
12003
zigging = True
12004
# check for totally zero column below diagonal
12005
while zigging: # zigging means we are building a block
12006
nonzero = -1
12007
for i in range(c+1, n):
12008
if Z[i, c] != 0:
12009
nonzero = i
12010
break
12011
zigging = (nonzero != -1)
12012
if zigging:
12013
Z.swap_rows(nonzero, c+1)
12014
Z.swap_columns(nonzero, c+1)
12015
if basis:
12016
if trans:
12017
U.swap_columns(nonzero, c+1)
12018
else:
12019
U.swap_rows(nonzero, c+1)
12020
12021
# create a subdiagonal entry 1
12022
scale = Z[c+1, c]
12023
Z.rescale_row(c+1, 1/scale)
12024
Z.rescale_col(c+1, scale)
12025
if basis:
12026
if trans:
12027
U.rescale_col(c+1, scale)
12028
else:
12029
U.rescale_row(c+1, 1/scale)
12030
12031
# clear column throughout the block,and in all rows below
12032
for i in range(s, n):
12033
if i != c+1:
12034
scale = Z[i, c]
12035
Z.add_multiple_of_row(i, c+1, -scale)
12036
Z.add_multiple_of_column(c+1, i, scale)
12037
if basis:
12038
if trans:
12039
U.add_multiple_of_column(c+1, i, scale)
12040
else:
12041
U.add_multiple_of_row(i, c+1, -scale)
12042
# move to next column
12043
# column of coefficients will cause zero search to fail
12044
# at the top of this loop, and then we leave the column alone
12045
# having built a block
12046
c = c + 1
12047
12048
# now have a companion matrix between rows s and c
12049
# (inclusive), use it to clear entries to the right
12050
# but first record polynomial for block just built
12051
# this is the full monic polynomial, with correct coefficients
12052
p = []
12053
for i in range(s, c+1):
12054
p.append(-Z[i, c])
12055
p.append(R(1))
12056
polys.append(p)
12057
12058
# use new unit columns (i) to clear rows to right (j)
12059
# all but top row of block to the right will become zero
12060
# it is important that the loop on i goes in reverse
12061
for i in range(c-1, s-1, -1):
12062
for j in range(c+1, n):
12063
scale = Z[i+1, j]
12064
# Effectively: Z.add_multiple_of_column(j, i, -scale)
12065
Z.set_unsafe(i+1, j, zero)
12066
# row j leads with zeros, up to, and including column c
12067
# Effectively: Z.add_multiple_of_row(i, j, scale)
12068
for k in range(c+1, n):
12069
# Z[i,k] = Z[i,k] + scale*Z[j,k]
12070
Z.set_unsafe(i, k, Z.get_unsafe(i,k)+scale*Z.get_unsafe(j,k))
12071
if basis:
12072
if trans:
12073
U.add_multiple_of_column(j, i, -scale)
12074
else:
12075
U.add_multiple_of_row(i, j, scale)
12076
12077
# row s to the right of the block needs care
12078
# we will be left with a leading one, or totally zeros
12079
nonzero = -1
12080
# locate a nonzero entry in row s
12081
for j in range(c+1, n):
12082
if Z[s, j] != 0:
12083
nonzero = j
12084
break
12085
if (nonzero != -1):
12086
# swap column wih nonzero entry just outside block
12087
if nonzero != c+1:
12088
Z.swap_columns(c+1, nonzero)
12089
Z.swap_rows(c+1, nonzero)
12090
if basis:
12091
if trans:
12092
U.swap_columns(c+1, nonzero)
12093
else:
12094
U.swap_rows(c+1, nonzero)
12095
scale = Z[s, c+1]
12096
Z.rescale_col(c+1, 1/scale)
12097
Z.rescale_row(c+1, scale)
12098
if basis:
12099
if trans:
12100
U.rescale_col(c+1, 1/scale)
12101
else:
12102
U.rescale_row(c+1, scale)
12103
for j in range(c+2, n):
12104
scale = Z[s, j]
12105
# exploiting leading zeros does not seem too beneficial here
12106
Z.add_multiple_of_column(j, c+1, -scale)
12107
Z.add_multiple_of_row(c+1, j, scale)
12108
if basis:
12109
if trans:
12110
U.add_multiple_of_column(j, c+1, -scale)
12111
else:
12112
U.add_multiple_of_row(c+1, j, scale)
12113
12114
# maybe move this closer to where we know which it is
12115
if c < n-1:
12116
corners.append(Z[s, c+1])
12117
# reset indices for constructing next block
12118
# transpose all elements, this is a zig or a zag
12119
c = c+1
12120
s = c
12121
Z = Z.transpose()
12122
if basis:
12123
U = U.transpose()
12124
trans = not trans
12125
12126
# maybe return to un-transposed state
12127
if trans:
12128
Z = Z.transpose()
12129
if basis:
12130
U = U.transpose()
12131
if basis:
12132
# Storjohann computes U, we return its inverse
12133
# after this step, the columns of U are basis for representing self
12134
# code could be re-arranged to compute U's inverse directly
12135
return U.inverse(), Z, polys, corners
12136
return Z, polys, corners
12137
12138
def zigzag_form(self, subdivide=True, transformation=False):
12139
r"""
12140
Find a matrix in ZigZag form that is similar to ``self``.
12141
12142
INPUT:
12143
12144
- ``self`` - a square matrix with entries from an exact field.
12145
12146
- ``transformation`` - default: False - if ``True`` return a
12147
change-of-basis matrix relating the matrix and its ZigZag form.
12148
12149
- ``subdivide`` - default: ``True`` - if ``True`` the ZigZag
12150
form matrix is subdivided according to the companion matrices
12151
described in the output section below.
12152
12153
OUTPUT:
12154
12155
A matrix in ZigZag form has blocks on the main diagonal that are
12156
companion matrices. The first companion matrix has ones just below
12157
the main diagonal. The last column has the negatives of coefficients
12158
of a monic polynomial, but not the leading one. Low degree monomials
12159
have their coefficients in the earlier rows. The second companion
12160
matrix is like the first only transposed. The third is like the first.
12161
The fourth is like the second. And so on.
12162
12163
These blocks on the main diagonal define blocks just off the diagonal.
12164
To the right of the first companion matrix, and above the second
12165
companion matrix is a block that is totally zero, except the entry
12166
of the first row and first column may be a one. Below the second
12167
block and to the left of the third block is a block that is totally
12168
zero, except the entry of the first row and first column may be one.
12169
This alternating pattern continues. It may now be apparent how this
12170
form gets its name. Any other entry of the matrix is zero. So this
12171
form is reminiscent of rational canonical form and is a good precursor
12172
to that form.
12173
12174
If ``transformation`` is ``True``, then the output is a pair of
12175
matrices. The first is the form ``Z`` and the second is an invertible
12176
matrix ``U`` such that ``U.inverse()*self*U`` equals ``Z``. In other
12177
words, the repsentation of ``self`` with respect to the columns
12178
of ``U`` will be ``Z``.
12179
12180
If subdivide is ``True`` then the matrix returned as the form is
12181
partitioned according to the companion matrices and these may be
12182
manipulated by several different matrix methods.
12183
12184
For output that may be more useful as input to other routines,
12185
see the helper method :meth:`_zigzag_form`.
12186
12187
.. note::
12188
12189
An efffort has been made to optimize computation of the form,
12190
but no such work has been done for the computation of the
12191
transformation matrix, so for fastest results do not request the
12192
transformation matrix.
12193
12194
ALGORITHM:
12195
12196
ZigZag form, and its computation, are due to Arne Storjohann
12197
and are described in [STORJOHANN-THESIS]_ and
12198
[STORJOHANN-ISACC98]_, where the former is more
12199
representative of the code here.
12200
12201
EXAMPLES:
12202
12203
Two examples that illustrate ZigZag form well. Notice that this is
12204
*not* a canonical form. The two matrices below are similar, since
12205
they have equal Jordan canonical forms, yet their ZigZag forms are
12206
quite different. In other words, while the computation of the form
12207
is deterministic, the final result, when viewed as a property of a
12208
linear transformation, is dependent on the basis used for the
12209
matrix representation. ::
12210
12211
sage: A = matrix(QQ, [[-68, 69, -27, -11, -65, 9, -181, -32],
12212
... [-52, 52, -27, -8, -52, -16, -133, -14],
12213
... [ 92, -97, 47, 14, 90, 32, 241, 18],
12214
... [139, -144, 60, 18, 148, -10, 362, 77],
12215
... [ 40, -41, 12, 6, 45, -24, 105, 42],
12216
... [-46, 48, -20, -7, -47, 0, -122, -22],
12217
... [-26, 27, -13, -4, -29, -6, -66, -14],
12218
... [-33, 34, -13, -5, -35, 7, -87, -23]])
12219
sage: Z, U = A.zigzag_form(transformation=True)
12220
sage: Z
12221
[ 0 0 0 40| 1 0| 0 0]
12222
[ 1 0 0 52| 0 0| 0 0]
12223
[ 0 1 0 18| 0 0| 0 0]
12224
[ 0 0 1 -1| 0 0| 0 0]
12225
[---------------+-------+-------]
12226
[ 0 0 0 0| 0 1| 0 0]
12227
[ 0 0 0 0|-25 10| 0 0]
12228
[---------------+-------+-------]
12229
[ 0 0 0 0| 1 0| 0 -4]
12230
[ 0 0 0 0| 0 0| 1 -4]
12231
sage: U.inverse()*A*U == Z
12232
True
12233
12234
sage: B = matrix(QQ, [[ 16, 69, -13, 2, -52, 143, 90, -3],
12235
... [ 26, 54, 6, -5, -28, 73, 73, -48],
12236
... [-16, -79, 12, -10, 64, -142, -115, 41],
12237
... [ 27, -7, 21, -33, 39, -20, -42, 43],
12238
... [ 8, -75, 34, -32, 86, -156, -130, 42],
12239
... [ 2, -17, 7, -8, 20, -33, -31, 16],
12240
... [-24, -80, 7, -3, 56, -136, -112, 42],
12241
... [ -6, -19, 0, -1, 13, -28, -27, 15]])
12242
sage: Z, U = B.zigzag_form(transformation=True)
12243
sage: Z
12244
[ 0 0 0 0 0 1000| 0| 0]
12245
[ 1 0 0 0 0 900| 0| 0]
12246
[ 0 1 0 0 0 -30| 0| 0]
12247
[ 0 0 1 0 0 -153| 0| 0]
12248
[ 0 0 0 1 0 3| 0| 0]
12249
[ 0 0 0 0 1 9| 0| 0]
12250
[-----------------------------+----+----]
12251
[ 0 0 0 0 0 0| -2| 0]
12252
[-----------------------------+----+----]
12253
[ 0 0 0 0 0 0| 1| -2]
12254
sage: U.inverse()*B*U == Z
12255
True
12256
12257
sage: A.jordan_form() == B.jordan_form()
12258
True
12259
12260
Two more examples, illustrating the two extremes of the zig-zag
12261
nature of this form. The first has a one in each of the
12262
off-diagonal blocks, the second has all zeros in each off-diagonal
12263
block. Notice again that the two matrices are similar, since their
12264
Jordan canonical forms are equal. ::
12265
12266
sage: C = matrix(QQ, [[2, 31, -10, -9, -125, 13, 62, -12],
12267
... [0, 48, -16, -16, -188, 20, 92, -16],
12268
... [0, 9, -1, 2, -33, 5, 18, 0],
12269
... [0, 15, -5, 0, -59, 7, 30, -4],
12270
... [0, -21, 7, 2, 84, -10, -42, 5],
12271
... [0, -42, 14, 8, 167, -17, -84, 13],
12272
... [0, -50, 17, 10, 199, -23, -98, 14],
12273
... [0, 15, -5, -2, -59, 7, 30, -2]])
12274
sage: Z, U = C.zigzag_form(transformation=True)
12275
sage: Z
12276
[2|1|0|0|0|0|0|0]
12277
[-+-+-+-+-+-+-+-]
12278
[0|2|0|0|0|0|0|0]
12279
[-+-+-+-+-+-+-+-]
12280
[0|1|2|1|0|0|0|0]
12281
[-+-+-+-+-+-+-+-]
12282
[0|0|0|2|0|0|0|0]
12283
[-+-+-+-+-+-+-+-]
12284
[0|0|0|1|2|1|0|0]
12285
[-+-+-+-+-+-+-+-]
12286
[0|0|0|0|0|2|0|0]
12287
[-+-+-+-+-+-+-+-]
12288
[0|0|0|0|0|1|2|1]
12289
[-+-+-+-+-+-+-+-]
12290
[0|0|0|0|0|0|0|2]
12291
sage: U.inverse()*C*U == Z
12292
True
12293
12294
sage: D = matrix(QQ, [[ -4, 3, 7, 2, -4, 5, 7, -3],
12295
... [ -6, 5, 7, 2, -4, 5, 7, -3],
12296
... [ 21, -12, 89, 25, 8, 27, 98, -95],
12297
... [ -9, 5, -44, -11, -3, -13, -48, 47],
12298
... [ 23, -13, 74, 21, 12, 22, 85, -84],
12299
... [ 31, -18, 135, 38, 12, 47, 155, -147],
12300
... [-33, 19, -138, -39, -13, -45, -156, 151],
12301
... [ -7, 4, -29, -8, -3, -10, -34, 34]])
12302
sage: Z, U = D.zigzag_form(transformation=True)
12303
sage: Z
12304
[ 0 -4| 0 0| 0 0| 0 0]
12305
[ 1 4| 0 0| 0 0| 0 0]
12306
[-----+-----+-----+-----]
12307
[ 0 0| 0 1| 0 0| 0 0]
12308
[ 0 0|-4 4| 0 0| 0 0]
12309
[-----+-----+-----+-----]
12310
[ 0 0| 0 0| 0 -4| 0 0]
12311
[ 0 0| 0 0| 1 4| 0 0]
12312
[-----+-----+-----+-----]
12313
[ 0 0| 0 0| 0 0| 0 1]
12314
[ 0 0| 0 0| 0 0|-4 4]
12315
sage: U.inverse()*D*U == Z
12316
True
12317
12318
sage: C.jordan_form() == D.jordan_form()
12319
True
12320
12321
ZigZag form is achieved entirely with the operations of the field, so
12322
while the eigenvalues may lie outside the field, this does not impede
12323
the computation of the form. ::
12324
12325
sage: F.<a> = GF(5^4)
12326
sage: A = matrix(F, [[ a, 0, 0, a + 3],
12327
... [ 0,a^2 + 1, 0, 0],
12328
... [ 0, 0,a^3, 0],
12329
... [a^2 +4 , 0, 0,a + 2]])
12330
sage: A.zigzag_form()
12331
[ 0 a^3 + 2*a^2 + 2*a + 2| 0| 0]
12332
[ 1 2*a + 2| 0| 0]
12333
[-------------------------------------------+---------------------+---------------------]
12334
[ 0 0| a^3| 0]
12335
[-------------------------------------------+---------------------+---------------------]
12336
[ 0 0| 0| a^2 + 1]
12337
sage: A.eigenvalues()
12338
Traceback (most recent call last):
12339
...
12340
NotImplementedError: eigenvalues() is not implemented for matrices with eigenvalues that are not in the fraction field of the base ring or in QQbar
12341
12342
Subdivisions are optional. ::
12343
12344
sage: F.<a> = GF(5^4)
12345
sage: A = matrix(F, [[ a, 0, 0, a + 3],
12346
... [ 0,a^2 + 1, 0, 0],
12347
... [ 0, 0,a^3, 0],
12348
... [a^2 +4 , 0, 0,a + 2]])
12349
sage: A.zigzag_form(subdivide=False)
12350
[ 0 a^3 + 2*a^2 + 2*a + 2 0 0]
12351
[ 1 2*a + 2 0 0]
12352
[ 0 0 a^3 0]
12353
[ 0 0 0 a^2 + 1]
12354
12355
TESTS::
12356
12357
sage: A = matrix(QQ, 2, 3, range(6))
12358
sage: A.zigzag_form()
12359
Traceback (most recent call last):
12360
...
12361
TypeError: matrix must be square, not 2 x 3
12362
12363
sage: A = matrix(Integers(6), 2, 2, range(4))
12364
sage: A.zigzag_form()
12365
Traceback (most recent call last):
12366
...
12367
TypeError: matrix entries must come from an exact field, not Ring of integers modulo 6
12368
12369
sage: A = matrix(RDF, 2, 2, range(4))
12370
sage: A.zigzag_form()
12371
Traceback (most recent call last):
12372
...
12373
TypeError: matrix entries must come from an exact field, not Real Double Field
12374
12375
sage: A = matrix(QQ, 2, range(4))
12376
sage: A.zigzag_form(transformation='junk')
12377
Traceback (most recent call last):
12378
...
12379
ValueError: 'transformation' keyword must be True or False, not junk
12380
12381
sage: A = matrix(QQ, 2, range(4))
12382
sage: A.zigzag_form(subdivide='garbage')
12383
Traceback (most recent call last):
12384
...
12385
ValueError: 'subdivide' keyword must be True or False, not garbage
12386
12387
.. rubric:: Citations
12388
12389
.. [STORJOHANN-THESIS] A. Storjohann, Algorithms
12390
for Matrix Canonical Forms. PhD Thesis. Department
12391
of Computer Science, Swiss Federal Institute of
12392
Technology -- ETH, 2000.
12393
12394
.. [STORJOHANN-ISACC98] A. Storjohann, An O(n^3)
12395
algorithm for Frobenius normal form. Proceedings
12396
of the International Symposium on Symbolic and
12397
Algebraic Computation (ISSAC'98), ACM Press, 1998, pp. 101-104.
12398
12399
AUTHOR:
12400
12401
- Rob Beezer (2011-06-09)
12402
"""
12403
R = self.base_ring()
12404
if not self.is_square():
12405
raise TypeError("matrix must be square, not {0} x {1}".format(self.nrows(), self.ncols()))
12406
if not (R.is_field() and R.is_exact()):
12407
raise TypeError("matrix entries must come from an exact field, not {0}".format(R))
12408
if transformation not in [True, False]:
12409
raise ValueError("'transformation' keyword must be True or False, not {0}".format(transformation))
12410
if subdivide not in [True, False]:
12411
raise ValueError("'subdivide' keyword must be True or False, not {0}".format(subdivide))
12412
if transformation:
12413
U, Z, polys, corners = self._zigzag_form(basis=True)
12414
else:
12415
Z, polys, corners = self._zigzag_form(basis=False)
12416
if subdivide:
12417
s = 0
12418
splits = []
12419
for p in polys[:-1]:
12420
s = s + len(p) - 1
12421
splits.append(s)
12422
Z.subdivide(splits, splits)
12423
if transformation:
12424
return Z, U
12425
else:
12426
return Z
12427
12428
def rational_form(self, format='right', subdivide=True):
12429
r"""
12430
Returns the rational canonical form, also known as Frobenius form.
12431
12432
INPUT:
12433
12434
- ``self`` - a square matrix with entries from an exact field.
12435
12436
- ``format`` - default: 'right' - one of 'right', 'bottom',
12437
'left', 'top' or 'invariants'. The first four will cause a
12438
matrix to be returned with companion matrices dictated by the
12439
keyword. The value 'invariants' will cause a list of lists to
12440
be returned, where each list contains coefficients of a
12441
polynomial associated with a companion matrix.
12442
12443
- `subdivide` - default: 'True' - if 'True' and a matrix is
12444
returned, then it contains subdivisions delineating the
12445
companion matrices along the diagonal.
12446
12447
OUTPUT:
12448
12449
The rational form of a matrix is a similar matrix composed of
12450
submatrices ("blocks") placed on the main diagonal. Each block
12451
is a companion matrix. Associated with each companion matrix is a
12452
polynomial. In rational form, the polynomial of one block will
12453
divide the polynomial of the next block (and thus, the polynomials
12454
of all subsequent blocks).
12455
12456
Rational form, also known as Frobenius form, is a canonical form.
12457
In other words, two matrices are similar if and only if their
12458
rational canonical forms are equal. The algorithm used does not
12459
provide the similarity transformation matrix (also known as the
12460
change-of-basis matrix).
12461
12462
Companion matrices may be written in one of four styles, and any
12463
such style may be selected with the ``format`` keyword. See the
12464
companion matrix constructor,
12465
:meth:`sage.matrix.constructor.companion_matrix`,
12466
for more information about companion matrices.
12467
12468
If the 'invariants' value is used for the ``format`` keyword,
12469
then the return value is a list of lists, where each list is the
12470
coefficients of the polynomial associated with one of the companion
12471
matrices on the diagonal. These coefficients include the leading
12472
one of the monic polynomial and are ready to be coerced into
12473
any polynomial ring over the same field (see examples of this below).
12474
This return value is intended to be the most compact representation
12475
and the easiest to use for testing equality of rational forms.
12476
12477
Because the minimal and characteristic polynomials of a companion
12478
matrix are the associated polynomial, it is easy to see that the
12479
product of the polynomials of the blocks will be the characteristic
12480
polynomial and the final polynomial will be the minimal polynomial
12481
of the entire matrix.
12482
12483
ALGORITHM:
12484
12485
We begin with ZigZag form, which is due to Arne Storjohann
12486
and is documented at :meth:`zigzag_form`. Then we eliminate
12487
''corner'' entries enroute to rational form via an additional
12488
algorithm of Storjohann's [STORJOHANN-EMAIL]_.
12489
12490
EXAMPLES:
12491
12492
The lists of coefficients returned with the ``invariants`` keyword
12493
are designed to easily convert to the polynomials associated with
12494
the companion matrices. This is illustrated by the construction
12495
below of the ``polys`` list. Then we can test the divisibility
12496
condition on the list of polynomials. Also the minimal and
12497
characteristic polynomials are easy to determine from this list. ::
12498
12499
sage: A = matrix(QQ, [[ 11, 14, -15, -4, -38, -29, 1, 23, 14, -63, 17, 24, 36, 32],
12500
... [ 18, 6, -17, -11, -31, -43, 12, 26, 0, -69, 11, 13, 17, 24],
12501
... [ 11, 16, -22, -8, -48, -34, 0, 31, 16, -82, 26, 31, 39, 37],
12502
... [ -8, -18, 22, 10, 46, 33, 3, -27, -12, 70, -19, -20, -42, -31],
12503
... [-13, -21, 16, 10, 52, 43, 4, -28, -25, 89, -37, -20, -53, -62],
12504
... [ -2, -6, 0, 0, 6, 10, 1, 1, -7, 14, -11, -3, -10, -18],
12505
... [ -9, -19, -3, 4, 23, 30, 8, -3, -27, 55, -40, -5, -40, -69],
12506
... [ 4, -8, -1, -1, 5, -4, 9, 5, -11, 4, -14, -2, -13, -17],
12507
... [ 1, -2, 16, -1, 19, -2, -1, -17, 2, 19, 5, -25, -7, 14],
12508
... [ 7, 7, -13, -4, -26, -21, 3, 18, 5, -40, 7, 15, 20, 14],
12509
... [ -6, -7, -12, 4, -1, 18, 3, 8, -11, 15, -18, 17, -15, -41],
12510
... [ 5, 11, -11, -3, -26, -19, -1, 14, 10, -42, 14, 17, 25, 23],
12511
... [-16, -15, 3, 10, 29, 45, -1, -13, -19, 71, -35, -2, -35, -65],
12512
... [ 4, 2, 3, -2, -2, -10, 1, 0, 3, -11, 6, -4, 6, 17]])
12513
sage: A.rational_form()
12514
[ 0 -4| 0 0 0 0| 0 0 0 0 0 0 0 0]
12515
[ 1 4| 0 0 0 0| 0 0 0 0 0 0 0 0]
12516
[---------+-------------------+---------------------------------------]
12517
[ 0 0| 0 0 0 12| 0 0 0 0 0 0 0 0]
12518
[ 0 0| 1 0 0 -4| 0 0 0 0 0 0 0 0]
12519
[ 0 0| 0 1 0 -9| 0 0 0 0 0 0 0 0]
12520
[ 0 0| 0 0 1 6| 0 0 0 0 0 0 0 0]
12521
[---------+-------------------+---------------------------------------]
12522
[ 0 0| 0 0 0 0| 0 0 0 0 0 0 0 -216]
12523
[ 0 0| 0 0 0 0| 1 0 0 0 0 0 0 108]
12524
[ 0 0| 0 0 0 0| 0 1 0 0 0 0 0 306]
12525
[ 0 0| 0 0 0 0| 0 0 1 0 0 0 0 -271]
12526
[ 0 0| 0 0 0 0| 0 0 0 1 0 0 0 -41]
12527
[ 0 0| 0 0 0 0| 0 0 0 0 1 0 0 134]
12528
[ 0 0| 0 0 0 0| 0 0 0 0 0 1 0 -64]
12529
[ 0 0| 0 0 0 0| 0 0 0 0 0 0 1 13]
12530
12531
sage: R = PolynomialRing(QQ, 'x')
12532
sage: invariants = A.rational_form(format='invariants')
12533
sage: invariants
12534
[[4, -4, 1], [-12, 4, 9, -6, 1], [216, -108, -306, 271, 41, -134, 64, -13, 1]]
12535
sage: polys = [R(p) for p in invariants]
12536
sage: [p.factor() for p in polys]
12537
[(x - 2)^2, (x - 3) * (x + 1) * (x - 2)^2, (x + 1)^2 * (x - 3)^3 * (x - 2)^3]
12538
sage: all(polys[i].divides(polys[i+1]) for i in range(len(polys)-1))
12539
True
12540
sage: polys[-1] == A.minimal_polynomial(var='x')
12541
True
12542
sage: prod(polys) == A.characteristic_polynomial(var='x')
12543
True
12544
12545
Rational form is a canonical form. Any two matrices are similar
12546
if and only if their rational forms are equal. By starting with
12547
Jordan canonical forms, the matrices ``C`` and ``D`` below were
12548
built as similar matrices, while ``E`` was built to be just
12549
slightly different. All three matrices have equal characteristic
12550
polynomials though ``E``'s minimal polynomial differs. ::
12551
12552
sage: C = matrix(QQ, [[2, 31, -10, -9, -125, 13, 62, -12],
12553
... [0, 48, -16, -16, -188, 20, 92, -16],
12554
... [0, 9, -1, 2, -33, 5, 18, 0],
12555
... [0, 15, -5, 0, -59, 7, 30, -4],
12556
... [0, -21, 7, 2, 84, -10, -42, 5],
12557
... [0, -42, 14, 8, 167, -17, -84, 13],
12558
... [0, -50, 17, 10, 199, -23, -98, 14],
12559
... [0, 15, -5, -2, -59, 7, 30, -2]])
12560
sage: C.minimal_polynomial().factor()
12561
(x - 2)^2
12562
sage: C.characteristic_polynomial().factor()
12563
(x - 2)^8
12564
sage: C.rational_form()
12565
[ 0 -4| 0 0| 0 0| 0 0]
12566
[ 1 4| 0 0| 0 0| 0 0]
12567
[-----+-----+-----+-----]
12568
[ 0 0| 0 -4| 0 0| 0 0]
12569
[ 0 0| 1 4| 0 0| 0 0]
12570
[-----+-----+-----+-----]
12571
[ 0 0| 0 0| 0 -4| 0 0]
12572
[ 0 0| 0 0| 1 4| 0 0]
12573
[-----+-----+-----+-----]
12574
[ 0 0| 0 0| 0 0| 0 -4]
12575
[ 0 0| 0 0| 0 0| 1 4]
12576
12577
sage: D = matrix(QQ, [[ -4, 3, 7, 2, -4, 5, 7, -3],
12578
... [ -6, 5, 7, 2, -4, 5, 7, -3],
12579
... [ 21, -12, 89, 25, 8, 27, 98, -95],
12580
... [ -9, 5, -44, -11, -3, -13, -48, 47],
12581
... [ 23, -13, 74, 21, 12, 22, 85, -84],
12582
... [ 31, -18, 135, 38, 12, 47, 155, -147],
12583
... [-33, 19, -138, -39, -13, -45, -156, 151],
12584
... [ -7, 4, -29, -8, -3, -10, -34, 34]])
12585
sage: D.minimal_polynomial().factor()
12586
(x - 2)^2
12587
sage: D.characteristic_polynomial().factor()
12588
(x - 2)^8
12589
sage: D.rational_form()
12590
[ 0 -4| 0 0| 0 0| 0 0]
12591
[ 1 4| 0 0| 0 0| 0 0]
12592
[-----+-----+-----+-----]
12593
[ 0 0| 0 -4| 0 0| 0 0]
12594
[ 0 0| 1 4| 0 0| 0 0]
12595
[-----+-----+-----+-----]
12596
[ 0 0| 0 0| 0 -4| 0 0]
12597
[ 0 0| 0 0| 1 4| 0 0]
12598
[-----+-----+-----+-----]
12599
[ 0 0| 0 0| 0 0| 0 -4]
12600
[ 0 0| 0 0| 0 0| 1 4]
12601
12602
sage: E = matrix(QQ, [[ 0, -8, 4, -6, -2, 5, -3, 11],
12603
... [-2, -4, 2, -4, -2, 4, -2, 6],
12604
... [ 5, 14, -7, 12, 3, -8, 6, -27],
12605
... [-3, -8, 7, -5, 0, 2, -6, 17],
12606
... [ 0, 5, 0, 2, 4, -4, 1, 2],
12607
... [-3, -7, 5, -6, -1, 5, -4, 14],
12608
... [ 6, 18, -10, 14, 4, -10, 10, -28],
12609
... [-2, -6, 4, -5, -1, 3, -3, 13]])
12610
sage: E.minimal_polynomial().factor()
12611
(x - 2)^3
12612
sage: E.characteristic_polynomial().factor()
12613
(x - 2)^8
12614
sage: E.rational_form()
12615
[ 2| 0 0| 0 0| 0 0 0]
12616
[---+-------+-------+-----------]
12617
[ 0| 0 -4| 0 0| 0 0 0]
12618
[ 0| 1 4| 0 0| 0 0 0]
12619
[---+-------+-------+-----------]
12620
[ 0| 0 0| 0 -4| 0 0 0]
12621
[ 0| 0 0| 1 4| 0 0 0]
12622
[---+-------+-------+-----------]
12623
[ 0| 0 0| 0 0| 0 0 8]
12624
[ 0| 0 0| 0 0| 1 0 -12]
12625
[ 0| 0 0| 0 0| 0 1 6]
12626
12627
12628
The principal feature of rational canonical form is that it
12629
can be computed over any field using only field operations. Other
12630
forms, such as Jordan canonical form, are complicated by the need to
12631
determine the eigenvalues of the matrix, which can lie outside
12632
the field. The following matrix has all of its eigenvalues
12633
outside the rationals - some are irrational (`\pm\sqrt{2}`) and
12634
the rest are complex (`-1\pm 2i`). ::
12635
12636
sage: A = matrix(QQ,
12637
... [[-154, -3, -54, 44, 48, -244, -19, 67, -326, 85, 355, 581],
12638
... [ 504, 25, 156, -145, -171, 793, 99, -213, 1036, -247, -1152, -1865],
12639
... [ 294, -1, 112, -89, -90, 469, 36, -128, 634, -160, -695, -1126],
12640
... [ -49, -32, 25, 7, 37, -64, -58, 12, -42, -14, 72, 106],
12641
... [-261, -123, 65, 47, 169, -358, -254, 70, -309, -29, 454, 673],
12642
... [-448, -123, -10, 109, 227, -668, -262, 163, -721, 95, 896, 1410],
12643
... [ 38, 7, 8, -14, -17, 66, 6, -23, 73, -29, -78, -143],
12644
... [ -96, 10, -55, 37, 24, -168, 17, 56, -231, 88, 237, 412],
12645
... [ 310, 67, 31, -81, -143, 473, 143, -122, 538, -98, -641, -1029],
12646
... [ 139, -35, 99, -49, -18, 236, -41, -70, 370, -118, -377, -619],
12647
... [ 243, 9, 81, -72, -81, 386, 43, -105, 508, -124, -564, -911],
12648
... [-155, -3, -55, 45, 50, -245, -27, 65, -328, 77, 365, 583]])
12649
sage: A.characteristic_polynomial().factor()
12650
(x^2 - 2)^2 * (x^2 + 2*x + 5)^4
12651
sage: A.eigenvalues(extend=False)
12652
[]
12653
sage: A.rational_form()
12654
[ 0 -5| 0 0 0 0| 0 0 0 0 0 0]
12655
[ 1 -2| 0 0 0 0| 0 0 0 0 0 0]
12656
[-------+---------------+-----------------------]
12657
[ 0 0| 0 0 0 10| 0 0 0 0 0 0]
12658
[ 0 0| 1 0 0 4| 0 0 0 0 0 0]
12659
[ 0 0| 0 1 0 -3| 0 0 0 0 0 0]
12660
[ 0 0| 0 0 1 -2| 0 0 0 0 0 0]
12661
[-------+---------------+-----------------------]
12662
[ 0 0| 0 0 0 0| 0 0 0 0 0 50]
12663
[ 0 0| 0 0 0 0| 1 0 0 0 0 40]
12664
[ 0 0| 0 0 0 0| 0 1 0 0 0 3]
12665
[ 0 0| 0 0 0 0| 0 0 1 0 0 -12]
12666
[ 0 0| 0 0 0 0| 0 0 0 1 0 -12]
12667
[ 0 0| 0 0 0 0| 0 0 0 0 1 -4]
12668
sage: F.<x> = QQ[]
12669
sage: polys = A.rational_form(format='invariants')
12670
sage: [F(p).factor() for p in polys]
12671
[x^2 + 2*x + 5, (x^2 - 2) * (x^2 + 2*x + 5), (x^2 - 2) * (x^2 + 2*x + 5)^2]
12672
12673
Rational form may be computed over any field. The matrix below is
12674
an example where the eigenvalues lie outside the field. ::
12675
12676
sage: F.<a> = FiniteField(7^2)
12677
sage: A = matrix(F,
12678
... [[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],
12679
... [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],
12680
... [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],
12681
... [ 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],
12682
... [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],
12683
... [ 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],
12684
... [4*a + 5, 3*a + 3, 6, 4*a + 1, 4*a + 3, 6*a + 3, 6, 3*a + 3, 3, a + 3, 0],
12685
... [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],
12686
... [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],
12687
... [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],
12688
... [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]])
12689
sage: A.rational_form()
12690
[ a + 2| 0 0 0| 0 0 0 0 0 0 0]
12691
[-------+-----------------------+-------------------------------------------------------]
12692
[ 0| 0 0 a + 6| 0 0 0 0 0 0 0]
12693
[ 0| 1 0 6*a + 4| 0 0 0 0 0 0 0]
12694
[ 0| 0 1 6*a + 4| 0 0 0 0 0 0 0]
12695
[-------+-----------------------+-------------------------------------------------------]
12696
[ 0| 0 0 0| 0 0 0 0 0 0 2*a]
12697
[ 0| 0 0 0| 1 0 0 0 0 0 6*a + 3]
12698
[ 0| 0 0 0| 0 1 0 0 0 0 6*a + 1]
12699
[ 0| 0 0 0| 0 0 1 0 0 0 a + 2]
12700
[ 0| 0 0 0| 0 0 0 1 0 0 a + 6]
12701
[ 0| 0 0 0| 0 0 0 0 1 0 2*a + 1]
12702
[ 0| 0 0 0| 0 0 0 0 0 1 2*a + 1]
12703
sage: invariants = A.rational_form(format='invariants')
12704
sage: invariants
12705
[[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]]
12706
sage: R.<x> = F[]
12707
sage: polys = [R(p) for p in invariants]
12708
sage: [p.factor() for p in polys]
12709
[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]
12710
sage: polys[-1] == A.minimal_polynomial()
12711
True
12712
sage: prod(polys) == A.characteristic_polynomial()
12713
True
12714
sage: A.eigenvalues()
12715
Traceback (most recent call last):
12716
...
12717
NotImplementedError: eigenvalues() is not implemented for matrices with eigenvalues that are not in the fraction field of the base ring or in QQbar
12718
12719
Companion matrices may be selected as any one of four different types.
12720
See the documentation for the companion matrix constructor,
12721
:meth:`sage.matrix.constructor.companion_matrix`, for more information. ::
12722
12723
sage: A = matrix(QQ, [[35, -18, -2, -45],
12724
... [22, -22, 12, -16],
12725
... [ 5, -12, 12, 4],
12726
... [16, -6, -4, -23]])
12727
sage: A.rational_form(format='right')
12728
[ 2| 0 0 0]
12729
[--+--------]
12730
[ 0| 0 0 10]
12731
[ 0| 1 0 -1]
12732
[ 0| 0 1 0]
12733
sage: A.rational_form(format='bottom')
12734
[ 2| 0 0 0]
12735
[--+--------]
12736
[ 0| 0 1 0]
12737
[ 0| 0 0 1]
12738
[ 0|10 -1 0]
12739
sage: A.rational_form(format='left')
12740
[ 2| 0 0 0]
12741
[--+--------]
12742
[ 0| 0 1 0]
12743
[ 0|-1 0 1]
12744
[ 0|10 0 0]
12745
sage: A.rational_form(format='top')
12746
[ 2| 0 0 0]
12747
[--+--------]
12748
[ 0| 0 -1 10]
12749
[ 0| 1 0 0]
12750
[ 0| 0 1 0]
12751
12752
TESTS::
12753
12754
sage: A = matrix(QQ, 2, 3, range(6))
12755
sage: A.rational_form()
12756
Traceback (most recent call last):
12757
...
12758
TypeError: matrix must be square, not 2 x 3
12759
12760
sage: A = matrix(Integers(6), 2, 2, range(4))
12761
sage: A.rational_form()
12762
Traceback (most recent call last):
12763
...
12764
TypeError: matrix entries must come from an exact field, not Ring of integers modulo 6
12765
12766
sage: A = matrix(RDF, 2, 2, range(4))
12767
sage: A.rational_form()
12768
Traceback (most recent call last):
12769
...
12770
TypeError: matrix entries must come from an exact field, not Real Double Field
12771
12772
sage: A = matrix(QQ, 2, range(4))
12773
sage: A.rational_form(format='junk')
12774
Traceback (most recent call last):
12775
...
12776
ValueError: 'format' keyword must be 'right', 'bottom', 'left', 'top' or 'invariants', not junk
12777
12778
sage: A = matrix(QQ, 2, range(4))
12779
sage: A.rational_form(subdivide='garbage')
12780
Traceback (most recent call last):
12781
...
12782
ValueError: 'subdivide' keyword must be True or False, not garbage
12783
12784
.. rubric:: Citations
12785
12786
.. [STORJOHANN-EMAIL] A. Storjohann, Email Communication. 30 May 2011.
12787
12788
AUTHOR:
12789
12790
- Rob Beezer (2011-06-09)
12791
"""
12792
from sage.rings.arith import gcd # remove if translated to object-oriented calls
12793
import sage.rings.polynomial.polynomial_ring_constructor
12794
import sage.matrix.constructor
12795
12796
R = self.base_ring()
12797
if not self.is_square():
12798
raise TypeError("matrix must be square, not {0} x {1}".format(self.nrows(), self.ncols()))
12799
if not (R.is_field() and R.is_exact()):
12800
raise TypeError("matrix entries must come from an exact field, not {0}".format(R))
12801
if format not in ['right', 'bottom', 'left', 'top', 'invariants']:
12802
raise ValueError("'format' keyword must be 'right', 'bottom', 'left', 'top' or 'invariants', not {0}".format(format))
12803
if subdivide not in [True, False]:
12804
raise ValueError("'subdivide' keyword must be True or False, not {0}".format(subdivide))
12805
12806
_, polys, corners = self._zigzag_form(basis=False)
12807
k = len(polys)
12808
F = sage.rings.polynomial.polynomial_ring_constructor.PolynomialRing(R, 'x')
12809
C = [F(p) for p in polys]
12810
B = [(b == 1) for b in corners]
12811
B.append(False) # no last block, so no corner
12812
12813
if B[0]:
12814
V = [F(1)]
12815
else:
12816
V = [F(0)]
12817
12818
for j in range(1, k):
12819
V[j-1] = gcd([V[j-1],C[j],C[j-1]])
12820
for i in range(j-2, -1, -1):
12821
V[i] = gcd([V[i], V[i+1], C[i]])
12822
m = F(-1)
12823
for i in range(j):
12824
g = gcd(m*V[i], C[i])
12825
q, _ = C[i].quo_rem(g)
12826
C[i] = g
12827
if B[j]:
12828
_, V[i] = m.quo_rem(C[i])
12829
else:
12830
V[i] = F(0)
12831
m = m * q
12832
C[j] = m * C[j]
12833
if B[j]:
12834
V.append(m)
12835
else:
12836
V.append(F(0))
12837
12838
# Leading constant polynomials in C are size zero blocks, so toss them
12839
# Massage remainder to have leading coefficient 1
12840
while (len(C) > 0) and C[0].degree() == 0:
12841
C.remove(C[0])
12842
for i in range(len(C)):
12843
unit = C[i].list()[-1]
12844
if unit != R(1):
12845
C[i] = (1/unit)*C[i]
12846
12847
if format == 'invariants':
12848
inv = []
12849
for poly in C:
12850
inv.append(poly.list())
12851
return inv
12852
elif format in ['right', 'left', 'top', 'bottom']:
12853
companions = []
12854
for poly in C:
12855
companions.append(sage.matrix.constructor.companion_matrix(poly, format=format))
12856
return sage.matrix.constructor.block_diagonal_matrix(companions, subdivide=subdivide)
12857
12858
# A limited number of access-only properties are provided for matrices
12859
property T:
12860
r"""
12861
Returns the transpose of a matrix.
12862
12863
EXAMPLE::
12864
12865
sage: A = matrix(QQ, 5, range(25))
12866
sage: A.T
12867
[ 0 5 10 15 20]
12868
[ 1 6 11 16 21]
12869
[ 2 7 12 17 22]
12870
[ 3 8 13 18 23]
12871
[ 4 9 14 19 24]
12872
"""
12873
def __get__(self):
12874
return self.transpose()
12875
12876
property C:
12877
r"""
12878
Returns the conjugate matrix.
12879
12880
EXAMPLE::
12881
12882
sage: A = matrix(QQbar, [[ -3, 5 - 3*I, 7 - 4*I],
12883
... [7 + 3*I, -1 + 6*I, 3 + 5*I],
12884
... [3 + 3*I, -3 + 6*I, 5 + I]])
12885
sage: A.C
12886
[ -3 5 + 3*I 7 + 4*I]
12887
[ 7 - 3*I -1 - 6*I 3 - 5*I]
12888
[ 3 - 3*I -3 - 6*I 5 - 1*I]
12889
12890
"""
12891
def __get__(self):
12892
return self.conjugate()
12893
12894
property H:
12895
r"""
12896
Returns the conjugate-transpose (Hermitian) matrix.
12897
12898
EXAMPLE::
12899
12900
sage: A = matrix(QQbar, [[ -3, 5 - 3*I, 7 - 4*I],
12901
... [7 + 3*I, -1 + 6*I, 3 + 5*I],
12902
... [3 + 3*I, -3 + 6*I, 5 + I]])
12903
sage: A.H
12904
[ -3 7 - 3*I 3 - 3*I]
12905
[ 5 + 3*I -1 - 6*I -3 - 6*I]
12906
[ 7 + 4*I 3 - 5*I 5 - 1*I]
12907
"""
12908
def __get__(self):
12909
return self.conjugate().transpose()
12910
12911
property I:
12912
r"""
12913
Returns the inverse of the matrix, if it exists.
12914
12915
EXAMPLES::
12916
12917
sage: A = matrix(QQ, [[-5, -3, -1, -7],
12918
... [ 1, 1, 1, 0],
12919
... [-1, -2, -2, 0],
12920
... [-2, -1, 0, -4]])
12921
sage: A.I
12922
[ 0 2 1 0]
12923
[-4 -8 -2 7]
12924
[ 4 7 1 -7]
12925
[ 1 1 0 -2]
12926
12927
sage: B = matrix(QQ, [[-11, -5, 18, -6],
12928
... [ 1, 2, -6, 8],
12929
... [ -4, -2, 7, -3],
12930
... [ 1, -2, 5, -11]])
12931
sage: B.I
12932
Traceback (most recent call last):
12933
...
12934
ZeroDivisionError: input matrix must be nonsingular
12935
"""
12936
def __get__(self):
12937
return self.inverse()
12938
12939
# end of Matrix class methods
12940
12941
def _smith_diag(d):
12942
r"""
12943
For internal use by the smith_form routine. Given a diagonal matrix d
12944
over a ring r, return matrices d', a,b such that a\*d\*b = d' and
12945
d' is diagonal with each entry dividing the next.
12946
12947
If any of the d's is a unit, it replaces it with 1 (but no other
12948
attempt is made to pick "good" representatives of ideals).
12949
12950
EXAMPLE::
12951
12952
sage: from sage.matrix.matrix2 import _smith_diag
12953
sage: OE = EquationOrder(x^2 - x + 2, 'w')
12954
sage: A = matrix(OE, 2, [2,0,0,3])
12955
sage: D,U,V = _smith_diag(A); D,U,V
12956
(
12957
[1 0] [2 1] [ 1 -3]
12958
[0 6], [3 2], [-1 4]
12959
)
12960
sage: D == U*A*V
12961
True
12962
sage: m = matrix(GF(7),2, [3,0,0,6]); d,u,v = _smith_diag(m); d
12963
[1 0]
12964
[0 1]
12965
sage: u*m*v == d
12966
True
12967
"""
12968
12969
dp = d.__copy__()
12970
n = min(d.nrows(), d.ncols())
12971
R = d.base_ring()
12972
left = d.new_matrix(d.nrows(), d.nrows(), 1)
12973
right = d.new_matrix(d.ncols(), d.ncols(), 1)
12974
for i in xrange(n):
12975
I = R.ideal(dp[i,i])
12976
12977
if I == R.unit_ideal():
12978
if dp[i,i] != 1:
12979
left.add_multiple_of_row(i,i,R(R(1)/(dp[i,i])) - 1)
12980
dp[i,i] = R(1)
12981
continue
12982
12983
for j in xrange(i+1,n):
12984
if dp[j,j] not in I:
12985
t = R.ideal([dp[i,i], dp[j,j]]).gens_reduced()
12986
if len(t) > 1: raise ArithmeticError
12987
t = t[0]
12988
# find lambda, mu such that lambda*d[i,i] + mu*d[j,j] = t
12989
lamb = R(dp[i,i]/t).inverse_mod( R.ideal(dp[j,j]/t))
12990
mu = R((t - lamb*dp[i,i]) / dp[j,j])
12991
12992
newlmat = dp.new_matrix(dp.nrows(), dp.nrows(), 1)
12993
newlmat[i,i] = lamb
12994
newlmat[i,j] = 1
12995
newlmat[j,i] = R(-dp[j,j]*mu/t)
12996
newlmat[j,j] = R(dp[i,i]/t)
12997
newrmat = dp.new_matrix(dp.ncols(), dp.ncols(), 1)
12998
newrmat[i,i] = 1
12999
newrmat[i,j] = R(-dp[j,j]/t)
13000
newrmat[j,i] = mu
13001
newrmat[j,j] = R(lamb*dp[i,i] / t)
13002
13003
left = newlmat*left
13004
right = right*newrmat
13005
dp = newlmat*dp*newrmat
13006
return dp, left, right
13007
13008
def _generic_clear_column(m):
13009
r"""
13010
Reduce the first column of m to canonical form -- that is, all entries
13011
below the first are nonzero -- by multiplying on the left by invertible
13012
matrices over the given base ring. This assumes that the base ring is a
13013
PID. Returns a pair (left, a) where left*self = a and a has first column in
13014
canonical form.
13015
13016
If the first column is zero, then this function doesn't do anything very
13017
exciting.
13018
13019
Used by the smith_form and hermite_form methods.
13020
13021
EXAMPLES::
13022
13023
sage: L.<w> = NumberField(x^2 - x + 2)
13024
sage: OL = L.ring_of_integers(); w = OL(w)
13025
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])
13026
sage: s,t = m.echelon_form(transformation=True); t*m == s # indirect doctest
13027
True
13028
sage: s[0]
13029
(w, 0, 0, 0)
13030
"""
13031
if m.nrows() <= 1 or m.ncols() <= 0:
13032
return m.new_matrix(m.nrows(), m.nrows(), 1), m
13033
13034
a = m.__copy__()
13035
left_mat = m.new_matrix(m.nrows(), m.nrows(), 1)
13036
R = m.base_ring()
13037
13038
# case 1: if a_{0, 0} = 0 and a_{k, 0} != 0 for some k, swap rows 0 and k.
13039
if a[0, 0] == 0:
13040
k = 0
13041
while a[k, 0] == 0:
13042
k += 1
13043
if k == a.nrows(): # first column is zero
13044
return left_mat, a
13045
# k is now first row such that a[k, 0] is nonzero
13046
left_mat[0,0] = 0
13047
left_mat[k,k] = 0
13048
left_mat[0,k] = 1
13049
left_mat[k,0] = -1
13050
a = left_mat*a
13051
if left_mat * m != a:
13052
raise ArithmeticError, "Something went wrong"
13053
13054
# case 2: if there is an entry at position (k,j) such that a_{0,j}
13055
# does not divide a_{k,j}, then we know that there are c,d in R such
13056
# that c.a_{0,j} - d.a_{k,j} = B where B = gcd(a_{0,j}, a_{k,j}) (which
13057
# is well-defined since R is a PID).
13058
# Then for appropriate e,f the matrix
13059
# [c,-d]
13060
# [e,f]
13061
# is invertible over R
13062
13063
if a[0,0] != 0:
13064
I = R.ideal(a[0, 0]) # need to make sure we change this when a[0,0] changes
13065
else:
13066
I = R.zero_ideal()
13067
for k in xrange(1, a.nrows()):
13068
if a[k,0] not in I:
13069
try:
13070
v = R.ideal(a[0,0], a[k,0]).gens_reduced()
13071
except Exception, msg:
13072
raise ArithmeticError, "%s\nCan't create ideal on %s and %s" % (msg, a[0,0], a[k,0])
13073
if len(v) > 1:
13074
raise ArithmeticError, "Ideal %s not principal" % R.ideal(a[0,0], a[k,0])
13075
B = v[0]
13076
13077
# now we find c,d, using the fact that c * (a_{0,0}/B) - d *
13078
# (a_{k,0}/B) = 1, so c is the inverse of a_{0,0}/B modulo
13079
# a_{k,0}/B.
13080
# need to handle carefully the case when a_{k,0}/B is a unit, i.e. a_{k,0} divides
13081
# a_{0,0}.
13082
13083
c = R(a[0,0] / B).inverse_mod(R.ideal(a[k,0] / B))
13084
d = R( (c*a[0,0] - B)/(a[k,0]) )
13085
13086
# sanity check
13087
if c*a[0,0] - d*a[k,0] != B:
13088
raise ArithmeticError
13089
13090
# now we find e,f such that e*d + c*f = 1 in the same way
13091
if c != 0:
13092
e = d.inverse_mod( R.ideal(c) )
13093
f = R((1 - d*e)/c)
13094
else:
13095
e = R(-a[k,0]/B) # here d is a unit and this is just 1/d
13096
f = R(1)
13097
13098
if e*d + c*f != 1:
13099
raise ArithmeticError
13100
newlmat = left_mat.parent()(1)
13101
newlmat[0,0] = c
13102
newlmat[0,k] = -d
13103
newlmat[k,0] = e
13104
newlmat[k,k] = f
13105
if newlmat.det() != 1:
13106
raise ArithmeticError
13107
a = newlmat*a
13108
I = R.ideal(a[0,0])
13109
left_mat = newlmat*left_mat
13110
if left_mat * m != a:
13111
raise ArithmeticError
13112
13113
# now everything in column 0 is divisible by the pivot
13114
for i in xrange(1,a.nrows()):
13115
s = R( a[i, 0]/a[0, 0])
13116
a.add_multiple_of_row(i, 0, -s )
13117
left_mat.add_multiple_of_row(i, 0, -s)
13118
if left_mat * m != a:
13119
raise ArithmeticError
13120
13121
return left_mat, a
13122
13123
def _smith_onestep(m):
13124
r"""
13125
Carry out one step of Smith normal form for matrix m. Returns three matrices a,b,c over
13126
the same base ring as m, such that a \* m \* c = b, a and c have
13127
determinant 1, and the zeroth row and column of b have no nonzero
13128
entries except b[0,0].
13129
13130
EXAMPLE::
13131
13132
sage: from sage.matrix.matrix2 import _smith_onestep
13133
sage: OE = NumberField(x^2 - x + 2,'w').ring_of_integers()
13134
sage: w = OE.ring_generators()[0]
13135
sage: m = matrix(OE, 3,3,[1,0,7,2,w, w+17, 13+8*w, 0, 6])
13136
sage: a,b,c = _smith_onestep(m); b
13137
[ 1 0 0]
13138
[ 0 w w + 3]
13139
[ 0 0 -56*w - 85]
13140
sage: a * m * c == b
13141
True
13142
"""
13143
13144
a = m.__copy__()
13145
left_mat = m.new_matrix(m.nrows(), m.nrows(), 1)
13146
right_mat = m.new_matrix(m.ncols(), m.ncols(), 1)
13147
13148
if m == 0 or (m.nrows() <= 1 and m.ncols() <= 1):
13149
return left_mat, m, right_mat
13150
13151
# preparation: if column 0 is zero, swap it with the first nonzero column
13152
j = 0
13153
while a.column(j) == 0: j += 1
13154
if j > 0:
13155
right_mat[0,0] = right_mat[j,j] = 0
13156
right_mat[0,j] = 1
13157
right_mat[j,0] = -1
13158
a = a*right_mat
13159
if m * right_mat != a:
13160
raise ArithmeticError
13161
13162
left_mat, a = _generic_clear_column(a)
13163
assert left_mat * m * right_mat == a
13164
13165
# test if everything to the right of the pivot in row 0 is good as well
13166
isdone = True
13167
for jj in xrange(j+1, a.ncols()):
13168
if a[0,jj] != 0:
13169
isdone = False
13170
13171
# if not we recurse -- algorithm must terminate if R is Noetherian.
13172
if isdone == False:
13173
s,t,u = _smith_onestep(a.transpose())
13174
left_mat = u.transpose() * left_mat
13175
a = t.transpose()
13176
right_mat = right_mat* s.transpose()
13177
13178
return left_mat, a, right_mat
13179
13180
def _dim_cmp(x,y):
13181
"""
13182
Used internally by matrix functions. Given 2-tuples (x,y), returns
13183
their comparison based on the first component.
13184
13185
EXAMPLES::
13186
13187
sage: from sage.matrix.matrix2 import _dim_cmp
13188
sage: V = [(QQ^3, 2), (QQ^2, 1)]
13189
sage: _dim_cmp(V[0], V[1])
13190
1
13191
"""
13192
return cmp(x[0].dimension(), y[0].dimension())
13193
13194
def decomp_seq(v):
13195
"""
13196
This function is used internally be the decomposition matrix
13197
method. It takes a list of tuples and produces a sequence that is
13198
correctly sorted and prints with carriage returns.
13199
13200
EXAMPLES::
13201
13202
sage: from sage.matrix.matrix2 import decomp_seq
13203
sage: V = [(QQ^3, 2), (QQ^2, 1)]
13204
sage: decomp_seq(V)
13205
[
13206
(Vector space of dimension 2 over Rational Field, 1),
13207
(Vector space of dimension 3 over Rational Field, 2)
13208
]
13209
"""
13210
list.sort(v, _dim_cmp)
13211
return Sequence(v, universe=tuple, check=False, cr=True)
13212
13213
13214
def cmp_pivots(x,y):
13215
"""
13216
Compare two sequences of pivot columns.
13217
13218
- If x is shorter than y, return -1, i.e., x < y, "not as good".
13219
13220
- If x is longer than y, x > y, "better".
13221
13222
- If the length is the same then x is better, i.e., x > y if the
13223
entries of x are correspondingly >= those of y with one being
13224
greater.
13225
"""
13226
if len(x) < len(y):
13227
return -1
13228
if len(x) > len(y):
13229
return 1
13230
if x < y:
13231
return 1
13232
elif x == y:
13233
return 0
13234
else:
13235
return -1
13236
13237
13238
def _choose(Py_ssize_t n, Py_ssize_t t):
13239
"""
13240
Returns all possible sublists of length t from range(n)
13241
13242
Based on algorithm T from Knuth's taocp part 4: 7.2.1.3 p.5 This
13243
function replaces the one based on algorithm L because it is
13244
faster.
13245
13246
EXAMPLES::
13247
13248
sage: from sage.matrix.matrix2 import _choose
13249
sage: _choose(1,1)
13250
[[0]]
13251
sage: _choose(4,1)
13252
[[0], [1], [2], [3]]
13253
sage: _choose(4,4)
13254
[[0, 1, 2, 3]]
13255
13256
AUTHORS:
13257
13258
- Jaap Spies (2007-11-14)
13259
"""
13260
cdef Py_ssize_t j, temp
13261
13262
x = [] # initialize T1
13263
c = range(t)
13264
if t == n:
13265
x.append(c)
13266
return x
13267
c.append(n)
13268
c.append(0)
13269
j = t-1
13270
13271
while True:
13272
x.append(c[:t]) # visit T2
13273
if j >= 0:
13274
c[j] = j+1
13275
j = j-1
13276
continue # goto T2
13277
13278
if c[0]+1 < c[1]: # T3 easy case!
13279
c[0] = c[0]+1
13280
continue
13281
else:
13282
j = 1
13283
13284
while True:
13285
c[j-1] = j-1 # T4 find j
13286
temp = c[j]+1
13287
if temp == c[j+1]:
13288
j = j+1
13289
else:
13290
break
13291
13292
13293
if j >= t: # T5 stop?
13294
break
13295
13296
c[j] = temp # T6
13297
j = j-1
13298
13299
return x
13300
13301
13302
def _binomial(Py_ssize_t n, Py_ssize_t k):
13303
"""
13304
Fast and unchecked implementation of binomial(n,k) This is only for
13305
internal use.
13306
13307
EXAMPLES::
13308
13309
sage: from sage.matrix.matrix2 import _binomial
13310
sage: _binomial(10,2)
13311
45
13312
sage: _binomial(10,5)
13313
252
13314
13315
AUTHORS:
13316
13317
- Jaap Spies (2007-10-26)
13318
"""
13319
cdef Py_ssize_t i
13320
13321
if k > (n/2):
13322
k = n-k
13323
if k == 0:
13324
return 1
13325
13326
result = n
13327
n, k = n-1, k-1
13328
i = 2
13329
while k > 0:
13330
result = (result*n)/i
13331
i, n, k = i+1, n-1, k-1
13332
return result
13333
13334
def _jordan_form_vector_in_difference(V, W):
13335
r"""
13336
Given two lists of vectors ``V`` and ``W`` over the same base field,
13337
returns a vector in the difference ``V - W``. If the difference is
13338
empty, returns ``None``.
13339
13340
NOTES:
13341
13342
This is meant to be a private helper method for the ``jordan_form`` method
13343
in the above class.
13344
13345
TEST::
13346
13347
sage: v = vector(ZZ, [1,0,0,0])
13348
sage: w = vector(ZZ, [0,1,0,0])
13349
sage: u = vector(ZZ, [1,1,0,0])
13350
sage: sage.matrix.matrix2._jordan_form_vector_in_difference([v,w], [u])
13351
(1, 0, 0, 0)
13352
"""
13353
if len(V) == 0:
13354
return None
13355
if len(W) == 0:
13356
return V[0]
13357
W_space = sage.all.span(W)
13358
for v in V:
13359
if v not in W_space:
13360
return v
13361
return None
13362
13363
13364