simFastBOIN 2.1.0
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
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 hasprint()andplot()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) andmin_completed(escalation requires two patients with a completed assessment, the default of the effective sample size method).min_follow_upadds 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 intite_boin_decision_table(),tite_boin_simulate(),sim_tite_boin()andsim_tite_boin_multi(), and defaults to 0, which changes nothing. Withmax_pending_ratio = 0.49(their rule 1 with A = 51) andmin_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 simulation engine
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 ofboin_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 positivemin_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_weightsweights 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 ofboin_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.
TITE-BOIN operating characteristics
sim_tite_boin()andsim_tite_boin_multi()summarize simulated TITE-BOIN trials in the same way assim_boin()andsim_boin_multi(), with the same options for selecting the MTD (bound_mtd,mtd_max_estimate,min_mtd_sample) and the sameoverdosecomponent. 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")andc("tite_boin_oc_multi", "boin_oc_multi")), so code that reads the result ofsim_boin()also reads them. They have their ownprint()methods, which also show the design and the timing; the table ofsim_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.
Backfilling: BF-BOIN and BE-BOIN
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 thann_cappatients 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.49andmin_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()andsim_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 insim_boin(). They have their ownprint()methods, and the table of the_multifunctions has seven rows per scenario.Points that the articles leave open are arguments:
no_slotdecides whether a patient with nowhere to go waits or is turned away,conflict_dosewhether the highest (Zhao et al., 2024) or the lowest (Chen et al., 2026) conflicting dose anchors the pooled estimate, andbackfill_dosewhich 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 inboin_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 ofboin_simulate()(BF-BOIN) and oftite_boin_simulate()(BE-BOIN withno_slot = "wait") with the same seed, which the tests check.With
stay_on_1_of_3 = TRUE,n_earlystop = 9,accrual = "uniform"andno_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.Rrepeats 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.
BOIN design for drug combinations
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 followsBOIN::get.oc.comb()withmtd.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 ofIso::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()andsim_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 aboveoverdose_cutoff. They have their ownprint()methods, and the table ofsim_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 hasprint()andplot()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()insrc/comb_core.h), so a trial is run with the rules whose operating characteristicssim_comb_boin()reports. These differ fromBOIN::next.comb()in three respects:BOIN::next.comb()stops as soon asn.earlystoppatients 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 abovelambda_d, and breaks ties at random. The tests check thatcomb_boin_next()takes the decision of simulated trials after every cohort, and that it agrees withBOIN::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 withBOIN::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.Rextends the comparison with BOIN to 200 configurations, andinst/validation/compare-with-LinYin2017.Rsets 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.
3+3 decision table
-
decision_table_3p3()tabulates the rule of the 3+3 design used byoc_3p3()andsim_3p3(): the decision at three and at six patients during dose escalation and, formtd_rule = "expand", during the search for the MTD that follows. It hasprint()andplot()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 ofoc_3p3().
Documentation
A second vignette,
vignette("simFastBOIN-tite"), describes the TITE-BOIN design. The introductory vignette gains a pointer to it and a paragraph ondecision_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 forsim_boin()on the same machine.The labels of
plot.tite_boin_decision_table()are shorter, the codes over the boundaries (for exampleE/Sover>=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 withcomb_boin_next().A pkgdown configuration (
_pkgdown.yml) groups the reference pages by design and lists the four vignettes as articles.The
plot()methods ofboin_decision_table(),tite_boin_decision_table()andcomb_boin_next()draw the legend key of every decision or status, including those that do not occur in the figure, whichggplot23.5.0 and later otherwise leave blank.
simFastBOIN 2.0.0
CRAN release: 2026-09-18
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.
Staying on one DLT out of three
-
stay_on_1_of_3makes 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 onboin_boundary(),boin_decision_table(),boin_simulate(),sim_boin()andsim_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 instay_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.
Bounding the MTD by a stated DLT rate
-
mtd_max_estimatecaps the isotonic estimate a dose may have and still be selected as the MTD, onboin_select_mtd(),sim_boin()andsim_boin_multi(). It changes only the selection, never the dose-finding, so the decision table is untouched.bound_mtdcaps 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 withbound_mtdat all, and needsmtd_max_estimate. The reason code
"no_dose_below_lambda_d"returned byboin_select_mtd()is now"no_dose_below_bound", since the bound need not be the de-escalation boundary.
Exposure to overly toxic doses
-
sim_boin()andsim_boin_multi()gainoverdose_cutoff, and report anoverdosecomponent 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_60andpct_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
overdose60andoverdose80components of the result, which are nowoverdose$pct_trials_over_60andoverdose$pct_trials_over_80. They are reported as zero rather thanNAwhen no dose exceeds the cutoff, and thedosescomponent names the dose levels that do.
Choosing a de-escalation boundary directly
-
boin_p_tox()returns the value ofp_toxfor which the de-escalation boundary equals a stated value, invertingboin_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_toxwithin ten percent oftarget. 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.
Printing
-
print()on the result ofsim_boin_multi()gainspercentanddigits, which the method for a single scenario already had. Passingpercent = TRUEto the cross-scenario method previously fell into...and was ignored, so the counts were printed as though nothing had been asked for.
Documentation
start_dose, added in version 1.4.0, is now documented as being ignored whentitration = 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
Languagefield, andtests/spelling.Rkeeps it that way. Thecoloursargument ofplot.boin_decision_table()is renamedcolorsaccordingly. The argument was introduced in version 1.4.0, which was never released, so no released code is affected.
The 3+3 design as a comparator
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 classoc_3p3whose components carry the same names as those ofsim_boin(), so the two designs can be tabulated side by side, andprint()lays them out the same way.mtd_ruleselects 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_cutoffworks as it does forsim_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.
Validation
-
inst/validation/compare-with-BOIN.Rcompares the package againstBOINover 200 configurations, five dose-toxicity scenarios by five designs by eight option combinations, and coversextrasafe,titrationandboundMTD. 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 thatBOINhas no counterpart for are checked separately, to confirm that each leaves the simulated trials untouched when it is off.
simFastBOIN 1.4.0
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.
Exact agreement with the BOIN package
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.
Corrected defects
max_total_ptswas computed asn_cohort * cohort_size[1], so a trial with a vectorcohort_sizeused the wrong maximum sample size. It is now the sum of the cohort sizes.With
titration = TRUEand a vectorcohort_size, the titration phase testedif (cohort_size > 1)on a vector, which stops with an error on R 4.2 and later.The early stopping rule at
n_earlystopwas 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 accruedn_earlystoppatients.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 insideselect_mtd(), and was indexed by dose level rather than by position in the admissible set. It is now applied once, during MTD selection, andboin_isotonic()returns the unperturbed estimates.get_pts_and_tox()calledset.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.
Renamed functions
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.
Changed interfaces
The design arguments come first:
sim_boin(target, p_true, n_cohort, cohort_size, ...), withn_trialsnow an optional argument. Calls that relied on positional matching must be updated.boundMTDis nowbound_mtd, andreturn_detailsis nowkeep_trials.sim_boin()returns an object of classboin_ocdirectly, rather than a list with asummaryelement. 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()andsim_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 unlessverbose = TRUE.sim_boin_multi()uses the same seed for every scenario. Version 1.3.2 usedseed + ifor 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 ofp_truevectors in addition to the list oflist(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 thancat(), so they can be suppressed withsuppressMessages().
New
-
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 withprintandplotmethods. 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 needsggplot2, 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 astop_reasonfor every trial, and has a print method. - Operating characteristics now include the risk of overdosing 60 and 80 percent of patients, and the distribution of the reason for stopping.
- Arguments are validated. Out-of-range probabilities, thresholds too close to the target, non-monotone
p_trueand inconsistent counts are reported instead of propagating silently.
Dependencies
- Added
Rcpp, andutilsfor one call toglobalVariables(). - Added
ggplot2toSuggests, used only byplot.boin_decision_table(). - Removed
Iso. The pool adjacent violators algorithm is implemented in C++;Isois now only suggested, and used in a test that checks the two agree. -
knitrandkableExtramoved out ofImports.knitris suggested and used for the vignette and for the optional table output;kableExtrais no longer used. -
utilswas imported inNAMESPACEbut absent fromDESCRIPTION. Neither imports it now.
Performance
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.
simFastBOIN 1.3.2
CRAN release: 2025-12-17
New Features
Customizable Safety and Toxicity Thresholds
-
Added
p_safandp_toxparameters to core functions-
sim_boin(),sim_boin_multi(), andget_pts_and_tox()now accept custom safety and toxicity thresholds -
p_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) - These parameters are passed to
get_boin_boundary()for boundary calculation - Stored in summary objects for reference and reproducibility
-
-
Usage 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 )
Documentation Improvements
-
Enhanced parameter documentation
- Added comprehensive roxygen2 documentation for
p_safandp_toxparameters - All @param entries now use consistent multi-line format for better readability
- Updated examples to demonstrate custom threshold usage
- Added comprehensive roxygen2 documentation for
-
Expanded test coverage
- Added tests for
p_safandp_toxparameter handling insim_boin() - Added tests for
p_safandp_toxparameter handling insim_boin_multi() - Added tests for
p_safandp_toxparameter handling inget_pts_and_tox() - Verified that custom values are correctly stored in summary objects
- Verified that default values are correctly calculated when not specified
- Added tests for
simFastBOIN 1.3.0
New Features
Progress Message Control
-
Added
verboseparameter tosim_boin()andsim_boin_multi()- Control whether progress messages are printed to console
-
verbose = FALSE(default): Run silently without progress messages -
verbose = TRUE: Display progress messages as in previous versions - Particularly useful for R Markdown documents and vignettes where clean output is desired
- Results are identical regardless of verbose setting
-
Usage 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 )
Documentation Improvements
-
Standardized roxygen2 documentation format
- All parameter descriptions now use consistent multi-line format
- Improved readability and maintenance
- Enhanced consistency across all functions
-
Updated vignettes
- Clean output without progress messages
- Better integration with R Markdown workflows
- Improved presentation quality
Breaking Changes
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.
Migration Guide
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
)simFastBOIN 1.2.1
New Features: Multi-Scenario Simulation and HTML Output
New Multi-Scenario Simulation Function
-
Added
sim_boin_multi()function- Run BOIN simulations across multiple dose-toxicity scenarios simultaneously
- Automatically orchestrates simulations for each scenario using
sim_boin() - Aggregates results into a unified comparison table
- Ideal for protocol development evaluating multiple dose-toxicity relationships
- Returns results organized by scenario for easy comparison
- Progress messages track simulation status for each scenario
-
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 )
Enhanced Print Methods: HTML Table Output
-
Added
htmlformat option toprint.boin_summary()andprint.boin_multi_summary()-
kable_format = "html": Generate HTML tables with enhanced styling - Includes striped rows, hover effects, and responsive formatting via kableExtra
- Automatically applies visual formatting including bold headers and borders
- Useful for web-based reports and interactive documents
- Full support for embedded HTML display in R Markdown documents
-
-
Updated 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
Documentation and Output Formatting Enhancements
Comprehensive roxygen2 Documentation
-
Added detailed roxygen2-formatted documentation to all functions
-
get_boin_boundary(): Escalation and de-escalation boundary calculation -
get_boin_decision(): Decision table generation with decision rules -
get_boin_stopping_boundaries(): Safety stopping rule table generation -
get_pts_and_tox(): Patient enrollment and toxicity simulation -
isotonic_regression(): Isotonic regression with PAVA algorithm -
select_mtd(): MTD selection with optional boundMTD constraint -
sim_boin(): Main simulation workflow -
sim_boin_multi(): Multi-scenario simulation orchestration -
print.boin_summary(): Summary table printing and formatting -
print.boin_multi_summary(): Multi-scenario summary printing and formatting
-
-
Enhanced function comments
- Added section headers for major processing blocks
- Detailed explanations of algorithm steps and decision logic
- Clear descriptions of parameter usage and constraints
- Clarified relationships between input parameters and outputs
simFastBOIN 1.2.0
Bug Fixes and Compatibility
Default Parameter Corrections
-
Updated default values to match BOIN standard
-
min_mtd_sample: Changed from 6 to 1- Doses with ≥1 patient can now be considered for MTD selection
- Matches BOIN package default behavior
-
n_earlystop_rule: Changed default from “simple” to “with_stay”- Trial now stops when n ≥ n_earlystop AND next decision = “Stay”
- Ensures algorithm convergence before stopping
- Follows BOIN standard implementation
-
Performance Optimizations
Vectorized Implementation
-
Batch processing for improved performance
- Uses vectorized operations for fast simulation
- Pre-allocated vectors and vectorized computations
- Early exit for trials with no valid doses
DLT Generation Optimization
-
Optimized random number generation in sim_boin()
- Uses
rbinom()for accurate DLT generation matching BOIN package - Vectorized operations for efficient computation
- Performance optimization particularly notable for large-scale simulations
- Uses
Internal Improvements
- Enhanced code documentation with detailed optimization rationale
- Improved memory efficiency through pre-allocation
- Maintained backward compatibility with existing APIs
Documentation Updates
- Updated roxygen2 documentation in sim_boin.R
- Updated parameter descriptions
- Updated README.md with corrected default values
Breaking Changes
None. The changes restore compatibility and fix defaults to match standard BOIN behavior. Users running with explicit parameters should see no change.
Migration Guide
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
...
)simFastBOIN 1.0.0
Initial Release
Core Features
-
High-Performance BOIN Simulation
- Vectorized implementation for 2-5x speedup over traditional approaches
- Batch processing of all trials simultaneously at each cohort
- Efficient matrix operations for state management
-
Automatic Decision Table Generation
-
sim_boin()automatically generates BOIN boundaries and decision tables - No need for manual pre-computation
- User-friendly API with minimal required parameters
-
-
Safety Features
- Optional
extrasafeparameter for safety stopping at lowest dose - Dose elimination rules based on posterior probability
- Configurable safety thresholds
- Optional
-
Professional Output
- Publication-ready summary tables
- Optional knitr::kable format for RMarkdown
- Detailed trial-level results available
Main Functions
-
sim_boin(): Run BOIN trial simulations -
get_boin_boundary(): Calculate BOIN interval boundaries -
get_boin_decision(): Generate decision table -
get_boin_stopping_boundaries(): Generate safety stopping boundaries -
isotonic_regression(): Apply isotonic regression for dose-toxicity estimation -
summarize_simulation_boin(): Aggregate simulation results
