% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/lsirmgrm.R
\name{lsirmgrm}
\alias{lsirmgrm}
\title{Fit an ordinal LSIRM with the graded response model}
\usage{
lsirmgrm(
  data,
  ncat = NULL,
  missing_data = NA,
  missing.val = 99,
  chains = 1,
  multicore = 1,
  seed = NA,
  ndim = 2,
  niter = 15000,
  nburn = 2500,
  nthin = 5,
  nprint = 500,
  jump_beta = 0.4,
  jump_theta = 1,
  jump_gamma = 0.2,
  jump_z = 0.5,
  jump_w = 0.5,
  pr_mean_beta = 0,
  pr_sd_beta = 1,
  pr_mean_theta = 0,
  pr_sd_theta = 1,
  pr_mean_gamma = 0.5,
  pr_sd_gamma = 1,
  pr_a_theta = 0.001,
  pr_b_theta = 0.001,
  fixed_gamma = FALSE,
  spikenslab = FALSE,
  pr_spike_mean = -3,
  pr_spike_sd = 1,
  pr_slab_mean = 0.5,
  pr_slab_sd = 1,
  pr_xi_a = 1,
  pr_xi_b = 1,
  adapt = NULL,
  verbose = FALSE,
  fix_theta_sd = FALSE
)
}
\arguments{
\item{data}{Matrix; an ordinal (ordered categorical) item response matrix. Each row represents a respondent, and
each column represents an item. Values can be either \code{0:(K-1)} or \code{1:K}. Missing values can be \code{NA}.}

\item{ncat}{Integer; number of categories \eqn{K}. If \code{NULL}, it is inferred from the observed data.}

\item{missing_data}{Character; the type of missing data assumed. Options are \code{NA} or \code{"mcar"}.
For GRM models, missing values are currently supported only under MCAR. If \code{data} contains \code{NA}
and \code{missing_data} is \code{NA}, it is set to \code{"mcar"} internally with a warning.}

\item{missing.val}{Numeric; numeric code used to represent missing values in the C++ sampler. Default is 99.}

\item{chains}{Integer; number of MCMC chains. Default is 1.}

\item{multicore}{Integer; number of cores for parallel execution when \code{chains > 1}. Default is 1.}

\item{seed}{Integer; RNG seed. Default is \code{NA}.}

\item{ndim}{Integer; latent space dimension. Default is 2.}

\item{niter}{Integer; total MCMC iterations. Default is 15000.}

\item{nburn}{Integer; burn-in iterations. Default is 2500.}

\item{nthin}{Integer; thinning interval. Default is 5.}

\item{nprint}{Integer; print interval if \code{verbose=TRUE}. Default is 500.}

\item{jump_beta}{Numeric; proposal SD for GRM thresholds. Default is 0.4. During MCMC sampling, threshold proposals are constrained to maintain the ordering \eqn{\beta_{i,1} > \beta_{i,2} > \cdots > \beta_{i,K-1}} for each item.}

\item{jump_theta}{Numeric; proposal SD for theta. Default is 1.}

\item{jump_gamma}{Numeric; proposal SD on log-scale for gamma. Default is 0.2.}

\item{jump_z}{Numeric; proposal SD for z. Default is 0.5.}

\item{jump_w}{Numeric; proposal SD for w. Default is 0.5.}

\item{pr_mean_beta}{Numeric; prior mean for thresholds. Default is 0.}

\item{pr_sd_beta}{Numeric; prior SD for thresholds. Default is 1.}

\item{pr_mean_theta}{Numeric; prior mean for theta. Default is 0.}

\item{pr_sd_theta}{Numeric; prior SD for theta. Default is 1.}

\item{pr_mean_gamma}{Numeric; log-normal prior mean for gamma. Default is 0.5.}

\item{pr_sd_gamma}{Numeric; log-normal prior SD for gamma. Default is 1.}

\item{pr_a_theta}{Numeric; shape for inverse-gamma prior on var(theta). Default is 0.001.}

\item{pr_b_theta}{Numeric; scale for inverse-gamma prior on var(theta). Default is 0.001.}

\item{fixed_gamma}{Logical; if TRUE, fixes \eqn{\gamma = 1} (no sampling). Default is FALSE.}

\item{spikenslab}{Logical; if TRUE, uses spike-and-slab priors for \eqn{\gamma}. Default is FALSE.}

\item{pr_spike_mean}{Numeric; prior mean for the spike component (on log-scale). Default is -3.}

\item{pr_spike_sd}{Numeric; prior SD for the spike component (on log-scale). Default is 1.}

\item{pr_slab_mean}{Numeric; prior mean for the slab component (on log-scale). Default is 0.5.}

\item{pr_slab_sd}{Numeric; prior SD for the slab component (on log-scale). Default is 1.}

\item{pr_xi_a}{Numeric; Beta prior shape a for mixing weight \eqn{\xi}. Default is 1.}

\item{pr_xi_b}{Numeric; Beta prior shape b for mixing weight \eqn{\xi}. Default is 1.}

\item{adapt}{List; optional adaptive MCMC control. If not \code{NULL}, proposal standard deviations are adapted during burn-in using a Robbins-Monro update on the log proposal SD and are held fixed during the main MCMC sampling.
When adaptation is enabled, the reported acceptance ratios in the output (\code{accept_beta}, \code{accept_theta}, etc.) are computed only from iterations after burn-in, reflecting the performance of the adapted proposal distributions.
The defaults are tuning heuristics for random-walk Metropolis proposals: scalar parameters use a target acceptance rate of \code{0.44}, while latent position block proposals use \code{0.234}. The \code{0.44} target is commonly used for one-dimensional random-walk proposals, and \code{0.234} is the high-dimensional optimal-scaling benchmark discussed by Roberts, Gelman and Gilks (1997) and Roberts and Rosenthal (2001). These values are proposal-tuning targets, not convergence diagnostics.
Elements of the list can include:
\itemize{
  \item \code{use_adapt}: Logical; if \code{TRUE}, adaptive MCMC is used. Default is \code{FALSE}.
  \item \code{adapt_interval}: Integer; the number of iterations between proposal SD updates. Smaller values react more quickly but can be noisy; larger values are smoother but adapt more slowly. Default is \code{100}.
  \item \code{adapt_rate}: Numeric; Robbins-Monro scaling constant \eqn{c} in the step-size formula \eqn{c / t^\alpha}. Larger values adapt faster but can oscillate; smaller values are more conservative. Default is \code{1.0}. Recommended starting range is \code{0.5}--\code{2.0}.
  \item \code{decay_rate}: Numeric; Robbins-Monro decay exponent \eqn{\alpha} in \eqn{c / t^\alpha}. Values above \code{0.5} give diminishing adaptation consistent with the usual stochastic-approximation square-summability condition. Default is \code{0.6}; recommended range is \code{0.6}--\code{0.8}.
  \item \code{jump_min}, \code{jump_max}: Numeric; advanced lower and upper bounds for adapted proposal SDs, used to prevent proposal scales from collapsing to zero or becoming excessively large. These are normally left unchanged.
  \item \code{target_accept}: Numeric; default target acceptance rate for scalar random-walk updates (beta, theta, gamma). Default is \code{0.44}.
  \item \code{target_accept_zw}: Numeric; target acceptance rate for latent position block updates z and w. Default is \code{0.234}.
  \item \code{target_accept_beta/theta/gamma}: Numeric; (optional) parameter-specific target acceptance rates to override \code{target_accept}.
}}

\item{verbose}{Logical; If TRUE, MCMC progress and parameter samples are printed to the console during execution. Default is FALSE.}

\item{fix_theta_sd}{Logical; If TRUE, the standard deviation of the respondent latent positions \eqn{\theta} is fixed at 1 instead of being sampled. Default is FALSE.}
}
\value{
An object of class \code{lsirm}. For multi-chain fits, it returns a list where each element (\code{chain1}, \code{chain2}, etc.) is a single-chain fit of class \code{lsirm}. The single-chain fit contains posterior summaries and MCMC draws, including:
\itemize{
  \item \code{z}, \code{w}: Procrustes-matched posterior samples of respondent and item latent positions.
  \item \code{z_raw}, \code{w_raw}: posterior samples of respondent and item latent positions before Procrustes matching.
  \item \code{z_estimate}, \code{w_estimate}: posterior mean latent positions after Procrustes matching.
}
}
\description{
\code{\link{lsirmgrm}} fits an ordinal latent space item response model for Likert-scale (ordered categorical)
responses using the graded response model (GRM). This approach extends the traditional GRM by incorporating
a latent space representation of respondent-item interactions, providing a spatial interpretation of response patterns.

The model captures interactions between respondents and items through the distance between latent respondent positions
\eqn{z_j} and item positions \eqn{w_i} in a shared latent space, allowing for the visualization and interpretation
of complex response patterns in Likert-scale assessments.
}
\details{
\code{lsirmgrm} implements the Graded Response Model (GRM) in a latent space framework. 
Let \eqn{Y_{j,i} \in \{0,\ldots,K-1\}} be the ordered categorical response of respondent \eqn{j} to item \eqn{i}.
The model is defined via cumulative logits:
\deqn{\Pr(Y_{j,i} \ge k | \theta_j, \beta_{i,k}, \gamma, z_j, w_i) = \text{logit}^{-1}(\theta_j + \beta_{i,k} - \gamma\,\|z_j-w_i\|)}
for \eqn{k=1,\ldots,K-1}, where \eqn{\beta_{i,k}} are item-specific thresholds (difficulty levels) that satisfy the ordering constraint \eqn{\beta_{i,1} > \beta_{i,2} > \cdots > \beta_{i,K-1}} for identifiability.

Missing data can be handled as follows:
\itemize{
  \item \code{"mcar"}: Missing responses are assumed to be Missing Completely At Random. They are ignored in the likelihood calculation.
}

For models with \code{spikenslab = TRUE}, a spike-and-slab prior is placed on \eqn{\log(\gamma)} to perform model selection between a standard Rasch-type model (\eqn{\gamma \approx 0}) and a latent space model (\eqn{\gamma > 0}).
}
\examples{
\donttest{
# generate example ordinal item response matrix
set.seed(123)
nsample <- 50
nitem <- 10
data <- matrix(sample(1:5, nsample * nitem, replace = TRUE), nrow = nsample)

# Fit GRM LSIRM using direct function call
fit <- lsirmgrm(data, niter = 1000, nburn = 500, nthin = 2)
summary(fit)

# Realistic example with BFPT data
data(BFPT)
dat <- BFPT
# Handle outliers or special codes
dat[(dat == 0) | (dat == 6)] <- NA
# Reverse code specific items
reverse <- c(2, 4, 6, 8, 10, 11, 13, 15, 16, 17, 18, 19, 20, 21, 23, 25, 27, 32, 34, 36, 42, 44, 46)
dat[, reverse] <- 6 - dat[, reverse]
# Remove missing cases for simple demonstration
dat <- dat[complete.cases(dat), ]
# Fit model (subset for speed)
fit_bfpt <- lsirm(dat[1:50, 1:10] ~ lsirmgrm(niter = 1000, nburn = 500))
summary(fit_bfpt)

# Fit with missing data under MCAR
data_mcar <- data
data_mcar[sample(length(data_mcar), 20)] <- NA
fit_mcar <- lsirm(data_mcar ~ lsirmgrm(niter = 1000, nburn = 500))

# Fit with Spike-and-Slab prior for model selection
fit_ss <- lsirm(data ~ lsirmgrm(spikenslab = TRUE, niter = 1000, nburn = 500))

# Fit with adaptive MCMC for automatic tuning
fit_adapt <- lsirmgrm(data, niter = 2000, nburn = 1000, 
                      adapt = list(use_adapt = TRUE, adapt_interval = 50))
# Check adapted jump sizes and acceptance rates
cat("Final jump_beta:", fit_adapt$tuning$jump_beta_final, "\n")
cat("Mean acceptance rate (post-burnin):", mean(fit_adapt$accept_beta), "\n")
}

}
\references{
De Carolis, L., Kang, I., & Jeon, M. (2025). A Latent Space Graded Response Model for Likert-Scale
Psychological Assessments. \emph{Multivariate Behavioral Research}. \doi{10.1080/00273171.2025.2605678}

Roberts, G. O., Gelman, A., & Gilks, W. R. (1997). Weak convergence and optimal scaling of random walk Metropolis algorithms. \emph{The Annals of Applied Probability}, 7(1), 110--120. \doi{10.1214/aoap/1034625254}

Roberts, G. O., & Rosenthal, J. S. (2001). Optimal scaling for various Metropolis-Hastings algorithms. \emph{Statistical Science}, 16(4), 351--367. \doi{10.1214/ss/1015346320}

Andrieu, C., & Thoms, J. (2008). A tutorial on adaptive MCMC. \emph{Statistics and Computing}, 18(4), 343--373. \doi{10.1007/s11222-008-9110-y}
}
