Generating not-so-much-random matrices
I’ve been using sage for a while now. I’ve also been teaching linear algebra for a few years. One of the problems in teaching linear algebra is coming up with a handful of examples of matrices that can nicely be row-reduced. One way to do this is to start with your “nice” row-reduced matrix and take a few (or many) “nice” elementary matrices and there is your example. So, one might want to code this in sage. I just recently found out that actually sage has such a function built in it. For example,
random_matrix(ZZ,4,5,algorithm='echelonizable',rank=3, upper_bound=7)
will create a random $4 \times 5$ matrix with rank $3$, integer entries (that’s the ZZ), and entries no bigger than $7$, which can “nicely” be turned into rref. So, here it is in sage cell server. I think this is a good thing to share with students so they can practice as many times as they want.
For the same reasons when generating a random matrix to find its inverse, we usually want a matrix with small-ish integer entries such that the inverse also has relatively small integer entries. It is easy to see that for a matrix $A$ with integer entries to have an inverse with integer entries, it is necessary that its determinant is $\pm 1$. It turns out that it is the sufficient condition too, surprisingly, thanks to Cramer’s rule! Though it might lose some pedagogical purposes, like relating the inverse to the determinant, but here is a code that generates random matrices with integer entries where their inverses also have integer entries:
random_matrix(ZZ,3,algorithm='unimodular',upper_bound=6)
To play around with it in sage cell server click here.
[ Ref: https://blogs.uoregon.edu/math341fa15lipshitz/issue-summary/random-matrices-for-practice ]
The sage documentation says:
Warning: Matrices generated are not uniformly distributed. For unimodular matrices over finite field this function does not even generate all of them: for example “Matrix.random(GF(3), 2, algorithm=’unimodular’)” never generates “[[2,0],[0,2]]”. This function is made for teaching purposes.
And
Random matrices in echelon form. The “algorithm=’echelon_form’” keyword, along with a requested number of non-zero rows (“num_pivots”) will return a random matrix in echelon form. When the base ring is “QQ” the result has integer entries. Other exact rings may be also specified.
sage: A=random_matrix(QQ, 4, 8, algorithm='echelon_form', num_pivots=3); A # random
[ 1 -5 0 -2 0 1 1 -2]
[ 0 0 1 -5 0 -3 -1 0]
[ 0 0 0 0 1 2 -2 1]
[ 0 0 0 0 0 0 0 0]
sage: A.base_ring()
Rational Field
sage: (A.nrows(), A.ncols())
(4, 8)
sage: A in sage.matrix.matrix_space.MatrixSpace(ZZ, 4, 8)
True
sage: A.rank()
3
sage: A==A.rref()
True
For more, see the documentation of the “random_rref_matrix()” function. In the notebook or at the Sage command-line, first execute the following to make this further documentation available:
from sage.matrix.constructor import random_rref_matrix
Random matrices with predictable echelon forms. The “algorithm=’echelonizable’” keyword, along with a requested rank (“rank”) and optional size control (“upper_bound”) will return a random matrix in echelon form. When the base ring is “ZZ” or “QQ” the result has integer entries, whose magnitudes can be limited by the value of “upper_bound”, and the echelon form of the matrix also has integer entries. Other exact rings may be also specified, but there is no notion of controlling the size. Square matrices of full rank generated by this function always have determinant one, and can be constructed with the “unimodular” keyword.
sage: A=random_matrix(QQ, 4, 8, algorithm='echelonizable', rank=3, upper_bound=60); A # random
sage: A.base_ring()
Rational Field
sage: (A.nrows(), A.ncols())
(4, 8)
sage: A in sage.matrix.matrix_space.MatrixSpace(ZZ, 4, 8)
True
sage: A.rank()
3
sage: all([abs(x)<60 for x in A.list()])
True
sage: A.rref() in sage.matrix.matrix_space.MatrixSpace(ZZ, 4, 8)
True
For more, see the documentation of the “random_echelonizable_matrix()” function. In the notebook or at the Sage command-line, first execute the following to make this further documentation available:
from sage.matrix.constructor import random_echelonizable_matrix
The “x” and “y” keywords can be used to distribute entries uniformly. When both are used “x” is the minimum and “y” is one greater than the maximum.
sage: random_matrix(ZZ, 4, 8, x=70, y=100)
[81 82 70 81 78 71 79 94]
[80 98 89 87 91 94 94 77]
[86 89 85 92 95 94 72 89]
[78 80 89 82 94 72 90 92]</pre>
If only “x” is given, then it is used as the upper bound of a range starting at 0.
sage: random_matrix(ZZ, 5, 5, x=25)
[20 16 8 3 8]
[ 8 2 2 14 5]
[18 18 10 20 11]
[19 16 17 15 7]
[ 0 24 3 17 24]</pre>
To control the number of nonzero entries, use the “density” keyword at a value strictly below the default of 1.0. The “density” keyword is used to compute the number of entries that will be nonzero, but the same entry may be selected more than once. So the value provided will be an upper bound for the density of the created matrix. Note that for a square matrix it is only necessary to set a single dimension.
sage: random_matrix(ZZ, 5, x=-10, y=10, density=0.75)
[-6 1 0 0 0]
[ 9 0 0 4 1]
[-6 0 0 -8 0]
[ 0 4 0 6 0]
[ 1 -9 0 0 -8]</pre>
For a matrix with low density it may be advisable to insist on a sparse representation, as this representation is not selected automatically.
sage: random_matrix(ZZ, 5, 5, density=0.3, sparse=True)
[ 4 0 0 0 -1]
[ 0 0 0 0 -7]
[ 0 0 2 0 0]
[ 0 0 1 0 -4]
[ 0 0 0 0 0]</pre>
Random rational matrices: sage: random_matrix(QQ, 2, 8, num_bound=20, den_bound=4) [ -1/2 6 13 -12 -2/3 -1/4 5 5] [ -9/2 5/3 19 15/2 19/2 20/3 -13/4 0]
Random matrices over other rings. Several classes of matrices have specialized “randomize()” methods. You can locate these with the Sage command:
search_def('randomize')</pre>
Leave a comment