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]blockdata: 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 replicatesseed: Random seed for reproducibilityverify: Run the frozen-schedule replay verifier after every (subject, replicate) (defaultTRUE). 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)(OBSERVEDisNAhere: 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 whenwith_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 notarget_windowis 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