Simulate state-reactive (adaptive / feedback) dosing

Description

Runs a forward simulation in which the dosing regimen is decided at run time by the model file’s [adaptive_dosing] block - a declarative first-matching-rule controller that reads the simulated (optionally assay-noised) state at each decision time and titrates the next dose. This is the file-driven therapeutic-drug-monitoring / feedback-dosing path; the plain [ferx_simulate](ferx_simulate.qmd) replays a fixed regimen from the data instead.

Usage

ferx_simulate_adaptive(
  model,
  data = NULL,
  n_sim = 1L,
  seed = 42L,
  verify = TRUE,
  max_decisions = 0L
)

Arguments

  • model: Path to a .ferx model file containing an [adaptive_dosing] block
  • data: Path to a NONMEM-format CSV: an observation grid, any covariates, and optionally a pre-scheduled base regimen (dose rows). When omitted, the model file’s [data] block (path = ...) is used.
  • n_sim: Number of simulation replicates
  • seed: Random seed for reproducibility
  • verify: Run the frozen-schedule replay verifier after every (subject, replicate) (default TRUE). A divergence is a hard error, not a warning: it means the realized dose ledger does not reproduce the trajectory, so the result is not trustworthy.
  • max_decisions: Per-run cap on the number of decision points (the runaway / closed-loop guard). 0 (default) keeps the engine default.

Details

The data may carry a pre-scheduled base regimen - ordinary dose rows (EVID = 1 or 4, with AMT, and optionally RATE, SS, II) such as a loading or maintenance dose. The controller then augments that standing prescription: at each decision time it reads the simulated (optionally assay-noised) state and appends its own dose. A dose-free base subject (observation grid only) is equally valid - the controller simply supplies the entire regimen. A model without an [adaptive_dosing] block is an error. The dose ledger ($doses) holds controller-issued doses only.Pre-scheduled base doses never appear in it, so $metrics$CUM_DOSE and $metrics$N_DOSESexclude the base regimen (e.g. a 1500 mg loading dose is not counted). The full realized regimen is the union of $doses with the input CSV’s EVID = 1/4 rows. In contrast $trajectories, $decisions, PCT_TIME_IN_WINDOW, and the auc_target attainment metric do reflect the base regimen. A base dose scheduled exactly at a decision time is read pre-dose (the trough), and a base dose scheduled after a stop still lands - a stop ends controller augmentation, not the standing prescription. System resets. An EVID = 3 row zeroes the compartments (and re-seeds any init(state) = expr) at its time; EVID = 4 does the same and then doses. Ordering at a shared time is reset, then dose, then observation. Some combinations remain rejected with a typed error rather than silently mis-integrated: a base regimen combined with a reset under a time-varying covariate or IOV; a steady-state, lag-timed, or modeled-rate (RATE) base dose under a time-varying covariate or IOV (these are supported on the constant-covariate path); and an auc_target metric combined with a time-varying covariate, a TIME-dependent PK parameter, IOV, or a reset.

Seealso

Other simulation: [ferx_calc_npde](ferx_calc_npde.qmd), [ferx_predict](ferx_predict.qmd), [ferx_predict_survival](ferx_predict_survival.qmd), [ferx_simulate](ferx_simulate.qmd), [ferx_simulate_with_uncertainty](ferx_simulate_with_uncertainty.qmd)

Concept

simulation

Value

A list of four data frames:

  • trajectories: DRAW, SIM, ID, TIME, CMT, IPRED, DV_SIM, OBSERVED - the per-observation predictions, as in [ferx_simulate](ferx_simulate.qmd) (OBSERVED is NA here: the adaptive path has no time-to-event endpoint).
  • doses: The realized dose ledger, controller-issued doses only (pre-scheduled base doses are excluded): DRAW, SIM, ID, TIME, AMT, CMT, RATE, DECISION, SIGNAL (the value the controller titrated on - assay-noised when with_assay_error), RULE (the rule that fired).
  • decisions: One row per decision including holds: DRAW, SIM, ID, DECISION, TIME, SIGNAL, OUTCOME (“dosed” / “hold” / “stop”), N_DOSED.
  • metrics: One row per realized run (subject x draw x replicate) - the per-subject outcome summary: DRAW, SIM, ID, CUM_DOSE (sum of controller-issued doses; excludes the base regimen), N_DOSES (controller doses only), N_INCREASES / N_DECREASES (realized dose-change counts, by dose delta), N_HOLDS, DISCONTINUED, TIME_TO_DISCONT, SIGNAL_MIN / SIGNAL_MAX / SIGNAL_MEAN (over the decisions that recorded a signal), and PCT_TIME_IN_WINDOW - the fraction of signal-bearing decisions whose observed value fell inside the model’s [adaptive_dosing] target_window (NA when no target_window is declared).

Examples

ex  <- ferx_example("adaptive_tdm")
res <- ferx_simulate_adaptive(ex$model, ex$data, n_sim = 20L, seed = 1L)
head(res$doses)         # how the dose was titrated per decision
head(res$trajectories)  # the resulting concentration-time profiles