In this problem, we’ll verify using R that SVD and Eigenvalues are related as worked out in the weekly module. Given a \(3 x 2\) matrix \(\textbf{A}\)
\[ A = \begin{bmatrix} 1 && 2 && 3 \\ -1 && 0 && 4 \end{bmatrix} \]
write code in R to compute \(X = AA^{T}\) and \(Y = A^{T}A\). Then, compute the eigenvalues and eigenvectors of X and Y using the built-in commands in R. Then, compute the left-singular, singular values, and right-singular vectors of A using the svd command. Examine the two sets of singular vectors and show that they are indeed eigenvectors of X and Y. In addition, the two non-zero eigenvalues (the 3rd value will be very close to zero, if not zero) of both X and Y are the same and are squares of the non-zero singular values of A. Your code should compute all these vectors and scalars and store them in variables. Please add enough comments in your code to show me how to interpret your steps.
A <- matrix(c(1,2,3,-1,0,4), nrow = 2, ncol = 3, byrow = TRUE)
A
## [,1] [,2] [,3]
## [1,] 1 2 3
## [2,] -1 0 4
A_T <- t(A)
A_T
## [,1] [,2]
## [1,] 1 -1
## [2,] 2 0
## [3,] 3 4
X = A%*%A_T
Y = A_T%*%A
Matrix \(A\)
A
## [,1] [,2] [,3]
## [1,] 1 2 3
## [2,] -1 0 4
Matrix \[X=AA^T\]
X
## [,1] [,2]
## [1,] 14 11
## [2,] 11 17
Matrix \(Y=A^TA\)
Y
## [,1] [,2] [,3]
## [1,] 2 2 -1
## [2,] 2 4 6
## [3,] -1 6 25
library(pracma)
eigenX <- eigen(X)
eigenY <- eigen(Y)
eValX <- eigenX$values
eVecX <- eigenX$vectors
eValX
## [1] 26.601802 4.398198
eVecX
## [,1] [,2]
## [1,] 0.6576043 -0.7533635
## [2,] 0.7533635 0.6576043
eValY <- eigenY$values
eVecY <- eigenY$vectors
eValY
## [1] 2.660180e+01 4.398198e+00 -1.233248e-16
eVecY
## [,1] [,2] [,3]
## [1,] -0.01856629 0.6727903 0.7396003
## [2,] 0.25499937 0.7184510 -0.6471502
## [3,] 0.96676296 -0.1765824 0.1849001
svdA <- svd(A)
svdA
## $d
## [1] 5.157693 2.097188
##
## $u
## [,1] [,2]
## [1,] -0.6576043 -0.7533635
## [2,] -0.7533635 0.6576043
##
## $v
## [,1] [,2]
## [1,] 0.01856629 -0.6727903
## [2,] -0.25499937 -0.7184510
## [3,] -0.96676296 0.1765824
round(eigenX$values, digits=10)
## [1] 26.601802 4.398198
round(eigenY$values, digits=10)
## [1] 26.601802 4.398198 0.000000
eigenX$vectors
## [,1] [,2]
## [1,] 0.6576043 -0.7533635
## [2,] 0.7533635 0.6576043
eigenY$vectors
## [,1] [,2] [,3]
## [1,] -0.01856629 0.6727903 0.7396003
## [2,] 0.25499937 0.7184510 -0.6471502
## [3,] 0.96676296 -0.1765824 0.1849001
svdA
## $d
## [1] 5.157693 2.097188
##
## $u
## [,1] [,2]
## [1,] -0.6576043 -0.7533635
## [2,] -0.7533635 0.6576043
##
## $v
## [,1] [,2]
## [1,] 0.01856629 -0.6727903
## [2,] -0.25499937 -0.7184510
## [3,] -0.96676296 0.1765824
round(eigenX$values, digits=10) == round(svdA$d^2, digits=10)
## [1] TRUE TRUE
# here, we compare eigenvectors of X and singular vectors of U
eigenX$vectors
## [,1] [,2]
## [1,] 0.6576043 -0.7533635
## [2,] 0.7533635 0.6576043
svdA$u
## [,1] [,2]
## [1,] -0.6576043 -0.7533635
## [2,] -0.7533635 0.6576043
we can clearly see from above that first vectors only differ by their signs, and therefore we invert the sign, just as we saw in the video accompagning the lecture explaining that it is possible to invert the sign of an eigenvector and resulting vector will also be an eigenvector
eigenX$vectors[,1] <- eigenX$vectors[,1] * (-1)
round(eigenX$vectors, digits=10) == round(svdA$u, digits=10)
## [,1] [,2]
## [1,] TRUE TRUE
## [2,] TRUE TRUE
** Like-wise, we do the same thing for \(Y\)**
round(eigenY$vectors[,1:2], digits=10)
## [,1] [,2]
## [1,] -0.01856629 0.6727903
## [2,] 0.25499937 0.7184510
## [3,] 0.96676296 -0.1765824
round(svdA$v, digits=10)
## [,1] [,2]
## [1,] 0.01856629 -0.6727903
## [2,] -0.25499937 -0.7184510
## [3,] -0.96676296 0.1765824
eigenY$vectors[,1:1] <- eigenY$vectors[,1:1] * (-1)
round(eigenY$vectors[,1:2], digits=10) == round(svdA$v, digits=10)
## [,1] [,2]
## [1,] TRUE FALSE
## [2,] TRUE FALSE
## [3,] TRUE FALSE
Using the procedure outlined in section 1 of the weekly handout, write a function to compute the inverse of a well-conditioned full-rank square matrix using co-factors. In order to compute the co-factors, you may use built-in commands to compute the determinant. Your function should have the following signature: \(B\) = myinverse(\(A\)) where \(A\) is a matrix and B is its inverse and \(AB = I\).
myinverse <- function(A) {
# What if A is not a square matrix
if (dim(A)[1] != dim(A)[2]) {
return(NA)
}
# A is inversable if and only if det(A) is not equal 0
if (det(A)==0) {
return(NA)
}
n <- dim(A)[1]
# Loop through all elements and compute co-factor matrix Co-Matrix
Co.Matrix <- matrix(0, n, n)
for(i in 1:n) {
for(j in 1:n) {
# The submatrix A[-i,-j] is forced into matrix type in case of 2x2 matrix
# Otherwise, if 2x2 matrix, then A[-i,-j] would produce a single element
Co.Matrix[i,j] <- (-1)^(i+j)*det(matrix(A[-i,-j], n-1))
}
}
# By definition, Inverse of A is equal to transpose of C divided by determinant of A
B <- t(Co.Matrix)/det(A)
return(B)
}
A <- matrix(c(2,1,3,-2,3,5,2,1,2), nrow=3)
B <- myinverse(A)
B
## [,1] [,2] [,3]
## [1,] -0.125 -1.75 1
## [2,] -0.125 0.25 0
## [3,] 0.500 2.00 -1
#verify B is really the inverse of A (I'm rounding for fun, just in case the number of decimals goes crazy)
round(solve(A), digits=10) == round(B, digits=10)
## [,1] [,2] [,3]
## [1,] TRUE TRUE TRUE
## [2,] TRUE TRUE TRUE
## [3,] TRUE TRUE TRUE
#also let's verify that AB = I holds as well just for fun (I'm also rounding here just in case the number of decimals goes beyond 10 digits)
round(A %*% B, digits=10)
## [,1] [,2] [,3]
## [1,] 1 0 0
## [2,] 0 1 0
## [3,] 0 0 1
Hit me with another test case, this time will make our matrix random and of dimensions 5x5
A <- matrix(sample(0:9, 25, replace = TRUE), nrow=5, ncol=5)
A
## [,1] [,2] [,3] [,4] [,5]
## [1,] 6 6 9 2 9
## [2,] 2 8 6 3 6
## [3,] 2 3 6 6 2
## [4,] 4 5 0 2 0
## [5,] 4 1 9 9 2
B <- myinverse(A)
B
## [,1] [,2] [,3] [,4] [,5]
## [1,] 0.1034483 -0.137931 -0.1206897 0.15517241 0.06896552
## [2,] 0.6896552 -1.586207 3.8620690 0.03448276 -2.20689655
## [3,] 2.3218391 -5.206897 11.7356322 -0.18390805 -6.56321839
## [4,] -1.9310345 4.241379 -9.4137931 0.10344828 5.37931034
## [5,] -2.3103448 5.413793 -12.1379310 0.03448276 6.79310345
round(solve(A), digits=10) == round(B, digits=10)
## [,1] [,2] [,3] [,4] [,5]
## [1,] TRUE TRUE TRUE TRUE TRUE
## [2,] TRUE TRUE TRUE TRUE TRUE
## [3,] TRUE TRUE TRUE TRUE TRUE
## [4,] TRUE TRUE TRUE TRUE TRUE
## [5,] TRUE TRUE TRUE TRUE TRUE
I = A%*%B
round(I, digits=10)
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 0 0 0 0
## [2,] 0 1 0 0 0
## [3,] 0 0 1 0 0
## [4,] 0 0 0 1 0
## [5,] 0 0 0 0 1