Skip to content

Commit cf22d04

Browse files
committed
blockband() -> sparsify_block_diag(), sparsify_block_banded()
1 parent 0515014 commit cf22d04

8 files changed

Lines changed: 234 additions & 152 deletions

DESCRIPTION

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ Encoding: UTF-8
3030
LazyData: true
3131
Imports:
3232
igraph,
33-
MASS,
3433
Rcpp,
3534
Rdpack
3635
LinkingTo:

NAMESPACE

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# Generated by roxygen2: do not edit by hand
22

3-
export(blockband)
43
export(gen_prec_sbm)
54
export(grasps)
6-
importFrom(MASS,mvrnorm)
5+
export(sparsify_block_banded)
6+
export(sparsify_block_diag)
77
importFrom(Rcpp,evalCpp)
88
importFrom(Rdpack,reprompt)
99
importFrom(igraph,as_adjacency_matrix)

R/blockband.R

Lines changed: 0 additions & 91 deletions
This file was deleted.

R/sparsify_block_banded.R

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#' Groupwise Block-Banded Sparsifier
2+
#'
3+
#' @description
4+
#' Make a precision-like matrix block-banded according to group membership,
5+
#' keeping only entries within specified group neighborhoods.
6+
#'
7+
#' @param mat A p-by-p precision-like matrix specifying the base matrix to be
8+
#' masked.
9+
#'
10+
#' @param membership An integer vector specifying the group membership.
11+
#' The length of \code{membership} must be consistent with the dimension p.
12+
#'
13+
#' @param neighbor.range An integer (default = 1) specifying the neighbor range,
14+
#' where groups whose labels differ by at most \code{neighbor.range} are
15+
#' considered neighbors and kept in the mask.
16+
#'
17+
#' @return A list containing:
18+
#' \describe{
19+
#' \item{Omega}{The masked precision matrix.}
20+
#' \item{Sigma}{The covariance matrix, i.e., the inverse of \code{Omega}.}
21+
#' \item{sparsity}{Proportion of zero entries in \code{Omega}.}
22+
#' \item{membership}{An integer vector specifying the group membership.}
23+
#' }
24+
#'
25+
#' @examples
26+
#' ## reproducibility for everything
27+
#' set.seed(1234)
28+
#'
29+
#' ## precision matrix estimation
30+
#' X <- matrix(rnorm(200), 10, 20)
31+
#' membership <- c(rep(1,5), rep(2,5), rep(3,4), rep(4,6))
32+
#' est <- grasps(X, membership = membership, penalty = "lasso", crit = "BIC")
33+
#'
34+
#' ## default: keep blocks within ±1 of each group
35+
#' res1 <- sparsify_block_banded(est$hatOmega, membership, neighbor.range = 1)
36+
#'
37+
#' ## wider band: keep blocks within ±2 of each group
38+
#' res2 <- sparsify_block_banded(est$hatOmega, membership, neighbor.range = 2)
39+
#'
40+
#' @export
41+
42+
sparsify_block_banded <- function(mat, membership, neighbor.range = 1) {
43+
44+
p <- ncol(mat)
45+
if (length(membership) != p) {
46+
stop(sprintf("Length of 'membership' (%d) must equal the matrix dimension p (%d).",
47+
length(membership), p))
48+
}
49+
50+
## determine which entries to keep: membership within 'neighbor.range'
51+
mask <- abs(outer(membership, membership, `-`)) <= neighbor.range
52+
53+
## apply mask to matrix
54+
Omega <- mat * mask
55+
## compute covariance
56+
Sigma <- solve(Omega)
57+
58+
return(list(Omega = Omega, Sigma = Sigma,
59+
sparsity = sum(Omega == 0) / length(Omega),
60+
membership = membership))
61+
}

R/sparsify_block_diag.R

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#' Groupwise Block-Diagonal Sparsifier
2+
#'
3+
#' @description
4+
#' Make a precision-like matrix block-diagonal according to group membership,
5+
#' keeping only within-group blocks. Optionally, further reduce selected
6+
#' within-group blocks to diagonal-only (identity-like) structure.
7+
#'
8+
#' @param mat A p-by-p precision-like matrix specifying the base matrix to be
9+
#' masked.
10+
#'
11+
#' @param membership An integer vector specifying the group membership.
12+
#' The length of \code{membership} must be consistent with the dimension p.
13+
#'
14+
#' @param group.diag (default = \code{NULL})
15+
#' \enumerate{
16+
#' \item \code{NULL}: Make \code{mat} block-diagonal, i.e., only keep all
17+
#' within-group blocks.
18+
#' \item An integer vector specifying which within-group blocks are further
19+
#' reduced to diagonal-only structure (based on the block-diagonal form).
20+
#' }
21+
#'
22+
#' @return A list containing:
23+
#' \describe{
24+
#' \item{Omega}{The masked precision matrix.}
25+
#' \item{Sigma}{The covariance matrix, i.e., the inverse of \code{Omega}.}
26+
#' \item{sparsity}{Proportion of zero entries in \code{Omega}.}
27+
#' \item{membership}{An integer vector specifying the group membership.}
28+
#' }
29+
#'
30+
#' @examples
31+
#' ## reproducibility for everything
32+
#' set.seed(1234)
33+
#'
34+
#' ## precision matrix estimation
35+
#' X <- matrix(rnorm(200), 10, 20)
36+
#' membership <- c(rep(1,5), rep(2,5), rep(3,4), rep(4,6))
37+
#' est <- grasps(X, membership = membership, penalty = "lasso", crit = "BIC")
38+
#'
39+
#' ## block-diagonalizel; within-group block for group 3 made diagonal-only.
40+
#' res <- sparsify_block_diag(est$hatOmega, membership, group.diag = 3)
41+
#'
42+
#' @export
43+
44+
sparsify_block_diag <- function(mat, membership, group.diag = NULL) {
45+
46+
p <- ncol(mat)
47+
if (length(membership) != p) {
48+
stop(sprintf("Length of 'membership' (%d) must equal the matrix dimension p (%d).",
49+
length(membership), p))
50+
}
51+
52+
## block-diagonal mask: TRUE only when in same group
53+
mask <- outer(membership, membership, `==`)
54+
55+
## adjust within-group blocks
56+
if (!is.null(group.diag)) {
57+
block_idx <- split(seq_along(membership), membership)
58+
for (g in group.diag) {
59+
idx <- block_idx[[as.character(g)]]
60+
mask[idx, idx] <- FALSE
61+
diag(mask[idx, idx]) <- TRUE
62+
}
63+
}
64+
65+
## apply mask to matrix
66+
Omega <- mat * mask
67+
## compute covariance
68+
Sigma <- solve(Omega)
69+
70+
return(list(Omega = Omega, Sigma = Sigma,
71+
sparsity = sum(Omega == 0) / length(Omega),
72+
membership = membership))
73+
}

man/blockband.Rd

Lines changed: 0 additions & 58 deletions
This file was deleted.

man/sparsify_block_banded.Rd

Lines changed: 48 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)