% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/mixirt.R
\name{mixed_irt}
\alias{mixed_irt}
\title{Mixed Item Response Model Estimation (Dichotomous & Polytomous) with Prior Support}
\usage{
mixed_irt(data, model = "2PL", method = "EM", control = list())
}
\arguments{
\item{data}{A N x J data.frame. Binary items must be 0/1. Polytomous items should be continuous integers (0, 1, 2...).}

\item{model}{A character vector of length J (one model per item).
Supported: "Rasch", "2PL" (2-Parameter Logistic), "3PL" (3-Parameter Logistic), "GRM" (Graded Response Model), "GPCM" (Generalized Partial Credit Model), "PCM" (Partial Credit Model).
If a single string is provided, it is applied to all the same type of items.}

\item{method}{String. "EM" (Marginal Maximum Likelihood via Expectation-Maximization) or "MLE" (Joint Maximum Likelihood).}

\item{control}{A \code{list} of control parameters for the estimation algorithm:
\itemize{
\item \code{max_iter}: Maximum number of EM iterations (default = 100).
\item \code{converge_tol}: Convergence criterion for parameter change (default = 1e-4).
\item \code{theta_range}: Numeric vector of length 2 specifying the integration
grid bounds (default = c(-4, 4)).
\item \code{quad_points}: Number of quadrature points (default = 21).
\item \code{verbose}: Logical; if \code{TRUE}, prints progress to console.
\item \code{prior}: A list of model-specific prior distributions. Default is NULL (no priors).
Format: \code{list("2PL" = list(a = function(x) ..., b = function(x) ...), "GRM" = list(...))}
Each model gets its own prior specification. All items of the same model share the same prior.
Example:
\code{prior = list(
        "2PL" = list(a = function(x) dlnorm(x, 0, 0.5, log=TRUE), b = function(x) dnorm(x, 0, 2, log=TRUE)),
        "GRM" = list(a = function(x) dlnorm(x, 0, 0.5, log=TRUE), d = function(x) dnorm(x, 0, 2, log=TRUE))
      )}
}}
}
\value{
A list containing:
\itemize{
\item \code{item_params}: Data frame of item parameters (discrimination, difficulty/thresholds, guessing).
\item \code{person_params}: A data frame of estimated person abilities (theta) and standard errors.
\item \code{model_fit}: A data frame containing fit statistics such as Akaike’s Information Criterion (AIC) and the Bayesian Information Criterion (BIC).
\item \code{settings}: A list of control parameters used in the estimation.
}
}
\description{
Provides a estimation framework for a broad class of different item response theory models.
This function can model different combinations of item categories.
Now supports flexible prior distributions for Bayesian estimation (MAP estimation).
}
\examples{
  # --- Example 1: Simulation (Mixed 2PL + GPCM) ---
  set.seed(2025)
  N <- 500
  n_bin <- 5
  n_poly <- 2
  J <- n_bin + n_poly

  # 1. Generate Theta (Wide range to match user request)
  true_theta <- rnorm(N, mean = 0, sd = 3)

  # 2. Simulation Helper: GPCM
  sim_gpcm <- function(theta, a, steps) {
    n_cat <- length(steps) + 1
    probs <- matrix(0, length(theta), n_cat)
    for(k in 1:n_cat) {
      score <- k - 1
      if(score == 0) numer <- rep(0, length(theta))
      else numer <- a * (score * theta - sum(steps[1:score]))
      probs[, k] <- exp(numer)
    }
    probs <- probs / rowSums(probs)
    apply(probs, 1, function(p) sample(0:(n_cat-1), 1, prob=p))
  }

  # 3. Create Data
  data_sim <- data.frame(matrix(NA, nrow = N, ncol = J))
  colnames(data_sim) <- paste0("Item_", 1:J)

  # Binary Items (2PL)
  a_bin <- runif(n_bin, 0.8, 1.5)
  b_bin <- seq(-3, 3, length.out = n_bin)
  for(j in 1:n_bin) {
    prob <- 1 / (1 + exp(-(a_bin[j] * (true_theta - b_bin[j]))))
    data_sim[, j] <- rbinom(N, 1, prob)
  }

  # Polytomous Items (GPCM)
  # Item 6: 2 steps (-2, 2)
  data_sim[, 6] <- sim_gpcm(true_theta, a=1.0, steps=c(-2, 2))
  # Item 7: 5 steps
  data_sim[, 7] <- sim_gpcm(true_theta, a=1.2, steps=c(-5, -2.5, 0, 2.5, 5))

  # 4. Run Estimation without prior
  # Note: Wide theta_range needed due to SD=3 in simulation
  my_models <- c(rep("2PL", n_bin), rep("GPCM", n_poly))

  res <- mixed_irt(data = data_sim, model = my_models, method = "EM",
                   control = list(max_iter = 20, theta_range = c(-6, 6)))

  head(res$item_params)
  print(res$model_fit)

  \donttest{
  # 5. Run Estimation with prior (MAP)
  res_prior <- mixed_irt(data = data_sim, model = my_models, method = "EM",
                         control = list(max_iter = 20, theta_range = c(-6, 6),
                                       prior = list(
                                         "2PL" = list(
                                           a = function(x) dlnorm(x, 0, 0.5, log=TRUE),
                                           b = function(x) dnorm(x, 0, 2, log=TRUE)
                                         ),
                                         "GPCM" = list(
                                           a = function(x) dlnorm(x, 0, 0.5, log=TRUE),
                                           d = function(x) dnorm(x, 0, 2, log=TRUE)
                                         )
                                       )))
  head(res_prior$item_params)
  print(res_prior$model_fit)
  # --- Example 2: With Package Data ---
  data("ela2", package = "tirt")

  # Define Models (7 Binary, 3 Poly)
  real_models <- c(rep("2PL", 7), rep("GRM", 3))

  # Run Estimation
  real_res <- mixed_irt(ela2, model = real_models, method = "EM",
                        control = list(max_iter = 10))

  head(real_res$item_params)
  print(real_res$model_fit)
  }
}
