---
title: "Introduction to ForceChoice"
author: "Haijiang Qin & Lei Guo"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Introduction to ForceChoice}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 7,
  fig.height = 5
)
```

## Overview

The **ForceChoice** package provides a unified framework for fitting,
simulating, and evaluating forced-choice and traditional item response
theory (IRT) models. It supports eight model families with full Bayesian
estimation via Stan (Hamiltonian Monte Carlo), a fast iterative stochastic EM
(iStEM) algorithm, and a deterministic EM backend for FCGDINA.

This vignette is intended as a reproducible user guide rather than a
complete methodological review. Model formulas and object components are
described using the parameterization implemented in **ForceChoice**. The
reference list gives DOI links where available so readers can verify the
underlying psychometric sources.

### Model Families

| Family | Description | Data Type |
|---|---|---|
| **MIRT** | Multidimensional IRT (1PL--4PL) | Binary |
| **MGPCM** | Multidimensional Generalized Partial Credit | Polytomous |
| **MGGUM** | Multidimensional Generalized Graded Unfolding | Polytomous |
| **FCMIRT** | Forced-Choice MIRT with Luce--Plackett ranking | Ranking/MOLE/PICK |
| **FCGGUM** | Forced-Choice GGUM with ranking | Ranking/MOLE/PICK |
| **TIRT** | Thurstonian IRT with pairwise probit | Ranking/MOLE/PICK |
| **FCDCM** | Forced-Choice Diagnostic Classification | Paired comparison |
| **FCGDINA** | Forced-Choice GDINA diagnostic model | Ranking/MOLE/PICK |

The forced-choice families accept full ranking (`"RANK"`), most-least
(`"MOLE"`), or best-only (`"PICK"`) data when supported by the corresponding
fitting function. FCDCM is the exception: it is a paired-comparison model
where every block contains exactly two statements.

### Model and Backend Coverage

| Family | Main response process | Backends | Primary outputs |
|---|---|---|---|
| MIRT | Dominance IRT for binary items | Stan, iStEM | item parameters, $\theta$, factor correlations |
| MGPCM | Dominance IRT for ordered categories | Stan, iStEM | category intercepts, $\theta$, factor correlations |
| MGGUM | Ideal-point/unfolding IRT | Stan, iStEM | slopes, locations, thresholds, $\theta$ |
| FCMIRT | MIRT endorsement plus Luce--Plackett ranking | Stan, iStEM | item parameters, $\theta$, block fit |
| FCGGUM | GGUM endorsement plus Luce--Plackett ranking | Stan, iStEM | unfolding item parameters, $\theta$, block fit |
| TIRT | Pairwise Thurstonian probit comparisons | Stan, iStEM | loadings, uniquenesses, $\theta$ |
| FCDCM | Higher-order DCM for two-statement FC blocks | Stan, iStEM | attribute profiles, higher-order parameters |
| FCGDINA | GDINA/DINA/DINO/ACDM plus FC ranking | Stan, iStEM, EM | attribute profiles, CDM item parameters |

### Estimation Backends

- **Stan** (`method = "stan"`): Full Bayesian inference via HMC/NUTS.
  Provides posterior means, standard deviations, and R-hat convergence
  diagnostics. Suitable for final inference with small-to-moderate datasets.

- **iStEM** (`method = "iStEM"`): Iterative Stochastic EM combining
  Metropolis-within-Gibbs person sampling with L-BFGS-B item optimization.
  Scales to large datasets. Convergence monitored via Geweke diagnostics.

- **EM** (`method = "EM"`): Deterministic posterior-weight EM for FCGDINA.

## Installation

```r
# Development version from GitHub
remotes::install_github("Naidantu/ForceChoice")
```

## Quick Start: Traditional IRT

### Simulating and Fitting a MIRT Model

```{r, eval=FALSE}
library(ForceChoice)

# Simulate binary response data
sim <- sim.data.MIRT(N = 20, I = 6, D = 2, model = "2PL")

# Fit via iStEM
fit <- fit.MIRT(sim$data, model = "2PL", D = 2,
                method = "iStEM",
                control.method = list(
                  vis = FALSE, seed = 123,
                  M = 2, B = 2, burnin.maxitr = 2,
                  maxitr = 3, eps1 = 10, eps2 = 10,
                  estimate.se = FALSE))

# Examine results
print(fit)
summary(fit)

# Item parameter estimates (first 6 items)
head(coef(fit))

# Factor correlation matrix
fit$Corr$est

# Trait recovery
diag(cor(fit$theta$est, sim$theta))
```

### Goodness-of-Fit Evaluation

```{r, eval=FALSE}
# Compute comprehensive fit indices
gof <- get.fit.index(fit)

# Summary of fit indices
summary(gof)

# Extract specific indices
gof$M2       # Limited-information M2 statistic
gof$RMSEA    # RMSEA with 90% CI
gof$CFI      # Comparative Fit Index
gof$TLI      # Tucker-Lewis Index
gof$SRMSR    # Standardized Root Mean Square Residual
gof$AIC      # Akaike Information Criterion
gof$BIC      # Bayesian Information Criterion
```

## Forced-Choice Modeling

### Simulating and Fitting FCMIRT

Forced-choice data uses ranking strings (e.g., `"2>1>3"` means item 2
is preferred over item 1 over item 3).

```{r, eval=FALSE}
# Simulate forced-choice ranking data
sim <- sim.data.FCMIRT(N.person = 20, N.block = 3, I.block = 2,
                       D = 2, model = "2PL", fc.type = "RANK")

# The data contains ranking strings
head(sim$data)

# Fit: block.items and fc.type are auto-detected
fit <- fit.FCMIRT(sim$data, model = "2PL", D = 2,
                  method = "iStEM",
                  control.method = list(
                    vis = FALSE, seed = 123,
                    M = 2, B = 2, burnin.maxitr = 2,
                    maxitr = 3, eps1 = 10, eps2 = 10,
                    estimate.se = FALSE))

# Trait recovery
cor(fit$theta$est, sim$theta)

# Goodness-of-fit (uses nominal binary expansion)
gof <- get.fit.index(fit)
summary(gof)
```

### Thurstonian IRT (TIRT)

```{r, eval=FALSE}
sim <- sim.data.TIRT(N.person = 20, N.block = 3, I.block = 2,
                     D = 2, fc.type = "RANK")

fit <- fit.TIRT(sim$data, Q.matrix = sim$Q.matrix,
                block.items = sim$block.items,
                method = "iStEM",
                control.method = list(
                  vis = FALSE, seed = 123,
                  M = 2, B = 2, burnin.maxitr = 2,
                  maxitr = 3, eps1 = 10, eps2 = 10,
                  estimate.se = FALSE))

# Structural parameters: loadings and uniquenesses
head(coef(fit))

# Gamma matrix (pairwise intercepts)
fit$gamma.matrix$est[1:5, 1:5]
```

### Forced-Choice DCM (FCDCM)

```{r, eval=FALSE}
sim <- sim.data.FCDCM(N.person = 20, N.block = 3, D = 2,
                      dcm.type = "DINA")

fit <- fit.FCDCM(sim$data, Q.matrix = sim$Q.matrix,
                 block.items = sim$block.items,
                 method = "iStEM",
                 control.method = list(
                   vis = FALSE, seed = 123,
                   M = 2, B = 2, burnin.maxitr = 2,
                   maxitr = 3, eps1 = 10, eps2 = 10,
                   estimate.se = FALSE))

# Posterior attribute mastery probabilities
head(fit$alpha$prob)

# Attribute mastery proportions
colMeans(fit$alpha$prob > 0.5)

# Higher-order IRT parameters
fit$delta$est
```

### Forced-Choice GDINA (FCGDINA)

FCGDINA is the diagnostic-classification counterpart for multi-statement
forced-choice blocks. Unlike FCDCM, which is restricted to paired
comparisons under a higher-order DCM structure, FCGDINA supports
`"GDINA"`, `"DINA"`, `"DINO"`, and `"ACDM"` statement-level models and can
be fitted to full ranking, most-least, or best-only forced-choice data.

```{r, eval=FALSE}
sim <- sim.data.FCGDINA(N.person = 20, N.block = 2, I.block = 2,
                        D = 2, model = "GDINA", fc.type = "RANK")

fit <- fit.FCGDINA(sim$data, Q.matrix = sim$Q.matrix,
                   block.items = sim$block.items, model = "GDINA",
                   fc.type = sim$fc.type, method = "EM",
                   control.method = list(vis = FALSE, seed = 123,
                                         maxitr = 2,
                                         estimate.se = FALSE))

# Posterior attribute mastery probabilities
head(fit$alpha$est)

# CDM item-parameter estimates
coef(fit, type = "delta")
```

## Working with Polytomous Data

### MGPCM (Dominance)

```{r, eval=FALSE}
sim <- sim.data.MGPCM(N = 20, I = 6, D = 2, length.poly = 4)

fit <- fit.MGPCM(sim$data, D = 2, method = "iStEM",
                 control.method = list(
                   vis = FALSE, seed = 123,
                   M = 2, B = 2, burnin.maxitr = 2,
                   maxitr = 3, eps1 = 10, eps2 = 10,
                   estimate.se = FALSE))

# Category threshold parameters
coef(fit)
```

### MGGUM (Ideal-Point / Unfolding)

```{r, eval=FALSE}
sim <- sim.data.MGGUM(N = 20, I = 6, D = 2, length.poly = 4)

fit <- fit.MGGUM(sim$data, D = 2, method = "iStEM",
                 control.method = list(
                   vis = FALSE, seed = 123,
                   M = 2, B = 2, burnin.maxitr = 2,
                   maxitr = 3, eps1 = 10, eps2 = 10,
                   estimate.se = FALSE))

coef(fit)
```

## Solution Rotation

For exploratory MIRT analyses, post-hoc rotation helps achieve simple
structure:

```{r, eval=FALSE}
fit_rot <- rotate.MIRT(fit, rotate = "oblimin")

# Compare original and rotated loadings
head(coef(fit))
head(coef(fit_rot))
```

## Diagnostic Plots

```{r, eval=FALSE}
# Item characteristic curves (ICC)
plot(fit, type = "icc", items = 1:8)

# Person parameter distributions
plot(fit, type = "theta")

# iStEM convergence trace
plot(fit, type = "trace")
```

## Estimation Control

### Common Parameters (top-level)

```{r, eval=FALSE}
fit <- fit.MIRT(data, model = "2PL", D = 2, method = "iStEM",
                control.method = list(
                  vis = FALSE,
                  seed = 123,      # Reproducibility
                  M = 2, B = 2, burnin.maxitr = 2,
                  maxitr = 3, eps1 = 10, eps2 = 10,
                  estimate.se = FALSE))
```

### Stan-Specific Control

```{r, eval=FALSE}
# stan code, long time
fit <- fit.MIRT(data, model = "2PL", D = 2, method = "stan",
                control.method = list(chains = 1, iter = 200,
                                      warmup = 100, cores = 1,
                                      seed = 123))
```

### iStEM-Specific Control (advanced)

```{r, eval=FALSE}
fit <- fit.MIRT(data, model = "2PL", D = 2, method = "iStEM",
                control.method = list(
                  seed = 123,
                  M = 2,            # Burn-in batches for convergence
                  B = 2,            # Iterations per batch
                  burnin.maxitr = 2,
                  maxitr = 3,
                  eps1 = 1.5,       # Geweke convergence threshold
                  eps2 = 0.4        # MC error tolerance
                ))
```

## References

- Brown, A., & Maydeu-Olivares, A. (2011). Item response modeling of
  forced-choice questionnaires. *Educational and Psychological Measurement*,
  *71*(3), 460--502. <https://doi.org/10.1177/0013164410375112>

- de la Torre, J. (2011). The generalized DINA model framework.
  *Psychometrika*, *76*(2), 179--199.
  <https://doi.org/10.1007/s11336-011-9207-7>

- Huang, H.-Y. (2022). Diagnostic classification model for forced-choice
  items and noncognitive tests. *Educational and Psychological Measurement*,
  *83*(1), 146--180. <https://doi.org/10.1177/00131644211069906>

- Lee, P., Joo, S.-H., Stark, S., & Chernyshenko, O. S. (2018). GGUM-RANK
  statement and person parameter estimation with multidimensional forced
  choice triplets. *Applied Psychological Measurement*, *43*(3), 226--240.
  <https://doi.org/10.1177/0146621618768294>

- Luce, R. D. (1959). *Individual choice behavior: A theoretical analysis*.
  Wiley.

- Maydeu-Olivares, A., & Joe, H. (2005). Limited- and full-information
  estimation and goodness-of-fit testing in 2^n contingency tables: A
  unified framework. *Journal of the American Statistical Association*,
  *100*(471), 1009--1020.
  <https://doi.org/10.1198/016214504000002069>

- Maydeu-Olivares, A., & Joe, H. (2006). Limited information goodness-of-fit
  testing in multidimensional contingency tables. *Psychometrika*, *71*(4),
  713--732. <https://doi.org/10.1007/s11336-005-1295-9>

- Muraki, E. (1992). A generalized partial credit model: Application of an
  EM algorithm. *Applied Psychological Measurement*, *16*(2), 159--176.
  <https://doi.org/10.1177/014662169201600206>

- Plackett, R. L. (1975). The analysis of permutations. *Journal of the
  Royal Statistical Society: Series C (Applied Statistics)*, *24*(2),
  193--202. <https://doi.org/10.2307/2346567>

- Reckase, M. D. (2009). *Multidimensional Item Response Theory*. Springer.
  <https://doi.org/10.1007/978-0-387-89976-3>

- Roberts, J. S., Donoghue, J. R., & Laughlin, J. E. (2000). A general item
  response theory model for unfolding unidimensional polytomous responses.
  *Applied Psychological Measurement*, *24*(1), 3--32.
  <https://doi.org/10.1177/01466216000241001>

- Zheng, C., Liu, J., Li, Y., Xu, P., Zhang, B., Wei, R., Zhang, W.,
  Liu, B., & Huang, J. (2024). A 2PLM-RANK multidimensional forced-choice
  model and its fast estimation algorithm. *Behavior Research Methods*,
  *56*(6), 6363--6388. <https://doi.org/10.3758/s13428-023-02315-x>
