Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/matrix/constructor.py
8817 views
1
"""
2
Matrix Constructor
3
"""
4
5
#*****************************************************************************
6
# Copyright (C) 2005 William Stein <[email protected]>
7
#
8
# Distributed under the terms of the GNU General Public License (GPL)
9
#
10
# This code is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
# General Public License for more details.
14
#
15
# The full text of the GPL is available at:
16
#
17
# http://www.gnu.org/licenses/
18
#*****************************************************************************
19
import types
20
import sage.rings.all as rings
21
from sage.rings.ring import is_Ring
22
import sage.matrix.matrix_space as matrix_space
23
from sage.modules.free_module_element import vector
24
from sage.structure.element import is_Vector
25
from sage.structure.sequence import Sequence
26
from sage.rings.real_double import RDF
27
from sage.rings.complex_double import CDF
28
from sage.rings.all import ZZ, QQ
29
from sage.misc.misc_c import running_total
30
from matrix import is_Matrix
31
from copy import copy
32
33
import sage.categories.pushout
34
35
def matrix_method(func=None, name=None):
36
"""
37
Allows a function to be tab-completed on the global matrix
38
constructor object.
39
40
INPUT:
41
42
- ``*function`` -- a single argument. The function that is being
43
decorated.
44
45
- ``**kwds`` -- a single optional keyword argument
46
``name=<string>``. The name of the corresponding method in the
47
global matrix constructor object. If not given, it is derived
48
from the function name.
49
50
EXAMPLES::
51
52
sage: from sage.matrix.constructor import matrix_method
53
sage: def foo_matrix(n): return matrix.diagonal(range(n))
54
sage: matrix_method(foo_matrix)
55
<function foo_matrix at ...>
56
sage: matrix.foo(5)
57
[0 0 0 0 0]
58
[0 1 0 0 0]
59
[0 0 2 0 0]
60
[0 0 0 3 0]
61
[0 0 0 0 4]
62
sage: matrix_method(foo_matrix, name='bar')
63
<function foo_matrix at ...>
64
sage: matrix.bar(3)
65
[0 0 0]
66
[0 1 0]
67
[0 0 2]
68
"""
69
if func is not None:
70
if name is None:
71
name = func.__name__.replace('matrix', '').strip('_')
72
prefix = " This function is available as %s(...) and matrix.%s(...)." % (
73
func.__name__, name)
74
func.__doc__ = "%s\n\n%s" % (prefix, func.__doc__)
75
setattr(matrix, name, func)
76
return func
77
else:
78
return lambda func: matrix_method(func, name=name)
79
80
def _matrix_constructor(*args, **kwds):
81
"""
82
Create a matrix.
83
84
This implements the ``matrix`` constructor::
85
86
sage: matrix([[1,2],[3,4]])
87
[1 2]
88
[3 4]
89
90
It also contains methods to create special types of matrices, see
91
``matrix.[tab]`` for more options. For example::
92
93
sage: matrix.identity(2)
94
[1 0]
95
[0 1]
96
97
INPUT:
98
99
The matrix command takes the entries of a matrix, optionally
100
preceded by a ring and the dimensions of the matrix, and returns a
101
matrix.
102
103
The entries of a matrix can be specified as a flat list of
104
elements, a list of lists (i.e., a list of rows), a list of Sage
105
vectors, a callable object, or a dictionary having positions as
106
keys and matrix entries as values (see the examples). If you pass
107
in a callable object, then you must specify the number of rows and
108
columns. You can create a matrix of zeros by passing an empty list
109
or the integer zero for the entries. To construct a multiple of
110
the identity (`cI`), you can specify square dimensions and pass in
111
`c`. Calling matrix() with a Sage object may return something that
112
makes sense. Calling matrix() with a NumPy array will convert the
113
array to a matrix.
114
115
The ring, number of rows, and number of columns of the matrix can
116
be specified by setting the ring, nrows, or ncols parameters or by
117
passing them as the first arguments to the function in the order
118
ring, nrows, ncols. The ring defaults to ZZ if it is not specified
119
or cannot be determined from the entries. If the numbers of rows
120
and columns are not specified and cannot be determined, then an
121
empty 0x0 matrix is returned.
122
123
124
- ``ring`` - the base ring for the entries of the
125
matrix.
126
127
- ``nrows`` - the number of rows in the matrix.
128
129
- ``ncols`` - the number of columns in the matrix.
130
131
- ``sparse`` - create a sparse matrix. This defaults
132
to True when the entries are given as a dictionary, otherwise
133
defaults to False.
134
135
136
OUTPUT:
137
138
a matrix
139
140
EXAMPLES::
141
142
sage: m=matrix(2); m; m.parent()
143
[0 0]
144
[0 0]
145
Full MatrixSpace of 2 by 2 dense matrices over Integer Ring
146
147
::
148
149
sage: m=matrix(2,3); m; m.parent()
150
[0 0 0]
151
[0 0 0]
152
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring
153
154
::
155
156
sage: m=matrix(QQ,[[1,2,3],[4,5,6]]); m; m.parent()
157
[1 2 3]
158
[4 5 6]
159
Full MatrixSpace of 2 by 3 dense matrices over Rational Field
160
161
::
162
163
sage: m = matrix(QQ, 3, 3, lambda i, j: i+j); m
164
[0 1 2]
165
[1 2 3]
166
[2 3 4]
167
sage: m = matrix(3, lambda i,j: i-j); m
168
[ 0 -1 -2]
169
[ 1 0 -1]
170
[ 2 1 0]
171
172
::
173
174
sage: matrix(QQ,2,3,lambda x, y: x+y)
175
[0 1 2]
176
[1 2 3]
177
sage: matrix(QQ,3,2,lambda x, y: x+y)
178
[0 1]
179
[1 2]
180
[2 3]
181
182
::
183
184
sage: v1=vector((1,2,3))
185
sage: v2=vector((4,5,6))
186
sage: m=matrix([v1,v2]); m; m.parent()
187
[1 2 3]
188
[4 5 6]
189
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring
190
191
::
192
193
sage: m=matrix(QQ,2,[1,2,3,4,5,6]); m; m.parent()
194
[1 2 3]
195
[4 5 6]
196
Full MatrixSpace of 2 by 3 dense matrices over Rational Field
197
198
::
199
200
sage: m=matrix(QQ,2,3,[1,2,3,4,5,6]); m; m.parent()
201
[1 2 3]
202
[4 5 6]
203
Full MatrixSpace of 2 by 3 dense matrices over Rational Field
204
205
::
206
207
sage: m=matrix({(0,1): 2, (1,1):2/5}); m; m.parent()
208
[ 0 2]
209
[ 0 2/5]
210
Full MatrixSpace of 2 by 2 sparse matrices over Rational Field
211
212
::
213
214
sage: m=matrix(QQ,2,3,{(1,1): 2}); m; m.parent()
215
[0 0 0]
216
[0 2 0]
217
Full MatrixSpace of 2 by 3 sparse matrices over Rational Field
218
219
::
220
221
sage: import numpy
222
sage: n=numpy.array([[1,2],[3,4]],float)
223
sage: m=matrix(n); m; m.parent()
224
[1.0 2.0]
225
[3.0 4.0]
226
Full MatrixSpace of 2 by 2 dense matrices over Real Double Field
227
228
::
229
230
sage: v = vector(ZZ, [1, 10, 100])
231
sage: m=matrix(v); m; m.parent()
232
[ 1 10 100]
233
Full MatrixSpace of 1 by 3 dense matrices over Integer Ring
234
sage: m=matrix(GF(7), v); m; m.parent()
235
[1 3 2]
236
Full MatrixSpace of 1 by 3 dense matrices over Finite Field of size 7
237
238
::
239
240
sage: g = graphs.PetersenGraph()
241
sage: m = matrix(g); m; m.parent()
242
[0 1 0 0 1 1 0 0 0 0]
243
[1 0 1 0 0 0 1 0 0 0]
244
[0 1 0 1 0 0 0 1 0 0]
245
[0 0 1 0 1 0 0 0 1 0]
246
[1 0 0 1 0 0 0 0 0 1]
247
[1 0 0 0 0 0 0 1 1 0]
248
[0 1 0 0 0 0 0 0 1 1]
249
[0 0 1 0 0 1 0 0 0 1]
250
[0 0 0 1 0 1 1 0 0 0]
251
[0 0 0 0 1 0 1 1 0 0]
252
Full MatrixSpace of 10 by 10 dense matrices over Integer Ring
253
254
::
255
256
sage: matrix(ZZ, 10, 10, range(100), sparse=True).parent()
257
Full MatrixSpace of 10 by 10 sparse matrices over Integer Ring
258
259
::
260
261
sage: R = PolynomialRing(QQ, 9, 'x')
262
sage: A = matrix(R, 3, 3, R.gens()); A
263
[x0 x1 x2]
264
[x3 x4 x5]
265
[x6 x7 x8]
266
sage: det(A)
267
-x2*x4*x6 + x1*x5*x6 + x2*x3*x7 - x0*x5*x7 - x1*x3*x8 + x0*x4*x8
268
269
TESTS::
270
271
sage: m=matrix(); m; m.parent()
272
[]
273
Full MatrixSpace of 0 by 0 dense matrices over Integer Ring
274
sage: m=matrix(QQ); m; m.parent()
275
[]
276
Full MatrixSpace of 0 by 0 dense matrices over Rational Field
277
sage: m=matrix(QQ,2); m; m.parent()
278
[0 0]
279
[0 0]
280
Full MatrixSpace of 2 by 2 dense matrices over Rational Field
281
sage: m=matrix(QQ,2,3); m; m.parent()
282
[0 0 0]
283
[0 0 0]
284
Full MatrixSpace of 2 by 3 dense matrices over Rational Field
285
sage: m=matrix([]); m; m.parent()
286
[]
287
Full MatrixSpace of 0 by 0 dense matrices over Integer Ring
288
sage: m=matrix(QQ,[]); m; m.parent()
289
[]
290
Full MatrixSpace of 0 by 0 dense matrices over Rational Field
291
sage: m=matrix(2,2,1); m; m.parent()
292
[1 0]
293
[0 1]
294
Full MatrixSpace of 2 by 2 dense matrices over Integer Ring
295
sage: m=matrix(QQ,2,2,1); m; m.parent()
296
[1 0]
297
[0 1]
298
Full MatrixSpace of 2 by 2 dense matrices over Rational Field
299
sage: m=matrix(2,3,0); m; m.parent()
300
[0 0 0]
301
[0 0 0]
302
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring
303
sage: m=matrix(QQ,2,3,0); m; m.parent()
304
[0 0 0]
305
[0 0 0]
306
Full MatrixSpace of 2 by 3 dense matrices over Rational Field
307
sage: m=matrix([[1,2,3],[4,5,6]]); m; m.parent()
308
[1 2 3]
309
[4 5 6]
310
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring
311
sage: m=matrix(QQ,2,[[1,2,3],[4,5,6]]); m; m.parent()
312
[1 2 3]
313
[4 5 6]
314
Full MatrixSpace of 2 by 3 dense matrices over Rational Field
315
sage: m=matrix(QQ,3,[[1,2,3],[4,5,6]]); m; m.parent()
316
Traceback (most recent call last):
317
...
318
ValueError: Number of rows does not match up with specified number.
319
sage: m=matrix(QQ,2,3,[[1,2,3],[4,5,6]]); m; m.parent()
320
[1 2 3]
321
[4 5 6]
322
Full MatrixSpace of 2 by 3 dense matrices over Rational Field
323
sage: m=matrix(QQ,2,4,[[1,2,3],[4,5,6]]); m; m.parent()
324
Traceback (most recent call last):
325
...
326
ValueError: Number of columns does not match up with specified number.
327
sage: m=matrix([(1,2,3),(4,5,6)]); m; m.parent()
328
[1 2 3]
329
[4 5 6]
330
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring
331
sage: m=matrix([1,2,3,4,5,6]); m; m.parent()
332
[1 2 3 4 5 6]
333
Full MatrixSpace of 1 by 6 dense matrices over Integer Ring
334
sage: m=matrix((1,2,3,4,5,6)); m; m.parent()
335
[1 2 3 4 5 6]
336
Full MatrixSpace of 1 by 6 dense matrices over Integer Ring
337
sage: m=matrix(QQ,[1,2,3,4,5,6]); m; m.parent()
338
[1 2 3 4 5 6]
339
Full MatrixSpace of 1 by 6 dense matrices over Rational Field
340
sage: m=matrix(QQ,3,2,[1,2,3,4,5,6]); m; m.parent()
341
[1 2]
342
[3 4]
343
[5 6]
344
Full MatrixSpace of 3 by 2 dense matrices over Rational Field
345
sage: m=matrix(QQ,2,4,[1,2,3,4,5,6]); m; m.parent()
346
Traceback (most recent call last):
347
...
348
ValueError: entries has the wrong length
349
sage: m=matrix(QQ,5,[1,2,3,4,5,6]); m; m.parent()
350
Traceback (most recent call last):
351
...
352
TypeError: cannot construct an element of
353
Full MatrixSpace of 5 by 1 dense matrices over Rational Field
354
from [1, 2, 3, 4, 5, 6]!
355
sage: m=matrix({(1,1): 2}); m; m.parent()
356
[0 0]
357
[0 2]
358
Full MatrixSpace of 2 by 2 sparse matrices over Integer Ring
359
sage: m=matrix(QQ,{(1,1): 2}); m; m.parent()
360
[0 0]
361
[0 2]
362
Full MatrixSpace of 2 by 2 sparse matrices over Rational Field
363
sage: m=matrix(QQ,3,{(1,1): 2}); m; m.parent()
364
[0 0 0]
365
[0 2 0]
366
[0 0 0]
367
Full MatrixSpace of 3 by 3 sparse matrices over Rational Field
368
sage: m=matrix(QQ,3,4,{(1,1): 2}); m; m.parent()
369
[0 0 0 0]
370
[0 2 0 0]
371
[0 0 0 0]
372
Full MatrixSpace of 3 by 4 sparse matrices over Rational Field
373
sage: m=matrix(QQ,2,{(1,1): 2}); m; m.parent()
374
[0 0]
375
[0 2]
376
Full MatrixSpace of 2 by 2 sparse matrices over Rational Field
377
sage: m=matrix(QQ,1,{(1,1): 2}); m; m.parent()
378
Traceback (most recent call last):
379
...
380
IndexError: invalid entries list
381
sage: m=matrix({}); m; m.parent()
382
[]
383
Full MatrixSpace of 0 by 0 sparse matrices over Integer Ring
384
sage: m=matrix(QQ,{}); m; m.parent()
385
[]
386
Full MatrixSpace of 0 by 0 sparse matrices over Rational Field
387
sage: m=matrix(QQ,2,{}); m; m.parent()
388
[0 0]
389
[0 0]
390
Full MatrixSpace of 2 by 2 sparse matrices over Rational Field
391
sage: m=matrix(QQ,2,3,{}); m; m.parent()
392
[0 0 0]
393
[0 0 0]
394
Full MatrixSpace of 2 by 3 sparse matrices over Rational Field
395
sage: m=matrix(2,{}); m; m.parent()
396
[0 0]
397
[0 0]
398
Full MatrixSpace of 2 by 2 sparse matrices over Integer Ring
399
sage: m=matrix(2,3,{}); m; m.parent()
400
[0 0 0]
401
[0 0 0]
402
Full MatrixSpace of 2 by 3 sparse matrices over Integer Ring
403
sage: m=matrix(0); m; m.parent()
404
[]
405
Full MatrixSpace of 0 by 0 dense matrices over Integer Ring
406
sage: m=matrix(0,2); m; m.parent()
407
[]
408
Full MatrixSpace of 0 by 2 dense matrices over Integer Ring
409
sage: m=matrix(2,0); m; m.parent()
410
[]
411
Full MatrixSpace of 2 by 0 dense matrices over Integer Ring
412
sage: m=matrix(0,[1]); m; m.parent()
413
Traceback (most recent call last):
414
...
415
ValueError: entries has the wrong length
416
sage: m=matrix(1,0,[]); m; m.parent()
417
[]
418
Full MatrixSpace of 1 by 0 dense matrices over Integer Ring
419
sage: m=matrix(0,1,[]); m; m.parent()
420
[]
421
Full MatrixSpace of 0 by 1 dense matrices over Integer Ring
422
sage: m=matrix(0,[]); m; m.parent()
423
[]
424
Full MatrixSpace of 0 by 0 dense matrices over Integer Ring
425
sage: m=matrix(0,{}); m; m.parent()
426
[]
427
Full MatrixSpace of 0 by 0 sparse matrices over Integer Ring
428
sage: m=matrix(0,{(1,1):2}); m; m.parent()
429
Traceback (most recent call last):
430
...
431
IndexError: invalid entries list
432
sage: m=matrix(2,0,{(1,1):2}); m; m.parent()
433
Traceback (most recent call last):
434
...
435
IndexError: invalid entries list
436
sage: import numpy
437
sage: n=numpy.array([[numpy.complex(0,1),numpy.complex(0,2)],[3,4]],complex)
438
sage: m=matrix(n); m; m.parent()
439
[1.0*I 2.0*I]
440
[ 3.0 4.0]
441
Full MatrixSpace of 2 by 2 dense matrices over Complex Double Field
442
sage: n=numpy.array([[1,2],[3,4]],'int32')
443
sage: m=matrix(n); m; m.parent()
444
[1 2]
445
[3 4]
446
Full MatrixSpace of 2 by 2 dense matrices over Integer Ring
447
sage: n = numpy.array([[1,2,3],[4,5,6],[7,8,9]],'float32')
448
sage: m=matrix(n); m; m.parent()
449
[1.0 2.0 3.0]
450
[4.0 5.0 6.0]
451
[7.0 8.0 9.0]
452
Full MatrixSpace of 3 by 3 dense matrices over Real Double Field
453
sage: n=numpy.array([[1,2,3],[4,5,6],[7,8,9]],'float64')
454
sage: m=matrix(n); m; m.parent()
455
[1.0 2.0 3.0]
456
[4.0 5.0 6.0]
457
[7.0 8.0 9.0]
458
Full MatrixSpace of 3 by 3 dense matrices over Real Double Field
459
sage: n=numpy.array([[1,2,3],[4,5,6],[7,8,9]],'complex64')
460
sage: m=matrix(n); m; m.parent()
461
[1.0 2.0 3.0]
462
[4.0 5.0 6.0]
463
[7.0 8.0 9.0]
464
Full MatrixSpace of 3 by 3 dense matrices over Complex Double Field
465
sage: n=numpy.array([[1,2,3],[4,5,6],[7,8,9]],'complex128')
466
sage: m=matrix(n); m; m.parent()
467
[1.0 2.0 3.0]
468
[4.0 5.0 6.0]
469
[7.0 8.0 9.0]
470
Full MatrixSpace of 3 by 3 dense matrices over Complex Double Field
471
sage: a = matrix([[1,2],[3,4]])
472
sage: b = matrix(a.numpy()); b
473
[1 2]
474
[3 4]
475
sage: a == b
476
True
477
sage: c = matrix(a.numpy('float32')); c
478
[1.0 2.0]
479
[3.0 4.0]
480
sage: matrix(numpy.array([[5]]))
481
[5]
482
sage: v = vector(ZZ, [1, 10, 100])
483
sage: m=matrix(ZZ['x'], v); m; m.parent()
484
[ 1 10 100]
485
Full MatrixSpace of 1 by 3 dense matrices over Univariate Polynomial Ring in x over Integer Ring
486
sage: matrix(ZZ, 10, 10, range(100)).parent()
487
Full MatrixSpace of 10 by 10 dense matrices over Integer Ring
488
sage: m = matrix(GF(7), [[1/3,2/3,1/2], [3/4,4/5,7]]); m; m.parent()
489
[5 3 4]
490
[6 5 0]
491
Full MatrixSpace of 2 by 3 dense matrices over Finite Field of size 7
492
sage: m = matrix([[1,2,3], [RDF(2), CDF(1,2), 3]]); m; m.parent()
493
[ 1.0 2.0 3.0]
494
[ 2.0 1.0 + 2.0*I 3.0]
495
Full MatrixSpace of 2 by 3 dense matrices over Complex Double Field
496
sage: m=matrix(3,3,1/2); m; m.parent()
497
[1/2 0 0]
498
[ 0 1/2 0]
499
[ 0 0 1/2]
500
Full MatrixSpace of 3 by 3 dense matrices over Rational Field
501
sage: matrix([[1],[2,3]])
502
Traceback (most recent call last):
503
...
504
ValueError: List of rows is not valid (rows are wrong types or lengths)
505
sage: matrix([[1],2])
506
Traceback (most recent call last):
507
...
508
ValueError: List of rows is not valid (rows are wrong types or lengths)
509
sage: matrix(vector(RR,[1,2,3])).parent()
510
Full MatrixSpace of 1 by 3 dense matrices over Real Field with 53 bits of precision
511
sage: matrix(ZZ, [[0] for i in range(10^5)]).is_zero() # see #10158
512
True
513
514
AUTHORS:
515
516
- ??: Initial implementation
517
518
- Jason Grout (2008-03): almost a complete rewrite, with bits and
519
pieces from the original implementation
520
"""
521
args = list(args)
522
sparse = kwds.get('sparse',False)
523
# if the first object already knows how to make itself into a
524
# matrix, try that, defaulting to a matrix over the integers.
525
if len(args) == 1 and hasattr(args[0], '_matrix_'):
526
try:
527
return args[0]._matrix_(sparse=sparse)
528
except TypeError:
529
return args[0]._matrix_()
530
elif len(args) == 2:
531
if hasattr(args[0], '_matrix_'):
532
try:
533
return args[0]._matrix_(args[1], sparse=sparse)
534
except TypeError:
535
return args[0]._matrix_(args[1])
536
elif hasattr(args[1], '_matrix_'):
537
try:
538
return args[1]._matrix_(args[0], sparse=sparse)
539
except TypeError:
540
return args[1]._matrix_(args[0])
541
542
if len(args) == 0:
543
# if nothing was passed return the empty matrix over the
544
# integer ring.
545
return matrix_space.MatrixSpace(rings.ZZ, 0, 0, sparse=sparse)([])
546
547
if len(args) >= 1 and is_Ring(args[0]):
548
# A ring is specified
549
if kwds.get('ring', args[0]) != args[0]:
550
raise ValueError, "Specified rings are not the same"
551
else:
552
ring = args[0]
553
args.pop(0)
554
else:
555
ring = kwds.get('ring', None)
556
557
if len(args) >= 1:
558
# check to see if the number of rows is specified
559
try:
560
import numpy
561
if isinstance(args[0], numpy.ndarray):
562
raise TypeError
563
nrows = int(args[0])
564
args.pop(0)
565
if kwds.get('nrows', nrows) != nrows:
566
raise ValueError, "Number of rows specified in two places and they are not the same"
567
except TypeError:
568
nrows = kwds.get('nrows', None)
569
else:
570
nrows = kwds.get('nrows', None)
571
572
if len(args) >= 1:
573
# check to see if additionally, the number of columns is specified
574
try:
575
import numpy
576
if isinstance(args[0], numpy.ndarray):
577
raise TypeError
578
ncols = int(args[0])
579
args.pop(0)
580
if kwds.get('ncols', ncols) != ncols:
581
raise ValueError, "Number of columns specified in two places and they are not the same"
582
except TypeError:
583
ncols = kwds.get('ncols', None)
584
else:
585
ncols = kwds.get('ncols', None)
586
587
588
# Now we've taken care of initial ring, nrows, and ncols arguments.
589
# We've also taken care of the Sage object case.
590
591
# Now the rest of the arguments are a list of rows, a flat list of
592
# entries, a callable, a dict, a numpy array, or a single value.
593
if len(args) == 0:
594
# If no entries are specified, pass back a zero matrix
595
entries = 0
596
entry_ring = rings.ZZ
597
elif len(args) == 1:
598
if isinstance(args[0], (types.FunctionType, types.LambdaType, types.MethodType)):
599
if ncols is None and nrows is None:
600
raise ValueError, "When passing in a callable, the dimensions of the matrix must be specified"
601
if ncols is None:
602
ncols = nrows
603
elif nrows is None:
604
nrows = ncols
605
606
f = args[0]
607
args[0] = [[f(i,j) for j in range(ncols)] for i in range(nrows)]
608
609
if isinstance(args[0], (list, tuple)):
610
if len(args[0]) == 0:
611
# no entries are specified, pass back the zero matrix
612
entries = 0
613
entry_ring = rings.ZZ
614
elif isinstance(args[0][0], (list, tuple)) or is_Vector(args[0][0]):
615
# Ensure we have a list of lists, each inner list having the same number of elements
616
first_len = len(args[0][0])
617
if not all( (isinstance(v, (list, tuple)) or is_Vector(v)) and len(v) == first_len for v in args[0]):
618
raise ValueError, "List of rows is not valid (rows are wrong types or lengths)"
619
# We have a list of rows or vectors
620
if nrows is None:
621
nrows = len(args[0])
622
elif nrows != len(args[0]):
623
raise ValueError, "Number of rows does not match up with specified number."
624
if ncols is None:
625
ncols = len(args[0][0])
626
elif ncols != len(args[0][0]):
627
raise ValueError, "Number of columns does not match up with specified number."
628
629
entries = []
630
for v in args[0]:
631
entries.extend(v)
632
633
else:
634
# We have a flat list; figure out nrows and ncols
635
if nrows is None:
636
nrows = 1
637
638
if nrows > 0:
639
if ncols is None:
640
ncols = len(args[0]) // nrows
641
elif ncols != len(args[0]) // nrows:
642
raise ValueError, "entries has the wrong length"
643
elif len(args[0]) > 0:
644
raise ValueError, "entries has the wrong length"
645
646
entries = args[0]
647
648
if nrows > 0 and ncols > 0 and ring is None:
649
entries, ring = prepare(entries)
650
651
elif isinstance(args[0], dict):
652
# We have a dictionary
653
# default to sparse
654
sparse = kwds.get('sparse', True)
655
if len(args[0]) == 0:
656
# no entries are specified, pass back the zero matrix
657
entries = 0
658
else:
659
entries, entry_ring = prepare_dict(args[0])
660
if nrows is None:
661
nrows = nrows_from_dict(entries)
662
ncols = ncols_from_dict(entries)
663
# note that ncols can still be None if nrows is set --
664
# it will be assigned nrows down below.
665
666
# See the construction after the numpy case below.
667
else:
668
import numpy
669
if isinstance(args[0], numpy.ndarray):
670
num_array = args[0]
671
str_dtype = str(num_array.dtype)
672
673
if not( num_array.flags.c_contiguous is True or num_array.flags.f_contiguous is True):
674
raise TypeError('numpy matrix must be either c_contiguous or f_contiguous')
675
if str_dtype.count('float32')==1:
676
m=matrix(RDF,num_array.shape[0],num_array.shape[1],0)
677
m._replace_self_with_numpy32(num_array)
678
679
elif str_dtype.count('float64')==1:
680
m=matrix(RDF,num_array.shape[0],num_array.shape[1],0)
681
m._replace_self_with_numpy(num_array)
682
683
elif str_dtype.count('complex64')==1:
684
m=matrix(CDF,num_array.shape[0],num_array.shape[1],0)
685
m._replace_self_with_numpy32(num_array)
686
687
elif str_dtype.count('complex128')==1:
688
m=matrix(CDF,num_array.shape[0],num_array.shape[1],0)
689
m._replace_self_with_numpy(num_array)
690
691
elif str_dtype.count('int') == 1:
692
m = matrix(ZZ, [list(row) for row in list(num_array)])
693
694
elif str_dtype.count('object') == 1:
695
#Get the raw nested list from the numpy array
696
#and feed it back into matrix
697
try:
698
return matrix( [list(row) for row in list(num_array)])
699
except TypeError:
700
raise TypeError("cannot convert NumPy matrix to Sage matrix")
701
else:
702
raise TypeError("cannot convert NumPy matrix to Sage matrix")
703
704
return m
705
elif nrows is not None and ncols is not None:
706
# assume that we should just pass the thing into the
707
# MatrixSpace constructor and hope for the best
708
# This is not documented, but it is doctested
709
if ring is None:
710
entry_ring = args[0].parent()
711
entries = args[0]
712
else:
713
raise ValueError, "Invalid matrix constructor. Type matrix? for help"
714
else:
715
raise ValueError, "Invalid matrix constructor. Type matrix? for help"
716
717
if nrows is None:
718
nrows = 0
719
if ncols is None:
720
ncols = nrows
721
722
723
if ring is None:
724
try:
725
ring = entry_ring
726
except NameError:
727
ring = rings.ZZ
728
729
return matrix_space.MatrixSpace(ring, nrows, ncols, sparse=sparse)(entries)
730
731
732
class MatrixFactory(object):
733
"""
734
The class of the ``matrix`` object.
735
736
See :func:`_matrix_constructor` for the implementation of the call
737
interface. Implemented as a class for nicer tab completion.
738
739
EXAMPLES::
740
741
sage: from sage.misc.sageinspect import sage_getdoc, sage_getsource
742
sage: sage_getdoc(matrix) # used in output of matrix?
743
' Create a matrix.\n\n This implements the "matrix" ...'
744
sage: sage_getsource(matrix) # used in output of matrix??
745
'def _matrix_constructor(*args, **kwds):...'
746
"""
747
748
__doc__ = _matrix_constructor.__doc__
749
__call__ = staticmethod(_matrix_constructor)
750
751
def _sage_src_(self):
752
"""
753
For introspection of the global matrix object.
754
755
TESTS::
756
757
sage: from sage.misc.sageinspect import sage_getsource
758
sage: sage_getsource(matrix) == sage_getsource(sage.matrix.constructor._matrix_constructor)
759
True
760
"""
761
from sage.misc.sageinspect import sage_getsource
762
return sage_getsource(_matrix_constructor)
763
764
Matrix = matrix = MatrixFactory()
765
766
767
def prepare(w):
768
"""
769
Given a list w of numbers, find a common ring that they all
770
canonically map to, and return the list of images of the elements
771
of w in that ring along with the ring.
772
773
This is for internal use by the matrix function.
774
775
INPUT:
776
777
- ``w`` - list
778
779
OUTPUT:
780
781
list, ring
782
783
EXAMPLES::
784
785
sage: sage.matrix.constructor.prepare([-2, Mod(1,7)])
786
([5, 1], Ring of integers modulo 7)
787
788
Notice that the elements must all canonically coerce to a common
789
ring (since Sequence is called)::
790
791
sage: sage.matrix.constructor.prepare([2/1, Mod(1,7)])
792
Traceback (most recent call last):
793
...
794
TypeError: unable to find a common ring for all elements
795
"""
796
if 0 == len(w):
797
return Sequence([], rings.ZZ), rings.ZZ
798
entries = Sequence(w)
799
ring = entries.universe()
800
if ring is int or ring is long:
801
ring = rings.ZZ
802
elif ring is float:
803
ring = rings.RDF
804
elif ring is complex:
805
ring = rings.CDF
806
elif not is_Ring(ring):
807
raise TypeError, "unable to find a common ring for all elements"
808
return entries, ring
809
810
def prepare_dict(w):
811
"""
812
Given a dictionary w of numbers, find a common ring that they all
813
canonically map to, and return the dictionary of images of the
814
elements of w in that ring along with the ring.
815
816
This is for internal use by the matrix function.
817
818
INPUT:
819
820
- ``w`` - dict
821
822
OUTPUT:
823
824
dict, ring
825
826
EXAMPLES::
827
828
sage: sage.matrix.constructor.prepare_dict({(0,1):2, (4,10):Mod(1,7)})
829
({(0, 1): 2, (4, 10): 1}, Ring of integers modulo 7)
830
"""
831
Z = w.items()
832
X = [x for _, x in Z]
833
entries, ring = prepare(X)
834
return dict([(Z[i][0],entries[i]) for i in xrange(len(entries))]), ring
835
836
def nrows_from_dict(d):
837
"""
838
Given a dictionary that defines a sparse matrix, return the number
839
of rows that matrix should have.
840
841
This is for internal use by the matrix function.
842
843
INPUT:
844
845
- ``d`` - dict
846
847
OUTPUT:
848
849
integer
850
851
EXAMPLES::
852
853
sage: sage.matrix.constructor.nrows_from_dict({})
854
0
855
856
Here the answer is 301 not 300, since there is a 0-th row.
857
858
::
859
sage: sage.matrix.constructor.nrows_from_dict({(300,4):10})
860
301
861
"""
862
if 0 == len(d):
863
return 0
864
return max([0] + [ij[0] for ij in d.keys()]) + 1
865
866
def ncols_from_dict(d):
867
"""
868
Given a dictionary that defines a sparse matrix, return the number
869
of columns that matrix should have.
870
871
This is for internal use by the matrix function.
872
873
INPUT:
874
875
- ``d`` - dict
876
877
OUTPUT:
878
879
integer
880
881
EXAMPLES::
882
883
sage: sage.matrix.constructor.ncols_from_dict({})
884
0
885
886
Here the answer is 301 not 300, since there is a 0-th row.
887
888
::
889
890
sage: sage.matrix.constructor.ncols_from_dict({(4,300):10})
891
301
892
"""
893
if 0 == len(d):
894
return 0
895
return max([0] + [ij[1] for ij in d.keys()]) + 1
896
897
898
@matrix_method
899
def column_matrix(*args, **kwds):
900
r"""
901
Constructs a matrix, and then swaps rows for columns and columns for rows.
902
903
.. note::
904
905
Linear algebra in Sage favors rows over columns. So,
906
generally, when creating a matrix, input vectors and lists are
907
treated as rows. This function is a convenience that turns
908
around this convention when creating a matrix. If you are not
909
familiar with the usual :class:`matrix <MatrixFactory>`
910
constructor, you might want to consider it first.
911
912
INPUT:
913
914
Inputs are almost exactly the same as for the :class:`matrix
915
<MatrixFactory>` constructor, which are documented there. But see
916
examples below for how dimensions are handled.
917
918
OUTPUT:
919
920
Output is exactly the transpose of what the :class:`matrix
921
<MatrixFactory>` constructor would return. In other words, the
922
``matrix`` constructor builds a matrix and then this function
923
exchanges rows for columns, and columns for rows.
924
925
EXAMPLES:
926
927
The most compelling use of this function is when you have a
928
collection of lists or vectors that you would like to become the
929
columns of a matrix. In almost any other situation, the
930
:class:`matrix <MatrixFactory>` constructor can probably do the
931
job just as easily, or easier. ::
932
933
sage: col_1 = [1,2,3]
934
sage: col_2 = [4,5,6]
935
sage: column_matrix([col_1, col_2])
936
[1 4]
937
[2 5]
938
[3 6]
939
940
sage: v1 = vector(QQ, [10, 20])
941
sage: v2 = vector(QQ, [30, 40])
942
sage: column_matrix(QQ, [v1, v2])
943
[10 30]
944
[20 40]
945
946
If you only specify one dimension along with a flat list of entries,
947
then it will be the number of columns in the result (which is different
948
from the behavior of the ``matrix`` constructor). ::
949
950
sage: column_matrix(ZZ, 8, range(24))
951
[ 0 3 6 9 12 15 18 21]
952
[ 1 4 7 10 13 16 19 22]
953
[ 2 5 8 11 14 17 20 23]
954
955
And when you specify two dimensions, then they should be number of
956
columns first, then the number of rows, which is the reverse of how
957
they would be specified for the ``matrix`` constructor. ::
958
959
sage: column_matrix(QQ, 5, 3, range(15))
960
[ 0 3 6 9 12]
961
[ 1 4 7 10 13]
962
[ 2 5 8 11 14]
963
964
And a few unproductive, but illustrative, examples. ::
965
966
sage: A = matrix(ZZ, 3, 4, range(12))
967
sage: B = column_matrix(ZZ, 3, 4, range(12))
968
sage: A == B.transpose()
969
True
970
971
sage: A = matrix(QQ, 7, 12, range(84))
972
sage: A == column_matrix(A.columns())
973
True
974
975
sage: A=column_matrix(QQ, matrix(ZZ, 3, 2, range(6)) )
976
sage: A
977
[0 2 4]
978
[1 3 5]
979
sage: A.parent()
980
Full MatrixSpace of 2 by 3 dense matrices over Rational Field
981
"""
982
return matrix(*args, **kwds).transpose()
983
984
985
@matrix_method
986
def random_matrix(ring, nrows, ncols=None, algorithm='randomize', *args, **kwds):
987
r"""
988
Return a random matrix with entries in a specified ring, and possibly with additional properties.
989
990
INPUT:
991
992
- ``ring`` - base ring for entries of the matrix
993
994
- ``nrows`` - Integer; number of rows
995
996
- ``ncols`` - (default: ``None``); number of columns; if ``None``
997
defaults to ``nrows``
998
999
- ``algorithm`` - (default: ``randomize``); determines what properties
1000
the matrix will have. See examples below for possible additional
1001
arguments.
1002
1003
- ``randomize`` - randomize the elements of the matrix, possibly
1004
controlling the density of non-zero entries.
1005
1006
- ``echelon_form`` - creates a matrix in echelon form
1007
1008
- ``echelonizable`` - creates a matrix that has a predictable
1009
echelon form
1010
1011
- ``subspaces`` - creates a matrix whose four subspaces, when
1012
explored, have reasonably sized, integral valued, entries.
1013
1014
- ``unimodular`` - creates a matrix of determinant 1.
1015
1016
- ``diagonalizable`` - creates a diagonalizable matrix whose
1017
eigenvectors, if computed by hand, will have only integer
1018
entries.
1019
1020
- ``*args, **kwds`` - arguments and keywords to describe additional properties.
1021
See more detailed documentation below.
1022
1023
.. warning::
1024
1025
An upper bound on the absolute value of the entries may be set
1026
when the ``algorithm`` is ``echelonizable`` or ``unimodular``.
1027
In these cases it is possible for this constructor to fail with
1028
a ``ValueError``. If you *must* have this routine return
1029
successfully, do not set ``upper_bound``. This behavior can
1030
be partially controlled by a ``max_tries`` keyword.
1031
1032
.. note::
1033
1034
When constructing matrices with random entries and no additional properties
1035
(i.e. when ``algorithm='randomize'``), most of the randomness
1036
is controlled by the ``random_element`` method for elements of the
1037
base ring of the matrix, so the documentation of that method may be
1038
relevant or useful. Also, the default is to not create zero entries,
1039
unless the ``density`` keyword is set to something strictly less
1040
than one.
1041
1042
EXAMPLES:
1043
1044
Random integer matrices. With no arguments, the majority of the entries
1045
are -1 and 1, never zero, and rarely "large." ::
1046
1047
sage: random_matrix(ZZ, 5, 5)
1048
[ -8 2 0 0 1]
1049
[ -1 2 1 -95 -1]
1050
[ -2 -12 0 0 1]
1051
[ -1 1 -1 -2 -1]
1052
[ 4 -4 -6 5 0]
1053
1054
The ``distribution`` keyword set to ``uniform`` will limit values
1055
between -2 and 2, and never zero. ::
1056
1057
sage: random_matrix(ZZ, 5, 5, distribution='uniform')
1058
[ 1 0 -2 1 1]
1059
[ 1 0 0 0 2]
1060
[-1 -2 0 2 -2]
1061
[-1 -1 1 1 2]
1062
[ 0 -2 -1 0 0]
1063
1064
The ``x`` and ``y`` keywords can be used to distribute entries uniformly.
1065
When both are used ``x`` is the minimum and ``y`` is one greater than the the maximum.
1066
But still entries are never zero, even if the range contains zero. ::
1067
1068
sage: random_matrix(ZZ, 4, 8, x=70, y=100)
1069
[81 82 70 81 78 71 79 94]
1070
[80 98 89 87 91 94 94 77]
1071
[86 89 85 92 95 94 72 89]
1072
[78 80 89 82 94 72 90 92]
1073
1074
sage: random_matrix(ZZ, 3, 7, x=-5, y=5)
1075
[-3 3 1 -5 3 1 2]
1076
[ 3 3 0 3 -5 -2 1]
1077
[ 0 -2 -2 2 -3 -4 -2]
1078
1079
If only ``x`` is given, then it is used as the upper bound of a range starting at 0. ::
1080
1081
sage: random_matrix(ZZ, 5, 5, x=25)
1082
[20 16 8 3 8]
1083
[ 8 2 2 14 5]
1084
[18 18 10 20 11]
1085
[19 16 17 15 7]
1086
[ 0 24 3 17 24]
1087
1088
To allow, and control, zero entries use the ``density`` keyword at a value
1089
strictly below the default of 1.0, even if distributing entries across an
1090
interval that does not contain zero already. Note that for a square matrix it
1091
is only necessary to set a single dimension. ::
1092
1093
sage: random_matrix(ZZ, 5, x=-10, y=10, density=0.75)
1094
[-6 1 0 0 0]
1095
[ 9 0 0 4 1]
1096
[-6 0 0 -8 0]
1097
[ 0 4 0 6 0]
1098
[ 1 -9 0 0 -8]
1099
1100
sage: random_matrix(ZZ, 5, x=20, y=30, density=0.75)
1101
[ 0 28 0 27 0]
1102
[25 28 20 0 0]
1103
[ 0 21 0 21 0]
1104
[ 0 28 22 0 0]
1105
[ 0 0 0 26 24]
1106
1107
It is possible to construct sparse matrices, where it may now be advisable
1108
(but not required) to control the density of nonzero entries. ::
1109
1110
sage: A=random_matrix(ZZ, 5, 5)
1111
sage: A.is_sparse()
1112
False
1113
sage: A=random_matrix(ZZ, 5, 5, sparse=True)
1114
sage: A.is_sparse()
1115
True
1116
1117
sage: random_matrix(ZZ, 5, 5, density=0.3, sparse=True)
1118
[ 4 0 0 0 -1]
1119
[ 0 0 0 0 -7]
1120
[ 0 0 2 0 0]
1121
[ 0 0 1 0 -4]
1122
[ 0 0 0 0 0]
1123
1124
For algorithm testing you might want to control the number of bits,
1125
say 10,000 entries, each limited to 16 bits. ::
1126
1127
sage: A = random_matrix(ZZ, 100, 100, x=2^16); A
1128
100 x 100 dense matrix over Integer Ring (type 'print A.str()' to see all of the entries)
1129
1130
Random rational matrices. Now ``num_bound`` and ``den_bound`` control the
1131
generation of random elements, by specifying limits on the absolute value of
1132
numerators and denominators (respectively). Entries will be positive and
1133
negative (map the absolute value function through the entries to get all
1134
positive values), and zeros are avoided unless the density is set. If either
1135
the numerator or denominator bound (or both) is not used, then the values
1136
default to the distribution for `ZZ` described above that is most frequently
1137
positive or negative one. ::
1138
1139
sage: random_matrix(QQ, 2, 8, num_bound=20, den_bound=4)
1140
[ -1/2 6 13 -12 -2/3 -1/4 5 5]
1141
[ -9/2 5/3 19 15/2 19/2 20/3 -13/4 0]
1142
1143
sage: random_matrix(QQ, 4, density = 0.5, sparse=True)
1144
[ 0 71 0 -1/2]
1145
[ 0 0 0 0]
1146
[31/85 0 -31/2 0]
1147
[ 1 -1/4 0 0]
1148
1149
sage: A = random_matrix(QQ, 3, 10, num_bound = 99, den_bound = 99)
1150
sage: positives = map(abs, A.list())
1151
sage: matrix(QQ, 3, 10, positives)
1152
[61/18 47/41 1/22 1/2 75/68 6/7 1 1/2 72/41 7/3]
1153
[33/13 9/2 40/21 45/46 17/22 1 70/79 97/71 7/24 12/5]
1154
[ 13/8 8/25 1/3 61/14 92/45 4/85 3/38 95/16 82/71 1/5]
1155
1156
sage: random_matrix(QQ, 4, 10, den_bound = 10)
1157
[ -1 0 1/8 1/6 2/9 -1/6 1/5 -1/8 1/5 -1/5]
1158
[ 1/9 1/5 -1 2/9 1/4 -1/7 1/8 -1/9 0 2]
1159
[ 2/3 2 1/8 -2 0 0 -2 2 0 -1/2]
1160
[ 0 2 1 -2/3 0 0 1/6 0 -1/3 -2/9]
1161
1162
Random matrices over other rings. Several classes of matrices have specialized
1163
``randomize()`` methods. You can locate these with the Sage command::
1164
1165
search_def('randomize')
1166
1167
The default implementation of :meth:`~sage.matrix.matrix2.randomize` relies
1168
on the ``random_element()`` method for the base ring. The ``density`` and
1169
``sparse`` keywords behave as described above. ::
1170
1171
sage: K.<a>=FiniteField(3^2)
1172
sage: random_matrix(K, 2, 5)
1173
[ 1 a 1 2*a + 1 2]
1174
[ 2*a a + 2 0 2 1]
1175
1176
sage: random_matrix(RR, 3, 4, density=0.66)
1177
[ 0.000000000000000 -0.806696574554030 -0.693915509972359 0.000000000000000]
1178
[ 0.629781664418083 0.000000000000000 -0.833709843116637 0.000000000000000]
1179
[ 0.922346867410064 0.000000000000000 0.000000000000000 -0.940316454178921]
1180
1181
sage: A = random_matrix(ComplexField(32), 3, density=0.8, sparse=True); A
1182
[ 0.000000000 0.399739209 + 0.909948633*I 0.000000000]
1183
[-0.361911424 - 0.455087671*I -0.687810605 + 0.460619713*I 0.625520058 - 0.360952012*I]
1184
[ 0.000000000 0.000000000 -0.162196416 - 0.193242896*I]
1185
sage: A.is_sparse()
1186
True
1187
1188
Random matrices in echelon form. The ``algorithm='echelon_form'`` keyword,
1189
along with a requested number of non-zero rows (``num_pivots``) will return
1190
a random matrix in echelon form. When the base ring is ``QQ`` the result has integer
1191
entries. Other exact rings may be also specified. ::
1192
1193
sage: A=random_matrix(QQ, 4, 8, algorithm='echelon_form', num_pivots=3); A # random
1194
[ 1 -5 0 -2 0 1 1 -2]
1195
[ 0 0 1 -5 0 -3 -1 0]
1196
[ 0 0 0 0 1 2 -2 1]
1197
[ 0 0 0 0 0 0 0 0]
1198
sage: A.base_ring()
1199
Rational Field
1200
sage: (A.nrows(), A.ncols())
1201
(4, 8)
1202
sage: A in sage.matrix.matrix_space.MatrixSpace(ZZ, 4, 8)
1203
True
1204
sage: A.rank()
1205
3
1206
sage: A==A.rref()
1207
True
1208
1209
For more, see the documentation of the :func:`~sage.matrix.constructor.random_rref_matrix`
1210
function. In the notebook or at the Sage command-line, first execute the following to make
1211
this further documentation available::
1212
1213
from sage.matrix.constructor import random_rref_matrix
1214
1215
Random matrices with predictable echelon forms. The ``algorithm='echelonizable'``
1216
keyword, along with a requested rank (``rank``) and optional size control
1217
(``upper_bound``) will return a random matrix in echelon form. When the
1218
base ring is ``ZZ`` or ``QQ`` the result has integer entries, whose magnitudes
1219
can be limited by the value of ``upper_bound``, and the echelon form of the
1220
matrix also has integer entries. Other exact rings may be also
1221
specified, but there is no notion of controlling the size. Square matrices
1222
of full rank generated by this function always have determinant one, and
1223
can be constructed with the ``unimodular`` keyword. ::
1224
1225
sage: A=random_matrix(QQ, 4, 8, algorithm='echelonizable', rank=3, upper_bound=60); A # random
1226
sage: A.base_ring()
1227
Rational Field
1228
sage: (A.nrows(), A.ncols())
1229
(4, 8)
1230
sage: A in sage.matrix.matrix_space.MatrixSpace(ZZ, 4, 8)
1231
True
1232
sage: A.rank()
1233
3
1234
sage: all([abs(x)<60 for x in A.list()])
1235
True
1236
sage: A.rref() in sage.matrix.matrix_space.MatrixSpace(ZZ, 4, 8)
1237
True
1238
1239
For more, see the documentation of the :func:`~sage.matrix.constructor.random_echelonizable_matrix`
1240
function. In the notebook or at the Sage command-line, first execute the following to make
1241
this further documentation available::
1242
1243
from sage.matrix.constructor import random_echelonizable_matrix
1244
1245
Random diagonalizable matrices. The ``algorithm='diagonalizable'`` keyword,
1246
along with a requested matrix size (``size``) and optional lists of
1247
eigenvalues (``eigenvalues``) and the corresponding eigenspace
1248
dimensions (``dimensions``) will return a random diagonalizable matrix.
1249
When the eigenvalues and dimensions are not specified the result will have
1250
randomly generated values for both that fit with the designated size. ::
1251
1252
sage: A=random_matrix(QQ, 5, algorithm='diagonalizable', eigenvalues=[2,3,-1], dimensions=[1,2,2]); A # random
1253
sage: all([x in ZZ for x in (A-(2*identity_matrix(5))).rref().list()])
1254
True
1255
sage: all([x in ZZ for x in (A-(3*identity_matrix(5))).rref().list()])
1256
True
1257
sage: all([x in ZZ for x in (A-(-1*identity_matrix(5))).rref().list()])
1258
True
1259
sage: A.jordan_form()
1260
[ 2| 0| 0| 0| 0]
1261
[--+--+--+--+--]
1262
[ 0| 3| 0| 0| 0]
1263
[--+--+--+--+--]
1264
[ 0| 0| 3| 0| 0]
1265
[--+--+--+--+--]
1266
[ 0| 0| 0|-1| 0]
1267
[--+--+--+--+--]
1268
[ 0| 0| 0| 0|-1]
1269
1270
For more, see the documentation of the :func:`~sage.matrix.constructor.random_diagonalizable_matrix`
1271
function. In the notebook or at the Sage command-line, first execute the following to make
1272
this further documentation available::
1273
1274
from sage.matrix.constructor import random_diagonalizable_matrix
1275
1276
Random matrices with predictable subspaces. The ``algorithm='subspaces'``
1277
keyword, along with an optional rank (``rank``) will return
1278
a matrix whose natural basis vectors for its four fundamental subspaces, if computed as
1279
described in the documentation of the :func:`~sage.matrix.constructor.random_subspaces_matrix`
1280
contain only integer entries. If ``rank``, is not set, the
1281
rank of the matrix will be generated randomly. ::
1282
1283
sage: B=random_matrix(QQ, 5, 6, algorithm='subspaces', rank=3); B #random
1284
sage: B_expanded=B.augment(identity_matrix(5)).rref()
1285
sage: (B.nrows(), B.ncols())
1286
(5, 6)
1287
sage: all([x in ZZ for x in B_expanded.list()])
1288
True
1289
sage: C=B_expanded.submatrix(0,0,B.nrows()-B.nullity(),B.ncols())
1290
sage: L=B_expanded.submatrix(B.nrows()-B.nullity(),B.ncols())
1291
sage: B.right_kernel()==C.right_kernel()
1292
True
1293
sage: B.row_space()==C.row_space()
1294
True
1295
sage: B.column_space()==L.right_kernel()
1296
True
1297
sage: B.left_kernel()==L.row_space()
1298
True
1299
1300
For more, see the documentation of the :func:`~sage.matrix.constructor.random_subspaces_matrix`
1301
function. In the notebook or at the Sage command-line, first execute the following to make
1302
this further documentation available::
1303
1304
from sage.matrix.constructor import random_subspaces_matrix
1305
1306
Random unimodular matrices. The ``algorithm='unimodular'``
1307
keyword, along with an optional entry size control (``upper_bound``)
1308
will return a matrix of determinant 1. When the base ring is ``ZZ``
1309
or ``QQ`` the result has integer entries, whose magnitudes
1310
can be limited by the value of ``upper_bound``. ::
1311
1312
sage: C=random_matrix(QQ, 5, algorithm='unimodular', upper_bound=70); C # random
1313
sage: det(C)
1314
1
1315
sage: C.base_ring()
1316
Rational Field
1317
sage: (C.nrows(), C.ncols())
1318
(5, 5)
1319
sage: all([abs(x)<70 for x in C.list()])
1320
True
1321
1322
For more, see the documentation of the :func:`~sage.matrix.constructor.random_unimodular_matrix`
1323
function. In the notebook or at the Sage command-line, first execute the following to make
1324
this further documentation available::
1325
1326
from sage.matrix.constructor import random_unimodular_matrix
1327
1328
TESTS:
1329
1330
We return an error for a bogus value of ``algorithm``::
1331
1332
sage: random_matrix(ZZ, 5, algorithm = 'bogus')
1333
Traceback (most recent call last):
1334
...
1335
ValueError: random matrix algorithm "bogus" is not recognized
1336
1337
AUTHOR:
1338
1339
- William Stein (2007-02-06)
1340
1341
- Rob Beezer (2010-08-25) Documentation, code to allow additional types of output
1342
"""
1343
if ncols is None:
1344
ncols = nrows
1345
sparse = kwds.pop('sparse', False)
1346
# Construct the parent of the desired matrix
1347
parent = matrix_space.MatrixSpace(ring, nrows, ncols, sparse=sparse)
1348
if algorithm == 'randomize':
1349
density = kwds.pop('density', None)
1350
# zero matrix is immutable, copy is mutable
1351
A = copy(parent.zero_matrix())
1352
if density is None:
1353
A.randomize(density=float(1), nonzero=False, *args, **kwds)
1354
else:
1355
A.randomize(density=density, nonzero=True, *args, **kwds)
1356
return A
1357
elif algorithm == 'echelon_form':
1358
return random_rref_matrix(parent, *args, **kwds)
1359
elif algorithm == 'echelonizable':
1360
return random_echelonizable_matrix(parent, *args, **kwds)
1361
elif algorithm == 'diagonalizable':
1362
return random_diagonalizable_matrix(parent, *args, **kwds)
1363
elif algorithm == 'subspaces':
1364
return random_subspaces_matrix(parent, *args, **kwds)
1365
elif algorithm == 'unimodular':
1366
return random_unimodular_matrix(parent, *args, **kwds)
1367
else:
1368
raise ValueError('random matrix algorithm "%s" is not recognized' % algorithm)
1369
1370
1371
@matrix_method
1372
def diagonal_matrix(arg0=None, arg1=None, arg2=None, sparse=True):
1373
r"""
1374
Return a square matrix with specified diagonal entries, and zeros elsewhere.
1375
1376
FORMATS:
1377
1378
1. diagonal_matrix(entries)
1379
1380
2. diagonal_matrix(nrows, entries)
1381
1382
3. diagonal_matrix(ring, entries)
1383
1384
4. diagonal_matrix(ring, nrows, entries)
1385
1386
INPUT:
1387
1388
- ``entries`` - the values to place along the diagonal
1389
of the returned matrix. This may be a flat list, a
1390
flat tuple, a vector or free module element, or
1391
a one-dimensional NumPy array.
1392
1393
- ``nrows`` - the size of the returned matrix, which
1394
will have an equal number of columns
1395
1396
- ``ring`` - the ring containing the entries of the
1397
diagonal entries. This may not be specified in
1398
combination with a NumPy array.
1399
1400
- ``sparse`` - default: ``True`` - whether or not
1401
the result has a sparse implementation.
1402
1403
OUTPUT:
1404
1405
A square matrix over the given ``ring`` with a size
1406
given by ``nrows``. If the ring is not given it
1407
is inferred from the given entries. The values on
1408
the diagonal of the returned matrix come from ``entries``.
1409
If the number of entries is not enough to fill the whole
1410
diagonal, it is padded with zeros.
1411
1412
EXAMPLES:
1413
1414
We first demonstrate each of the input formats with various
1415
different ways to specify the entries.
1416
1417
Format 1: a flat list of entries. ::
1418
1419
sage: A = diagonal_matrix([2, 1.3, 5]); A
1420
[ 2.00000000000000 0.000000000000000 0.000000000000000]
1421
[0.000000000000000 1.30000000000000 0.000000000000000]
1422
[0.000000000000000 0.000000000000000 5.00000000000000]
1423
sage: A.parent()
1424
Full MatrixSpace of 3 by 3 sparse matrices over Real Field with 53 bits of precision
1425
1426
Format 2: size specified, a tuple with initial entries. Note that a short list of entries
1427
is effectively padded with zeros. ::
1428
1429
sage: A = diagonal_matrix(3, (4, 5)); A
1430
[4 0 0]
1431
[0 5 0]
1432
[0 0 0]
1433
sage: A.parent()
1434
Full MatrixSpace of 3 by 3 sparse matrices over Integer Ring
1435
1436
Format 3: ring specified, a vector of entries. ::
1437
1438
sage: A = diagonal_matrix(QQ, vector(ZZ, [1,2,3])); A
1439
[1 0 0]
1440
[0 2 0]
1441
[0 0 3]
1442
sage: A.parent()
1443
Full MatrixSpace of 3 by 3 sparse matrices over Rational Field
1444
1445
Format 4: ring, size and list of entries. ::
1446
1447
sage: A = diagonal_matrix(FiniteField(3), 3, [2, 16]); A
1448
[2 0 0]
1449
[0 1 0]
1450
[0 0 0]
1451
sage: A.parent()
1452
Full MatrixSpace of 3 by 3 sparse matrices over Finite Field of size 3
1453
1454
NumPy arrays may be used as input. ::
1455
1456
sage: import numpy
1457
sage: entries = numpy.array([1.2, 5.6]); entries
1458
array([ 1.2, 5.6])
1459
sage: A = diagonal_matrix(3, entries); A
1460
[1.2 0.0 0.0]
1461
[0.0 5.6 0.0]
1462
[0.0 0.0 0.0]
1463
sage: A.parent()
1464
Full MatrixSpace of 3 by 3 sparse matrices over Real Double Field
1465
1466
sage: j = numpy.complex(0,1)
1467
sage: entries = numpy.array([2.0+j, 8.1, 3.4+2.6*j]); entries
1468
array([ 2.0+1.j , 8.1+0.j , 3.4+2.6j])
1469
sage: A = diagonal_matrix(entries); A
1470
[2.0 + 1.0*I 0.0 0.0]
1471
[ 0.0 8.1 0.0]
1472
[ 0.0 0.0 3.4 + 2.6*I]
1473
sage: A.parent()
1474
Full MatrixSpace of 3 by 3 sparse matrices over Complex Double Field
1475
1476
sage: entries = numpy.array([4, 5, 6])
1477
sage: A = diagonal_matrix(entries); A
1478
[4 0 0]
1479
[0 5 0]
1480
[0 0 6]
1481
sage: A.parent()
1482
Full MatrixSpace of 3 by 3 sparse matrices over Integer Ring
1483
1484
sage: entries = numpy.array([4.1, 5.2, 6.3])
1485
sage: A = diagonal_matrix(ZZ, entries); A
1486
Traceback (most recent call last):
1487
...
1488
TypeError: Cannot convert non-integral float to integer
1489
1490
By default returned matrices have a sparse implementation. This can be changed
1491
when using any of the formats. ::
1492
1493
sage: A = diagonal_matrix([1,2,3], sparse=False)
1494
sage: A.parent()
1495
Full MatrixSpace of 3 by 3 dense matrices over Integer Ring
1496
1497
An empty list and no ring specified defaults to the integers. ::
1498
1499
sage: A = diagonal_matrix([])
1500
sage: A.parent()
1501
Full MatrixSpace of 0 by 0 sparse matrices over Integer Ring
1502
1503
Giving the entries improperly may first complain about not having a length. ::
1504
1505
sage: diagonal_matrix(QQ, 5, 10)
1506
Traceback (most recent call last):
1507
...
1508
TypeError: unable to determine number of entries for diagonal matrix construction
1509
1510
Giving too many entries will raise an error. ::
1511
1512
sage: diagonal_matrix(QQ, 3, [1,2,3,4])
1513
Traceback (most recent call last):
1514
...
1515
ValueError: number of diagonal matrix entries (4) exceeds the requested matrix size (3)
1516
1517
A negative size sometimes causes the error that there are too many elements. ::
1518
1519
sage: diagonal_matrix(-2, [2])
1520
Traceback (most recent call last):
1521
...
1522
ValueError: number of diagonal matrix entries (1) exceeds the requested matrix size (-2)
1523
1524
Types for the entries are limited, even though they may have a length. ::
1525
1526
sage: diagonal_matrix(x^2)
1527
Traceback (most recent call last):
1528
...
1529
TypeError: diagonal matrix entries are not a supported type (list, tuple, vector, or NumPy array)
1530
1531
AUTHOR:
1532
1533
- Rob Beezer (2011-01-11): total rewrite
1534
"""
1535
# Roll arguments leftward
1536
#
1537
# Leads with a ring?
1538
# Formats 3, 4, else remains None
1539
ring = None
1540
if is_Ring(arg0):
1541
ring = arg0
1542
arg0 = arg1
1543
arg1 = arg2
1544
# Size of matrix specified?
1545
# Formats 2, 4
1546
nrows = None
1547
if isinstance(arg0, (int, long, rings.Integer)):
1548
nrows = arg0
1549
arg0 = arg1
1550
# Object holding entries
1551
# Formats 1, 2, 3, 4
1552
entries = arg0
1553
1554
# Reconcile matrix size and number of entries
1555
try:
1556
nentries = len(entries)
1557
except TypeError:
1558
raise TypeError('unable to determine number of entries for diagonal matrix construction')
1559
# sometimes catches a negative size
1560
if not nrows is None and nentries > nrows:
1561
raise ValueError('number of diagonal matrix entries (%s) exceeds the requested matrix size (%s)' % (nentries, nrows))
1562
if nrows is None:
1563
nrows = nentries
1564
1565
# provide a default ring for an empty list
1566
if len(entries) == 0 and ring is None:
1567
ring = rings.ZZ
1568
1569
# Sanity check on entries (partially, e.g. a list of lists will survive this check)
1570
from numpy import ndarray
1571
if not any([isinstance(entries, (list, tuple)), isinstance(entries, ndarray), is_Vector(entries)]):
1572
raise TypeError('diagonal matrix entries are not a supported type (list, tuple, vector, or NumPy array)')
1573
1574
# Convert entries to a list v over a common ring
1575
from sage.modules.free_module_element import prepare
1576
v, ring = prepare(entries, ring)
1577
1578
# Create a "diagonal" dictionary for matrix constructor
1579
# If nentries < nrows, diagonal is effectively padded with zeros at end
1580
w = {}
1581
for i in range(len(v)):
1582
w[(i,i)] = v[i]
1583
1584
# Ship ring, matrix size, dictionary to matrix constructor
1585
if ring is None:
1586
return matrix(nrows, nrows, w, sparse=sparse)
1587
else:
1588
return matrix(ring, nrows, nrows, w, sparse=sparse)
1589
1590
1591
@matrix_method
1592
def identity_matrix(ring, n=0, sparse=False):
1593
r"""
1594
Return the `n \times n` identity matrix over the given
1595
ring.
1596
1597
The default ring is the integers.
1598
1599
EXAMPLES::
1600
1601
sage: M = identity_matrix(QQ, 2); M
1602
[1 0]
1603
[0 1]
1604
sage: M.parent()
1605
Full MatrixSpace of 2 by 2 dense matrices over Rational Field
1606
sage: M = identity_matrix(2); M
1607
[1 0]
1608
[0 1]
1609
sage: M.parent()
1610
Full MatrixSpace of 2 by 2 dense matrices over Integer Ring
1611
sage: M.is_mutable()
1612
True
1613
sage: M = identity_matrix(3, sparse=True); M
1614
[1 0 0]
1615
[0 1 0]
1616
[0 0 1]
1617
sage: M.parent()
1618
Full MatrixSpace of 3 by 3 sparse matrices over Integer Ring
1619
sage: M.is_mutable()
1620
True
1621
"""
1622
if isinstance(ring, (int, long, rings.Integer)):
1623
n = ring
1624
ring = rings.ZZ
1625
return matrix_space.MatrixSpace(ring, n, n, sparse)(1)
1626
1627
1628
@matrix_method
1629
def zero_matrix(ring, nrows, ncols=None, sparse=False):
1630
r"""
1631
Return the `nrows \times ncols` zero matrix over the given
1632
ring.
1633
1634
The default ring is the integers.
1635
1636
EXAMPLES::
1637
1638
sage: M = zero_matrix(QQ, 2); M
1639
[0 0]
1640
[0 0]
1641
sage: M.parent()
1642
Full MatrixSpace of 2 by 2 dense matrices over Rational Field
1643
sage: M = zero_matrix(2, 3); M
1644
[0 0 0]
1645
[0 0 0]
1646
sage: M.parent()
1647
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring
1648
sage: M.is_mutable()
1649
True
1650
sage: M = zero_matrix(3, 1, sparse=True); M
1651
[0]
1652
[0]
1653
[0]
1654
sage: M.parent()
1655
Full MatrixSpace of 3 by 1 sparse matrices over Integer Ring
1656
sage: M.is_mutable()
1657
True
1658
"""
1659
if isinstance(ring, (int, long, rings.Integer)):
1660
nrows, ncols = (ring, nrows)
1661
ring = rings.ZZ
1662
return matrix_space.MatrixSpace(ring, nrows, ncols, sparse)(0)
1663
1664
1665
@matrix_method
1666
def ones_matrix(ring, nrows=None, ncols=None, sparse=False):
1667
r"""
1668
Return a matrix with all entries equal to 1.
1669
1670
CALL FORMATS:
1671
1672
In each case, the optional keyword ``sparse`` can be used.
1673
1674
1. ones_matrix(ring, nrows, ncols)
1675
2. ones_matrix(ring, nrows)
1676
3. ones_matrix(nrows, ncols)
1677
4. ones_matrix(nrows)
1678
1679
INPUT:
1680
1681
- ``ring`` - default: ``ZZ`` - base ring for the matrix.
1682
- ``nrows`` - number of rows in the matrix.
1683
- ``ncols`` - number of columns in the matrix.
1684
If omitted, defaults to the number of rows, producing a square matrix.
1685
- ``sparse`` - default: ``False`` - if ``True`` creates a sparse representation.
1686
1687
OUTPUT:
1688
1689
A matrix of size ``nrows`` by ``ncols`` over the ``ring`` with every
1690
entry equal to 1. While the result is far from sparse, you may wish
1691
to choose a sparse representation when mixing this matrix with
1692
other sparse matrices.
1693
1694
EXAMPLES:
1695
1696
A call specifying the ring and the size. ::
1697
1698
sage: M= ones_matrix(QQ, 2, 5); M
1699
[1 1 1 1 1]
1700
[1 1 1 1 1]
1701
sage: M.parent()
1702
Full MatrixSpace of 2 by 5 dense matrices over Rational Field
1703
1704
Without specifying the number of columns, the result is square. ::
1705
1706
sage: M = ones_matrix(RR, 2); M
1707
[1.00000000000000 1.00000000000000]
1708
[1.00000000000000 1.00000000000000]
1709
sage: M.parent()
1710
Full MatrixSpace of 2 by 2 dense matrices over Real Field with 53 bits of precision
1711
1712
The ring defaults to the integers if not given. ::
1713
1714
sage: M = ones_matrix(2, 3); M
1715
[1 1 1]
1716
[1 1 1]
1717
sage: M.parent()
1718
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring
1719
1720
A lone integer input produces a square matrix over the integers. ::
1721
1722
sage: M = ones_matrix(3); M
1723
[1 1 1]
1724
[1 1 1]
1725
[1 1 1]
1726
sage: M.parent()
1727
Full MatrixSpace of 3 by 3 dense matrices over Integer Ring
1728
1729
The result can have a sparse implementation. ::
1730
1731
sage: M = ones_matrix(3, 1, sparse=True); M
1732
[1]
1733
[1]
1734
[1]
1735
sage: M.parent()
1736
Full MatrixSpace of 3 by 1 sparse matrices over Integer Ring
1737
1738
Giving just a ring will yield an error. ::
1739
1740
sage: ones_matrix(CC)
1741
Traceback (most recent call last):
1742
...
1743
ValueError: constructing an all ones matrix requires at least one dimension
1744
"""
1745
if isinstance(ring, (int, long, rings.Integer)):
1746
nrows, ncols = (ring, nrows)
1747
ring = rings.ZZ
1748
if nrows is None:
1749
raise ValueError("constructing an all ones matrix requires at least one dimension")
1750
if ncols is None:
1751
nents = nrows**2
1752
else:
1753
nents = nrows*ncols
1754
one = ring(1)
1755
return matrix_space.MatrixSpace(ring, nrows, ncols, sparse).matrix([one]*nents)
1756
1757
1758
@matrix_method
1759
def elementary_matrix(arg0, arg1=None, **kwds):
1760
r"""
1761
Creates a square matrix that corresponds to a row operation or a column operation.
1762
1763
FORMATS:
1764
1765
In each case, ``R`` is the base ring, and is optional. ``n`` is the size
1766
of the square matrix created. Any call may include the ``sparse`` keyword
1767
to determine the representation used. The default is ``False`` which
1768
leads to a dense representation. We describe the matrices by their
1769
associated row operation, see the output description for more.
1770
1771
- ``elementary_matrix(R, n, row1=i, row2=j)``
1772
1773
The matrix which swaps rows ``i`` and ``j``.
1774
1775
- ``elementary_matrix(R, n, row1=i, scale=s)``
1776
1777
The matrix which multiplies row ``i`` by ``s``.
1778
1779
- ``elementary_matrix(R, n, row1=i, row2=j, scale=s)``
1780
1781
The matrix which multiplies row ``j`` by ``s``
1782
and adds it to row ``i``.
1783
1784
Elementary matrices representing column operations are created
1785
in an entirely analogous way, replacing ``row1`` by ``col1`` and
1786
replacing ``row2`` by ``col2``.
1787
1788
Specifying the ring for entries of the matrix is optional. If it
1789
is not given, and a scale parameter is provided, then a ring containing
1790
the value of ``scale`` will be used. Otherwise, the ring defaults
1791
to the integers.
1792
1793
OUTPUT:
1794
1795
An elementary matrix is a square matrix that is very close to being
1796
an identity matrix. If ``E`` is an elementary matrix and ``A`` is any
1797
matrix with the same number of rows, then ``E*A`` is the result of
1798
applying a row operation to ``A``. This is how the three types
1799
created by this function are described. Similarly, an elementary matrix
1800
can be associated with a column operation, so if ``E`` has the same number
1801
of columns as ``A`` then ``A*E`` is the result of performing a column
1802
operation on ``A``.
1803
1804
An elementary matrix representing a row operation is created if ``row1``
1805
is specified, while an elementary matrix representing a column operation
1806
is created if ``col1`` is specified.
1807
1808
EXAMPLES:
1809
1810
Over the integers, creating row operations. Recall that row
1811
and column numbering begins at zero. ::
1812
1813
sage: A = matrix(ZZ, 4, 10, range(40)); A
1814
[ 0 1 2 3 4 5 6 7 8 9]
1815
[10 11 12 13 14 15 16 17 18 19]
1816
[20 21 22 23 24 25 26 27 28 29]
1817
[30 31 32 33 34 35 36 37 38 39]
1818
1819
sage: E = elementary_matrix(4, row1=1, row2=3); E
1820
[1 0 0 0]
1821
[0 0 0 1]
1822
[0 0 1 0]
1823
[0 1 0 0]
1824
sage: E*A
1825
[ 0 1 2 3 4 5 6 7 8 9]
1826
[30 31 32 33 34 35 36 37 38 39]
1827
[20 21 22 23 24 25 26 27 28 29]
1828
[10 11 12 13 14 15 16 17 18 19]
1829
1830
sage: E = elementary_matrix(4, row1=2, scale=10); E
1831
[ 1 0 0 0]
1832
[ 0 1 0 0]
1833
[ 0 0 10 0]
1834
[ 0 0 0 1]
1835
sage: E*A
1836
[ 0 1 2 3 4 5 6 7 8 9]
1837
[ 10 11 12 13 14 15 16 17 18 19]
1838
[200 210 220 230 240 250 260 270 280 290]
1839
[ 30 31 32 33 34 35 36 37 38 39]
1840
1841
sage: E = elementary_matrix(4, row1=2, row2=1, scale=10); E
1842
[ 1 0 0 0]
1843
[ 0 1 0 0]
1844
[ 0 10 1 0]
1845
[ 0 0 0 1]
1846
sage: E*A
1847
[ 0 1 2 3 4 5 6 7 8 9]
1848
[ 10 11 12 13 14 15 16 17 18 19]
1849
[120 131 142 153 164 175 186 197 208 219]
1850
[ 30 31 32 33 34 35 36 37 38 39]
1851
1852
Over the rationals, now as column operations. Recall that row
1853
and column numbering begins at zero. Checks now have the
1854
elementary matrix on the right. ::
1855
1856
sage: A = matrix(QQ, 5, 4, range(20)); A
1857
[ 0 1 2 3]
1858
[ 4 5 6 7]
1859
[ 8 9 10 11]
1860
[12 13 14 15]
1861
[16 17 18 19]
1862
1863
sage: E = elementary_matrix(QQ, 4, col1=1, col2=3); E
1864
[1 0 0 0]
1865
[0 0 0 1]
1866
[0 0 1 0]
1867
[0 1 0 0]
1868
sage: A*E
1869
[ 0 3 2 1]
1870
[ 4 7 6 5]
1871
[ 8 11 10 9]
1872
[12 15 14 13]
1873
[16 19 18 17]
1874
1875
sage: E = elementary_matrix(QQ, 4, col1=2, scale=1/2); E
1876
[ 1 0 0 0]
1877
[ 0 1 0 0]
1878
[ 0 0 1/2 0]
1879
[ 0 0 0 1]
1880
sage: A*E
1881
[ 0 1 1 3]
1882
[ 4 5 3 7]
1883
[ 8 9 5 11]
1884
[12 13 7 15]
1885
[16 17 9 19]
1886
1887
sage: E = elementary_matrix(QQ, 4, col1=2, col2=1, scale=10); E
1888
[ 1 0 0 0]
1889
[ 0 1 10 0]
1890
[ 0 0 1 0]
1891
[ 0 0 0 1]
1892
sage: A*E
1893
[ 0 1 12 3]
1894
[ 4 5 56 7]
1895
[ 8 9 100 11]
1896
[ 12 13 144 15]
1897
[ 16 17 188 19]
1898
1899
An elementary matrix is always nonsingular. Then repeated row
1900
operations can be represented by products of elementary matrices,
1901
and this product is again nonsingular. If row operations are to
1902
preserve fundamental properties of a matrix (like rank), we do not
1903
allow scaling a row by zero. Similarly, the corresponding elementary
1904
matrix is not constructed. Also, we do not allow adding a multiple
1905
of a row to itself, since this could also lead to a new zero row. ::
1906
1907
sage: A = matrix(QQ, 4, 10, range(40)); A
1908
[ 0 1 2 3 4 5 6 7 8 9]
1909
[10 11 12 13 14 15 16 17 18 19]
1910
[20 21 22 23 24 25 26 27 28 29]
1911
[30 31 32 33 34 35 36 37 38 39]
1912
1913
sage: E1 = elementary_matrix(QQ, 4, row1=0, row2=1)
1914
sage: E2 = elementary_matrix(QQ, 4, row1=3, row2=0, scale=100)
1915
sage: E = E2*E1
1916
sage: E.is_singular()
1917
False
1918
sage: E*A
1919
[ 10 11 12 13 14 15 16 17 18 19]
1920
[ 0 1 2 3 4 5 6 7 8 9]
1921
[ 20 21 22 23 24 25 26 27 28 29]
1922
[1030 1131 1232 1333 1434 1535 1636 1737 1838 1939]
1923
1924
sage: E3 = elementary_matrix(QQ, 4, row1=3, scale=0)
1925
Traceback (most recent call last):
1926
...
1927
ValueError: scale parameter of row of elementary matrix must be non-zero
1928
1929
sage: E4 = elementary_matrix(QQ, 4, row1=3, row2=3, scale=12)
1930
Traceback (most recent call last):
1931
...
1932
ValueError: cannot add a multiple of a row to itself
1933
1934
If the ring is not specified, and a scale parameter is given, the
1935
base ring for the matrix is chosen to contain the scale parameter.
1936
Otherwise, if no ring is given, the default is the integers. ::
1937
1938
sage: E = elementary_matrix(4, row1=1, row2=3)
1939
sage: E.parent()
1940
Full MatrixSpace of 4 by 4 dense matrices over Integer Ring
1941
1942
sage: E = elementary_matrix(4, row1=1, scale=4/3)
1943
sage: E.parent()
1944
Full MatrixSpace of 4 by 4 dense matrices over Rational Field
1945
1946
sage: E = elementary_matrix(4, row1=1, scale=I)
1947
sage: E.parent()
1948
Full MatrixSpace of 4 by 4 dense matrices over Symbolic Ring
1949
1950
sage: E = elementary_matrix(4, row1=1, scale=CDF(I))
1951
sage: E.parent()
1952
Full MatrixSpace of 4 by 4 dense matrices over Complex Double Field
1953
1954
sage: E = elementary_matrix(4, row1=1, scale=QQbar(I))
1955
sage: E.parent()
1956
Full MatrixSpace of 4 by 4 dense matrices over Algebraic Field
1957
1958
Returned matrices have a dense implementation by default,
1959
but a sparse implementation may be requested. ::
1960
1961
sage: E = elementary_matrix(4, row1=0, row2=1)
1962
sage: E.is_dense()
1963
True
1964
1965
sage: E = elementary_matrix(4, row1=0, row2=1, sparse=True)
1966
sage: E.is_sparse()
1967
True
1968
1969
And the ridiculously small cases. The zero-row matrix cannot be built
1970
since then there are no rows to manipulate. ::
1971
1972
sage: elementary_matrix(QQ, 1, row1=0, row2=0)
1973
[1]
1974
sage: elementary_matrix(QQ, 0, row1=0, row2=0)
1975
Traceback (most recent call last):
1976
...
1977
ValueError: size of elementary matrix must be 1 or greater, not 0
1978
1979
TESTS::
1980
1981
sage: E = elementary_matrix('junk', 5, row1=3, row2=1, scale=12)
1982
Traceback (most recent call last):
1983
...
1984
TypeError: optional first parameter must be a ring, not junk
1985
1986
sage: E = elementary_matrix(5, row1=3, scale='junk')
1987
Traceback (most recent call last):
1988
...
1989
TypeError: scale must be an element of some ring, not junk
1990
1991
sage: E = elementary_matrix(ZZ, 5, row1=3, col2=3, scale=12)
1992
Traceback (most recent call last):
1993
...
1994
ValueError: received an unexpected keyword: col2=3
1995
1996
sage: E = elementary_matrix(QQ, row1=3, scale=12)
1997
Traceback (most recent call last):
1998
...
1999
ValueError: size of elementary matrix must be given
2000
2001
sage: E = elementary_matrix(ZZ, 4/3, row1=3, row2=1, scale=12)
2002
Traceback (most recent call last):
2003
...
2004
TypeError: size of elementary matrix must be an integer, not 4/3
2005
2006
sage: E = elementary_matrix(ZZ, -3, row1=3, row2=1, scale=12)
2007
Traceback (most recent call last):
2008
...
2009
ValueError: size of elementary matrix must be 1 or greater, not -3
2010
2011
sage: E = elementary_matrix(ZZ, 5, row2=1, scale=12)
2012
Traceback (most recent call last):
2013
...
2014
ValueError: row1 or col1 must be specified
2015
2016
sage: E = elementary_matrix(ZZ, 5, row1=3, col1=3, scale=12)
2017
Traceback (most recent call last):
2018
...
2019
ValueError: cannot specify both row1 and col1
2020
2021
sage: E = elementary_matrix(ZZ, 5, row1=4/3, row2=1, scale=12)
2022
Traceback (most recent call last):
2023
...
2024
TypeError: row of elementary matrix must be an integer, not 4/3
2025
2026
sage: E = elementary_matrix(ZZ, 5, col1=5, col2=1, scale=12)
2027
Traceback (most recent call last):
2028
...
2029
ValueError: column of elementary matrix must be positive and smaller than 5, not 5
2030
2031
sage: E = elementary_matrix(ZZ, 5, col1=3, col2=4/3, scale=12)
2032
Traceback (most recent call last):
2033
...
2034
TypeError: column of elementary matrix must be an integer, not 4/3
2035
2036
sage: E = elementary_matrix(ZZ, 5, row1=3, row2=-1, scale=12)
2037
Traceback (most recent call last):
2038
...
2039
ValueError: row of elementary matrix must be positive and smaller than 5, not -1
2040
2041
sage: E = elementary_matrix(ZZ, 5, row1=3, row2=1, scale=4/3)
2042
Traceback (most recent call last):
2043
...
2044
TypeError: scale parameter of elementary matrix must an element of Integer Ring, not 4/3
2045
2046
sage: E = elementary_matrix(ZZ, 5, row1=3)
2047
Traceback (most recent call last):
2048
...
2049
ValueError: insufficient parameters provided to construct elementary matrix
2050
2051
sage: E = elementary_matrix(ZZ, 5, row1=3, row2=3, scale=12)
2052
Traceback (most recent call last):
2053
...
2054
ValueError: cannot add a multiple of a row to itself
2055
2056
sage: E = elementary_matrix(ZZ, 5, col1=3, scale=0)
2057
Traceback (most recent call last):
2058
...
2059
ValueError: scale parameter of column of elementary matrix must be non-zero
2060
2061
AUTHOR:
2062
2063
- Rob Beezer (2011-03-04)
2064
"""
2065
import sage.structure.element
2066
# determine ring and matrix size
2067
if not arg1 is None and not is_Ring(arg0):
2068
raise TypeError('optional first parameter must be a ring, not {0}'.format(arg0))
2069
scale = kwds.pop('scale', None)
2070
if is_Ring(arg0):
2071
R = arg0
2072
arg0 = arg1
2073
elif scale is not None:
2074
if not sage.structure.element.is_RingElement(scale):
2075
raise TypeError('scale must be an element of some ring, not {0}'.format(scale))
2076
R = scale.parent()
2077
else:
2078
R = rings.ZZ
2079
if arg0 is None:
2080
raise ValueError('size of elementary matrix must be given')
2081
try:
2082
n = rings.Integer(arg0)
2083
except TypeError:
2084
raise TypeError('size of elementary matrix must be an integer, not {0}'.format(arg0))
2085
if n <= 0:
2086
raise ValueError('size of elementary matrix must be 1 or greater, not {0}'.format(n))
2087
# row operations or column operations?
2088
# column operation matrix will be transpose of a row operation matrix
2089
row1 = kwds.pop('row1', None)
2090
col1 = kwds.pop('col1', None)
2091
if row1 is None and col1 is None:
2092
raise ValueError('row1 or col1 must be specified')
2093
if not row1 is None and not col1 is None:
2094
raise ValueError('cannot specify both row1 and col1')
2095
rowop = not row1 is None
2096
if rowop:
2097
opstring = "row"
2098
row2 = kwds.pop('row2', None)
2099
else:
2100
opstring = "column"
2101
row1 = col1
2102
row2 = kwds.pop('col2', None)
2103
sparse = kwds.pop('sparse', False)
2104
if kwds:
2105
extra = kwds.popitem()
2106
raise ValueError('received an unexpected keyword: {0}={1}'.format(extra[0], extra[1]))
2107
2108
# analyze parameters to determine matrix type
2109
try:
2110
row1 = rings.Integer(row1)
2111
except TypeError:
2112
raise TypeError('{0} of elementary matrix must be an integer, not {1}'.format(opstring, row1))
2113
if row1 < 0 or row1 >= n :
2114
raise ValueError('{0} of elementary matrix must be positive and smaller than {1}, not {2}'.format(opstring, n, row1))
2115
if not row2 is None:
2116
try:
2117
row2 = rings.Integer(row2)
2118
except TypeError:
2119
raise TypeError('{0} of elementary matrix must be an integer, not {1}'.format(opstring, row2))
2120
if row2 < 0 or row2 >= n :
2121
raise ValueError('{0} of elementary matrix must be positive and smaller than {1}, not {2}'.format(opstring, n, row2))
2122
if not scale is None:
2123
try:
2124
scale = R(scale)
2125
except Exception:
2126
raise TypeError('scale parameter of elementary matrix must an element of {0}, not {1}'.format(R, scale))
2127
2128
# determine type of matrix and adjust an identity matrix
2129
# return row operation matrix or the transpose as a column operation matrix
2130
elem = identity_matrix(R, n, sparse=sparse)
2131
if row2 is None and scale is None:
2132
raise ValueError('insufficient parameters provided to construct elementary matrix')
2133
elif not row2 is None and not scale is None:
2134
if row1 == row2:
2135
raise ValueError('cannot add a multiple of a {0} to itself'.format(opstring))
2136
elem[row1, row2] = scale
2137
elif not row2 is None and scale is None:
2138
elem[row1, row1] = 0
2139
elem[row2, row2] = 0
2140
elem[row1, row2] = 1
2141
elem[row2, row1] = 1
2142
elif row2 is None and not scale is None:
2143
if scale == 0:
2144
raise ValueError('scale parameter of {0} of elementary matrix must be non-zero'.format(opstring))
2145
elem[row1, row1] = scale
2146
if rowop:
2147
return elem
2148
else:
2149
return elem.transpose()
2150
2151
def _determine_block_matrix_grid(sub_matrices):
2152
r"""
2153
For internal use. This tries to determine the dimensions
2154
of rows/columns when assembling the matrices in sub_matrices in a
2155
rectangular grid. It returns a pair of lists containing
2156
respectively the sizes of rows and columns.
2157
2158
sub_matrices must be a list of lists of matrices. All sublists
2159
are expected to be the same size.
2160
2161
Non-zero scalars are considered to be square matrices of any size,
2162
and zeroes are considered to be zero matrices of any size.
2163
2164
A ValueError is raised if there is insufficient or
2165
conflicting information.
2166
2167
TESTS::
2168
2169
sage: from sage.matrix.constructor import _determine_block_matrix_grid
2170
sage: A = matrix(QQ, 2, 2, [3,9,6,10])
2171
sage: _determine_block_matrix_grid([[A, A], [A, A]])
2172
([2, 2], [2, 2])
2173
2174
sage: B = matrix(QQ, 1, 1, [ 1 ] )
2175
sage: C = matrix(QQ, 2, 2, [ 2, 3, 4, 5 ] )
2176
sage: _determine_block_matrix_grid([[B, 0], [0, C]])
2177
([1, 2], [1, 2])
2178
"""
2179
2180
nrows = len(sub_matrices)
2181
if nrows == 0:
2182
return ([], [])
2183
ncols = len(sub_matrices[0])
2184
2185
if ncols == 0:
2186
return ([0] * nrows, [])
2187
2188
row_heights = [None] * nrows
2189
col_widths = [None] * ncols
2190
2191
changing = True
2192
while changing:
2193
changing = False
2194
for i in range(nrows):
2195
for j in range(ncols):
2196
M = sub_matrices[i][j]
2197
sub_width = None
2198
sub_height = None
2199
if is_Matrix(M):
2200
sub_width = M.ncols()
2201
sub_height = M.nrows()
2202
elif M: # non-zero scalar is interpreted as a square matrix
2203
if row_heights[i] is None:
2204
sub_width = col_widths[j]
2205
else:
2206
sub_width = row_heights[i]
2207
sub_height = sub_width
2208
if sub_width is not None:
2209
if col_widths[j] is None:
2210
changing = True
2211
col_widths[j] = sub_width
2212
elif col_widths[j] != sub_width:
2213
raise ValueError("incompatible submatrix widths")
2214
if sub_height is not None:
2215
if row_heights[i] is None:
2216
changing = True
2217
row_heights[i] = sub_height
2218
elif row_heights[i] != sub_height:
2219
raise ValueError("incompatible submatrix heights")
2220
2221
if None in row_heights or None in col_widths:
2222
if None in row_heights or None in col_widths:
2223
raise ValueError("insufficient information to determine dimensions.")
2224
2225
return (row_heights, col_widths)
2226
2227
def _determine_block_matrix_rows(sub_matrices):
2228
"""
2229
For internal use. This tests if the matrices in sub_matrices
2230
fit in a rectangular matrix when assembled a row at a time.
2231
2232
sub_matrices must be a list of lists of matrices.
2233
2234
It returns a pair (row_heights, zero_widths, width) where
2235
row_heights is the list of row heights, zero_widths is the
2236
total width filled up by zero matrices per row, and width
2237
is the total width of the resulting matrix.
2238
2239
Non-zero scalars are considered to be square matrices of any size,
2240
and zeroes are considered to be zero matrices of any size.
2241
2242
A ValueError is raised if there is insufficient or
2243
conflicting information.
2244
2245
TESTS::
2246
2247
sage: from sage.matrix.constructor import _determine_block_matrix_rows
2248
sage: A = Matrix(ZZ, 1, 4, [1, 2, 3, 4])
2249
sage: _determine_block_matrix_rows([ [1, 1], [ A ] ])
2250
([2, 1], [0, 0], 4)
2251
2252
sage: B = Matrix(ZZ, 2, 2, [1, 2, 3, 4])
2253
sage: _determine_block_matrix_rows([ [B, B], [B, 1] ])
2254
([2, 2], [0, 0], 4)
2255
"""
2256
2257
total_height = 0
2258
total_width = None
2259
2260
row_heights = [ None ] * len(sub_matrices)
2261
zero_widths = [ 0 ] * len(sub_matrices)
2262
2263
# We first do a pass to see if we can determine the width
2264
unknowns = False
2265
for i in range(len(sub_matrices)):
2266
R = sub_matrices[i]
2267
height = None
2268
# We first do a pass to see if we can determine the height
2269
# of this row
2270
found_zeroes = False
2271
for M in R:
2272
if is_Matrix(M):
2273
if height is None:
2274
height = M.nrows()
2275
elif height != M.nrows():
2276
raise ValueError("incompatible submatrix heights")
2277
elif not M:
2278
found_zeroes = True
2279
if len(R) == 0:
2280
height = 0
2281
2282
# If we have a height, then we know the dimensions of any
2283
# non-zero scalars, and can maybe compute the width
2284
if height is not None and not found_zeroes:
2285
width = 0
2286
for M in R:
2287
if is_Matrix(M):
2288
width += M.ncols()
2289
else:
2290
# non-zero scalar
2291
width += height
2292
if total_width is None:
2293
total_width = width
2294
elif total_width != width:
2295
raise ValueError("incompatible submatrix widths")
2296
row_heights[i] = height
2297
else:
2298
# We don't set height here even if we know it,
2299
# to signal this row hasn't been fit yet.
2300
unknowns = True
2301
2302
if total_width is None:
2303
raise ValueError("insufficient information to determine submatrix widths")
2304
2305
if unknowns:
2306
# Do a second pass and see if the remaining rows can be
2307
# determined now that we know the width of the matrix.
2308
for i in range(len(sub_matrices)):
2309
if row_heights[i] is not None:
2310
continue
2311
R = sub_matrices[i]
2312
zero_state = 0
2313
# 0: no zeroes found
2314
# 1: consecutive zeroes found
2315
# 2: consecutive zeroes followed by non-zero found
2316
# 3: non-consecutive zeroes found
2317
scalars = 0
2318
width = 0
2319
height = None
2320
for j in range(len(R)):
2321
M = R[j]
2322
if is_Matrix(M):
2323
height = M.nrows()
2324
width += M.ncols()
2325
if zero_state == 1:
2326
zero_state = 2
2327
elif not M:
2328
if zero_state == 0:
2329
zero_state = 1
2330
elif zero_state == 2:
2331
zero_state = 3
2332
else:
2333
scalars += 1
2334
2335
remaining_width = total_width - width
2336
# This remaining width has to be split over the
2337
# zeroes and (non-zero) scalars
2338
2339
if height is not None:
2340
remaining_width -= scalars * height
2341
if remaining_width < 0:
2342
raise ValueError("incompatible submatrix widths")
2343
if remaining_width > 0 and zero_state == 3:
2344
raise ValueError("insufficient information to determine submatrix widths")
2345
if remaining_width > 0 and zero_state == 0:
2346
raise ValueError("incompatible submatrix widths")
2347
# otherwise, things fit
2348
row_heights[i] = height
2349
zero_widths[i] = remaining_width
2350
elif zero_state != 0:
2351
# if we don't know the height, and there are zeroes,
2352
# we can't determine the height
2353
raise ValueError("insufficient information to determine submatrix heights")
2354
elif total_width % len(R) != 0:
2355
raise ValueError("incompatible submatrix widths")
2356
else:
2357
height = int(total_width / len(R))
2358
row_heights[i] = height
2359
2360
# If we got this far, then everything fits
2361
return (row_heights, zero_widths, total_width)
2362
2363
2364
@matrix_method
2365
def block_matrix(*args, **kwds):
2366
r"""
2367
Returns a larger matrix made by concatenating submatrices
2368
(rows first, then columns). For example, the matrix
2369
2370
::
2371
2372
[ A B ]
2373
[ C D ]
2374
2375
is made up of submatrices A, B, C, and D.
2376
2377
INPUT:
2378
2379
The block_matrix command takes a list of submatrices to add
2380
as blocks, optionally preceded by a ring and the number of block rows
2381
and block columns, and returns a matrix.
2382
2383
The submatrices can be specified as a list of matrices (using
2384
``nrows`` and ``ncols`` to determine their layout), or a list
2385
of lists of matrices, where each list forms a row.
2386
2387
- ``ring`` - the base ring
2388
2389
- ``nrows`` - the number of block rows
2390
2391
- ``ncols`` - the number of block cols
2392
2393
- ``sub_matrices`` - matrices (see below for syntax)
2394
2395
- ``subdivide`` - boolean, whether or not to add
2396
subdivision information to the matrix
2397
2398
- ``sparse`` - boolean, whether to make the resulting matrix sparse
2399
2400
2401
EXAMPLES::
2402
2403
sage: A = matrix(QQ, 2, 2, [3,9,6,10])
2404
sage: block_matrix([ [A, -A], [~A, 100*A] ])
2405
[ 3 9| -3 -9]
2406
[ 6 10| -6 -10]
2407
[-----------+-----------]
2408
[-5/12 3/8| 300 900]
2409
[ 1/4 -1/8| 600 1000]
2410
2411
If the number of submatrices in each row is the same,
2412
you can specify the submatrices as a single list too::
2413
2414
sage: block_matrix(2, 2, [ A, A, A, A ])
2415
[ 3 9| 3 9]
2416
[ 6 10| 6 10]
2417
[-----+-----]
2418
[ 3 9| 3 9]
2419
[ 6 10| 6 10]
2420
2421
2422
One can use constant entries::
2423
2424
sage: block_matrix([ [1, A], [0, 1] ])
2425
[ 1 0| 3 9]
2426
[ 0 1| 6 10]
2427
[-----+-----]
2428
[ 0 0| 1 0]
2429
[ 0 0| 0 1]
2430
2431
A zero entry may represent any square or non-square zero matrix::
2432
2433
sage: B = matrix(QQ, 1, 1, [ 1 ] )
2434
sage: C = matrix(QQ, 2, 2, [ 2, 3, 4, 5 ] )
2435
sage: block_matrix([ [B, 0], [0, C] ])
2436
[1|0 0]
2437
[-+---]
2438
[0|2 3]
2439
[0|4 5]
2440
2441
One can specify the number of rows or columns as keywords too::
2442
2443
sage: block_matrix([A, -A, ~A, 100*A], ncols=4)
2444
[ 3 9| -3 -9|-5/12 3/8| 300 900]
2445
[ 6 10| -6 -10| 1/4 -1/8| 600 1000]
2446
2447
sage: block_matrix([A, -A, ~A, 100*A], nrows=1)
2448
[ 3 9| -3 -9|-5/12 3/8| 300 900]
2449
[ 6 10| -6 -10| 1/4 -1/8| 600 1000]
2450
2451
It handles base rings nicely too::
2452
2453
sage: R.<x> = ZZ['x']
2454
sage: block_matrix(2, 2, [1/2, A, 0, x-1])
2455
[ 1/2 0| 3 9]
2456
[ 0 1/2| 6 10]
2457
[-----------+-----------]
2458
[ 0 0|x - 1 0]
2459
[ 0 0| 0 x - 1]
2460
2461
sage: block_matrix(2, 2, [1/2, A, 0, x-1]).parent()
2462
Full MatrixSpace of 4 by 4 dense matrices over Univariate Polynomial Ring in x over Rational Field
2463
2464
Subdivisions are optional. If they are disabled, the columns need not line up::
2465
2466
sage: B = matrix(QQ, 2, 3, range(6))
2467
sage: block_matrix([ [~A, B], [B, ~A] ], subdivide=False)
2468
[-5/12 3/8 0 1 2]
2469
[ 1/4 -1/8 3 4 5]
2470
[ 0 1 2 -5/12 3/8]
2471
[ 3 4 5 1/4 -1/8]
2472
2473
Without subdivisions it also deduces dimensions for scalars if possible::
2474
2475
sage: C = matrix(ZZ, 1, 2, range(2))
2476
sage: block_matrix([ [ C, 0 ], [ 3, 4 ], [ 5, 6, C ] ], subdivide=False )
2477
[0 1 0 0]
2478
[3 0 4 0]
2479
[0 3 0 4]
2480
[5 6 0 1]
2481
2482
If all submatrices are sparse (unless there are none at all), the result
2483
will be a sparse matrix. Otherwise it will be dense by default. The
2484
``sparse`` keyword can be used to override this::
2485
2486
sage: A = Matrix(ZZ, 2, 2, [0, 1, 0, 0], sparse=True)
2487
sage: block_matrix([ [ A ], [ A ] ]).parent()
2488
Full MatrixSpace of 4 by 2 sparse matrices over Integer Ring
2489
sage: block_matrix([ [ A ], [ A ] ], sparse=False).parent()
2490
Full MatrixSpace of 4 by 2 dense matrices over Integer Ring
2491
2492
Consecutive zero submatrices are consolidated. ::
2493
2494
sage: B = matrix(2, range(4))
2495
sage: C = matrix(2, 8, range(16))
2496
sage: block_matrix(2, [[B,0,0,B],[C]], subdivide=False)
2497
[ 0 1 0 0 0 0 0 1]
2498
[ 2 3 0 0 0 0 2 3]
2499
[ 0 1 2 3 4 5 6 7]
2500
[ 8 9 10 11 12 13 14 15]
2501
2502
Ambiguity is not tolerated. ::
2503
2504
sage: B = matrix(2, range(4))
2505
sage: C = matrix(2, 8, range(16))
2506
sage: block_matrix(2, [[B,0,B,0],[C]], subdivide=False)
2507
Traceback (most recent call last):
2508
...
2509
ValueError: insufficient information to determine submatrix widths
2510
2511
Historically, giving only a flat list of submatrices, whose number
2512
was a perfect square, would create a new matrix by laying out the submatrices
2513
in a square grid. This behavior is now deprecated. ::
2514
2515
sage: A = matrix(2, 3, range(6))
2516
sage: B = matrix(3, 3, range(9))
2517
sage: block_matrix([A, A, B, B])
2518
doctest:...: DeprecationWarning: invocation of block_matrix with just a list whose length is a perfect square is deprecated. See the documentation for details.
2519
[0 1 2|0 1 2]
2520
[3 4 5|3 4 5]
2521
[-----+-----]
2522
[0 1 2|0 1 2]
2523
[3 4 5|3 4 5]
2524
[6 7 8|6 7 8]
2525
2526
Historically, a flat list of matrices whose number is not a perfect square,
2527
with no specification of the number of rows or columns, would raise an error.
2528
This behavior continues, but could be removed when the deprecation above is
2529
completed. ::
2530
2531
sage: A = matrix(2, 3, range(6))
2532
sage: B = matrix(3, 3, range(9))
2533
sage: block_matrix([A, A, A, B, B, B])
2534
Traceback (most recent call last):
2535
...
2536
ValueError: must specify nrows or ncols for non-square block matrix.
2537
"""
2538
args = list(args)
2539
sparse = kwds.get('sparse',None)
2540
2541
if len(args) == 0:
2542
if sparse is not None:
2543
return matrix_space.MatrixSpace(rings.ZZ, 0, 0, sparse=sparse)([])
2544
else:
2545
return matrix_space.MatrixSpace(rings.ZZ, 0, 0)([])
2546
2547
if len(args) >= 1 and is_Ring(args[0]):
2548
# A ring is specified
2549
if kwds.get('ring', args[0]) != args[0]:
2550
raise ValueError("base ring specified twice and they are different")
2551
ring = args[0]
2552
args.pop(0)
2553
else:
2554
ring = kwds.get('ring', None)
2555
2556
if len(args) >= 1:
2557
try:
2558
nrows = int(args[0])
2559
args.pop(0)
2560
if kwds.get('nrows', nrows) != nrows:
2561
raise ValueError("number of rows specified twice and they are different")
2562
except TypeError:
2563
nrows = kwds.get('nrows', None)
2564
else:
2565
nrows = kwds.get('nrows', None)
2566
2567
if len(args) >= 1:
2568
# check to see if additionally, the number of columns is specified
2569
try:
2570
ncols = int(args[0])
2571
args.pop(0)
2572
if kwds.get('ncols', ncols) != ncols:
2573
raise ValueError("number of columns specified twice and they are different")
2574
except TypeError:
2575
ncols = kwds.get('ncols', None)
2576
else:
2577
ncols = kwds.get('ncols', None)
2578
2579
# Now we've taken care of initial ring, nrows, and ncols arguments.
2580
2581
# Now the rest of the arguments are a list of rows, a flat list of
2582
# matrices, or a single value.
2583
2584
if len(args) == 0:
2585
args = [[]]
2586
if len(args) > 1:
2587
print args
2588
raise TypeError("invalid block_matrix invocation")
2589
2590
sub_matrices = args[0]
2591
2592
if is_Matrix(sub_matrices):
2593
# a single matrix (check nrows/ncols/ring)
2594
if (nrows is not None and nrows != 1) or \
2595
(ncols is not None and ncols != 1):
2596
raise ValueError("invalid nrows/ncols passed to block_matrix")
2597
if ring is not None:
2598
M = M.change_ring(ring)
2599
if sparse is not None and M.is_sparse() != sparse:
2600
M = M.sparse_matrix() if sparse else M.dense_matrix()
2601
return M
2602
2603
if not isinstance(sub_matrices, (list, tuple)):
2604
raise TypeError("invalid block_matrix invocation")
2605
2606
subdivide = kwds.get('subdivide', True)
2607
2608
# Will we try to place the matrices in a rectangular grid?
2609
try_grid = True
2610
2611
2612
if len(sub_matrices) == 0:
2613
if (nrows is not None and nrows != 0) or \
2614
(ncols is not None and ncols != 0):
2615
raise ValueError("invalid nrows/ncols passed to block_matrix")
2616
elif isinstance(sub_matrices[0], (list, tuple)):
2617
# A list of lists: verify all elements are lists, and if
2618
# ncols is set, the lengths match.
2619
if nrows is not None and len(sub_matrices) != nrows:
2620
raise ValueError("invalid nrows passed to block_matrix")
2621
first_len = len(sub_matrices[0])
2622
if ncols is not None and first_len != ncols:
2623
raise ValueError("invalid ncols passed to block_matrix")
2624
same_length = all(isinstance(v, (list, tuple)) and len(v) == first_len for v in sub_matrices)
2625
if subdivide and not same_length:
2626
raise ValueError("list of rows is not valid (rows are wrong types or lengths)")
2627
try_grid = same_length
2628
else:
2629
# A flat list
2630
# determine the block dimensions
2631
n = ZZ(len(sub_matrices))
2632
if nrows is None:
2633
if ncols is None:
2634
if n.is_square():
2635
import warnings
2636
warnings.resetwarnings()
2637
warnings.warn("invocation of block_matrix with just a list whose length is a perfect square is deprecated. See the documentation for details.", DeprecationWarning, stacklevel=2)
2638
nrows = ncols = n.sqrt()
2639
else:
2640
# this form (ie just a flat list) could be allowed once deprecated invocation (above) goes away
2641
raise ValueError("must specify nrows or ncols for non-square block matrix.")
2642
else:
2643
nrows = int(n/ncols)
2644
elif ncols is None:
2645
ncols = int(n/nrows)
2646
if nrows * ncols != n:
2647
raise ValueError("given number of rows (%s), columns (%s) incompatible with number of submatrices (%s)" % (nrows, ncols, n))
2648
# Now create a list of lists from this
2649
sub_matrices = [ sub_matrices[i*ncols : (i+1)*ncols] for i in range(nrows) ]
2650
2651
# At this point sub_matrices is a list of lists
2652
2653
# determine the base ring and sparsity
2654
if ring is None:
2655
ring = ZZ
2656
for row in sub_matrices:
2657
for M in row:
2658
R = M.base_ring() if is_Matrix(M) else M.parent()
2659
if R is not ZZ:
2660
ring = sage.categories.pushout.pushout(ring, R)
2661
2662
if sparse is None:
2663
sparse = True
2664
for row in sub_matrices:
2665
for M in row:
2666
if sparse and is_Matrix(M) and not M.is_sparse():
2667
sparse = False
2668
2669
row_heights = None
2670
col_widths = None
2671
zero_widths = None
2672
total_width = None
2673
2674
# We first try to place the matrices in a rectangular grid
2675
if try_grid:
2676
try:
2677
(row_heights, col_widths) = _determine_block_matrix_grid(sub_matrices)
2678
except ValueError as e:
2679
if subdivide:
2680
raise ValueError(e)
2681
2682
2683
if col_widths is None:
2684
# Try placing the matrices in rows instead
2685
# (Only if subdivide is False)
2686
(row_heights, zero_widths, total_width) = _determine_block_matrix_rows(sub_matrices)
2687
2688
2689
# Success, so assemble the final matrix
2690
2691
big = None
2692
for i in range(len(sub_matrices)):
2693
R = sub_matrices[i]
2694
row = None
2695
for j in range(len(R)):
2696
M = R[j]
2697
2698
if is_Matrix(M):
2699
if M.base_ring() is not ring:
2700
M = M.change_ring(ring)
2701
if M.is_sparse() != sparse:
2702
M = M.sparse_matrix() if sparse else M.dense_matrix()
2703
elif not M and zero_widths is not None:
2704
if zero_widths[i] > 0:
2705
M = matrix(ring, row_heights[i], zero_widths[i], 0, sparse=sparse)
2706
zero_widths[i] = 0
2707
else:
2708
continue # zero-width matrix
2709
else:
2710
if zero_widths is not None:
2711
M = matrix(ring, row_heights[i], row_heights[i], M, sparse=sparse)
2712
else:
2713
M = matrix(ring, row_heights[i], col_widths[j], M, sparse=sparse)
2714
2715
# append M to this row
2716
if row is None:
2717
row = M
2718
else:
2719
row = row.augment(M)
2720
2721
# append row to final matrix
2722
if big is None:
2723
big = row
2724
else:
2725
big = big.stack(row)
2726
2727
if big is None:
2728
if ring is None:
2729
ring = ZZ
2730
big = Matrix(ring, 0, 0)
2731
2732
if subdivide:
2733
big.subdivide(running_total(row_heights[:-1]),
2734
running_total(col_widths[:-1]))
2735
2736
return big
2737
2738
2739
@matrix_method
2740
def block_diagonal_matrix(*sub_matrices, **kwds):
2741
"""
2742
Create a block matrix whose diagonal block entries are given by
2743
sub_matrices, with zero elsewhere.
2744
2745
See also :meth:`block_matrix`.
2746
2747
EXAMPLES::
2748
2749
sage: A = matrix(ZZ, 2, [1,2,3,4])
2750
sage: block_diagonal_matrix(A, A)
2751
[1 2|0 0]
2752
[3 4|0 0]
2753
[---+---]
2754
[0 0|1 2]
2755
[0 0|3 4]
2756
2757
The sub-matrices need not be square::
2758
2759
sage: B = matrix(QQ, 2, 3, range(6))
2760
sage: block_diagonal_matrix(~A, B)
2761
[ -2 1| 0 0 0]
2762
[ 3/2 -1/2| 0 0 0]
2763
[---------+--------------]
2764
[ 0 0| 0 1 2]
2765
[ 0 0| 3 4 5]
2766
"""
2767
if isinstance(sub_matrices, (list, tuple)) and len(sub_matrices) == 1:
2768
sub_matrices = sub_matrices[0]
2769
n = len(sub_matrices)
2770
entries = [ZZ.zero_element()] * n**2
2771
for i in range(n):
2772
entries[n*i+i] = sub_matrices[i]
2773
return block_matrix(n, n, entries, **kwds)
2774
2775
2776
@matrix_method
2777
def jordan_block(eigenvalue, size, sparse=False):
2778
r"""
2779
Returns the Jordan block for the given eigenvalue with given size.
2780
2781
INPUT:
2782
2783
- ``eigenvalue`` - eigenvalue for the diagonal entries of the block
2784
- ``size`` - size of the square matrix
2785
- ``sparse`` - (default: False) - if True, return a sparse matrix
2786
2787
2788
EXAMPLE::
2789
2790
sage: jordan_block(5, 3)
2791
[5 1 0]
2792
[0 5 1]
2793
[0 0 5]
2794
2795
TESTS::
2796
2797
sage: jordan_block(6.2, 'junk')
2798
Traceback (most recent call last):
2799
...
2800
TypeError: size of Jordan block needs to be an integer, not junk
2801
sage: jordan_block(6.2, -1)
2802
Traceback (most recent call last):
2803
...
2804
ValueError: size of Jordan block must be non-negative, not -1
2805
"""
2806
try:
2807
size = ZZ(size)
2808
except TypeError:
2809
msg = "size of Jordan block needs to be an integer, not {0}"
2810
raise TypeError(msg.format(size))
2811
if size < 0:
2812
msg = "size of Jordan block must be non-negative, not {0}"
2813
raise ValueError(msg.format(size))
2814
block = diagonal_matrix([eigenvalue]*size, sparse=sparse)
2815
for i in xrange(size-1):
2816
block[i,i+1]=1
2817
return block
2818
2819
2820
@matrix_method
2821
def companion_matrix(poly, format='right'):
2822
r"""
2823
Create a companion matrix from a monic polynomial.
2824
2825
INPUT:
2826
2827
- ``poly`` - a univariate polynomial, or an iterable containing
2828
the coefficients of a polynomial, with low-degree coefficients first.
2829
The polynomial (or the polynomial implied by the coefficients) must
2830
be monic. In other words, the leading coefficient must be one.
2831
A symbolic expression that might also be a polynomial is not
2832
proper input, see examples below.
2833
2834
- ``format`` - default: 'right' - specifies one of four
2835
variations of a companion matrix. Allowable values are
2836
'right', 'left', 'top' and 'bottom', which indicates which
2837
border of the matrix contains the negatives of the coefficients.
2838
2839
OUTPUT:
2840
2841
A square matrix with a size equal to the degree of the polynomial.
2842
The returned matrix has ones above, or below the diagonal, and the
2843
negatives of the coefficients along the indicated border of the
2844
matrix (excepting the leading one coefficient).
2845
See the first examples below for precise illustrations.
2846
2847
EXAMPLES:
2848
2849
Each of the four possibilities. Notice that the coefficients are
2850
specified and their negatives become the entries of the matrix. The
2851
leading one must be given, but is not used. The permutation matrix
2852
``P`` is the identity matrix, with the columns reversed. The last three
2853
statements test the general relationships between the four variants. ::
2854
2855
sage: poly = [-2, -3, -4, -5, -6, 1]
2856
sage: R = companion_matrix(poly, format='right'); R
2857
[0 0 0 0 2]
2858
[1 0 0 0 3]
2859
[0 1 0 0 4]
2860
[0 0 1 0 5]
2861
[0 0 0 1 6]
2862
sage: L = companion_matrix(poly, format='left'); L
2863
[6 1 0 0 0]
2864
[5 0 1 0 0]
2865
[4 0 0 1 0]
2866
[3 0 0 0 1]
2867
[2 0 0 0 0]
2868
sage: B = companion_matrix(poly, format='bottom'); B
2869
[0 1 0 0 0]
2870
[0 0 1 0 0]
2871
[0 0 0 1 0]
2872
[0 0 0 0 1]
2873
[2 3 4 5 6]
2874
sage: T = companion_matrix(poly, format='top'); T
2875
[6 5 4 3 2]
2876
[1 0 0 0 0]
2877
[0 1 0 0 0]
2878
[0 0 1 0 0]
2879
[0 0 0 1 0]
2880
2881
sage: perm = Permutation([5, 4, 3, 2, 1])
2882
sage: P = perm.to_matrix()
2883
sage: L == P*R*P
2884
True
2885
sage: B == R.transpose()
2886
True
2887
sage: T == P*R.transpose()*P
2888
True
2889
2890
A polynomial may be used as input, however a symbolic expression,
2891
even if it looks like a polynomial, is not regarded as such when used
2892
as input to this routine. Obtaining the list of coefficients from a
2893
symbolic polynomial is one route to the companion matrix. ::
2894
2895
sage: x = polygen(QQ, 'x')
2896
sage: p = x^3 - 4*x^2 + 8*x - 12
2897
sage: companion_matrix(p)
2898
[ 0 0 12]
2899
[ 1 0 -8]
2900
[ 0 1 4]
2901
2902
sage: y = var('y')
2903
sage: q = y^3 -2*y + 1
2904
sage: companion_matrix(q)
2905
Traceback (most recent call last):
2906
...
2907
TypeError: input must be a polynomial (not a symbolic expression, see docstring), or other iterable, not y^3 - 2*y + 1
2908
2909
sage: coeff_list = [q(y=0)] + [q.coeff(y^k) for k in range(1, q.degree(y)+1)]
2910
sage: coeff_list
2911
[1, -2, 0, 1]
2912
sage: companion_matrix(coeff_list)
2913
[ 0 0 -1]
2914
[ 1 0 2]
2915
[ 0 1 0]
2916
2917
The minimal polynomial of a companion matrix is equal to the
2918
polynomial used to create it. Used in a block diagonal
2919
construction, they can be used to create matrices with
2920
any desired minimal polynomial, or characteristic polynomial. ::
2921
2922
sage: t = polygen(QQ, 't')
2923
sage: p = t^12 - 7*t^4 + 28*t^2 - 456
2924
sage: C = companion_matrix(p, format='top')
2925
sage: q = C.minpoly(var=t); q
2926
t^12 - 7*t^4 + 28*t^2 - 456
2927
sage: p == q
2928
True
2929
2930
sage: p = t^3 + 3*t - 8
2931
sage: q = t^5 + t - 17
2932
sage: A = block_diagonal_matrix( companion_matrix(p),
2933
... companion_matrix(p^2),
2934
... companion_matrix(q),
2935
... companion_matrix(q) )
2936
sage: A.charpoly(var=t).factor()
2937
(t^3 + 3*t - 8)^3 * (t^5 + t - 17)^2
2938
sage: A.minpoly(var=t).factor()
2939
(t^3 + 3*t - 8)^2 * (t^5 + t - 17)
2940
2941
TESTS::
2942
2943
sage: companion_matrix([4, 5, 1], format='junk')
2944
Traceback (most recent call last):
2945
...
2946
ValueError: format must be 'right', 'left', 'top' or 'bottom', not junk
2947
2948
sage: companion_matrix(sin(x))
2949
Traceback (most recent call last):
2950
...
2951
TypeError: input must be a polynomial (not a symbolic expression, see docstring), or other iterable, not sin(x)
2952
2953
sage: companion_matrix([2, 3, 896])
2954
Traceback (most recent call last):
2955
...
2956
ValueError: polynomial (or the polynomial implied by coefficients) must be monic, not a leading coefficient of 896
2957
2958
sage: F.<a> = GF(2^2)
2959
sage: companion_matrix([4/3, a+1, 1])
2960
Traceback (most recent call last):
2961
...
2962
TypeError: unable to find common ring for coefficients from polynomial
2963
2964
sage: A = companion_matrix([1])
2965
sage: A.nrows(); A.ncols()
2966
0
2967
0
2968
2969
sage: A = companion_matrix([])
2970
Traceback (most recent call last):
2971
...
2972
ValueError: polynomial cannot be specified by an empty list
2973
2974
AUTHOR:
2975
2976
- Rob Beezer (2011-05-19)
2977
"""
2978
import sage.matrix.constructor
2979
if format not in ['right', 'left', 'top', 'bottom']:
2980
raise ValueError("format must be 'right', 'left', 'top' or 'bottom', not {0}".format(format))
2981
try:
2982
poly = list(poly)
2983
except TypeError:
2984
raise TypeError('input must be a polynomial (not a symbolic expression, see docstring), or other iterable, not {0}'.format(poly))
2985
n = len(poly) - 1
2986
if n == -1:
2987
raise ValueError('polynomial cannot be specified by an empty list')
2988
if not poly[n] == 1:
2989
raise ValueError('polynomial (or the polynomial implied by coefficients) must be monic, not a leading coefficient of {0}'.format(poly[n]))
2990
entries = [0]*(n*n)
2991
# 1's below diagonal, or above diagonal
2992
if format in ['right', 'top']:
2993
for i in range(n-1):
2994
entries[(i+1)*n + i] = 1
2995
else:
2996
for i in range(n-1):
2997
entries[i*n + i+1] = 1
2998
# right side, left side (reversed), bottom edge, top edge (reversed)
2999
if format == 'right':
3000
for i in range(n):
3001
entries[i*n + n-1] = -poly[i]
3002
elif format == 'left':
3003
for i in range(n):
3004
entries[(n-1-i)*n + 0] = -poly[i]
3005
elif format == 'bottom':
3006
for i in range(n):
3007
entries[(n-1)*n + i] = -poly[i]
3008
elif format == 'top':
3009
for i in range(n):
3010
entries[0*n + n-1-i] = -poly[i]
3011
try:
3012
M = sage.matrix.constructor.matrix(n, n, entries)
3013
except TypeError:
3014
raise TypeError("unable to find common ring for coefficients from polynomial")
3015
return M
3016
3017
@matrix_method
3018
def random_rref_matrix(parent, num_pivots):
3019
r"""
3020
Generate a matrix in reduced row-echelon form with a specified number of non-zero rows.
3021
3022
INPUT:
3023
3024
- ``parent`` - A matrix space specifying the base ring, dimensions and
3025
representation (dense/sparse) for the result. The base ring must be exact.
3026
3027
- ``num_pivots`` - The number of non-zero rows in the result, i.e. the rank.
3028
3029
OUTPUT:
3030
3031
A matrix in reduced row echelon form with ``num_pivots`` non-zero rows. If the
3032
base ring is `ZZ` or `QQ` then the entries are all integers.
3033
3034
.. note::
3035
3036
It is easiest to use this function via a call to the
3037
:func:`~sage.matrix.constructor.random_matrix`
3038
function with the ``algorithm='echelon_form'`` keyword. We provide
3039
one example accessing this function directly, while the remainder will
3040
use this more general function.
3041
3042
EXAMPLES:
3043
3044
Matrices generated are in reduced row-echelon form with specified rank. If the
3045
base ring is `QQ` the result has only integer entries. ::
3046
3047
sage: from sage.matrix.constructor import random_rref_matrix
3048
sage: matrix_space = sage.matrix.matrix_space.MatrixSpace(QQ, 5, 6)
3049
sage: A=random_rref_matrix(matrix_space, num_pivots=4); A # random
3050
[ 1 0 0 -6 0 -3]
3051
[ 0 1 0 2 0 3]
3052
[ 0 0 1 -4 0 -2]
3053
[ 0 0 0 0 1 3]
3054
[ 0 0 0 0 0 0]
3055
sage: A.base_ring()
3056
Rational Field
3057
sage: (A.nrows(), A.ncols())
3058
(5, 6)
3059
sage: A in sage.matrix.matrix_space.MatrixSpace(ZZ, 5, 6)
3060
True
3061
sage: A.rank()
3062
4
3063
sage: A==A.rref()
3064
True
3065
3066
Matrices can be generated over other exact rings. ::
3067
3068
sage: B=random_matrix(FiniteField(7), 4, 4, algorithm='echelon_form', num_pivots=3); B # random
3069
[1 0 0 0]
3070
[0 1 0 6]
3071
[0 0 1 4]
3072
[0 0 0 0]
3073
sage: B.rank() == 3
3074
True
3075
sage: B.base_ring()
3076
Finite Field of size 7
3077
sage: B==B.rref()
3078
True
3079
3080
TESTS:
3081
3082
Rank of a matrix must be an integer. ::
3083
3084
sage: random_matrix(QQ, 120, 56, algorithm='echelon_form', num_pivots=61/2)
3085
Traceback (most recent call last):
3086
...
3087
TypeError: the number of pivots must be an integer.
3088
3089
Matrices must be generated over exact fields. ::
3090
3091
sage: random_matrix(RR, 40, 88, algorithm='echelon_form', num_pivots=39)
3092
Traceback (most recent call last):
3093
...
3094
TypeError: the base ring must be exact.
3095
3096
Matrices must have the number of pivot columns be less than or equal to the number of rows. ::
3097
3098
sage: C=random_matrix(ZZ, 6,4, algorithm='echelon_form', num_pivots=7); C
3099
Traceback (most recent call last):
3100
...
3101
ValueError: number of pivots cannot exceed the number of rows or columns.
3102
3103
Matrices must have the number of pivot columns be less than or equal to the number of columns. ::
3104
3105
sage: D=random_matrix(QQ, 1,3, algorithm='echelon_form', num_pivots=5); D
3106
Traceback (most recent call last):
3107
...
3108
ValueError: number of pivots cannot exceed the number of rows or columns.
3109
3110
Matrices must have the number of pivot columns be greater than zero. ::
3111
3112
sage: random_matrix(QQ, 5, 4, algorithm='echelon_form', num_pivots=-1)
3113
Traceback (most recent call last):
3114
...
3115
ValueError: the number of pivots must be zero or greater.
3116
3117
AUTHOR:
3118
3119
Billy Wonderly (2010-07)
3120
"""
3121
3122
import sage.gsl.probability_distribution as pd
3123
from sage.misc.prandom import randint
3124
3125
try:
3126
num_pivots=ZZ(num_pivots)
3127
except TypeError:
3128
raise TypeError("the number of pivots must be an integer.")
3129
if num_pivots<0:
3130
raise ValueError("the number of pivots must be zero or greater.")
3131
ring = parent.base_ring()
3132
if not ring.is_exact():
3133
raise TypeError("the base ring must be exact.")
3134
num_row = parent.nrows()
3135
num_col = parent.ncols()
3136
if num_pivots>num_row or num_pivots>num_col:
3137
raise ValueError("number of pivots cannot exceed the number of rows or columns.")
3138
else:
3139
one=ring.one()
3140
# Create a matrix of the desired size to be modified and then returned.
3141
return_matrix=copy(parent.zero_matrix())
3142
pivots=[0] #Force first column to be a pivot. No harm if no pivots at all.
3143
# Probability distribution for the placement of leading one's.
3144
pivot_generator=pd.RealDistribution("beta",[1.6,4.3])
3145
while len(pivots)<num_pivots:
3146
pivot_column=int(pivot_generator.get_random_element()*num_col)
3147
if pivot_column not in pivots:
3148
pivots.append(pivot_column)
3149
pivots.sort()
3150
pivot_row=0
3151
# Use the list of pivot columns to set the pivot entries of the return_matrix to leading ones.
3152
while pivot_row<num_pivots:
3153
return_matrix[pivot_row,pivots[pivot_row]]=one
3154
pivot_row+=1
3155
if ring==QQ or ring==ZZ:
3156
# Keep track of the non-pivot columns by using the pivot_index, start at the first column to
3157
# the right of the initial pivot column, go until the first column to the left of the next
3158
# pivot column.
3159
for pivot_index in range(num_pivots-1):
3160
for non_pivot_column_index in range(pivots[pivot_index]+1,pivots[pivot_index+1]):
3161
entry_generator1=pd.RealDistribution("beta",[6,4])
3162
# Experimental distribution used to generate the values.
3163
for non_pivot_column_entry in range(pivot_index+1):
3164
sign1=(2*randint(0,1)-1)
3165
return_matrix[non_pivot_column_entry,non_pivot_column_index]=sign1*int(entry_generator1.get_random_element()*((1-non_pivot_column_entry/return_matrix.ncols())*7))
3166
# Use index to fill entries of the columns to the right of the last pivot column.
3167
for rest_non_pivot_column in range(pivots[num_pivots-1]+1,num_col):
3168
entry_generator2=pd.RealDistribution("beta",[2.6,4])
3169
# experimental distribution to generate small values.
3170
for rest_entries in range(num_pivots):
3171
sign2=(2*randint(0,1)-1)
3172
return_matrix[rest_entries,rest_non_pivot_column]=sign2*int(entry_generator2.get_random_element()*5)
3173
else:
3174
for pivot_index in range(num_pivots-1):
3175
for non_pivot_column_index in range(pivots[pivot_index]+1,pivots[pivot_index+1]):
3176
for non_pivot_column_entry in range(pivot_index+1):
3177
return_matrix[non_pivot_column_entry,non_pivot_column_index]=ring.random_element()
3178
for rest_non_pivot_column in range(pivots[num_pivots-1]+1,num_col):
3179
for rest_entries in range(num_pivots):
3180
return_matrix[rest_entries,rest_non_pivot_column]=ring.random_element()
3181
return return_matrix
3182
3183
@matrix_method
3184
def random_echelonizable_matrix(parent, rank, upper_bound=None, max_tries=100):
3185
r"""
3186
Generate a matrix of a desired size and rank, over a desired ring, whose reduced
3187
row-echelon form has only integral values.
3188
3189
INPUT:
3190
3191
- ``parent`` - A matrix space specifying the base ring, dimensions and
3192
representation (dense/sparse) for the result. The base ring must be exact.
3193
3194
- ``rank`` - Rank of result, i.e the number of non-zero rows in the
3195
reduced row echelon form.
3196
3197
- ``upper_bound`` - If designated, size control of the matrix entries is desired.
3198
Set ``upper_bound`` to 1 more than the maximum value entries can achieve.
3199
If None, no size control occurs. But see the warning below. (default: None)
3200
3201
- ``max_tries`` - If designated, number of tries used to generate each new random row;
3202
only matters when upper_bound!=None. Used to prevent endless looping. (default: 100)
3203
3204
OUTPUT:
3205
3206
A matrix not in reduced row-echelon form with the desired dimensions and properties.
3207
3208
.. warning::
3209
3210
When ``upper_bound`` is set, it is possible for this constructor to
3211
fail with a ``ValueError``. This may happen when the ``upper_bound``,
3212
``rank`` and/or matrix dimensions are all so small that it becomes
3213
infeasible or unlikely to create the requested matrix. If you *must*
3214
have this routine return successfully, do not set ``upper_bound``.
3215
3216
.. note::
3217
3218
It is easiest to use this function via a call to the
3219
:func:`~sage.matrix.constructor.random_matrix`
3220
function with the ``algorithm='echelonizable'`` keyword. We provide
3221
one example accessing this function directly, while the remainder will
3222
use this more general function.
3223
3224
EXAMPLES:
3225
3226
Generated matrices have the desired dimensions, rank and entry size. The
3227
matrix in reduced row-echelon form has only integer entries. ::
3228
3229
sage: from sage.matrix.constructor import random_echelonizable_matrix
3230
sage: matrix_space = sage.matrix.matrix_space.MatrixSpace(QQ, 5, 6)
3231
sage: A=random_echelonizable_matrix(matrix_space, rank=4, upper_bound=40); A # random
3232
[ 1 -1 1 -3 -4 6]
3233
[ 5 -4 0 8 4 19]
3234
[ -3 3 -2 4 7 -16]
3235
[ -4 5 -7 26 31 -31]
3236
[ 2 -3 4 -11 -14 17]
3237
sage: A.rank()
3238
4
3239
sage: max(map(abs,A.list()))<40
3240
True
3241
sage: A.rref()==A.rref().change_ring(ZZ)
3242
True
3243
3244
An example with default settings (i.e. no entry size control). ::
3245
3246
sage: C=random_matrix(QQ, 6, 7, algorithm='echelonizable', rank=5); C # random
3247
[ 1 0 5 -2 -26 -16 0]
3248
[ -3 1 -19 6 97 61 1]
3249
[ 0 4 -15 -1 71 50 3]
3250
[ 2 4 -9 0 39 25 8]
3251
[ 2 2 3 -3 -18 -9 3]
3252
[ -3 -4 -2 14 14 -6 4]
3253
sage: C.rank()
3254
5
3255
sage: C.rref()==C.rref().change_ring(ZZ)
3256
True
3257
3258
A matrix without size control may have very large entry sizes. ::
3259
3260
sage: D=random_matrix(ZZ, 7, 8, algorithm='echelonizable', rank=6); D # random
3261
[ 9 -53 -255 45 -1519 4043 9819 3324]
3262
[ 3 -14 -64 8 -369 972 2350 810]
3263
[ 2 -14 -65 9 -377 1000 2420 829]
3264
[ 4 -24 -116 21 -693 1846 4485 1516]
3265
[ -3 14 68 -16 426 -1134 -2767 -919]
3266
[ -5 21 92 -13 548 -1432 -3466 -1183]
3267
[ 1 -9 -42 7 -254 670 1624 547]
3268
3269
Matrices can be generated over any exact ring. ::
3270
3271
sage: F.<a>=GF(2^3)
3272
sage: B=random_matrix(F, 4, 5, algorithm='echelonizable', rank=4, upper_bound=None); B # random
3273
[ a + 1 a^2 + a + 1 a^2 0 1]
3274
[ 1 a a + 1 a^2 a^2 + a]
3275
[ a a^2 a^2 + a + 1 a + 1 1]
3276
[ 1 0 a^2 + a + 1 0 a^2 + 1]
3277
sage: B.rank()
3278
4
3279
3280
Square matrices over ZZ or QQ with full rank are always unimodular. ::
3281
3282
sage: E=random_matrix(QQ, 7, 7, algorithm='echelonizable', rank=7); E # random
3283
[ 1 -1 5 12 -24 -41 47]
3284
[ 0 1 -1 3 0 -11 40]
3285
[ 1 -1 6 6 -19 -20 -11]
3286
[ -2 1 -10 -12 35 44 -4]
3287
[ 3 -1 9 7 -35 -40 -18]
3288
[ 0 0 0 -4 4 13 -32]
3289
[ 3 -3 11 6 -33 -31 -35]
3290
sage: det(E)
3291
1
3292
3293
TESTS:
3294
3295
Matrices must have a rank zero or greater, and less than
3296
both the number of rows and the number of columns. ::
3297
3298
sage: random_matrix(QQ, 3, 4, algorithm='echelonizable', rank=-1)
3299
Traceback (most recent call last):
3300
...
3301
ValueError: matrices must have rank zero or greater.
3302
sage: random_matrix(QQ, 3, 8, algorithm='echelonizable', rank=4)
3303
Traceback (most recent call last):
3304
...
3305
ValueError: matrices cannot have rank greater than min(ncols,nrows).
3306
sage: random_matrix(QQ, 8, 3, algorithm='echelonizable', rank=4)
3307
Traceback (most recent call last):
3308
...
3309
ValueError: matrices cannot have rank greater than min(ncols,nrows).
3310
3311
The base ring must be exact. ::
3312
3313
sage: random_matrix(RR, 3, 3, algorithm='echelonizable', rank=2)
3314
Traceback (most recent call last):
3315
...
3316
TypeError: the base ring must be exact.
3317
3318
Works for rank==1, too. ::
3319
3320
sage: random_matrix( QQ, 3, 3, algorithm='echelonizable', rank=1).ncols()
3321
3
3322
3323
3324
AUTHOR:
3325
3326
Billy Wonderly (2010-07)
3327
"""
3328
3329
from sage.misc.prandom import randint
3330
3331
ring = parent.base_ring()
3332
rows = parent.nrows()
3333
if rank<0:
3334
raise ValueError("matrices must have rank zero or greater.")
3335
if rank>min(rows,parent.ncols()):
3336
raise ValueError("matrices cannot have rank greater than min(ncols,nrows).")
3337
matrix = random_rref_matrix(parent, rank)
3338
3339
# Entries of matrices over the ZZ or QQ can get large, entry size is regulated by finding the largest
3340
# entry of the resultant matrix after addition of scalar multiple of a row.
3341
if ring==QQ or ring==ZZ:
3342
# If upper_bound is not set, don't control entry size.
3343
if upper_bound==None:
3344
# If size control is not desired, the routine will run slightly faster, particularly with large matrices.
3345
for pivots in range(rank-1,-1,-1):
3346
row_index=0
3347
while row_index<rows:
3348
if pivots==row_index:
3349
row_index+=1
3350
if pivots!=row_index and row_index!=rows:
3351
matrix.add_multiple_of_row(row_index,matrix.pivot_rows()[pivots],randint(-5,5))
3352
row_index+=1
3353
if rows>1:
3354
matrix.add_multiple_of_row(0,randint(1,rows-1),randint(-3,3))
3355
else:
3356
if rank==1: # would be better just to have a special generator...
3357
tries = 0
3358
while max(map(abs,matrix.list()))>=upper_bound:
3359
matrix = random_rref_matrix(parent, rank)
3360
tries += 1
3361
if tries > max_tries: # to prevent endless attempts
3362
raise ValueError("tried "+str(max_tries)+" times to get a rank 1 random matrix. Try bigger upper_bound?")
3363
matrix_copy = matrix
3364
3365
rrr = range(len(matrix.pivots())-1,-1,-1)
3366
for pivots in rrr:
3367
# keep track of the pivot column positions from the pivot column with the largest index to
3368
# the one with the smallest.
3369
row_index=0
3370
tries = 0
3371
while row_index<rows:
3372
# To each row in a pivot column add a scalar multiple of the pivot row.
3373
# for full rank, square matrices, using only this row operation preserves the determinant of 1.
3374
if pivots!=row_index:
3375
# To ensure a leading one is not removed by the addition of the pivot row by its
3376
# additive inverse.
3377
matrix_copy=matrix.with_added_multiple_of_row(row_index,matrix.pivot_rows()[pivots],randint(-5,5))
3378
tries += 1
3379
# Range for scalar multiples determined experimentally.
3380
if max(map(abs,matrix_copy.list()))<upper_bound:
3381
# Continue if the the largest entry after a row operation is within the bound.
3382
matrix=matrix_copy
3383
row_index+=1
3384
tries = 0
3385
if tries > max_tries: # to prevent endless unsuccessful row adding
3386
raise ValueError("tried "+str(max_tries)+" times to get row number "+str(row_index)+". Try bigger upper_bound?")
3387
# The leading one in row one has not been altered, so add a scalar multiple of a random row
3388
# to row one.
3389
row1=0
3390
if rows>1:
3391
while row1<1:
3392
matrix_copy=matrix.with_added_multiple_of_row(0,randint(1,rows-1),randint(-3,3))
3393
if max(map(abs,matrix_copy.list()))<upper_bound:
3394
matrix=matrix_copy
3395
row1+=1
3396
# If the matrix generated over a different ring, random elements from the designated ring are used as and
3397
# the routine is run similarly to the size unchecked version for rationals and integers.
3398
else:
3399
for pivots in range(rank-1,-1,-1):
3400
row_index=0
3401
while row_index<rows:
3402
if pivots==row_index:
3403
row_index+=1
3404
if pivots!=row_index and row_index!=rows:
3405
matrix.add_multiple_of_row(row_index,matrix.pivot_rows()[pivots],ring.random_element())
3406
row_index+=1
3407
if rows>1:
3408
matrix.add_multiple_of_row(0,randint(1,rows-1),ring.random_element())
3409
return matrix
3410
3411
@matrix_method
3412
def random_subspaces_matrix(parent, rank=None):
3413
r"""
3414
Create a matrix of the designated size and rank whose right and
3415
left null spaces, column space, and row space have desirable
3416
properties that simplify the subspaces.
3417
3418
INPUT:
3419
3420
- ``parent`` - A matrix space specifying the base ring, dimensions, and
3421
representation (dense/sparse) for the result. The base ring must be exact.
3422
3423
- ``rank`` - The desired rank of the return matrix (default: None).
3424
3425
OUTPUT:
3426
3427
A matrix whose natrual basis vectors for its four subspaces, when
3428
computed, have reasonably sized, integral valued, entries.
3429
3430
.. note::
3431
3432
It is easiest to use this function via a call to the
3433
:func:`~sage.matrix.constructor.random_matrix`
3434
function with the ``algorithm='subspaces'`` keyword. We provide
3435
one example accessing this function directly, while the remainder will
3436
use this more general function.
3437
3438
EXAMPLES:
3439
3440
A 6x8 matrix with designated rank of 3. The four subspaces are
3441
determined using one simple routine in which we augment the
3442
original matrix with the equal row dimension identity matrix. The
3443
resulting matrix is then put in reduced row-echelon form and the
3444
subspaces can then be determined by analyzing subdivisions of this
3445
matrix. See the four subspaces routine in [BEEZER]_ for more. ::
3446
3447
sage: from sage.matrix.constructor import random_subspaces_matrix
3448
sage: matrix_space = sage.matrix.matrix_space.MatrixSpace(QQ, 6, 8)
3449
sage: B=random_subspaces_matrix(matrix_space, rank=3); B # random
3450
[ 113 339 -46 218 -243 641 -269 -306]
3451
[ -33 -99 13 -63 69 -185 77 90]
3452
[ 35 105 -14 67 -74 197 -82 -95]
3453
[ -18 -54 7 -34 37 -100 41 49]
3454
[ -26 -78 10 -49 53 -144 59 71]
3455
[ -8 -24 3 -15 16 -44 18 22]
3456
sage: B.rank()
3457
3
3458
sage: B.nullity()
3459
3
3460
sage: (B.nrows(), B.ncols())
3461
(6, 8)
3462
sage: all([x in ZZ for x in B.list()])
3463
True
3464
sage: B_expanded=B.augment(identity_matrix(6)).rref()
3465
sage: all([x in ZZ for x in B_expanded.list()])
3466
True
3467
sage: B_expanded # random
3468
[ 1 3 0 0 1 1 3 -2 0 0 -3 0 -9 16]
3469
[ 0 0 1 0 3 -2 -1 -3 0 0 2 0 11 -27]
3470
[ 0 0 0 1 -1 2 -3 -1 0 0 2 0 7 -14]
3471
[ 0 0 0 0 0 0 0 0 1 0 -5 0 -3 2]
3472
[ 0 0 0 0 0 0 0 0 0 1 1 0 1 -3]
3473
[ 0 0 0 0 0 0 0 0 0 0 0 1 -1 1]
3474
3475
Check that we fixed Trac #10543 (echelon forms should be immutable)::
3476
3477
sage: B_expanded.is_immutable()
3478
True
3479
3480
We want to modify B_expanded, so replace it with a copy::
3481
3482
sage: B_expanded = copy(B_expanded)
3483
sage: B_expanded.subdivide(B.nrows()-B.nullity(),B.ncols());B_expanded # random
3484
[ 1 3 0 0 1 1 3 -2| 0 0 -3 0 -9 16]
3485
[ 0 0 1 0 3 -2 -1 -3| 0 0 2 0 11 -27]
3486
[ 0 0 0 1 -1 2 -3 -1| 0 0 2 0 7 -14]
3487
[-------------------------------+-----------------------]
3488
[ 0 0 0 0 0 0 0 0| 1 0 -5 0 -3 2]
3489
[ 0 0 0 0 0 0 0 0| 0 1 1 0 1 -3]
3490
[ 0 0 0 0 0 0 0 0| 0 0 0 1 -1 1]
3491
sage: C=B_expanded.subdivision(0,0)
3492
sage: C # random
3493
[ 1 3 0 0 1 1 3 -2]
3494
[ 0 0 1 0 3 -2 -1 -3]
3495
[ 0 0 0 1 -1 2 -3 -1]
3496
sage: L=B_expanded.subdivision(1,1)
3497
sage: L # random
3498
[ 1 0 -5 0 -3 2]
3499
[ 0 1 1 0 1 -3]
3500
[ 0 0 0 1 -1 1]
3501
sage: B.right_kernel()==C.right_kernel()
3502
True
3503
sage: B.row_space()==C.row_space()
3504
True
3505
sage: B.column_space()==L.right_kernel()
3506
True
3507
sage: B.left_kernel()==L.row_space()
3508
True
3509
3510
A matrix to show that the null space of the L matrix is the column space of the starting matrix. ::
3511
3512
sage: A=random_matrix(QQ, 5, 7, algorithm='subspaces', rank=None); A # random
3513
[-31 12 -9 -27 21 2 -15]
3514
[105 -24 6 103 -30 -34 79]
3515
[ 29 -9 5 26 -14 -5 17]
3516
[233 -55 16 228 -71 -73 173]
3517
[-42 10 -3 -41 13 13 -31]
3518
sage: (A.nrows(), A.ncols())
3519
(5, 7)
3520
sage: all([x in ZZ for x in A.list()])
3521
True
3522
sage: A.nullity() # random
3523
1
3524
sage: A_expanded=A.augment(identity_matrix(5)).rref()
3525
sage: A_expanded # random
3526
[ 1 0 0 0 0 1 0 0 3 7 25 151]
3527
[ 0 1 0 0 1 2 1 0 5 21 84 493]
3528
[ 0 0 1 0 -1 2 0 0 2 13 53 308]
3529
[ 0 0 0 1 0 -1 1 0 -2 -3 -9 -57]
3530
[ 0 0 0 0 0 0 0 1 -3 1 1 -2]
3531
sage: all([x in ZZ for x in A_expanded.list()])
3532
True
3533
sage: C=A_expanded.submatrix(0,0,A.nrows()-A.nullity(),A.ncols())
3534
sage: L=A_expanded.submatrix(A.nrows()-A.nullity(),A.ncols())
3535
sage: A.right_kernel()==C.right_kernel()
3536
True
3537
sage: A.row_space()==C.row_space()
3538
True
3539
sage: A.column_space()==L.right_kernel()
3540
True
3541
sage: A.left_kernel()==L.row_space()
3542
True
3543
3544
TESTS:
3545
3546
The designated rank of the L matrix cannot be greater than the
3547
number of desired rows, nor can the rank be negative. ::
3548
3549
sage: random_matrix(QQ, 19, 20, algorithm='subspaces', rank=21)
3550
Traceback (most recent call last):
3551
...
3552
ValueError: rank cannot exceed the number of rows or columns.
3553
sage: random_matrix(QQ, 19, 20, algorithm='subspaces', rank=-1)
3554
Traceback (most recent call last):
3555
...
3556
ValueError: matrices must have rank zero or greater.
3557
3558
REFERENCES:
3559
3560
.. [BEEZER] `A First Course in Linear Algebra <http://linear.ups.edu/>`_.
3561
Robert A. Beezer, accessed 15 July 2010.
3562
3563
AUTHOR:
3564
3565
Billy Wonderly (2010-07)
3566
"""
3567
3568
import sage.gsl.probability_distribution as pd
3569
3570
ring = parent.base_ring()
3571
rows = parent.nrows()
3572
columns = parent.ncols()
3573
3574
# If rank is not designated, generate using probability distribution
3575
# skewing to smaller numbers, always at least 1.
3576
if rank is None:
3577
left_nullity_generator = pd.RealDistribution("beta", [1.4, 5.5])
3578
nullity = int(left_nullity_generator.get_random_element()*(rows-1) + 1)
3579
rank = rows - nullity
3580
if rank<0:
3581
raise ValueError("matrices must have rank zero or greater.")
3582
if rank > rows or rank > columns:
3583
raise ValueError("rank cannot exceed the number of rows or columns.")
3584
nullity = rows - rank
3585
B = random_matrix(ring, rows, columns, algorithm='echelon_form',
3586
num_pivots=rank)
3587
3588
# Create a nonsingular matrix whose columns will be used to stack a matrix
3589
# over the L matrix, forming a nonsingular matrix.
3590
K_nonzero_columns = random_matrix(ring, rank, rank,
3591
algorithm='echelonizable', rank=rank)
3592
K = matrix(QQ, rank, rows)
3593
L = random_matrix(ring, nullity, rows, algorithm='echelon_form',
3594
num_pivots=nullity)
3595
for column in range(len(L.nonpivots())):
3596
for entry in range(rank):
3597
K[entry, L.nonpivots()[column]] = K_nonzero_columns[entry, column]
3598
J = K.stack(L)
3599
3600
# By multiplying the B matrix by J.inverse() we hide the B matrix of the
3601
# solution using row operations required to change the solution K matrix to
3602
# the identity matrix.
3603
return J.inverse()*B
3604
3605
@matrix_method
3606
def random_unimodular_matrix(parent, upper_bound=None, max_tries=100):
3607
r"""
3608
Generate a random unimodular (determinant 1) matrix of a desired size over a desired ring.
3609
3610
INPUT:
3611
3612
- ``parent`` - A matrix space specifying the base ring, dimensions
3613
and representation (dense/sparse) for the result. The base ring
3614
must be exact.
3615
3616
- ``upper_bound`` - For large matrices over QQ or ZZ,
3617
``upper_bound`` is the largest value matrix entries can achieve. But
3618
see the warning below.
3619
3620
- ``max_tries`` - If designated, number of tries used to generate each new random row;
3621
only matters when upper_bound!=None. Used to prevent endless looping. (default: 100)
3622
3623
A matrix not in reduced row-echelon form with the desired dimensions and properties.
3624
3625
OUTPUT:
3626
3627
An invertible matrix with the desired properties and determinant 1.
3628
3629
.. warning::
3630
3631
When ``upper_bound`` is set, it is possible for this constructor to
3632
fail with a ``ValueError``. This may happen when the ``upper_bound``,
3633
``rank`` and/or matrix dimensions are all so small that it becomes
3634
infeasible or unlikely to create the requested matrix. If you *must*
3635
have this routine return successfully, do not set ``upper_bound``.
3636
3637
.. note::
3638
3639
It is easiest to use this function via a call to the
3640
:func:`~sage.matrix.constructor.random_matrix`
3641
function with the ``algorithm='unimodular'`` keyword. We provide
3642
one example accessing this function directly, while the remainder will
3643
use this more general function.
3644
3645
EXAMPLES:
3646
3647
A matrix size 5 over QQ. ::
3648
3649
sage: from sage.matrix.constructor import random_unimodular_matrix
3650
sage: matrix_space = sage.matrix.matrix_space.MatrixSpace(QQ, 5)
3651
sage: A=random_unimodular_matrix(matrix_space); A # random
3652
[ -8 31 85 148 -419]
3653
[ 2 -9 -25 -45 127]
3654
[ -1 10 30 65 -176]
3655
[ -3 12 33 58 -164]
3656
[ 5 -21 -59 -109 304]
3657
sage: det(A)
3658
1
3659
3660
A matrix size 6 with entries no larger than 50. ::
3661
3662
sage: B=random_matrix(ZZ, 7, algorithm='unimodular', upper_bound=50);B # random
3663
[ -1 0 3 1 -2 2 9]
3664
[ 1 2 -5 0 14 19 -49]
3665
[ -3 -2 12 5 -6 -4 24]
3666
[ 1 2 -9 -3 3 4 -7]
3667
[ -2 -1 7 2 -8 -5 31]
3668
[ 2 2 -6 -3 8 16 -32]
3669
[ 1 2 -9 -2 5 6 -12]
3670
sage: det(B)
3671
1
3672
3673
A matrix over the number Field in `y` with defining polynomial `y^2-2y-2`. ::
3674
3675
sage: y = var('y')
3676
sage: K=NumberField(y^2-2*y-2,'y')
3677
sage: C=random_matrix(K, 3, algorithm='unimodular');C # random
3678
[ 2*y - 33 681*y - 787 31*y - 37]
3679
[ y + 6 -155*y + 83 -7*y + 4]
3680
[ -y 24*y + 51 y + 3]
3681
sage: det(C)
3682
1
3683
3684
TESTS:
3685
3686
Unimodular matrices are square. ::
3687
3688
sage: random_matrix(QQ, 5, 6, algorithm='unimodular')
3689
Traceback (most recent call last):
3690
...
3691
TypeError: a unimodular matrix must be square.
3692
3693
Only matrices over ZZ and QQ can have size control. ::
3694
3695
sage: F.<a>=GF(5^7)
3696
sage: random_matrix(F, 5, algorithm='unimodular', upper_bound=20)
3697
Traceback (most recent call last):
3698
...
3699
TypeError: only matrices over ZZ or QQ can have size control.
3700
3701
AUTHOR:
3702
3703
Billy Wonderly (2010-07)
3704
"""
3705
3706
ring=parent.base_ring()
3707
size=parent.nrows()
3708
if parent.nrows()!=parent.ncols():
3709
raise TypeError("a unimodular matrix must be square.")
3710
if upper_bound!=None and (ring!=ZZ and ring!=QQ):
3711
raise TypeError("only matrices over ZZ or QQ can have size control.")
3712
if upper_bound==None:
3713
# random_echelonizable_matrix() always returns a determinant one matrix if given full rank.
3714
return random_matrix(ring, size, algorithm='echelonizable', rank=size)
3715
elif upper_bound!=None and (ring==ZZ or ring==QQ):
3716
return random_matrix(ring, size,algorithm='echelonizable',rank=size, upper_bound=upper_bound, max_tries=max_tries)
3717
3718
3719
@matrix_method
3720
def random_diagonalizable_matrix(parent,eigenvalues=None,dimensions=None):
3721
"""
3722
Create a random matrix that diagonalizes nicely.
3723
3724
To be used as a teaching tool. Return matrices have only real
3725
eigenvalues.
3726
3727
INPUT:
3728
3729
If eigenvalues and dimensions are not specified in a list,
3730
they will be assigned randomly.
3731
3732
- ``parent`` - the desired size of the square matrix.
3733
3734
- ``eigenvalues`` - the list of desired eigenvalues (default=None).
3735
3736
- ``dimensions`` - the list of dimensions corresponding to each
3737
eigenspace (default=None).
3738
3739
OUTPUT:
3740
3741
A square, diagonalizable, matrix with only integer entries. The
3742
eigenspaces of this matrix, if computed by hand, give basis
3743
vectors with only integer entries.
3744
3745
.. note::
3746
3747
It is easiest to use this function via a call to the
3748
:func:`~sage.matrix.constructor.random_matrix`
3749
function with the ``algorithm='diagonalizable'`` keyword. We provide
3750
one example accessing this function directly, while the remainder will
3751
use this more general function.
3752
3753
EXAMPLES:
3754
3755
A diagonalizable matrix, size 5. ::
3756
3757
sage: from sage.matrix.constructor import random_diagonalizable_matrix
3758
sage: matrix_space = sage.matrix.matrix_space.MatrixSpace(QQ, 5)
3759
sage: A=random_diagonalizable_matrix(matrix_space); A # random
3760
[ 10 18 8 4 -18]
3761
[ 20 10 8 4 -16]
3762
[-60 -54 -22 -12 18]
3763
[-60 -54 -24 -6 6]
3764
[-20 -18 -8 -4 8]
3765
sage: A.eigenvalues() # random
3766
[10,6,2,-8,-10]
3767
sage: S=A.right_eigenmatrix()[1]; S # random
3768
[ 1 1 1 1 0]
3769
[ 1 1 1 0 1]
3770
[-3 -3 -4 -3 -3]
3771
[-3 -4 -3 -3 -3]
3772
[-1 -1 -1 -1 -1]
3773
sage: S_inverse=S.inverse(); S_inverse # random
3774
[ 1 1 1 1 -5]
3775
[ 0 0 0 -1 3]
3776
[ 0 0 -1 0 3]
3777
[ 0 -1 0 0 -1]
3778
[-1 0 0 0 -1]
3779
sage: S_inverse*A*S # random
3780
[ 10 0 0 0 0]
3781
[ 0 6 0 0 0]
3782
[ 0 0 2 0 0]
3783
[ 0 0 0 -8 0]
3784
[ 0 0 0 0 -10]
3785
3786
A diagonalizable matrix with eigenvalues and dimensions designated,
3787
with a check that if eigenvectors were calculated by hand
3788
entries would all be integers. ::
3789
3790
sage: B=random_matrix(QQ, 6, algorithm='diagonalizable', eigenvalues=[-12,4,6],dimensions=[2,3,1]); B # random
3791
[ -52 32 240 -464 -96 -520]
3792
[ 6 4 -48 72 36 90]
3793
[ 46 -32 -108 296 -12 274]
3794
[ 24 -16 -64 164 0 152]
3795
[ 18 -16 0 72 -48 30]
3796
[ 2 0 -16 24 12 34]
3797
sage: all([x in ZZ for x in (B-(-12*identity_matrix(6))).rref().list()])
3798
True
3799
sage: all([x in ZZ for x in (B-(4*identity_matrix(6))).rref().list()])
3800
True
3801
sage: all([x in ZZ for x in (B-(6*identity_matrix(6))).rref().list()])
3802
True
3803
sage: S=B.right_eigenmatrix()[1]; S_inverse=S.inverse(); S_inverse*B*S # random
3804
[ 6 0 0 0 0 0]
3805
[ 0 -12 0 0 0 0]
3806
[ 0 0 -12 0 0 0]
3807
[ 0 0 0 4 0 0]
3808
[ 0 0 0 0 4 0]
3809
[ 0 0 0 0 0 4]
3810
3811
TESTS:
3812
3813
Eigenvalues must all be integers. ::
3814
3815
sage: random_matrix(QQ,3,algorithm='diagonalizable', eigenvalues=[2+I,2-I,2],dimensions=[1,1,1])
3816
Traceback (most recent call last):
3817
...
3818
TypeError: eigenvalues must be integers.
3819
3820
Diagonal matrices must be square. ::
3821
3822
sage: random_matrix(QQ, 5, 7, algorithm='diagonalizable', eigenvalues=[-5,2,-3], dimensions=[1,1,3])
3823
Traceback (most recent call last):
3824
...
3825
TypeError: a diagonalizable matrix must be square.
3826
3827
A list of eigenvalues must be accompanied with a list of dimensions. ::
3828
3829
sage: random_matrix(QQ,10,algorithm='diagonalizable',eigenvalues=[4,8])
3830
Traceback (most recent call last):
3831
...
3832
ValueError: the list of eigenvalues must have a list of dimensions corresponding to each eigenvalue.
3833
3834
A list of dimensions must be accompanied with a list of eigenvalues. ::
3835
3836
sage: random_matrix(QQ, 10,algorithm='diagonalizable',dimensions=[2,2,4,2])
3837
Traceback (most recent call last):
3838
...
3839
ValueError: the list of dimensions must have a list of corresponding eigenvalues.
3840
3841
The sum of the eigenvalue dimensions must equal the size of the matrix. ::
3842
3843
sage: random_matrix(QQ,12,algorithm='diagonalizable',eigenvalues=[4,2,6,-1],dimensions=[2,3,5,1])
3844
Traceback (most recent call last):
3845
...
3846
ValueError: the size of the matrix must equal the sum of the dimensions.
3847
3848
Each eigenspace dimension must be at least 1. ::
3849
3850
sage: random_matrix(QQ,9,algorithm='diagonalizable',eigenvalues=[-15,22,8,-4,90,12],dimensions=[4,2,2,4,-3,0])
3851
Traceback (most recent call last):
3852
...
3853
ValueError: eigenspaces must have a dimension of at least 1.
3854
3855
Each eigenvalue must have a corresponding eigenspace dimension. ::
3856
3857
sage: random_matrix(QQ,12,algorithm='diagonalizable',eigenvalues=[4,2,6,-1],dimensions=[4,3,5])
3858
Traceback (most recent call last):
3859
...
3860
ValueError: each eigenvalue must have a corresponding dimension and each dimension a corresponding eigenvalue.
3861
3862
Each dimension must have an eigenvalue paired to it. ::
3863
3864
sage: random_matrix(QQ,12,algorithm='diagonalizable',eigenvalues=[4,2,6],dimensions=[2,3,5,2])
3865
Traceback (most recent call last):
3866
...
3867
ValueError: each eigenvalue must have a corresponding dimension and each dimension a corresponding eigenvalue.
3868
3869
TODO:
3870
3871
Modify the routine to allow for complex eigenvalues.
3872
3873
AUTHOR:
3874
3875
Billy Wonderly (2010-07)
3876
"""
3877
3878
from sage.misc.prandom import randint
3879
3880
size=parent.nrows()
3881
if parent.nrows()!=parent.ncols():
3882
raise TypeError("a diagonalizable matrix must be square.")
3883
if eigenvalues!=None and dimensions==None:
3884
raise ValueError("the list of eigenvalues must have a list of dimensions corresponding to each eigenvalue.")
3885
if eigenvalues==None and dimensions!=None:
3886
raise ValueError("the list of dimensions must have a list of corresponding eigenvalues.")
3887
if eigenvalues==None and dimensions==None:
3888
values=[]
3889
#create a list with "size" number of entries
3890
for eigen_index in range(size):
3891
eigenvalue=randint(-10,10)
3892
values.append(eigenvalue)
3893
values.sort()
3894
dimensions=[]
3895
eigenvalues=[]
3896
#create a list with no duplicate values to be the eigenvalues
3897
for eigenvalue in range(size):
3898
if values[eigenvalue] not in eigenvalues:
3899
eigenvalues.append(values[eigenvalue])
3900
for dimension in range(len(eigenvalues)):
3901
#dimension is equal to how many times an eigenvalue was generated in the 'values' list
3902
dimensions.append(values.count(eigenvalues[dimension]))
3903
size_check=0
3904
for check in range(len(dimensions)):
3905
size_check=size_check+dimensions[check]
3906
if not map(lambda x: x in ZZ, eigenvalues)==[True]*len(eigenvalues):
3907
raise TypeError("eigenvalues must be integers.")
3908
if size!=size_check:
3909
raise ValueError("the size of the matrix must equal the sum of the dimensions.")
3910
if min(dimensions)<1:
3911
raise ValueError("eigenspaces must have a dimension of at least 1.")
3912
if len(eigenvalues)!=len(dimensions):
3913
raise ValueError("each eigenvalue must have a corresponding dimension and each dimension a corresponding eigenvalue.")
3914
#sort the dimensions in order of increasing size, and sort the eigenvalues list in an identical fashion, to maintain corresponding values.
3915
dimensions_sort=zip(dimensions,eigenvalues)
3916
dimensions_sort.sort()
3917
dimensions=[x[0] for x in dimensions_sort]
3918
eigenvalues=[x[1] for x in dimensions_sort]
3919
#Create the matrix of eigenvalues on the diagonal. Use a lower limit and upper limit determined by the eigenvalue dimensions.
3920
diagonal_matrix=matrix(QQ,size)
3921
up_bound=0
3922
low_bound=0
3923
for row_index in range(len(dimensions)):
3924
up_bound=up_bound+dimensions[row_index]
3925
for entry in range(low_bound,up_bound):
3926
diagonal_matrix[entry,entry]=eigenvalues[row_index]
3927
low_bound=low_bound+dimensions[row_index]
3928
# Create a matrix to hold each of the eigenvectors as its columns, begin with an identity matrix so that after row and column
3929
# operations the resulting matrix will be unimodular.
3930
eigenvector_matrix=matrix(QQ,size,size,1)
3931
upper_limit=0
3932
lower_limit=0
3933
#run the routine over the necessary number of columns corresponding eigenvalue dimension.
3934
for dimension_index in range(len(dimensions)-1):
3935
upper_limit=upper_limit+dimensions[dimension_index]
3936
lowest_index_row_with_one=size-dimensions[dimension_index]
3937
#assign a one to the row that is the eigenvalue dimension rows up from the bottom row then assign ones diagonally down to the right.
3938
for eigen_ones in range(lower_limit,upper_limit):
3939
eigenvector_matrix[lowest_index_row_with_one,eigen_ones]=1
3940
lowest_index_row_with_one+=1
3941
lower_limit=lower_limit+dimensions[dimension_index]
3942
#Create a list to give the eigenvalue dimension corresponding to each column.
3943
dimension_check=[]
3944
for i in range(len(dimensions)):
3945
for k in range(dimensions[i]):
3946
dimension_check.append(dimensions[i])
3947
#run routine over the rows that are in the range of the protected ones. Use addition of column multiples to fill entries.
3948
for dimension_multiplicity in range(max(dimensions),min(dimensions),-1):
3949
highest_one_row=size-dimension_multiplicity
3950
highest_one_column=0
3951
#find the column with the protected one in the lowest indexed row.
3952
while eigenvector_matrix[highest_one_row,highest_one_column]==0:
3953
highest_one_column+=1
3954
#dimension_check determines if column has a low enough eigenvalue dimension to take a column multiple.
3955
for bottom_entry_filler in range(len(dimension_check)):
3956
if dimension_check[bottom_entry_filler]<dimension_multiplicity and eigenvector_matrix[highest_one_row,bottom_entry_filler]==0:
3957
# randint range determined experimentally to keep entries manageable.
3958
eigenvector_matrix.add_multiple_of_column(bottom_entry_filler,highest_one_column,randint(-4,4))
3959
#Fill remaining rows using scalar row addition.
3960
for row in range(size-max(dimensions),size):
3961
for upper_row in range(size-max(dimensions)):
3962
# range of multiplier determined experimentally so that entries stay manageable for small matrices
3963
eigenvector_matrix.add_multiple_of_row(upper_row,row,randint(-4,4))
3964
return eigenvector_matrix*diagonal_matrix*(eigenvector_matrix.inverse())
3965
3966
3967
@matrix_method
3968
def vector_on_axis_rotation_matrix(v, i, ring=None):
3969
r"""
3970
Return a rotation matrix `M` such that `det(M)=1` sending the vector
3971
`v` on the i-th axis so that all other coordinates of `Mv` are zero.
3972
3973
.. NOTE::
3974
3975
Such a matrix is not uniquely determined. This function returns one
3976
such matrix.
3977
3978
INPUT:
3979
3980
- ``v``` - vector
3981
- ``i`` - integer
3982
- ``ring`` - ring (optional, default: None) of the resulting matrix
3983
3984
OUTPUT:
3985
3986
A matrix
3987
3988
EXAMPLES::
3989
3990
sage: from sage.matrix.constructor import vector_on_axis_rotation_matrix
3991
sage: v = vector((1,2,3))
3992
sage: vector_on_axis_rotation_matrix(v, 2) * v
3993
(0, 0, sqrt(14))
3994
sage: vector_on_axis_rotation_matrix(v, 1) * v
3995
(0, sqrt(14), 0)
3996
sage: vector_on_axis_rotation_matrix(v, 0) * v
3997
(sqrt(14), 0, 0)
3998
3999
::
4000
4001
sage: x,y = var('x,y')
4002
sage: v = vector((x,y))
4003
sage: vector_on_axis_rotation_matrix(v, 1)
4004
[ y/sqrt(x^2 + y^2) -x/sqrt(x^2 + y^2)]
4005
[ x/sqrt(x^2 + y^2) y/sqrt(x^2 + y^2)]
4006
sage: vector_on_axis_rotation_matrix(v, 0)
4007
[ x/sqrt(x^2 + y^2) y/sqrt(x^2 + y^2)]
4008
[-y/sqrt(x^2 + y^2) x/sqrt(x^2 + y^2)]
4009
sage: vector_on_axis_rotation_matrix(v, 0) * v
4010
(x^2/sqrt(x^2 + y^2) + y^2/sqrt(x^2 + y^2), 0)
4011
sage: vector_on_axis_rotation_matrix(v, 1) * v
4012
(0, x^2/sqrt(x^2 + y^2) + y^2/sqrt(x^2 + y^2))
4013
4014
::
4015
4016
sage: v = vector((1,2,3,4))
4017
sage: vector_on_axis_rotation_matrix(v, 0) * v
4018
(sqrt(30), 0, 0, 0)
4019
sage: vector_on_axis_rotation_matrix(v, 0, ring=RealField(10))
4020
[ 0.18 0.37 0.55 0.73]
4021
[-0.98 0.068 0.10 0.14]
4022
[ 0.00 -0.93 0.22 0.30]
4023
[ 0.00 0.00 -0.80 0.60]
4024
sage: vector_on_axis_rotation_matrix(v, 0, ring=RealField(10)) * v
4025
(5.5, 0.00098, 0.00098, 0.00)
4026
4027
AUTHORS:
4028
4029
Sebastien Labbe (April 2010)
4030
"""
4031
dim = len(v)
4032
v = vector(v)
4033
m = identity_matrix(dim, sparse=True)
4034
L = range(i-1, -1, -1) + range(dim-1,i,-1)
4035
for i in L:
4036
rot = ith_to_zero_rotation_matrix(v, i, ring=ring)
4037
v = rot * v
4038
m = rot * m
4039
return m
4040
4041
4042
@matrix_method
4043
def ith_to_zero_rotation_matrix(v, i, ring=None):
4044
r"""
4045
Return a rotation matrix that sends the i-th coordinates of the
4046
vector v to zero by doing a rotation with the (i-1)-th coordinate.
4047
4048
INPUT:
4049
4050
- ``v``` - vector
4051
- ``i`` - integer
4052
- ``ring`` - ring (optional, default: None) of the resulting matrix
4053
4054
OUTPUT:
4055
4056
A matrix
4057
4058
EXAMPLES::
4059
4060
sage: from sage.matrix.constructor import ith_to_zero_rotation_matrix
4061
sage: v = vector((1,2,3))
4062
sage: ith_to_zero_rotation_matrix(v, 2)
4063
[ 1 0 0]
4064
[ 0 2/13*sqrt(13) 3/13*sqrt(13)]
4065
[ 0 -3/13*sqrt(13) 2/13*sqrt(13)]
4066
sage: ith_to_zero_rotation_matrix(v, 2) * v
4067
(1, sqrt(13), 0)
4068
4069
::
4070
4071
sage: ith_to_zero_rotation_matrix(v, 0)
4072
[ 3/10*sqrt(10) 0 -1/10*sqrt(10)]
4073
[ 0 1 0]
4074
[ 1/10*sqrt(10) 0 3/10*sqrt(10)]
4075
sage: ith_to_zero_rotation_matrix(v, 1)
4076
[ 1/5*sqrt(5) 2/5*sqrt(5) 0]
4077
[-2/5*sqrt(5) 1/5*sqrt(5) 0]
4078
[ 0 0 1]
4079
sage: ith_to_zero_rotation_matrix(v, 2)
4080
[ 1 0 0]
4081
[ 0 2/13*sqrt(13) 3/13*sqrt(13)]
4082
[ 0 -3/13*sqrt(13) 2/13*sqrt(13)]
4083
4084
::
4085
4086
sage: ith_to_zero_rotation_matrix(v, 0) * v
4087
(0, 2, sqrt(10))
4088
sage: ith_to_zero_rotation_matrix(v, 1) * v
4089
(sqrt(5), 0, 3)
4090
sage: ith_to_zero_rotation_matrix(v, 2) * v
4091
(1, sqrt(13), 0)
4092
4093
Other ring::
4094
4095
sage: ith_to_zero_rotation_matrix(v, 2, ring=RR)
4096
[ 1.00000000000000 0.000000000000000 0.000000000000000]
4097
[ 0.000000000000000 0.554700196225229 0.832050294337844]
4098
[ 0.000000000000000 -0.832050294337844 0.554700196225229]
4099
sage: ith_to_zero_rotation_matrix(v, 2, ring=RDF)
4100
[ 1.0 0.0 0.0]
4101
[ 0.0 0.554700196225 0.832050294338]
4102
[ 0.0 -0.832050294338 0.554700196225]
4103
4104
On the symbolic ring::
4105
4106
sage: x,y,z = var('x,y,z')
4107
sage: v = vector((x,y,z))
4108
sage: ith_to_zero_rotation_matrix(v, 2)
4109
[ 1 0 0]
4110
[ 0 y/sqrt(y^2 + z^2) z/sqrt(y^2 + z^2)]
4111
[ 0 -z/sqrt(y^2 + z^2) y/sqrt(y^2 + z^2)]
4112
sage: ith_to_zero_rotation_matrix(v, 2) * v
4113
(x, y^2/sqrt(y^2 + z^2) + z^2/sqrt(y^2 + z^2), 0)
4114
4115
TESTS::
4116
4117
sage: ith_to_zero_rotation_matrix((1,0,0), 0)
4118
[ 0 0 -1]
4119
[ 0 1 0]
4120
[ 1 0 0]
4121
sage: ith_to_zero_rotation_matrix((1,0,0), 1)
4122
[1 0 0]
4123
[0 1 0]
4124
[0 0 1]
4125
sage: ith_to_zero_rotation_matrix((1,0,0), 2)
4126
[1 0 0]
4127
[0 1 0]
4128
[0 0 1]
4129
4130
AUTHORS:
4131
4132
Sebastien Labbe (April 2010)
4133
"""
4134
if not ring is None:
4135
# coerce the vector so that computations
4136
# are done in that ring
4137
v = vector(ring, v)
4138
dim = len(v)
4139
i = i % dim
4140
j = (i-1) % dim
4141
a, b = v[j], v[i]
4142
if b == 0:
4143
return identity_matrix(dim, sparse=True)
4144
from sage.functions.all import sqrt
4145
norm = sqrt(a*a + b*b)
4146
aa = a / norm
4147
bb = b / norm
4148
entries = {}
4149
for k in range(dim):
4150
entries[(k, k)] = 1
4151
entries.update({(j,j):aa, (j,i):bb, (i,j):-bb, (i,i):aa})
4152
return matrix(entries, nrows=dim, ring=ring)
4153
4154
4155
4156
4157