Skip to content

Commit b22a503

Browse files
committed
organize: gen_prec_sbm, expand_spec, draw_sample
1 parent 239f2bd commit b22a503

6 files changed

Lines changed: 109 additions & 129 deletions

File tree

R/draw_sample.R

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66
#'
77
#' @param sampler A specification of the sampling distribution, either:
88
#' \enumerate{
9-
#' \item A string specifying the distribution family. Supported distribution
10-
#' families (corresponding base R generators in parentheses) include:
9+
#' \item A user-supplied sampling function. The function must accept an argument
10+
#' \code{n} specifying the number of samples.
11+
#' \item A character string specifying the distribution family.
12+
#' Supported distribution families (corresponding base R generators
13+
#' in parentheses) include:
1114
#' \itemize{
1215
#' \item "beta": Beta distribution (\code{\link[stats]{rbeta}})
1316
#' \item "cauchy": Cauchy distribution (\code{\link[stats]{rcauchy}}).
@@ -21,8 +24,6 @@
2124
#' \item "unif": Uniform distribution (\code{\link[stats]{runif}}).
2225
#' \item "weibull": Weibull distribution (\code{\link[stats]{rweibull}}).
2326
#' }
24-
#' \item A user-supplied function used for sampling. The function must accept
25-
#' an argument \code{n} specifying the number of samples.
2627
#' }
2728
#'
2829
#' @param para A list (default = \code{list()}) specifying the required
@@ -33,9 +34,6 @@
3334
#' @return
3435
#' A numeric vector of length \eqn{n} containing simulated data.
3536
#'
36-
#' @example
37-
#' inst/example/ex-draw_sample.R
38-
#'
3937
#' @noRd
4038

4139
draw_sample <- function(sampler, para = list(), n) {

R/expand_spec.R

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@
2121
#' correspond to within-group blocks, and the remaining \eqn{K(K-1)/2}
2222
#' correspond to between-group blocks.
2323
#'
24-
#' @example
25-
#' inst/example/ex-expand_spec.R
26-
#'
2724
#' @noRd
2825

2926
expand_spec <- function(spec, K) {

R/gen_prec_sbm.R

Lines changed: 60 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,21 @@
1313
#' @param K An integer (default = 3) specifying the number of groups.
1414
#' Ignored if \code{block.sizes} is provided; then \code{K <- length(block.sizes)}.
1515
#'
16-
#' @param prob.mat A \eqn{K}-by-\eqn{K} symmetric matrix (default = \code{NULL})
17-
#' specifying the Bernoulli rates. Element (i,j) gives the probability of
18-
#' creating an edge between vertices from groups i and j. If \code{NULL},
19-
#' a matrix with \code{within.prob} on the diagonal and \code{between.prob}
20-
#' off-diagonal is used.
16+
#' @param prob.mat A \eqn{K \times K} symmetric matrix (default = \code{NULL})
17+
#' specifying the Bernoulli rates. Element \eqn{(i, j)} gives the probability of
18+
#' creating an edge between vertices from groups \eqn{i} and \eqn{j}.
19+
#' If \code{NULL}, a matrix with \code{within.prob} on the diagonal and
20+
#' \code{between.prob} on the off-diagonal is used.
2121
#'
22-
#' @param within.prob A scalar in [0,1] (default = 0.25) specifying
22+
#' @param within.prob A numeric value in [0, 1] (default = 0.25) specifying
2323
#' the probability of creating an edge between vertices within the same group.
2424
#' This argument is used only when \code{prob.mat = NULL}.
2525
#'
26-
#' @param between.prob A scalar in [0,1] (default = 0.05) specifying
26+
#' @param between.prob A numeric value in [0, 1] (default = 0.05) specifying
2727
#' the probability of creating an edge between vertices from different groups.
2828
#' This argument is used only when \code{prob.mat = NULL}.
2929
#'
30-
#' @param weight.mat A \eqn{d}-by-\eqn{d} symmetric matrix (default = \code{NULL})
30+
#' @param weight.mat A \eqn{d \times d} symmetric matrix (default = \code{NULL})
3131
#' specifying the edge weights. If \code{NULL}, weights are generated block-wise
3232
#' according to \code{weight.dists} and \code{weight.paras}.
3333
#'
@@ -39,15 +39,18 @@
3939
#' \item length = 2: First for within-group blocks, second for between-group
4040
#' blocks.
4141
#' \item length = \eqn{K + K(K-1)/2}: Full specification for each block.
42-
#' The first \eqn{K} elements correspond to within-group blocks with indices 1,
43-
#' \dots, K, and the remaining \eqn{K(K-1)/2} elements correspond to
44-
#' between-group blocks ordered as (1,2), (1,3), \dots, (1,K), (2,3), \dots,
45-
#' (K-1,K).
42+
#' The first \eqn{K} elements correspond to within-group blocks with indices
43+
#' \eqn{1, \dots, K}, and the remaining \eqn{K(K-1)/2} elements correspond to
44+
#' between-group blocks ordered as \eqn{(1,2)}, \eqn{(1,3)}, \eqn{(1,4)}, \dots,
45+
#' \eqn{(1,K)}, \eqn{(2,3)}, \dots, \eqn{(K-1,K)}.
4646
#' }
4747
#' Each element of \code{weight.dists} can be:
4848
#' \enumerate{
49-
#' \item A string specifying the distribution family. Accepted distributions
50-
#' (base R samplers in parentheses) include: \itemize{
49+
#' \item A user-supplied sampling function. The function must accept an argument
50+
#' \code{n} specifying the number of samples.
51+
#' \item A character string specifying the distribution family.
52+
#' Accepted distributions (base R samplers in parentheses) include:
53+
#' \itemize{
5154
#' \item "beta": Beta distribution (\code{\link[stats]{rbeta}})
5255
#' \item "cauchy": Cauchy distribution (\code{\link[stats]{rcauchy}}).
5356
#' \item "chisq": Chi-squared distribution (\code{\link[stats]{rchisq}}).
@@ -60,21 +63,26 @@
6063
#' \item "unif": Uniform distribution (\code{\link[stats]{runif}}).
6164
#' \item "weibull": Weibull distribution (\code{\link[stats]{rweibull}}).
6265
#' }
63-
#' \item A user-supplied function used for sampling. The function must accept
64-
#' an argument \code{n} specifying the number of samples.
6566
#' }
6667
#'
67-
#' @param weight.paras A list (default =
68-
#' \code{list(c(shape = 1e4, rate = 1e2), c(min = 0, max = 5))}) specifying
69-
#' the parameters associated with \code{weight.dists}. It must follow the same
70-
#' length rules as \code{weight.dists}. Each element should be a named vector
71-
#' or list suitable for the corresponding sampler.
68+
#' @param weight.paras A list
69+
#' (default = \code{list(c(shape = 1e4, rate = 1e2), c(min = 0, max = 5))})
70+
#' specifying the parameters associated with \code{weight.dists}. It must follow
71+
#' the same length rules as \code{weight.dists}. Each element should be a named
72+
#' vector or list suitable for the corresponding sampler.
7273
#'
73-
#' @param cond.target A scalar (default = 100) specifying the target condition
74-
#' number for the precision matrix. A diagonal shift is applied so that
75-
#' the smallest eigenvalue satisfies
76-
#' \eqn{\lambda_{\min} \geq \lambda_{\max}/\code{cond.target}},
77-
#' ensuring both positive definiteness and numerical stability.
74+
#' @param cond.target A numeric value > 1 (default = 100) specifying the target
75+
#' condition number for the precision matrix. When necessary, a diagonal shift
76+
#' is applied to ensure positive definiteness and numerical stability.
77+
#'
78+
#' @return
79+
#' An object with S3 class "gen_prec_sbm" containing the following components:
80+
#' \describe{
81+
#' \item{Omega}{The precision matrix with SBM block structure.}
82+
#' \item{Sigma}{The covariance matrix, i.e., the inverse of \code{Omega}.}
83+
#' \item{sparsity}{Proportion of zero entries in \code{Omega}.}
84+
#' \item{membership}{An integer vector specifying the group membership.}
85+
#' }
7886
#'
7987
#' @details
8088
#' \strong{Edge sampling.}
@@ -91,45 +99,43 @@
9199
#' \item length = 1: Same specification for all blocks.
92100
#' \item length = 2: first for within-group blocks, second for between-group
93101
#' blocks.
94-
#' \item length = \eqn{K + K(K - 1)/2}: Full specification for each block.
102+
#' \item length = \eqn{K + K(K-1)/2}: Full specification for each block.
95103
#' }
96104
#'
97105
#' \strong{Block indexing.}
98106
#' The order for blocks is:
99107
#' \itemize{
100-
#' \item Within-group blocks: Indices 1, \dots, K.
101-
#' \item Between-group blocks: \eqn{K(K-1)/2} blocks in order (1,2), (1,3),
102-
#' \dots, (1,K), (2,3), \dots, (K-1,K).
108+
#' \item Within-group blocks: Indices \eqn{1, \dots, K}.
109+
#' \item Between-group blocks: \eqn{K(K-1)/2} blocks in order \eqn{(1,2)},
110+
#' \eqn{(1,3)}, \eqn{(1,4)}, \dots, \eqn{(1,K)}, \eqn{(2,3)}, \dots, \eqn{(K-1,K)}.
103111
#' }
104112
#'
105113
#' \strong{Positive definiteness.}
106114
#' The weighted adjacency matrix is symmetrized and used as the precision matrix
107115
#' \eqn{\Omega_0}. Since arbitrary block-structured weights may not be positive
108116
#' definite, a diagonal adjustment is applied to control the eigenvalue spectrum.
109117
#' Specifically, let \eqn{\lambda_{\max}} and \eqn{\lambda_{\min}} denote
110-
#' the largest and smallest eigenvalues of the initial matrix. A scalar
111-
#' \eqn{\tau} is added to the diagonal so that
112-
#' \deqn{\lambda_{\min}(\Omega_0 + \tau I) \;\geq\;
113-
#' \lambda_{\max} / \code{cond.target},
114-
#' }
115-
#' which ensures both positive definiteness and that the condition number
116-
#' does not exceed \code{cond.target}. This guarantees numerical stability even
117-
#' in high-dimensional settings.
118-
#'
119-
#' @importFrom igraph as_adjacency_matrix sample_sbm
120-
#'
121-
#' @return
122-
#' An object with S3 class "grasps" containing the following components:
123-
#' \describe{
124-
#' \item{Omega}{The precision matrix with SBM block structure.}
125-
#' \item{Sigma}{The covariance matrix, i.e., the inverse of \code{Omega}.}
126-
#' \item{sparsity}{Proportion of zero entries in \code{Omega}.}
127-
#' \item{membership}{An integer vector specifying the group membership.}
118+
#' the largest and smallest eigenvalues of a matrix. A non-negative numeric
119+
#' value \eqn{\tau} is added to the diagonal so that
120+
#' \deqn{
121+
#' \left\{
122+
#' \begin{array}{l}
123+
#' \dfrac{\lambda_{\max}(\Omega_0 + \tau I)}{\lambda_{\min}(\Omega_0 + \tau I)}
124+
#' \leq \texttt{cond.target} \\[1em]
125+
#' \lambda_{\min}(\Omega_0 + \tau I) > 0 \\[.5em]
126+
#' \tau \geq 0
127+
#' \end{array}
128+
#' \right.
128129
#' }
130+
#' which ensures both positive definiteness and guarantees that the condition
131+
#' number does not exceed \code{cond.target}, providing numerical stability
132+
#' even in high-dimensional settings.
129133
#'
130134
#' @example
131135
#' inst/example/ex-gen_prec_sbm.R
132136
#'
137+
#' @importFrom igraph as_adjacency_matrix sample_sbm
138+
#'
133139
#' @export
134140

135141
gen_prec_sbm <- function(d,
@@ -212,15 +218,15 @@ gen_prec_sbm <- function(d,
212218
Omega <- (Omega + t(Omega)) / 2 ## symmetric; diag still 0
213219

214220
## ensure positive definiteness and control the condition number
215-
## add a scalar tau to the diagonal so that lambda_min(Omega + tau*I) >= target_min,
216-
## where target_min = lambda_max / cond.target
217-
## this guarantees the condition number satisfies kappa(Omega) <= cond.target
218-
## (shift all eigenvalues by the same tau)
221+
## add a scalar tau to the diagonal so that
222+
## lambda_max(Omega + tau*I) / lambda_min(Omega + tau*I) <= cond.target
223+
## (diagonal loading shifts all eigenvalues by the same tau)
219224
eigvals <- eigen(Omega, only.values = TRUE)$values
220225
eigval_max <- max(eigvals)
221226
eigval_min <- min(eigvals)
222-
target_min <- eigval_max / cond.target
223-
tau <- ifelse(eigval_min < target_min, target_min - eigval_min, 0)
227+
tau <- max(0, ## no adjustment
228+
-eigval_min, ## ensure positive definiteness
229+
(eigval_max - cond.target * eigval_min) / (cond.target - 1)) ## enforce kappa <= cond.target
224230
diag(Omega) <- diag(Omega) + tau
225231

226232
## covariance matrix

inst/example/ex-draw_sample.R

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

inst/example/ex-expand_spec.R

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

man/gen_prec_sbm.Rd

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

0 commit comments

Comments
 (0)