# CMR Extensions

This vignette shows three extension workflows that keep the same applied pattern: pass simulated pilot outcomes and design labels, inspect the main-wave allocation, and record the CMR certificate.

    knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
    library(cmrdesign)

## Shared-control multi-arm designs

Use `cmr_multiarm()` when the pilot has multiple treatment arms and one shared control group. The outcome vector `y` has one entry per pilot unit, and `arm` labels the corresponding arm. The control arm is standardized to `"0"` in the result.

    set.seed(505)

    n_per_arm <- 180
    arm <- rep(c(0, 1, 2), each = n_per_arm)
    y <- c(
      rbeta(n_per_arm, shape1 = 4, shape2 = 4),
      rbeta(n_per_arm, shape1 = 2.5, shape2 = 6),
      rbeta(n_per_arm, shape1 = 5, shape2 = 3)
    )

    fit_multi <- cmr_multiarm(y, arm, alpha = 0.05, method = "bounded")

    round(fit_multi$pi, 3)
    #>     0     1     2
    #> 0.414 0.298 0.288
    fit_multi$U_CMR
    #> [1] 0.4317102
    fit_multi$method
    #> [1] "bounded"
    fit_multi$pilot$n
    #>   0   1   2
    #> 180 180 180

The returned `pi` is a named vector of total main-wave assignment shares across control and all treatment arms.

    multi_counts <- realize_allocation(fit_multi, n_main = 1200)

    multi_counts$counts
    #>   0   1   2
    #> 497 357 346
    multi_counts$realized_U_CMR
    #> [1] 0.4325058

## Stratified designs

Use `cmr_stratified()` when the main-wave allocation should adapt across known target-population strata. The `strata_share` input should describe the target population shares, not only the realized pilot composition.

    set.seed(506)

    n_per_cell <- 100
    strata <- rep(c("urban", "rural"), each = 2 * n_per_cell)
    d <- rep(c(rep(1, n_per_cell), rep(0, n_per_cell)), times = 2)
    y <- c(
      rbeta(n_per_cell, shape1 = 2, shape2 = 5),
      rbeta(n_per_cell, shape1 = 4, shape2 = 4),
      rbeta(n_per_cell, shape1 = 3, shape2 = 6),
      rbeta(n_per_cell, shape1 = 5, shape2 = 4)
    )
    strata_share <- c(urban = 0.55, rural = 0.45)

    fit_strata <- cmr_stratified(
      y = y,
      d = d,
      strata = strata,
      strata_share = strata_share,
      alpha = 0.05,
      method = "bounded"
    )

    round(fit_strata$pi_matrix, 3)
    #>   urban rural
    #> 1 0.275 0.220
    #> 0 0.278 0.227
    round(fit_strata$sampling_margin, 3)
    #> urban rural
    #> 0.553 0.447
    round(fit_strata$treatment_margin, 3)
    #> urban rural
    #> 0.498 0.492
    fit_strata$U_CMR
    #> [1] 0.2281025

`pi_matrix` gives the total assignment share for each treatment/control by stratum cell. `sampling_margin` gives the total sample share assigned to each stratum, and `treatment_margin` gives the treatment share within each stratum.

If field implementation fixes the number of main-wave units in each stratum, pass those totals through `strata_counts`; the function rounds the treatment/control split within stratum.

    strata_counts <- realize_allocation(
      fit_strata,
      strata_counts = c(urban = 550, rural = 450)
    )

    strata_counts$counts
    #> 1:urban 0:urban 1:rural 0:rural
    #>     274     276     222     228

## Raw unbounded outcomes

Use `cmr_unbounded()` when the two-arm outcome is raw and finite but not assumed to be bounded on a known scale. This method requires a bounded-kurtosis input `psi`. It is currently a two-arm extension only.

    set.seed(507)

    n_per_arm <- 1500
    d <- c(rep(1, n_per_arm), rep(0, n_per_arm))
    y <- c(
      0.20 + 1.10 * rt(n_per_arm, df = 8),
      0.00 + 0.70 * rt(n_per_arm, df = 8)
    )

    fit_unbounded <- cmr_unbounded(
      y = y,
      d = d,
      psi = c(treatment = 6, control = 6),
      alpha = 0.10
    )

    fit_unbounded$pi
    #> [1] 0.6152421
    fit_unbounded$U_CMR
    #> [1] 0.9331825
    fit_unbounded$pilot[c("rho", "b", "active", "status")]
    #> $rho
    #>      rho1      rho0
    #> 0.6720215 0.6720215
    #>
    #> $b
    #> b1 b0
    #> 31 31
    #>
    #> $active
    #> [1] TRUE
    #>
    #> $status
    #> [1] "active"

If the median-of-means variance interval is inactive because the pilot is too small, the relative radius is too large, or the variance estimate is zero, the function returns the balanced assignment with no finite certificate. Check `fit_unbounded$pilot$status` before using the result.