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
)p_saf
and p_tox parametersp_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
)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")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 formattingpercent 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
...
)sim_boin() automatically generates BOIN boundaries and
decision tablesextrasafe parameter for safety stopping at
lowest dosesim_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