################################################################################# # This is the generalized cholesky routine. Reference: # # # # Gill, Jeff and Gary King. ``What to do When Your Hessian is Not Invertible: # # Alternatives to Model Respecification in Nonlinear Estimation,'' Sociological # # Methods and Research, Vol. 32, No. 1 (2004): Pp. 54--87. # # # # Abstract # # # # What should a researcher do when statistical analysis software terminates # # before completion with a message that the Hessian is not invertable? The # # standard textbook advice is to respecify the model, but this is another way # # of saying that the researcher should change the question being asked. # # Obviously, however, computer programs should not be in the business of # # deciding what questions are worthy of study. Although noninvertable # # Hessians are sometimes signals of poorly posed questions, nonsensical # # models, or inappropriate estimators, they also frequently occur when # # information about the quantities of interest exists in the data, through # # the likelihood function. We explain the problem in some detail and lay out # # two preliminary proposals for ways of dealing with noninvertable Hessians # # without changing the question asked. # # # # Also available is the software to implement the procedure described in this # # paper in Gauss format. # ################################################################################# sechol <- function(A) { n <- nrow(A) L <- matrix(rep(0,n*n),ncol=ncol(A)) macheps <- 2.23e-16; tau <- macheps^(1/3) # made to match gauss gamm <- max(A) deltaprev <- 0 Pprod <- diag(n) if (n > 2) { for (k in 1:(n-2)) { if( (min(diag(A[(k+1):n,(k+1):n]) - A[k,(k+1):n]^2/A[k,k]) < tau*gamm) && (min(svd(A[(k+1):n,(k+1):n])$d)) < 0) { dmax <- order(diag(A[k:n,k:n]))[(n-(k-1))] if (A[(k+dmax-1),(k+dmax-1)] > A[k,k]) { print(paste("iteration:",k,"pivot on:",dmax,"with absolute:",(k+dmax-1))) P <- diag(n) Ptemp <- P[k,]; P[k,] <- P[(k+dmax-1),]; P[(k+dmax-1),] = Ptemp A <- P%*%A%*%P L <- P%*%L%*%P Pprod <- P%*%Pprod } g <- rep(0,length=(n-(k-1))) for (i in k:n) { if (i == 1) sum1 <- 0 else sum1 <- sum(abs(A[i,k:(i-1)])) if (i == n) sum2 <- 0 else sum2 <- sum(abs(A[(i+1):n,i])) g[i-(k-1)] <- A[i,i] - sum1 - sum2 } gmax <- order(g)[length(g)] if (gmax != k) { print(paste("iteration:",k,"gerschgorin pivot on:",gmax,"with absolute:",(k+gmax-1))) P <- diag(ncol(A)) Ptemp <- P[k,]; P[k,] <- P[(k+dmax-1),]; P[(k+dmax-1),] = Ptemp A <- P%*%A%*%P L <- P%*%L%*%P Pprod <- P%*%Pprod } normj <- sum(abs(A[(k+1):n,k])) delta <- max(0,deltaprev,-A[k,k]+max(normj,tau*gamm)) if (delta > 0) { A[k,k] <- A[k,k] + delta deltaprev <- delta } } L[k,k] <- A[k,k] <- sqrt(A[k,k]) for (i in (k+1):n) { L[i,k] <- A[i,k] <- A[i,k]/L[k,k] A[i,(k+1):i] <- A[i,(k+1):i] - L[i,k]*L[(k+1):i,k] if(A[i,i] < 0) A[i,i] <- 0 } } } A[(n-1),n] <- A[n,(n-1)] eigvals <- eigen(A[(n-1):n,(n-1):n])$values delta <- max(0,deltaprev, -min(eigvals)+tau*max((1/(1-tau))*(max(eigvals)-min(eigvals)),gamm)) if (delta > 0) { print(paste("delta:",delta)) A[(n-1),(n-1)] <- A[(n-1),(n-1)] + delta A[n,n] <- A[n,n] + delta deltaprev <- delta } L[(n-1),(n-1)] <- A[(n-1),(n-1)] <- sqrt(A[(n-1),(n-1)]) L[n,(n-1)] <- A[n,(n-1)] <- A[n,(n-1)]/L[(n-1),(n-1)] L[n,n] <- A[n,n] <- sqrt(A[n,n] - L[n,(n-1)]^2) return(t(Pprod)%*%t(L)%*%t(Pprod)) }