Skip to content

Commit

Permalink
refine function for finding blocks in covariance matrices
Browse files Browse the repository at this point in the history
  • Loading branch information
ecmerkle committed Oct 9, 2023
1 parent 9bf1257 commit 5760ab5
Showing 1 changed file with 14 additions and 12 deletions.
26 changes: 14 additions & 12 deletions R/blav_utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -429,13 +429,14 @@ checkcovs <- function(lavobject){

## check whether model cov matrix is block diagonal
## uses matrices from lavInspect(, "free")
blkdiag <- function(mat) {
## eqcon is attributes(lavInspect(, "free"))$header
blkdiag <- function(mat, eqcon = NULL) {
isblk <- TRUE
cnum <- 1L
nblks <- 0
matrows <- NROW(mat)
blkse <- matrix(0, matrows, 3) # start/end of each block, and first free param in that block
while (isblk && cnum <= matrows) {
blkse <- matrix(0, matrows, 3) # start/end of each block, is it a fully unrestricted block
while (cnum <= matrows) {
## ending row of this potential block
currend <- which(mat[, cnum] > 0)
if (length(currend) > 0) {
Expand All @@ -445,6 +446,7 @@ blkdiag <- function(mat) {
currend <- cnum
}

nblks <- nblks + 1
if (currend > cnum) {
## check that columns cnum+1 to max() also equal max()
othend <- sapply((cnum + 1):currend, function(i) {
Expand All @@ -455,31 +457,31 @@ blkdiag <- function(mat) {
out <- i
}
out})

if (all(othend == currend)) {
## is this entire submatrix free?
submat <- mat[cnum:currend, cnum:currend]
if (all(submat[lower.tri(submat)] > 0)) {
nblks <- nblks + 1
blkse[nblks,] <- c(cnum, currend, min(submat[lower.tri(submat)]))
cnum <- currend + 1
submat <- submat[lower.tri(submat)]
if (all(submat > 0) & all(!(submat %in% as.numeric(eqcon$rhs)))) {
blkse[nblks,] <- c(cnum, currend, TRUE)
} else {
isblk <- FALSE
blkse[nblks,] <- c(cnum, currend, FALSE)
}
} else {
isblk <- FALSE
blkse[nblks,] <- c(cnum, currend, FALSE)
}
} else if (currend == cnum) {
## 1x1 block
nblks <- nblks + 1
blkse[nblks,] <- c(cnum, cnum, 0)
cnum <- cnum + 1
blkse[nblks,] <- c(cnum, cnum, TRUE)
} else {
isblk <- FALSE
}
cnum <- currend + 1
}

if (isblk) blkse <- blkse[1:nblks, , drop = FALSE]
blkse <- blkse[1:nblks, , drop = FALSE]

list(isblk = isblk, nblks = nblks, blkse = blkse)
}
Expand Down

0 comments on commit 5760ab5

Please sign in to comment.