This version adds the time-to-event BOIN (TITE-BOIN) design, the BF-BOIN and BE-BOIN designs, which backfill patients to lower doses while the dose escalation waits, the BOIN design for trials of two drugs given together, and a decision table for the 3+3 design. No existing function or result changes.
tite_boin_decision_table() tabulates the decision rule of the TITE-BOIN
design, which lets new patients be treated while the DLT assessment of earlier
patients is still pending. Two methods are offered: the single mean
imputation of Yuan et al. (2018), method = "imputation", with boundaries on
the standardized total follow-up time (STFT), and the effective sample size
of Lin and Yuan (2020), method = "ess", with boundaries on the effective
sample size (ESS). The table has print() and plot() methods, and the
printed layout follows the published tables.
The suspension rules of the two articles are available for both methods:
max_pending_ratio (accrual is suspended when more than half of the patients
are pending, the default of the imputation method) and min_completed
(escalation requires two patients with a completed assessment, the default of
the effective sample size method).
min_follow_up adds rule 2 of Chen et al. (2025): while patients are
pending, escalation requires every pending patient at the current dose to
have been followed for at least this fraction of the assessment window, and
accrual is suspended until then. It is available in
tite_boin_decision_table(), tite_boin_simulate(), sim_tite_boin() and
sim_tite_boin_multi(), and defaults to 0, which changes nothing. With
max_pending_ratio = 0.49 (their rule 1 with A = 51) and
min_follow_up = 0.25, the imputation method reproduces every entry of
Table 1 (target 0.3) of Chen et al. (2025) and of Table A1 (target 0.25) of
the supplementary materials of Chen et al. (2026), 131 states in all. The
printed table shows the condition, for example >= 0.22 & MF >= 0.25.
With the defaults, the imputation method reproduces every entry of Table 1 (target 0.2) of Yuan et al. (2018) and Table S1 (target 0.3) of its supplementary appendix, 640 states in all, and the printed table has the same rows. The published tables allow de-escalation when the observed DLT rate equals the target, which equation (5) of the appendix, read literally, does not; the implementation follows the tables. The dose decisions of the trial example in Figure 1 of that article are reproduced as well.
Elimination counts the pending patients as treated without DLT, as both
articles define it. States without pending patients agree with
boin_decision_table().
tite_boin_simulate() simulates TITE-BOIN trials in which patients arrive
over time and DLTs can occur late in the assessment window. It returns the
patient and DLT counts of boin_simulate() together with the duration of each
trial, the number of suspensions of accrual and the time spent suspended. The
engine is written in C++ (src/tite_core.h), like the BOIN engine.
The dose for a cohort is decided when its first patient arrives, with the
rules of tite_boin_decision_table(); the engine and the table are checked
against each other at every state. A suspension lasts until the next pending
patient at the current dose completes the assessment or, with a positive
min_follow_up, until the minimum follow-up is reached, whichever comes
first. Because DLTs can be
observed after a dose has been left, the elimination rule is checked at every
dose, not only the current one.
Times between arrivals can be exponential, uniform or fixed, and the time to
DLT Weibull, with the share of DLTs in the second half of the window set by
late_fraction, or uniform.
prior_weights weights the follow-up of the pending patients by a piecewise
uniform prior for the time to DLT over the three thirds of the window, as in
Appendix D of Yuan et al. (2018) and Section S1 of Lin and Yuan (2020). The
decision table is unchanged; only the follow-up compared with it is. Equal
weights, the default, use the unweighted computation, so the default results
do not change. The weighted trials agree exactly with the separate Python
implementation, which uses the formula of Lin and Yuan's reference code.
One uniform variate per patient, drawn from R's stream in the order used by
boin_simulate(), decides both whether a DLT occurs and when; arrivals come
from a separate generator. Whenever no patient is pending at a decision the
trials are therefore identical to those of boin_simulate() with the same
seed, which the tests check for both methods and several designs.
The trials agree exactly with a separate implementation written in Python, run on a replica of R's random number stream.
sim_tite_boin() and sim_tite_boin_multi() summarize simulated TITE-BOIN
trials in the same way as sim_boin() and sim_boin_multi(), with the same
options for selecting the MTD (bound_mtd, mtd_max_estimate,
min_mtd_sample) and the same overdose component. They add the average
and standard deviation of the trial duration, the percentage of trials with
accrual suspended, and the average number and total time of suspensions.
The results inherit from the BOIN classes (c("tite_boin_oc", "boin_oc") and
c("tite_boin_oc_multi", "boin_oc_multi")), so code that reads the result of
sim_boin() also reads them. They have their own print() methods, which
also show the design and the timing; the table of sim_tite_boin_multi()
has two rows more per scenario, for the duration and the suspensions.
Whenever no patient is pending at a decision, every summary agrees exactly
with that of sim_boin() under the same seed, including the options of MTD
selection and the safety rules; the tests check this for both methods.
bf_boin_simulate() simulates the BOIN design with backfilling (BF-BOIN) of
Zhao et al. (2024). The dose escalation proceeds in fully staggered cohorts
with the BOIN decision table, and a patient who arrives while it waits is
backfilled to a lower dose that has not been eliminated, has fewer than
n_cap patients and has a response observed at or below it. Doses are
closed for backfilling, and conflicts between the backfilled doses and the
current dose are resolved with pooled data, as in Table 2 of the article.
be_boin_simulate() simulates BE-BOIN of Chen et al. (2026), which combines
backfilling with TITE-BOIN. The escalation decides while patients are
pending, with rules 1 and 2 of the article (max_pending_ratio = 0.49 and
min_follow_up = 0.25), and every estimate imputes the pending patients,
over several doses with equation (2) of the article.
sim_bf_boin(), sim_be_boin(), sim_bf_boin_multi() and
sim_be_boin_multi() summarize the simulated trials. The results inherit
from the BOIN classes, count backfilled patients among the patients treated,
and add the backfilled patients and the responses at each dose, the trial
duration, the waits of the escalation and the patients turned away. The MTD
is selected from the data of all patients, as in sim_boin(). They have
their own print() methods, and the table of the _multi functions has
seven rows per scenario.
Points that the articles leave open are arguments: no_slot decides
whether a patient with nowhere to go waits or is turned away,
conflict_dose whether the highest (Zhao et al., 2024) or the lowest (Chen
et al., 2026) conflicting dose anchors the pooled estimate, and
backfill_dose which open dose receives a backfill patient. The time to
response is Weibull (resp_window, resp_late_fraction), and the DLT and
the response are linked by a Gaussian copula (resp_cor, 0 by default), as
in Takeda et al. (2025).
The engine is written in C++ (src/backfill_core.h). The DLT variates of
the escalation are drawn from R's stream as in boin_simulate(); arrivals,
backfill patients and responses have generators of their own. When no dose
is ever opened for backfilling the trials are identical to those of
boin_simulate() (BF-BOIN) and of tite_boin_simulate() (BE-BOIN with
no_slot = "wait") with the same seed, which the tests check.
With stay_on_1_of_3 = TRUE, n_earlystop = 9, accrual = "uniform" and
no_slot = "leave", the operating characteristics of Table 4 of Zhao et al.
(2024), twelve scenarios of BF-BOIN and five of BOIN, are reproduced within
simulation error, durations included; over 20 seeds of 10,000 trials the
largest gaps were 2.1 points for the selection, 0.4 patients and 0.17
months. The article states a Poisson process of arrivals, but its durations
agree with uniform times between arrivals and patients turned away while the
escalation waits. inst/validation/compare-with-Zhao2024.R repeats the
comparison.
The trial examples of Figure 1 of Zhao et al. (2024) and of Section S2 of the supplementary materials of Chen et al. (2026) are replayed patient by patient, and the simulated trials agree exactly with a separate implementation written in Python, over 2,700 trials of both designs.
comb_boin_simulate() simulates the BOIN drug-combination design of Lin and
Yin (2017), which looks for a single MTD in a matrix of dose combinations of
two drugs. After each cohort the decision of the single-agent design is
taken at the current combination; an escalation goes one level up of either
drug, and a de-escalation one level down, to the neighbor with the larger
posterior probability that its DLT rate lies between the boundaries. The
engine is written in C++ (src/comb_core.h) and follows
BOIN::get.oc.comb() with mtd.contour = FALSE: the same rules, applied in
the same order, with the random variates drawn in the same order, so that
with the same seed the two produce the same trials.
comb_boin_select_mtd() selects the MTD combination from completed trials,
with the bivariate isotonic regression of Iso::biviso(), the routine the
reference implementation calls. Combinations that the regression pools are
equal in exact arithmetic but can differ in their last digits, and these
digits decide between combinations on the same anti-diagonal, so another
algorithm would select differently in a few trials out of a thousand. The
'Iso' package, which version 1.4.0 moved to Suggests, is therefore imported
again.
sim_comb_boin() and sim_comb_boin_multi() summarize the simulated trials:
the selection percentage and the average numbers of patients and DLTs at
every combination, the percentages of trials selecting a true MTD
combination and of patients treated at one, and the exposure to
combinations above overdose_cutoff. They have their own print()
methods, and the table of sim_comb_boin_multi() has one row per scenario.
comb_boin_next() gives the combination for the next cohort of a trial in
progress, from the numbers of patients and DLTs observed at every combination
and the combination of the last cohort. It reports the boundaries that apply,
the two candidates with their posterior probabilities and scores, both
candidates when they tie, the combinations eliminated, and why the trial
stops when it does. It has print() and plot() methods; the plot draws the
dose matrix with the data, the current and next combinations and the
eliminated ones. The decision is taken by the same C++ code as in the
simulations (comb_decide() in src/comb_core.h), so a trial is run with the
rules whose operating characteristics sim_comb_boin() reports. These differ
from BOIN::next.comb() in three respects: BOIN::next.comb() stops as soon
as n.earlystop patients have been treated at the current combination,
blocks an escalation of one drug when a combination at the next level of that
drug has an observed DLT rate at or above lambda_d, and breaks ties at
random. The tests check that comb_boin_next() takes the decision of
simulated trials after every cohort, and that it agrees with
BOIN::next.comb() on random data wherever the rules coincide. The C++ code
also takes the same decision as the Python implementation at each of the
40,664 states reached by 3,300 simulated trials in 11 settings.
The tests reproduce the example of Yan et al. (2020): every number printed
by summary() in the article agrees to the printed precision. The one
average exactly half-way between two printed values, 1.905 patients at A2B4,
is printed 1.90 in the article and 1.91 by R 4.6.0; how such a value is
rounded depends on the version of R. The tests also check exact agreement
with BOIN::get.oc.comb() in nine settings whenever the BOIN package is
installed. The simulated trials also agree exactly with a separate
implementation written in Python and run on a replica of R's random number
stream, over 5,500 trials in 11 settings.
inst/validation/compare-comb-with-BOIN.R extends the comparison with BOIN
to 200 configurations, and inst/validation/compare-with-LinYin2017.R sets
the results beside Tables 2 and 3 of Lin and Yin (2017), whose rules differ
in some details.
The waterfall design of Zhang and Yuan (2016), which looks for the MTD contour, and a time-to-event version of the drug-combination design are not provided.
decision_table_3p3() tabulates the rule of the 3+3 design used by
oc_3p3() and sim_3p3(): the decision at three and at six patients during
dose escalation and, for mtd_rule = "expand", during the search for the MTD
that follows. It has print() and plot() methods in the style of the BOIN
decision table. The tests follow the table through every possible course of a
trial and obtain the operating characteristics of oc_3p3().A second vignette, vignette("simFastBOIN-tite"), describes the TITE-BOIN
design. The introductory vignette gains a pointer to it and a paragraph on
decision_table_3p3().
The README describes the design, how it is checked, and its speed: 10,000
trials of five doses and 20 cohorts of three take 0.09 s with the imputation
method and 0.11 s with the effective sample size, against 0.05 s for
sim_boin() on the same machine.
The labels of plot.tite_boin_decision_table() are shorter, the codes over
the boundaries (for example E/S over >=2.15), so that they fit in the
cells.
A third vignette, vignette("simFastBOIN-backfill"), describes the BF-BOIN
and BE-BOIN designs, and the README and the introductory vignette point to
it.
The DESCRIPTION cites the two TITE-BOIN articles and the three articles on backfilling and its suspension rules.
A fourth vignette, vignette("simFastBOIN-combination"), describes the
drug-combination design, and the README and the introductory vignette point
to it. The DESCRIPTION cites Lin and Yin (2017). The vignette also shows the
decision table for a protocol and how to run a trial with
comb_boin_next().
A pkgdown configuration (_pkgdown.yml) groups the reference pages by design
and lists the four vignettes as articles.
The plot() methods of boin_decision_table(),
tite_boin_decision_table() and comb_boin_next() draw the legend key of
every decision or status, including those that do not occur in the figure,
which ggplot2 3.5.0 and later otherwise leave blank.
The first release since 1.3.2, and a breaking one. Versions 1.4.0 and 1.5.0 were development versions on GitHub and were never released; their entries are kept below because the changes they describe are all part of this release. Anyone upgrading from 1.3.2 should read the 1.4.0 entry, which lists the renamed functions and the corrected defects.
This section covers three design options requested for a quality control review.
Every new option is off by default, so a simulation run with version 1.4.0
arguments produces exactly the same trials, selections and summary figures. Two
names in the returned objects did change, and are listed under their respective
headings below: overdose60 and overdose80 moved into the new overdose
component, and one reason code was renamed.
stay_on_1_of_3 makes one DLT out of three patients a stay rather than a
de-escalation, which is the modification offered by the BOIN web application.
It is available on boin_boundary(), boin_decision_table(),
boin_simulate(), sim_boin() and sim_boin_multi().
The option raises the de-escalation boundary at three patients from one DLT to
two, so exactly one cell of the decision table changes and nothing else moves.
It is applied only where one DLT out of three currently de-escalates: it never
overrides an escalation, and it never overrides an elimination, which is a
safety rule. boin_boundary() reports whether it took effect in
stay_on_1_of_3_applied.
With the default thresholds it takes effect for target rates from about 0.098 to 0.279. Note that the web application describes the range as 0.25 to 0.279; the upper end agrees, but the lower end is 0.098, below which one DLT out of three already eliminates the dose.
mtd_max_estimate caps the isotonic estimate a dose may have and still be
selected as the MTD, on boin_select_mtd(), sim_boin() and
sim_boin_multi(). It changes only the selection, never the dose-finding, so
the decision table is untouched.
bound_mtd caps the estimate at the de-escalation boundary, which always lies
above the target rate. A cap at or below the target therefore cannot be
expressed with bound_mtd at all, and needs mtd_max_estimate.
The reason code "no_dose_below_lambda_d" returned by boin_select_mtd() is
now "no_dose_below_bound", since the bound need not be the de-escalation
boundary.
sim_boin() and sim_boin_multi() gain overdose_cutoff, and report an
overdose component describing how far patients were exposed to doses whose
true DLT probability exceeds it:
pct_patients, the percentage of all simulated patients treated at such a
dose, that is the probability that a patient is dosed above the cutoff;pct_patients_by_trial, the same percentage computed within each trial and
then averaged;avg_n_patients, pct_trials_any, pct_trials_over_60 and
pct_trials_over_80.and how often the design ends up recommending such a dose, which is a separate question from exposure during the trial:
pct_trials_mtd_above, the percentage of all trials whose selected MTD is
above the cutoff;pct_mtd_above_when_selected, the same among the trials that selected an
MTD at all.The cutoff defaults to target, which reproduces the earlier behavior.
This replaces the overdose60 and overdose80 components of the result, which
are now overdose$pct_trials_over_60 and overdose$pct_trials_over_80. They
are reported as zero rather than NA when no dose exceeds the cutoff, and the
doses component names the dose levels that do.
boin_p_tox() returns the value of p_tox for which the de-escalation
boundary equals a stated value, inverting boin_lambda(). A design team that
wants to tighten the boundary usually states the boundary rather than the
threshold behind it, and this turns that statement into the argument the other
functions take.
A boundary close to the target needs a threshold close to the target, and the
rest of the package refuses a p_tox within ten percent of target. The
inverted value is still returned, but a warning names the smallest boundary
that leaves a usable threshold: about 0.315 for a target of 0.30.
print() on the result of sim_boin_multi() gains percent and digits,
which the method for a single scenario already had. Passing percent = TRUE
to the cross-scenario method previously fell into ... and was ignored, so
the counts were printed as though nothing had been asked for.start_dose, added in version 1.4.0, is now documented as being ignored when
titration = TRUE, because the titration phase always begins at the lowest
dose. This matches the reference implementation.
The spelling throughout the documentation is now the United States spelling
declared by the Language field, and tests/spelling.R keeps it that way.
The colours argument of plot.boin_decision_table() is renamed colors
accordingly. The argument was introduced in version 1.4.0, which was never
released, so no released code is affected.
oc_3p3() returns the operating characteristics of the traditional 3+3
design. The probability of every path the design can take is evaluated in
closed form, so the result carries no Monte Carlo error and takes no seed.
sim_3p3() simulates the same design and is there to confirm the closed form.
Both return an object of class oc_3p3 whose components carry the same names
as those of sim_boin(), so the two designs can be tabulated side by side, and
print() lays them out the same way.
mtd_rule selects between the two definitions of the MTD in common use.
"previous" names the dose below the one declared too toxic. "expand" takes
the MTD to be the highest dose at which at most one of six patients had a DLT,
expanding a dose that has only three patients before assessing it. Neither is
universally the standard, so the comparator being matched should be checked
before a rule is chosen. The two agree on which doses are visited during
escalation, and therefore on the probability that a patient is exposed to an
overly toxic dose; they differ in the sample size and in the selection
percentages.
overdose_cutoff works as it does for sim_boin() and defaults to one third
here, which is the rate the regulatory question is asked about. The 3+3 design
has no fixed maximum sample size, so the within-trial exposure percentage and
the 60 percent and 80 percent thresholds reported for BOIN have no counterpart
and are not returned.
inst/validation/compare-with-BOIN.R compares the package against BOIN over
200 configurations, five dose-toxicity scenarios by five designs by eight
option combinations, and covers extrasafe, titration and boundMTD. All
200 agree to within floating point on the selection percentages, the patients
and DLTs at each dose, the percentage of trials ending without an MTD and the
totals. This is a defect test rather than a Monte Carlo comparison, because the
two implementations draw the same variates in the same order for a given seed.
The options that BOIN has no counterpart for are checked separately, to
confirm that each leaves the simulated trials untouched when it is off.This is a substantial revision. The simulation engine has been rewritten in C++, the user-facing functions have been renamed, and several defects that affected numerical results have been corrected. Results obtained with version 1.3.2 are not reproduced by this version, even with the same seed.
The engine now draws one uniform variate per patient, in enrollment order, and
applies the decision rules in the same order as
BOIN::get.oc(). With the same seed and matching arguments the two
implementations agree trial by trial rather than only on average. The test suite
checks this directly against BOIN::get.oc() and BOIN::get.boundary() when the
BOIN package is installed.
Version 1.3.2 claimed in its README that random number generation was the same as that of the BOIN package when the seed was fixed. That claim was incorrect, because trials were generated across trials rather than one at a time, and it has been removed.
max_total_pts was computed as n_cohort * cohort_size[1], so a trial with a
vector cohort_size used the wrong maximum sample size. It is now the sum of
the cohort sizes.
With titration = TRUE and a vector cohort_size, the titration phase tested
if (cohort_size > 1) on a vector, which stops with an error on R 4.2 and
later.
The early stopping rule at n_earlystop was evaluated after the dose had
already been changed, and therefore against the wrong dose. It is now evaluated
at the dose that was just treated, before the transition, as in the reference
implementation. This changes operating characteristics, in particular when a
de-escalation lands on a dose that has already accrued n_earlystop patients.
MTD selection now re-derives dose elimination from the final data of the trial instead of carrying the elimination status over from the dose-finding stage. The two differ when a trial ends at its maximum sample size, because the last cohort was then never checked against the elimination boundary.
The isotonic fit used for MTD selection is now computed over the admissible doses only. Previously every treated dose entered the fit, so an eliminated dose could change the estimates at the doses below it and hence the selected MTD.
The tie-breaking perturbation was applied twice, once inside
isotonic_regression() and once inside select_mtd(), and was indexed by dose
level rather than by position in the admissible set. It is now applied once,
during MTD selection, and boin_isotonic() returns the unperturbed estimates.
get_pts_and_tox() called set.seed() without restoring the state of the
random number generator. The new functions restore it on exit.
Random number generation was not consistent within a trial: the titration phase, the ordinary cohorts and the final partial cohort used three different schemes, the last of which drew a binomial variate. All patients now use a single scheme.
The old names remain available and issue a deprecation warning, but they return
the value of the replacement function, which is not the value returned by version
1.3.2. See ?"simFastBOIN-deprecated".
| Version 1.3.2 | Version 1.4.0 |
|---|---|
| get_boin_boundary() | boin_lambda(), and boin_boundary() for the integer boundaries |
| get_boin_decision() | boin_decision_table() |
| get_boin_stopping_boundaries() | boin_boundary(extrasafe = TRUE) |
| get_pts_and_tox() | boin_simulate() |
| isotonic_regression() | boin_isotonic() |
| select_mtd() | boin_select_mtd() |
sim_boin() and sim_boin_multi() keep their names.
The design arguments come first: sim_boin(target, p_true, n_cohort, cohort_size, ...), with n_trials now an optional argument. Calls that relied
on positional matching must be updated.
boundMTD is now bound_mtd, and return_details is now keep_trials.
sim_boin() returns an object of class boin_oc directly, rather than a list
with a summary element. Selection percentages, average patient counts and
average DLT counts are separate components, and the percentage of trials
selecting no MTD is no longer appended to the selection vector.
sim_boin() and sim_boin_multi() now return their result visibly, so calling
them at the prompt prints the summary and assigning the result is silent.
Previously the result was invisible unless verbose = TRUE.
sim_boin_multi() uses the same seed for every scenario. Version 1.3.2 used
seed + i for the i-th scenario, so a scenario simulated in a multi-scenario
run did not match the same scenario simulated on its own.
sim_boin_multi() accepts a plain named list of p_true vectors in addition
to the list of list(name, p_true) used previously.
boin_select_mtd() takes the patient and DLT counts, not precomputed isotonic
estimates, since the fit depends on which doses are admissible.
Progress messages are emitted with message() rather than cat(), so they can
be suppressed with suppressMessages().
start_dose, matching the reference implementation, which did not exist in
version 1.3.2.boin_boundary() returns the escalation, de-escalation, elimination and safety
stopping boundaries as integer DLT counts indexed by sample size, with a print
method that can restrict the table to the end of each cohort.boin_decision_table() returns a classed object with print and plot
methods. The print method blanks the impossible combinations and can restrict
the table to the sample sizes reached at the end of a cohort; the plot method
draws the table as a grid of colored cells, each carrying its decision letter
so that the figure does not rely on color alone. It needs ggplot2, which is
suggested rather than required.boin_stopping_table() lays the safety stopping boundary out as a two-row
table, one column per sample size.boin_simulate() returns the raw trial data with a stop_reason for every
trial, and has a print method.p_true and inconsistent counts are reported instead
of propagating silently.Rcpp, and utils for one call to globalVariables().ggplot2 to Suggests, used only by plot.boin_decision_table().Iso. The pool adjacent violators algorithm is implemented in C++;
Iso is now only suggested, and used in a test that checks the two agree.knitr and kableExtra moved out of Imports. knitr is suggested and used
for the vignette and for the optional table output; kableExtra is no longer
used.utils was imported in NAMESPACE but absent from DESCRIPTION. Neither
imports it now.The C++ engine replaces the vectorised R implementation, and MTD selection no
longer calls out to R once per trial. For five doses, 20 cohorts of three,
n_earlystop = 18 and 10000 simulated trials, one measurement gave 9.98 seconds
elapsed for BOIN::get.oc() against 0.07 seconds for sim_boin(). The ratio
depends on the design and on the machine, and the README carries the code that
reproduces the measurement.
Added p_saf and p_tox parameters to core functions
sim_boin(), sim_boin_multi(), and get_pts_and_tox() now accept custom safety and toxicity thresholdsp_saf: Highest toxicity probability deemed acceptable for safety (default: 0.6 * target)p_tox: Lowest toxicity probability deemed unacceptable for toxicity (default: 1.4 * target)get_boin_boundary() for boundary calculationUsage examples
# Using default thresholds (0.6 * target and 1.4 * target)
result_default <- sim_boin(
n_trials = 10000,
target = 0.30,
p_true = c(0.10, 0.25, 0.40, 0.55, 0.70),
n_cohort = 10,
cohort_size = 3,
seed = 123
)
# Using custom thresholds
result_custom <- sim_boin(
n_trials = 10000,
target = 0.30,
p_true = c(0.10, 0.25, 0.40, 0.55, 0.70),
n_cohort = 10,
cohort_size = 3,
p_saf = 0.15, # Custom safety threshold
p_tox = 0.45, # Custom toxicity threshold
seed = 123
)
Enhanced parameter documentation
p_saf and p_tox parametersExpanded test coverage
p_saf and p_tox parameter handling in sim_boin()p_saf and p_tox parameter handling in sim_boin_multi()p_saf and p_tox parameter handling in get_pts_and_tox()None. All existing code continues to work as before. The new p_saf and p_tox parameters have sensible defaults (0.6 * target and 1.4 * target respectively) that match the standard BOIN methodology, ensuring full backward compatibility.
p_saf and p_tox parameters with NULL defaultsp_saf and p_tox values for reproducibilityNo functional changes. All code and features remain identical to version 1.3.0.
Added verbose parameter to sim_boin() and sim_boin_multi()
verbose = FALSE (default): Run silently without progress messagesverbose = TRUE: Display progress messages as in previous versionsUsage examples
# Silent mode (default) - ideal for vignettes and reports
result <- sim_boin(
n_trials = 10000,
target = 0.30,
p_true = c(0.10, 0.25, 0.40, 0.55, 0.70),
n_cohort = 10,
cohort_size = 3,
seed = 123
)
# With progress messages
result <- sim_boin(
n_trials = 10000,
target = 0.30,
p_true = c(0.10, 0.25, 0.40, 0.55, 0.70),
n_cohort = 10,
cohort_size = 3,
verbose = TRUE,
seed = 123
)
Standardized roxygen2 documentation format
Updated vignettes
None. All existing code continues to work as before. The new verbose parameter defaults to FALSE, which changes the default behavior to silent mode, but all functionality remains identical.
For users who prefer the previous behavior with progress messages:
# Add verbose = TRUE to see progress messages
result <- sim_boin(
n_trials = 10000,
target = 0.30,
p_true = p_true,
n_cohort = 48,
cohort_size = 3,
verbose = TRUE, # Add this line
seed = 123
)
Added sim_boin_multi() function
sim_boin()Usage example
scenarios <- list(
list(name = "Scenario 1: MTD at DL4",
p_true = c(0.05, 0.10, 0.20, 0.30, 0.45)),
list(name = "Scenario 2: MTD at DL3",
p_true = c(0.10, 0.15, 0.30, 0.45, 0.60))
)
result <- sim_boin_multi(
scenarios = scenarios,
target = 0.30,
n_trials = 10000,
n_cohort = 48,
cohort_size = 3,
seed = 123
)
Added html format option to print.boin_summary() and print.boin_multi_summary()
kable_format = "html": Generate HTML tables with enhanced stylingUpdated kable_format parameter documentation
"pipe" (default): Markdown pipe table format"simple": Minimal text table format"latex": LaTeX table format"html": HTML table format with enhanced styling (NEW)Enhanced print output examples
# HTML table for web display
print(result$summary, kable = TRUE, kable_format = "html")
# Multi-scenario results as HTML
print(multi_result, kable = TRUE, kable_format = "html")
Added detailed roxygen2-formatted documentation to all functions
get_boin_boundary(): Escalation and de-escalation boundary calculationget_boin_decision(): Decision table generation with decision rulesget_boin_stopping_boundaries(): Safety stopping rule table generationget_pts_and_tox(): Patient enrollment and toxicity simulationisotonic_regression(): Isotonic regression with PAVA algorithmselect_mtd(): MTD selection with optional boundMTD constraintsim_boin(): Main simulation workflowsim_boin_multi(): Multi-scenario simulation orchestrationprint.boin_summary(): Summary table printing and formattingprint.boin_multi_summary(): Multi-scenario summary printing and formattingEnhanced function comments
percent parameter
percent = FALSE (default): Display Avg Pts and Avg DLTs as absolute numberspercent = TRUE: Display as percentages of totalAll changes are backward compatible. New parameters have sensible defaults.
runif() back to rbinom()rbinom() ensures identical random number sequence as BOIN with same seedmin_mtd_sample: Changed from 6 to 1
n_earlystop_rule: Changed default from "simple" to "with_stay"
rbinom() for accurate DLT generation matching BOIN packageNone. The changes restore compatibility and fix defaults to match standard BOIN behavior. Users running with explicit parameters should see no change.
For users upgrading from simFastBOIN 1.1.0:
If you were using defaults:
# Old code (simFastBOIN 1.0.0)
result <- sim_boin(n_trials = 10000, target = 0.30, p_true = p_true, ...)
# New code (simFastBOIN 1.2.0) - No change needed!
# Default behavior now matches BOIN package
result <- sim_boin(n_trials = 10000, target = 0.30, p_true = p_true, ...)
If you were using custom parameters:
# Explicitly setting these will ensure consistent behavior across versions
result <- sim_boin(
n_trials = 10000,
target = 0.30,
p_true = p_true,
min_mtd_sample = 1, # Now the default
n_earlystop_rule = "with_stay", # Now the default
...
)
High-Performance BOIN Simulation
Automatic Decision Table Generation
sim_boin() automatically generates BOIN boundaries and decision tablesSafety Features
extrasafe parameter for safety stopping at lowest doseProfessional Output
sim_boin(): Run BOIN trial simulationsget_boin_boundary(): Calculate BOIN interval boundariesget_boin_decision(): Generate decision tableget_boin_stopping_boundaries(): Generate safety stopping boundariesisotonic_regression(): Apply isotonic regression for dose-toxicity estimationsummarize_simulation_boin(): Aggregate simulation results