Reputation: 3561
I have the following matrix
K <- matrix(c(1.250000e+00, 3.366892e-07, 4.641930e-10, 1.455736e-08, 1.049863e-06,
3.366892e-07, 1.250000e+00, 5.482775e-01, 8.606555e-01, 9.776887e-01,
4.641930e-10, 5.482775e-01, 1.250000e+00, 8.603413e-01, 4.246732e-01,
1.455736e-08, 8.606555e-01, 8.603413e-01, 1.250000e+00, 7.490100e-01,
1.049863e-06, 9.776887e-01, 4.246732e-01, 7.490100e-01, 1.250000e+00), nrow=5)
and the following vector
y <- matrix(c(39.13892, 12.34428, 12.38426, 14.71951, 10.52160), nrow=5)
I want to calculate the product between the inverse of K
and the vector y
.
The naive method works (I have a way of checking, but doesn't matter here)
solve(K) %*% y
[,1]
[1,] 31.3111308
[2,] 3.0620869
[3,] 3.7383357
[4,] 6.6257060
[5,] 0.7820081
However the "clever" method fails. I use cholesky decomposition which gives me an upper triangular matrix. Then I solve the system L z = y
by backward substitution and the system L^T x = L^{-1} y
by forward substitution.
L <- chol(K) ## upper triangular
forwardsolve(t(L), backsolve(L, y))
[,1]
[1,] 31.31112
[2,] -14.16259
[3,] 9.84534
[4,] 39.67900
[5,] 33.54842
What is happening? This matrix K
and this vector 'y` are just an example. It happens with many other similar vectors and matrices. Why?
Upvotes: 4
Views: 931
Reputation: 269481
The key point is that when taking the inverse of a product one must reverse the product of the inverses:
solve(A %*% B) = solve(B) %*% solve(A)
In the question the order was not reversed.
If R = chol(K)
where we use R
to emphasize that it is upper right triangular then:
solve(K, y)
= solve(t(R) %*% R, y) since K = t(R) %*% R
= solve(t(R) %*% R) %*% y
= solve(R) %*% solve(t(R)) %*% y note that we have reversed the order
= solve(R) %*% solve(t(R), y)
= backsolve(R, forwardsolve(t(R), y))
In the last line we used the fact that the transpose of R is lower left triangular and forwardsolve
works on such matrices whereas backsolve
works on upper right triangular matrices.
We can check that this does give the same answer as using solve
direclty:
R = chol(K)
all.equal(backsolve(R, forwardsolve(t(R), y)), solve(K, y))
# [1] TRUE
Upvotes: 3
Reputation: 3561
This is just a partial answer, but it's better than nothing. Basically finding K^{-1}y is equivalent to solving the following system
Writing this using the cholesky decomposition we have
Basically we now consider Lz
to be our variable first, call it x
and since L
is upper-triangular, it's transpose is lower-triangular, so that we can use forwardsolve
to find x
forwardsolve(t(L), y)
Once we've found x
, we can just remember what it means, i.e.
so that we can use 'backsolveto find
z`
backsolve(L, forwardsolve(t(L), y))
and this gives the correct answer. Not sure why the other way around does't work as well.
Upvotes: 1