Author: Gosuke Homma
Date: 2025-12-11

# Introduction to simFastBOIN

#### Gosuke Homma

#### 2025-12-11

## Overview

simFastBOIN provides fast and efficient simulation tools for Bayesian Optimal Interval (BOIN) designs in Phase I clinical trials. The package enables researchers to evaluate operating characteristics and design performance across different dose-toxicity scenarios.

### Key Features

- High Performance: Vectorized implementation (2-5x faster than traditional approaches)
- BOIN Compatible: Results match BOIN package within <0.5% across all scenarios
- User-Friendly: Simplified API with automatic decision table generation
- Flexible: Multiple safety stopping rules and customizable design parameters
- Multi-Scenario Support: Evaluate multiple dose-toxicity scenarios simultaneously
- Publication-Ready Output: Professional table formatting options

## Installation

    # Install from GitHub
    devtools::install_github("gosukehommaEX/simFastBOIN")

## Basic Usage

    library(simFastBOIN)

### Running a Basic BOIN Simulation

The most basic simulation requires only a few parameters:

    # Define design parameters
    target <- 0.30  # Target DLT rate (30%)
    p_true <- c(0.10, 0.25, 0.40, 0.55, 0.70)  # True toxicity probabilities

    # Run simulation (progress messages suppressed)
    result <- sim_boin(
      n_trials = 1000,
      target = target,
      p_true = p_true,
      n_cohort = 10,
      cohort_size = 3,
      seed = 123
    )

    # Display results
    print(result$summary)
    #> |         Metric|       DL1|       DL2|       DL3|       DL4|       DL5|Total/No MTD|
    #> ----------------------------------------------------------------------------------
    #> |   True Tox (%)|      10.0|      25.0|      40.0|      55.0|      70.0|          |
    #> |    MTD Sel (%)|      10.8|      52.4|      33.8|       2.8|       0.1|       0.1|
    #> |        Avg Pts|       6.8|      11.9|       7.7|       1.8|       0.1|      28.4|
    #> |       Avg DLTs|       0.7|       3.0|       3.1|       1.0|       0.1|       7.9|
    #> ----------------------------------------------------------------------------------

### Understanding the Output

The summary table contains four key sections:

1. True Toxicity (%): The actual DLT rate at each dose
2. MTD Selected (%): Percentage of trials selecting each dose as MTD
3. Participants Treated (mean): Average patient enrollment at each dose
4. Participants w/ DLTs (mean): Average DLT counts at each dose

## BOIN Standard Implementation

For BOIN standard compliance, use the following recommended settings:

    result_standard <- sim_boin(
      n_trials = 1000,
      target = 0.30,
      p_true = c(0.10, 0.25, 0.40, 0.55, 0.70),
      n_cohort = 10,
      cohort_size = 3,
      boundMTD = TRUE,              # Conservative MTD selection
      n_earlystop_rule = "with_stay",  # Stop when converged
      seed = 123
    )

    print(result_standard$summary, scenario_name = "BOIN Standard")
    #> Scenario: BOIN Standard
    #>
    #> |         Metric|       DL1|       DL2|       DL3|       DL4|       DL5|Total/No MTD|
    #> ----------------------------------------------------------------------------------
    #> |   True Tox (%)|      10.0|      25.0|      40.0|      55.0|      70.0|          |
    #> |    MTD Sel (%)|      17.0|      55.8|      25.8|       1.2|       0.1|       0.1|
    #> |        Avg Pts|       6.8|      11.9|       7.7|       1.8|       0.1|      28.4|
    #> |       Avg DLTs|       0.7|       3.0|       3.1|       1.0|       0.1|       7.9|
    #> ----------------------------------------------------------------------------------

### Key Parameters

- `boundMTD = TRUE`: Ensures selected MTD’s isotonic estimate is below the de-escalation boundary
- `n_earlystop_rule = "with_stay"`: Stops trial when dose stays at n_earlystop threshold

## Safety Features

### Extra Safety Stopping

For scenarios with high toxicity uncertainty:

    result_safe <- sim_boin(
      n_trials = 1000,
      target = 0.30,
      p_true = c(0.05, 0.10, 0.20, 0.30, 0.45),
      n_cohort = 10,
      cohort_size = 3,
      extrasafe = TRUE,  # Safety monitoring at lowest dose
      offset = 0.05,     # Safety cutoff adjustment
      seed = 123
    )

    print(result_safe$summary, scenario_name = "With Extra Safety")
    #> Scenario: With Extra Safety
    #>
    #> |         Metric|       DL1|       DL2|       DL3|       DL4|       DL5|Total/No MTD|
    #> ----------------------------------------------------------------------------------
    #> |   True Tox (%)|       5.0|      10.0|      20.0|      30.0|      45.0|          |
    #> |    MTD Sel (%)|       0.3|       5.1|      26.7|      48.4|      18.8|       0.7|
    #> |        Avg Pts|       3.7|       5.4|       8.1|       8.2|       4.0|      29.5|
    #> |       Avg DLTs|       0.2|       0.5|       1.6|       2.4|       1.8|       6.6|
    #> ----------------------------------------------------------------------------------

### Maximum Conservatism

Combining all safety features:

    result_conservative <- sim_boin(
      n_trials = 1000,
      target = 0.30,
      p_true = seq(0.05, 0.45, by = 0.05),
      n_cohort = 20,
      cohort_size = 3,
      extrasafe = TRUE,
      boundMTD = TRUE,
      n_earlystop_rule = "with_stay",
      seed = 123
    )

    print(result_conservative$summary, scenario_name = "Maximum Conservatism")
    #> Scenario: Maximum Conservatism
    #>
    #> |         Metric|       DL1|       DL2|       DL3|       DL4|       DL5|       DL6|       DL7|       DL8|       DL9|Total/No MTD|
    #> ------------------------------------------------------------------------------------------------------------------------------
    #> |   True Tox (%)|       5.0|      10.0|      15.0|      20.0|      25.0|      30.0|      35.0|      40.0|      45.0|          |
    #> |    MTD Sel (%)|       0.3|       2.0|       7.0|      22.0|      25.5|      23.1|      13.0|       5.5|       0.9|       0.7|
    #> |        Avg Pts|       3.7|       4.8|       6.2|       8.6|       8.8|       7.1|       4.3|       1.8|       0.4|      45.8|
    #> |       Avg DLTs|       0.2|       0.5|       0.9|       1.7|       2.2|       2.1|       1.5|       0.7|       0.2|      10.1|
    #> ------------------------------------------------------------------------------------------------------------------------------

## Multi-Scenario Simulations

Evaluate multiple dose-toxicity scenarios simultaneously:

    # Define multiple scenarios
    scenarios <- list(
      list(name = "Scenario 1: MTD at DL3",
           p_true = c(0.05, 0.10, 0.20, 0.30, 0.45)),
      list(name = "Scenario 2: MTD at DL4",
           p_true = c(0.10, 0.15, 0.25, 0.30, 0.45)),
      list(name = "Scenario 3: All doses safe",
           p_true = c(0.05, 0.10, 0.15, 0.20, 0.25))
    )

    # Run multi-scenario simulation
    result_multi <- sim_boin_multi(
      scenarios = scenarios,
      target = 0.30,
      n_trials = 1000,
      n_cohort = 10,
      cohort_size = 3,
      seed = 123
    )

    # Display aggregated results
    print(result_multi)
    #>                    Scenario         Item DL1  DL2  DL3  DL4  DL5 Total/No MTD
    #>      Scenario 1: MTD at DL3 True Tox (%)   5   10   20   30   45
    #>                              MTD Sel (%) 0.2    5 27.9 48.4 18.4          0.1
    #>                                  Avg Pts 3.9  5.5  8.2  8.1    4         29.7
    #>                                 Avg DLTs 0.2  0.5  1.6  2.4  1.8          6.6
    #>      Scenario 2: MTD at DL4 True Tox (%)  10   15   25   30   45
    #>                              MTD Sel (%)   2 12.6 32.6 37.4 15.2          0.2
    #>                                  Avg Pts 4.8  6.9  8.5    6  3.2         29.3
    #>                                 Avg DLTs 0.5    1  2.1  1.8  1.4          6.8
    #>  Scenario 3: All doses safe True Tox (%)   5   10   15   20   25
    #>                              MTD Sel (%) 0.8  2.3 12.2 22.6 62.1            0
    #>                                  Avg Pts 3.7  4.9  6.2  6.3  8.7         29.8
    #>                                 Avg DLTs 0.2  0.5  0.9  1.3  2.2          5.1

## Output Formatting Options

### Percentage Format

Display values as percentages instead of absolute numbers:

    print(result$summary, percent = TRUE)
    #> |         Metric|       DL1|       DL2|       DL3|       DL4|       DL5|Total/No MTD|
    #> ----------------------------------------------------------------------------------
    #> |   True Tox (%)|      10.0|      25.0|      40.0|      55.0|      70.0|          |
    #> |    MTD Sel (%)|      10.8|      52.4|      33.8|       2.8|       0.1|       0.1|
    #> |    Avg Pts (%)|      24.0|      41.9|      27.2|       6.5|       0.5|      28.4|
    #> |   Avg DLTs (%)|       8.6|      38.1|      39.0|      13.2|       1.1|       7.9|
    #> ----------------------------------------------------------------------------------

### Markdown Table Format

For R Markdown documents:

    print(result$summary, kable = TRUE, kable_format = "pipe")
    #>
    #>
    #> |Item         |DL1  |DL2  |DL3  |DL4 |DL5 |Total/No MTD |
    #> |:------------|:----|:----|:----|:---|:---|:------------|
    #> |True Tox (%) |10   |25   |40   |55  |70  |             |
    #> |MTD Sel (%)  |10.8 |52.4 |33.8 |2.8 |0.1 |0.1          |
    #> |Avg Pts      |6.8  |11.9 |7.7  |1.8 |0.1 |28.4         |
    #> |Avg DLTs     |0.7  |3    |3.1  |1   |0.1 |7.9          |

### HTML Format

For web-based reports:

    print(result$summary, kable = TRUE, kable_format = "html")

## Accessing Detailed Results

When `return_details = TRUE`, you can access trial-level information:

    result_detailed <- sim_boin(
      n_trials = 100,
      target = 0.30,
      p_true = c(0.10, 0.25, 0.40, 0.55, 0.70),
      n_cohort = 10,
      cohort_size = 3,
      return_details = TRUE,
      seed = 123
    )

    # Check first trial
    trial_1 <- result_detailed$detailed_results[[1]]
    cat("Trial 1 MTD:", trial_1$mtd, "\n")
    #> Trial 1 MTD: 2
    cat("Trial 1 stopping reason:", trial_1$reason, "\n")
    #> Trial 1 stopping reason: trial_completed

    # Summary of stopping reasons
    stopping_reasons <- table(sapply(result_detailed$detailed_results,
                                    function(x) x$reason))
    print(stopping_reasons)
    #>
    #> trial_completed
    #>             100

## Design Comparison

Compare different safety configurations:

    # Baseline
    result_baseline <- sim_boin(
      n_trials = 1000,
      target = 0.30,
      p_true = c(0.05, 0.10, 0.20, 0.30, 0.45, 0.60),
      n_cohort = 20,
      cohort_size = 3,
      seed = 123
    )

    # With boundMTD
    result_boundMTD <- sim_boin(
      n_trials = 1000,
      target = 0.30,
      p_true = c(0.05, 0.10, 0.20, 0.30, 0.45, 0.60),
      n_cohort = 20,
      cohort_size = 3,
      boundMTD = TRUE,
      seed = 123
    )

    # Create comparison
    comparison <- data.frame(
      Setting = c("Baseline", "boundMTD"),
      Avg_Patients = c(
        result_baseline$summary$avg_total_n_pts,
        result_boundMTD$summary$avg_total_n_pts
      ),
      MTD_Selection_at_DL4 = c(
        result_baseline$summary$mtd_selection_percent[4],
        result_boundMTD$summary$mtd_selection_percent[4]
      )
    )

    print(comparison)
    #>    Setting Avg_Patients MTD_Selection_at_DL4
    #> 1 Baseline       40.842                 52.5
    #> 2 boundMTD       40.842                 52.3

## Performance Benchmarking

simFastBOIN is optimized for speed:

    # Benchmark with 10,000 trials
    system.time({
      result_large <- sim_boin(
        n_trials = 10000,
        target = 0.30,
        p_true = seq(0.05, 0.45, by = 0.05),
        n_cohort = 48,
        cohort_size = 3,
        seed = 123
      )
    })

Typical performance: - 1,000 trials: ~0.02 seconds - 10,000 trials: ~0.25 seconds - 100,000 trials: ~2.7 seconds

## Advanced Features

### Custom Cohort Sizes

Use variable cohort sizes:

    result_variable <- sim_boin(
      n_trials = 1000,
      target = 0.30,
      p_true = c(0.10, 0.25, 0.40, 0.55, 0.70),
      n_cohort = 10,
      cohort_size = c(1, 3, 3, 3, 3, 3, 3, 3, 3, 3),  # First cohort: 1 patient
      seed = 123
    )

### Titration Phase

Enable accelerated dose escalation:

    result_titration <- sim_boin(
      n_trials = 1000,
      target = 0.30,
      p_true = c(0.05, 0.10, 0.20, 0.30, 0.45),
      n_cohort = 20,
      cohort_size = 3,
      titration = TRUE,  # Enable titration phase
      seed = 123
    )

## Stopping Reasons

The package tracks why each trial terminated:

- `"max_cohorts_reached"`: Normal completion
- `"n_earlystop_with_stay"`: Converged at sample size limit
- `"n_earlystop_simple"`: Reached sample size limit (simple rule)
- `"lowest_dose_too_toxic"`: Safety stopping at lowest dose
- `"lowest_dose_eliminated"`: Lowest dose eliminated during trial
- `"max_sample_size_reached"`: Maximum total patients reached

## References

Liu, S. and Yuan, Y. (2015). Bayesian Optimal Interval Designs for Phase I Clinical Trials. Journal of the Royal Statistical Society: Series C, 64, 507–523.

## See Also

- `?sim_boin` - Main simulation function
- `?sim_boin_multi` - Multi-scenario simulation
- `?get_boin_boundary` - BOIN boundary calculation
- `?get_boin_decision` - Decision table generation