Problem Set 1

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.

Let’s calculate the Transpose of A and name it A_T:

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

Calculate X and Y as described in the problem statement:

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

Next, let’s find the EigenValues and EigenVectors of X and Y:

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

Calculate SVD

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

Eigenvectors of \(X\) and \(Y\)

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

Singular Value Decomposition:

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

Compare Eigenvalues and Singular Values of our matrix \(A\):

round(eigenX$values, digits=10) == round(svdA$d^2, digits=10)
## [1] TRUE TRUE

Compare Eigenvectors and Singular Vectors of or matrix \(A\) :

# 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

Problem Set 2

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)
}

Let’s prove myinverse works

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

Looks like all our properties hold for the matrix and its inverse, therefore our function is indeed pretty good.

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