Using row reduction (GJE) not only we can the rref of a given matrix $A$, but we can find a matrix $M$, as indicated in Notes 8, that $MA =$ rref$(A)$. Let us illustrate this by working out Checkpoint 2 in Notes 8.
Let $A$ be the following $4 \times 5$ matrix
%display latex
latex.matrix_delimiters(left='[',right=']')
A = matrix([[-2,-2,1,3,-1],[0,0,-1,1,0],[2,4,-1,-3,-2],[2,3,-1,-3,-2]]); A
To find such an $M$, as shown in Notes 8, we need to attach an identity matrix of the right size, in this case, a $4\times 4$, then find the rref of the resulting matrix.
I4 = identity_matrix(4); B = block_matrix([A,I4],ncols=2); B
R = B.rref(); R #the right half of the rref of AI is a matrix M so that MA = rref(A)
Let's extract that right-half using the command matrix_from_columns
M = R.matrix_from_columns([5..8]); M
Finally, let's check that $MA =$ rref($A$)
M*A, A.rref(), M*A==A.rref()
Since (see Notes 8),
Theorem. $A$ is invertible if and only if rref(A) is the identity matrix (of the same shape as $A$).
So the method above can be used to decide whether a square matrix $A$ is invertible and if so, find the inverse of $A$.
Again let's illustrate this by examples. Let $A$ be the following matrix.
%display latex
A = matrix(QQ,[[-1,-3,5],[3,-2,0],[-1,0,1]]); A
The tag along the identity matrix (of the right shape) to the right of $A$.
I3 = identity_matrix(3)
B = block_matrix([A,I3], ncols = 2); B
Certainly, finding the rref of $B$ is a simple call but this time let us we carry out GJE step-by-step to illustrate the algorithm.
B.rescale_row(0,-1); B
B.rescale_row(2,-1); B
B.add_multiple_of_row(2,0,-1); B
B.add_multiple_of_row(1,0,-3); B
B.rescale_row(1,-1/11); B
B.add_multiple_of_row(2,1,3); B
B.rescale_row(2,-11); B
B.add_multiple_of_row(1,2,15/11); B
B.add_multiple_of_row(0,2,5); B
B.add_multiple_of_row(0,1,-3); B
After all these steps, we arrived to the rref of $B$ as above. So the left-half of the matrix is the rref of $A$. And we can see that it is the identity matrix. Thus, according the the theorem stated at the beginning, $A$ is invertible. Moreover, in that case, the left-half of $B$, as explained in class, is the inverse of $A$.
Let's extract the left-half of $B$ as call it $M$
M = B.matrix_from_columns([3..5])
Finally, let's check that $M$ is the inverse of $A$.
M*A, M ==A.inverse()
Bravo!!
Our last example illustrates how this method can be use to tell if a matrix is not invertible. Let $A$ be the following matrix
A = matrix([[1,0,1],[-1,2,1],[1,2,3]]); A
AI = block_matrix([A,I3], ncols=2); AI, AI.rref()
This time the left-half of rref($[A|I]$), which is rref($A$), is $\begin{bmatrix}1 & 0 & 1 \\ 0 & 1 & 1 \\ 0 & 0 & 0\end{bmatrix}$, and is not an identity matrix. That means $A$ is not invertible.