Reputation: 129
For some reason, the if-statement in my code generates some weird error in R whenever I run my function:
Error in if (P > 0) { : missing value where TRUE/FALSE needed
My function is supposed to return the smallest eigenvalue of the symmetric, positive semi-definite matrix A, if B is the identity matrix. I tested my function using
set.seed(12345)
a <- crossprod(matrix (rnorm(40), 10 ,4)) / 10
b <- diag(1, 4, 4)
and it does yield the correct answer (I checked using the eigen function.)
Anyway, I need to set theta to the value that minimizes a certain function. For the example I used, that value is (-Q - sqrt(under.sqrt)) / (2 * P), but in general it depends on the sign of P. Why does my if-statement give me such an error? I have been stuck here for a while. Any help would be appreciated.
myFunction <- function(A, B, eps = 1e-6, itmax = 100, verbose = FALSE) {
n <- nrow(A)
m <- ncol(A)
x <- rep (1, n)
u <- A %*% x
v <- B %*% x
r <- t(u) %*% x
s <- t(v) %*% x
y <- r / s
itel <- 1
repeat {
tmax <- 0
for(j in 1:m) {
P <- (u[j] * B[j, j]) - (v[j] * A[j, j])
Q <- (r * B[j, j]) - (s * A[j, j])
R <- (r * v[j]) - (s * u[j])
under.sqrt <- Q^2 - 4 * P * R
# Error right here
if (P > 0) {
theta <- (-Q + sqrt(under.sqrt)) / (2 * P)
}
else {
theta <- (-Q - sqrt(under.sqrt)) / (2 * P)
}
x[j] <- x[j] + theta
r <- r + 2 * theta * u[j] + A[j, j] * theta * theta
s <- s + 2 * theta * v[j] + B[j, j] * theta * theta
u <- u + theta * A[ ,j]
v <- v + theta * B[, j]
y <- r / s
tmax <- max(tmax, abs(theta))
}
if ((tmax < eps) || (itel == itmax)) {
break()
}
itel <- itel + 1
}
return(y)
}
Upvotes: 2
Views: 2737
Reputation: 66834
You algorithm is not stable. Using options(error=recover)
you can browse the function where it is going wrong:
Browse[1]> P
[1] NaN
Browse[1]> theta
[,1]
[1,] Inf
Here you can see that P
is NaN
and this is caused by theta
blowing up to infinite values. This feeds through to x
, u
, v
and ultimately P
and makes the comparison fail.
Upvotes: 4
Reputation: 20045
Here's my bet: P is NA
> if(NA > 0){}
Error in if (NA > 0) { : missing value where TRUE/FALSE needed
P renders NaN:
> if(NaN > 0){}
Error in if (NaN > 0) { : missing value where TRUE/FALSE needed
regarding the guess that P is a vector:
> if(1:2 > 0){}
NULL
Warning message:
In if (1:2 > 0) { :
the condition has length > 1 and only the first element will be used
Upvotes: 2
Reputation: 56149
Try ifelse
:
theta <- ifelse(P > 0,
(-Q + sqrt(under.sqrt)) / (2 * P),
(-Q - sqrt(under.sqrt)) / (2 * P))
ifelse
can handle NA comparison:
ifelse(NA>0,print("x"),print("y"))
[1] NA
if(NA>0) print("x") else print("y")
Error in if (NA > 0) print("x") else print("y") :
missing value where TRUE/FALSE needed
Upvotes: 0
Reputation: 741
Are you sure P
is a single value? Ie, not a vector of length > 1?
Upvotes: 0