Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

The documentation of random_matrix contains the information:

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.

So the matrix A constructed above is a matrix with entries in $\mathbb Z$ (and base ring $\mathbb Q$) and determinant $$\det A = 1\ .$$ Since the inverse of $A$ is the "adjoint matrix", A.adjoint(), we have the information that the entries of $A^{-1}$ are integers. This information is important in the context of the question, since we get first and approximative inverse, having entries very closed to some integers, then we round.

In an explicit example:

This time i have got:

sage: A = random_matrix(QQ, 6, algorithm='echelonizable', rank=6, upper_bound=9)
sage: A

[ 1  0  2  2 -2  5]
[-1  0 -2 -3  3 -5]
[-1 -1  0 -4  5  5]
[ 0  1 -1  4 -5 -5]
[ 0  0  2  6 -5  5]
[ 1  1  0 -1 -1  1]

As promised:

sage: A.inverse() == A.adjoint()
True

but we do not print either one... Instead, let us associate:

sage: B = A.change_ring(RDF)
sage: U, S, V = B.SVD()

The matrices $U,V$ are orthogonal, so the transposed are the inverses:

sage: (U*U.transpose()).round()

[ 1.0 -0.0 -0.0  0.0  0.0 -0.0]
[-0.0  1.0  0.0 -0.0  0.0  0.0]
[-0.0  0.0  1.0  0.0 -0.0  0.0]
[ 0.0 -0.0  0.0  1.0 -0.0  0.0]
[ 0.0  0.0 -0.0 -0.0  1.0  0.0]
[-0.0  0.0  0.0  0.0  0.0  1.0]
sage: (V*V.transpose()).round()

[ 1.0 -0.0  0.0  0.0  0.0 -0.0]
[-0.0  1.0  0.0  0.0  0.0  0.0]
[ 0.0  0.0  1.0 -0.0 -0.0  0.0]
[ 0.0  0.0 -0.0  1.0 -0.0  0.0]
[ 0.0  0.0 -0.0 -0.0  1.0  0.0]
[-0.0  0.0  0.0  0.0  0.0  1.0]

The matrix $S$ contains on the diagonal the singular values, we can check for instance:

sage: B.singular_values()

[13.351058796439338,
 11.46537265710543,
 2.4430917321568475,
 1.1384557335300527,
 0.1717356340018411,
 0.013676651355763396]
sage: S.round()

[13.0  0.0  0.0  0.0  0.0  0.0]
[ 0.0 11.0  0.0  0.0  0.0  0.0]
[ 0.0  0.0  2.0  0.0  0.0  0.0]
[ 0.0  0.0  0.0  1.0  0.0  0.0]
[ 0.0  0.0  0.0  0.0  0.0  0.0]
[ 0.0  0.0  0.0  0.0  0.0  0.0]

(No space to show $S$ here...) Inverting $S$ is easy. So we build the inverse of $B=USV'$, which is $VS^{-1}U'$. The entries of this matrix are

sage: C = VS.inverse()U.transpose() sage: C

[-28.000000000000274 -17.000000000000092 -7.0000000000001155 -12.000000000000169   5.000000000000092   5.000000000000067]
[  -18.0000000000002  -7.000000000000057  -6.000000000000087 -10.000000000000128   6.000000000000075   5.000000000000055]
[ 28.000000000000302   17.00000000000011   6.000000000000119  11.000000000000178  -5.000000000000096  -5.000000000000072]
[-26.000000000000284 -14.000000000000098  -7.000000000000118 -12.000000000000174   6.000000000000098   5.000000000000072]
[-25.000000000000263 -13.000000000000085  -7.000000000000111 -12.000000000000163   6.000000000000092  5.0000000000000675]
[ -5.000000000000057 -3.0000000000000213  -1.000000000000022 -2.0000000000000333   1.000000000000018  1.0000000000000135]

and we round:

sage: C.round()

[-28.0 -17.0  -7.0 -12.0   5.0   5.0]
[-18.0  -7.0  -6.0 -10.0   6.0   5.0]
[ 28.0  17.0   6.0  11.0  -5.0  -5.0]
[-26.0 -14.0  -7.0 -12.0   6.0   5.0]
[-25.0 -13.0  -7.0 -12.0   6.0   5.0]
[ -5.0  -3.0  -1.0  -2.0   1.0   1.0]
sage: C.round().change_ring(ZZ)

[-28 -17  -7 -12   5   5]
[-18  -7  -6 -10   6   5]
[ 28  17   6  11  -5  -5]
[-26 -14  -7 -12   6   5]
[-25 -13  -7 -12   6   5]
[ -5  -3  -1  -2   1   1]
sage: C.round().change_ring(ZZ) == A.inverse()
True

The documentation of random_matrix contains the information:

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.

So the matrix A constructed above is a matrix with entries in $\mathbb Z$ (and base ring $\mathbb Q$) and determinant $$\det A = 1\ .$$ Since the inverse of $A$ is the "adjoint matrix", A.adjoint(), we have the information that the entries of $A^{-1}$ are integers. This information is important in the context of the question, since we get first and approximative inverse, having entries very closed to some integers, then we round.

In an explicit example:

This time i have got:

sage: A = random_matrix(QQ, 6, algorithm='echelonizable', rank=6, upper_bound=9)
sage: A

[ 1  0  2  2 -2  5]
[-1  0 -2 -3  3 -5]
[-1 -1  0 -4  5  5]
[ 0  1 -1  4 -5 -5]
[ 0  0  2  6 -5  5]
[ 1  1  0 -1 -1  1]

As promised:

sage: A.inverse() == A.adjoint()
True

but we do not print either one... Instead, let us associate:

sage: B = A.change_ring(RDF)
sage: U, S, V = B.SVD()

The matrices $U,V$ are orthogonal, so the transposed are the inverses:

sage: (U*U.transpose()).round()

[ 1.0 -0.0 -0.0  0.0  0.0 -0.0]
[-0.0  1.0  0.0 -0.0  0.0  0.0]
[-0.0  0.0  1.0  0.0 -0.0  0.0]
[ 0.0 -0.0  0.0  1.0 -0.0  0.0]
[ 0.0  0.0 -0.0 -0.0  1.0  0.0]
[-0.0  0.0  0.0  0.0  0.0  1.0]
sage: (V*V.transpose()).round()

[ 1.0 -0.0  0.0  0.0  0.0 -0.0]
[-0.0  1.0  0.0  0.0  0.0  0.0]
[ 0.0  0.0  1.0 -0.0 -0.0  0.0]
[ 0.0  0.0 -0.0  1.0 -0.0  0.0]
[ 0.0  0.0 -0.0 -0.0  1.0  0.0]
[-0.0  0.0  0.0  0.0  0.0  1.0]

The matrix $S$ contains on the diagonal the singular values, we can check for instance:

sage: B.singular_values()

[13.351058796439338,
 11.46537265710543,
 2.4430917321568475,
 1.1384557335300527,
 0.1717356340018411,
 0.013676651355763396]
sage: S.round()

[13.0  0.0  0.0  0.0  0.0  0.0]
[ 0.0 11.0  0.0  0.0  0.0  0.0]
[ 0.0  0.0  2.0  0.0  0.0  0.0]
[ 0.0  0.0  0.0  1.0  0.0  0.0]
[ 0.0  0.0  0.0  0.0  0.0  0.0]
[ 0.0  0.0  0.0  0.0  0.0  0.0]

(No space to show $S$ here...) Inverting $S$ is easy. So we build the inverse of $B=USV'$, which is $VS^{-1}U'$. The entries of this matrix are

sage: C = VS.inverse()U.transpose()
sage: C

V*S.inverse()*U.transpose()
sage: C
[-28.000000000000274 -17.000000000000092 -7.0000000000001155 -12.000000000000169   5.000000000000092   5.000000000000067]
[  -18.0000000000002  -7.000000000000057  -6.000000000000087 -10.000000000000128   6.000000000000075   5.000000000000055]
[ 28.000000000000302   17.00000000000011   6.000000000000119  11.000000000000178  -5.000000000000096  -5.000000000000072]
[-26.000000000000284 -14.000000000000098  -7.000000000000118 -12.000000000000174   6.000000000000098   5.000000000000072]
[-25.000000000000263 -13.000000000000085  -7.000000000000111 -12.000000000000163   6.000000000000092  5.0000000000000675]
[ -5.000000000000057 -3.0000000000000213  -1.000000000000022 -2.0000000000000333   1.000000000000018  1.0000000000000135]

and we round:

sage: C.round()

[-28.0 -17.0  -7.0 -12.0   5.0   5.0]
[-18.0  -7.0  -6.0 -10.0   6.0   5.0]
[ 28.0  17.0   6.0  11.0  -5.0  -5.0]
[-26.0 -14.0  -7.0 -12.0   6.0   5.0]
[-25.0 -13.0  -7.0 -12.0   6.0   5.0]
[ -5.0  -3.0  -1.0  -2.0   1.0   1.0]
sage: C.round().change_ring(ZZ)

[-28 -17  -7 -12   5   5]
[-18  -7  -6 -10   6   5]
[ 28  17   6  11  -5  -5]
[-26 -14  -7 -12   6   5]
[-25 -13  -7 -12   6   5]
[ -5  -3  -1  -2   1   1]
sage: C.round().change_ring(ZZ) == A.inverse()
True