---
title: "Chained Onsets"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Chained Onsets}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

This vignette shows how to define staged processing with `after()`. Here
accumulator `C` starts only after accumulator `B` has finished.

```{r}
library(AccumulatR)
```

## Define the model

`A` is directly observed. `B` is latent. `C` is observed and starts only after
`B` has finished.

```{r}
model <- race_spec() |>
  add_accumulator("A", "lognormal") |>
  add_accumulator("B", "lognormal") |>
  add_accumulator("C", "lognormal", onset = after("B")) |>
  add_outcome("A", "A") |>
  add_outcome("C", "C") |>
  set_parameters(separate = list(m = TRUE, s = TRUE)) |>
  finalize_model()

true_params <- c(
  A.m = log(0.28),
  A.s = 0.14,
  B.m = log(0.1),
  B.s = 0.1,
  C.m = log(0.15),
  C.s = 0.1
)
```

## Simulate data

Each trial contributes an observed response label and response time.

```{r}
set.seed(123456)

n_trials <- 2000
params_df <- build_param_matrix(model, true_params, n_trials = n_trials)

sim <- simulate(model, params_df)

data_df <- data.frame(
  trials = sim$trials,
  R = factor(sim$R),
  rt = sim$rt,
  stringsAsFactors = FALSE
)

table(data_df$R)
```


## Estimate parameters with `optim()`

We estimate `A.m`, `A.s`, `B.m`, `B.s`, `C.m`, and `C.s`. The spread
parameters are optimized on the log scale.

```{r eval=FALSE}
prepared <- prepare_data(model, data_df)
ctx <- make_context(model)

neg_loglik <- function(theta) {
  est <- true_params
  est[c("A.m", "A.s", "B.m", "B.s", "C.m", "C.s")] <- theta[c("A.m", "A.s", "B.m", "B.s", "C.m", "C.s")]
  est[c("A.s", "B.s", "C.s")] <- exp(est[c("A.s", "B.s", "C.s")])
  params_df <- build_param_matrix(
    model,
    est,
    n_trials = n_trials
  )
  ll <- log_likelihood(ctx, prepared, params_df)
  -as.numeric(ll)
}

start <- c(
  A.m = log(0.22),
  A.s = log(0.10),
  B.m = log(0.28),
  B.s = log(0.10),
  C.m = log(0.28),
  C.s = log(0.10)
)

fit <- optim(start, neg_loglik, method = "Nelder-Mead")

fit_params <- fit$par
fit_params[c("A.s", "B.s", "C.s")] <- exp(fit_params[c("A.s", "B.s", "C.s")])
target <- true_params[c("A.m", "A.s", "B.m", "B.s", "C.m", "C.s")]

data.frame(
  true = target,
  recovered = fit_params,
  miss = abs(target - fit_params)
)
```

Only the combined finishing time of `B` and `C` is observed through response
`C`. Separating their timing parameters can therefore be difficult. Additional
observations of the stages or constraints on their parameters can help identify
the individual contributions.
