CGF Object of a linearly mapped random variable \(Y = A \, X\)
Source:R/D-LinearlyMappedCGF.R
linearlyMappedCGF.RdCreates a CGF object for the random vector \(Y = A(\theta) \, X\), where
\(X\) is described by the input CGF cgf. The argument matrix_A can be:
A numeric matrix (dense or sparse).
A function: \(\theta \mapsto A(\theta)\) See details for the possible options of
matrix_A.
If matrix_A is a function, it is called for each invocation of the CGF
methods to retrieve the current matrix (allowing parameter-dependent transformations).
Arguments
- cgf
An object of class
CGFfor the base distribution \(X\).- matrix_A
Either a numeric matrix (dense or
Matrixsparse), or a functionfunction(theta) -> A(theta)returning one of: numeric dense matrix,Matrixsparse matrix, RTMB AD‑dense (anadvectorwith adim) or RTMBadsparse.- iidReps
Either
"any"(default) or a positive integer. SeeiidReplicatesCGFfor the replication semantics.- ...
Additional named arguments passed to
CGFcreation functions.
Details
Accepted types for matrix_A:
numeric constant matrix, dense or
Matrixsparse. If dense, it is converted once at construction to a sparseMatrix.function \(\theta \mapsto A(\theta)\) returning one of:
a numeric
matrix(dense); it will be internally handled as sparse;a
Matrixsparse matrix (preferred for large problems);an RTMB::AD-dense matrix (RTMB
advectorwith adimattribute);an RTMB::AD-sparse matrix (RTMB
adsparse), created e.g. viaA = RTMB::AD(Matrix::sparseMatrix(...)); A@x[] = ....
Examples
## Example 1: constant numeric A
if (FALSE) { # \dontrun{
lambda_fun <- function(theta) c(theta[1], theta[2]) # two Poisson rates
pois2 <- PoissonModelCGF(lambda = lambda_fun, iidReps = "any")
A_const <- rbind(c(1, 0),
c(0.5, 1))
mapped <- linearlyMappedCGF(cgf = pois2, matrix_A = A_const, iidReps = "any")
B <- 3L # 3 replicated 2-d blocks
t_one <- c(0.10, -0.05)
y_one <- c(3.0, 4.0)
tvec <- rep(t_one, B)
y <- rep(y_one, B)
theta <- c(2.0, 3.0)
## Identity check: K1_Y(t) = A K1_X(A^T t)
t_block <- t_one
A_now <- A_const
lhs_K1 <- mapped$K1(t_block, theta)
poisk1 <- pois2$K1(as.vector(t(A_now) %*% t_block), theta)
rhs_K1 <- A_now %*% poisk1
## SPA negative log-likelihood + gradient + Hessian
res <- compute.spa.negll(
parameter_vector = theta,
observed.data = y,
cgf = mapped,
gradient = TRUE,
hessian = TRUE,
tvec_source = "newton",
spa_method = "standard"
)
} # }
## Example 2: A(theta) dense-vs-sparse (adsparse)
if (FALSE) { # \dontrun{
library(Matrix)
lambda_fun <- function(theta) c(theta[1], theta[2]) # base 2-d Poisson
pois2 <- PoissonModelCGF(lambda = lambda_fun, iidReps = "any")
## Dense A(theta) depending on theta[1]
A_theta_dense <- function(theta) {
matrix(c(1, 0,
0.5*theta[1], 1), 2, 2, byrow = TRUE)
}
## AD-sparse A(theta) with fixed sparsity pattern, AD-filled values
A_theta_sparse <- function(theta) {
A0 <- sparseMatrix(i = c(1L, 2L, 2L),
j = c(1L, 1L, 2L),
x = c(1, 0, 1),
dims = c(2L, 2L))
A <- RTMB::AD(A0)
A@x[] = c(1, 0.5*theta[1], 1)
A
}
mapped_dense <- linearlyMappedCGF(cgf = pois2, matrix_A = A_theta_dense, iidReps = "any")
mapped_sparse <- linearlyMappedCGF(cgf = pois2, matrix_A = A_theta_sparse, iidReps = "any")
## Data: B = 3 identical 2-vectors
B <- 3L
y_one <- c(3.0, 4.0)
y <- rep(y_one, B)
theta <- c(2.0, 3.0) # only theta[1] affects A(theta)
nll_dense <- compute.spa.negll(theta, y, mapped_dense,
gradient=TRUE, hessian=TRUE,
tvec_source="newton", spa_method="standard")
nll_sparse <- compute.spa.negll(theta, y, mapped_sparse,
gradient=TRUE, hessian=TRUE,
tvec_source="newton", spa_method="standard")
} # }