Author: Metin Bulus & Nianbo Dong
Date: 2021-11-20

# Bound Constrained Optimal Design of Multilevel Regression Discontinuity Designs and Randomized Controlled Trials

#### Metin Bulus & Nianbo Dong

#### 2021-11-20

To install and load the package:

    install.packages("cosa")
    library(cosa)

The following examples demonstrate how to perform bound constrained optimal sample size allocation (BCOSSA) for a two-level cluster randomized trial (CRT) and for the corresponding cluster-level regression discontinuity (CRD) design under three primary constraints. Note: `NULL` arguments are provided for clarity, otherwise they do not have to be explicit.

## Primary Constraint on the Total Cost

    # cost constrained - optimize p and n2
    # CRT('order = 0' or 'rhots = 0')
    crt <- cosa.crd2(order = 0,
                     constrain = "cost", cost = 12500,
                     cn1 = c(5, 2), cn2 = c(50, 20),
                     es = .20,  power = .80, rho2 = .20,
                     g2 = 1, r21 = .20, r22 = .30,
                     p = NULL, n1 = 20,  n2 = NULL)

    ## Solution converged with LBFGS
    ##
    ## Rounded solution:
    ## ---------------------------------------------------
    ##  [n1]  n2     p [cost]  mdes 95%lcl 95%ucl power
    ##    20 132 0.386  12510 0.209  0.063  0.356 0.764
    ## ---------------------------------------------------
    ## Per unit marginal costs:
    ##  Level 1 treatment: 5
    ##  Level 1 control: 2
    ##  Level 2 treatment: 50
    ##  Level 2 control: 20
    ## ---------------------------------------------------
    ## MDES = 0.209 (with power = 80)
    ## power = 0.764 (for ES = 0.2)
    ## ---------------------------------------------------
    ## []: point constrained (fixed)
    ## <<: bound constrained
    ## Random assignment design

    # comparisons to CRDs
    # CRD w/ linear score variable interacting with the treatment
    crd1 <- cosa.crd2(order = 1, interaction = TRUE,
                      constrain = "cost", cost = 12500,
                      cn1 = c(5, 2), cn2 = c(50, 20),
                      es = .20,  power = .80, rho2 = .20,
                      g2 = 1, r21 = .20, r22 = .30,
                      p = .386, n1 = 24,  n2 = NULL)

    ##
    ## RDDE for normal distribution
    ##  based on population moments---------------------------------------
    ## Polynomial order = 1
    ## Interaction w/ treatment = TRUE
    ## Treat if score < cutoff = TRUE
    ## Cutoff = -0.29 | p = 0.386
    ## RDDE = 2.736
    ##
    ## Solution converged with LBFGS
    ##
    ## Rounded solution:
    ## ---------------------------------------------------
    ##  [n1]  n2   [p] [cost]  mdes 95%lcl 95%ucl power
    ##    24 116 0.388  12478 0.364  0.109  0.619 0.338
    ## ---------------------------------------------------
    ## Per unit marginal costs:
    ##  Level 1 treatment: 5
    ##  Level 1 control: 2
    ##  Level 2 treatment: 50
    ##  Level 2 control: 20
    ## ---------------------------------------------------
    ## MDES = 0.364 (with power = 80)
    ## power = 0.338 (for ES = 0.2)
    ## ---------------------------------------------------
    ## []: point constrained (fixed)
    ## <<: bound constrained
    ## Regression discontinuity design

    # CRD w/ quadratic score variable interacting with the treatment
    crd2 <- cosa.crd2(order = 2, interaction = TRUE,
                      constrain = "cost", cost = 12500,
                      cn1 = c(5, 2), cn2 = c(50, 20),
                      es = .20,  power = .80, rho2 = .20,
                      g2 = 1, r21 = .20, r22 = .30,
                      p = .386, n1 = 24,  n2 = NULL)

    ##
    ## RDDE for normal distribution
    ##  based on population moments---------------------------------------
    ## Polynomial order = 2
    ## Interaction w/ treatment = TRUE
    ## Treat if score < cutoff = TRUE
    ## Cutoff = -0.29 | p = 0.386
    ## RDDE = 4.992
    ##
    ## Solution converged with LBFGS
    ##
    ## Rounded solution:
    ## ---------------------------------------------------
    ##  [n1]  n2   [p] [cost]  mdes 95%lcl 95%ucl power
    ##    24 116 0.388  12478 0.491  0.147  0.836 0.207
    ## ---------------------------------------------------
    ## Per unit marginal costs:
    ##  Level 1 treatment: 5
    ##  Level 1 control: 2
    ##  Level 2 treatment: 50
    ##  Level 2 control: 20
    ## ---------------------------------------------------
    ## MDES = 0.491 (with power = 80)
    ## power = 0.207 (for ES = 0.2)
    ## ---------------------------------------------------
    ## []: point constrained (fixed)
    ## <<: bound constrained
    ## Regression discontinuity design

    # example plots
    par(mfrow = c(2, 3), mai = c(.6, .6, .6, .2))
    # compare minimum detectable effect size and 95% CI
    plot(crt, ypar = "mdes", xpar = "n2",
         ylim = c(.10, .90), xlim = c(10, 800),
         ylab = "MDES (with Power = .80)", xlab = "Number of Clusters",
         main = expression(CRT), locate = TRUE)
    plot(crd1, ypar = "mdes", xpar = "n2",
         ylim = c(.10, .90), xlim = c(10, 800),
         ylab = "MDES (with Power = .80)", xlab = "Number of Clusters",
         main = expression(CRD (S + TS)), locate = TRUE)
    plot(crd2, ypar = "mdes", xpar = "n2",
         ylim = c(.10, .90), xlim = c(10, 800),
         ylab = "MDES (with Power = .80)", xlab = "Number of Clusters",
         main = expression(CRD (S + S^2 + TS + TS^2)), locate = TRUE)
    # compare statistical power
    plot(crt, ypar = "power", xpar = "n2",
         ylim = c(.10, .85), xlim = c(10, 800),
         ylab = "Power (for ES = .20)", xlab = "Number of Clusters",
         main = expression(CRT), locate = TRUE)
    plot(crd1, ypar = "power", xpar = "n2",
         ylim = c(.10, .85), xlim = c(10, 800),
         ylab = "Power (for ES = .20)", xlab = "Number of Clusters",
         main = expression(CRD(S + TS)), locate = TRUE)
    plot(crd2, ypar = "power", xpar = "n2",
         ylim = c(.10, .85), xlim = c(10, 800),
         ylab = "Power (for ES = .20)", xlab = "Number of Clusters",
         main = expression(CRD (S + S^2 + TS + TS^2)), locate = TRUE)

As seen from the MDES and power plots, a little less than 150 clusters are needed to obtain the benchmark power rate of 80% for the CRT, more than 350 cluster are needed for CRD with linear score variable interacting with the treatment, and more than 650 clusters are needed for CRD with quadratic score variable interacting with the treatment. Precise number of clusters can be found via placing the primary constraint on either the effect size or the power rate.

## Primary Constraint on the Effect Size

    # cost constrained - optimize p and n2
    # CRT('order = 0' or 'rhots = 0')
    cosa.crd2(order = 0,
              constrain = "es", es = .20,
              cn1 = c(5, 2), cn2 = c(50, 20),
              power = .80, rho2 = .20,
              g2 = 1, r21 = .20, r22 = .30,
              p = NULL, n1 = 20,  n2 = NULL)

    ## Solution converged with SLSQP
    ##
    ## Rounded solution:
    ## ---------------------------------------------------
    ##  [n1]  n2     p  cost [mdes] 95%lcl 95%ucl power
    ##    20 144 0.389 13680    0.2   0.06   0.34   0.8
    ## ---------------------------------------------------
    ## Per unit marginal costs:
    ##  Level 1 treatment: 5
    ##  Level 1 control: 2
    ##  Level 2 treatment: 50
    ##  Level 2 control: 20
    ## ---------------------------------------------------
    ## MDES = 0.2 (with power = 80)
    ## power = 0.8 (for ES = 0.2)
    ## ---------------------------------------------------
    ## []: point constrained (fixed)
    ## <<: bound constrained
    ## Random assignment design

    # comparisons to CRDs
    # CRD w/ linear score variable interacting with the treatment
    cosa.crd2(order = 1, interaction = TRUE,
              constrain = "es", es = .20,
              cn1 = c(5, 2), cn2 = c(50, 20),
              power = .80, rho2 = .20,
              g2 = 1, r21 = .20, r22 = .30,
              p = .389, n1 = 24,  n2 = NULL)

    ##
    ## RDDE for normal distribution
    ##  based on population moments---------------------------------------
    ## Polynomial order = 1
    ## Interaction w/ treatment = TRUE
    ## Treat if score < cutoff = TRUE
    ## Cutoff = -0.282 | p = 0.389
    ## RDDE = 2.737
    ##
    ## Solution converged with SLSQP
    ##
    ## Rounded solution:
    ## ---------------------------------------------------
    ##  [n1]  n2   [p]  cost [mdes] 95%lcl 95%ucl power
    ##    24 379 0.388 40766    0.2   0.06   0.34   0.8
    ## ---------------------------------------------------
    ## Per unit marginal costs:
    ##  Level 1 treatment: 5
    ##  Level 1 control: 2
    ##  Level 2 treatment: 50
    ##  Level 2 control: 20
    ## ---------------------------------------------------
    ## MDES = 0.2 (with power = 80)
    ## power = 0.8 (for ES = 0.2)
    ## ---------------------------------------------------
    ## []: point constrained (fixed)
    ## <<: bound constrained
    ## Regression discontinuity design

    # CRD w/ quadratic score variable interacting with the treatment
    cosa.crd2(order = 2, interaction = TRUE,
              constrain = "es", es = .20,
              cn1 = c(5, 2), cn2 = c(50, 20),
              power = .80, rho2 = .20,
              g2 = 1, r21 = .20, r22 = .30,
              p = .389, n1 = 24,  n2 = NULL)

    ##
    ## RDDE for normal distribution
    ##  based on population moments---------------------------------------
    ## Polynomial order = 2
    ## Interaction w/ treatment = TRUE
    ## Treat if score < cutoff = TRUE
    ## Cutoff = -0.282 | p = 0.389
    ## RDDE = 4.994
    ##
    ## Solution converged with SLSQP
    ##
    ## Rounded solution:
    ## ---------------------------------------------------
    ##  [n1]  n2   [p]  cost [mdes] 95%lcl 95%ucl power
    ##    24 689 0.389 74188    0.2   0.06   0.34   0.8
    ## ---------------------------------------------------
    ## Per unit marginal costs:
    ##  Level 1 treatment: 5
    ##  Level 1 control: 2
    ##  Level 2 treatment: 50
    ##  Level 2 control: 20
    ## ---------------------------------------------------
    ## MDES = 0.2 (with power = 80)
    ## power = 0.8 (for ES = 0.2)
    ## ---------------------------------------------------
    ## []: point constrained (fixed)
    ## <<: bound constrained
    ## Regression discontinuity design

## Primary Constraint on the Power Rate

    # cost constrained - optimize p and n2
    # CRT('order = 0' or 'rhots = 0')
    cosa.crd2(order = 0,
              constrain = "power", power = .80,
              cn1 = c(5, 2), cn2 = c(50, 20),
              es = .20, rho2 = .20,
              g2 = 1, r21 = .20, r22 = .30,
              p = NULL, n1 = 20,  n2 = NULL)

    ## Solution converged with SLSQP
    ##
    ## Rounded solution:
    ## ---------------------------------------------------
    ##  [n1]  n2     p  cost mdes 95%lcl 95%ucl [power]
    ##    20 144 0.389 13680  0.2   0.06   0.34     0.8
    ## ---------------------------------------------------
    ## Per unit marginal costs:
    ##  Level 1 treatment: 5
    ##  Level 1 control: 2
    ##  Level 2 treatment: 50
    ##  Level 2 control: 20
    ## ---------------------------------------------------
    ## MDES = 0.2 (with power = 80)
    ## power = 0.8 (for ES = 0.2)
    ## ---------------------------------------------------
    ## []: point constrained (fixed)
    ## <<: bound constrained
    ## Random assignment design

    # comparisons to CRDs
    # CRD w/ linear score variable interacting with the treatment
    cosa.crd2(order = 1, interaction = TRUE,
              constrain = "power", power = .80,
              cn1 = c(5, 2), cn2 = c(50, 20),
              es = .20, rho2 = .20,
              g2 = 1, r21 = .20, r22 = .30,
              p = .389, n1 = 24,  n2 = NULL)

    ##
    ## RDDE for normal distribution
    ##  based on population moments---------------------------------------
    ## Polynomial order = 1
    ## Interaction w/ treatment = TRUE
    ## Treat if score < cutoff = TRUE
    ## Cutoff = -0.282 | p = 0.389
    ## RDDE = 2.737
    ##
    ## Solution converged with SLSQP
    ##
    ## Rounded solution:
    ## ---------------------------------------------------
    ##  [n1]  n2   [p]  cost mdes 95%lcl 95%ucl [power]
    ##    24 378 0.389 40698  0.2   0.06   0.34   0.799
    ## ---------------------------------------------------
    ## Per unit marginal costs:
    ##  Level 1 treatment: 5
    ##  Level 1 control: 2
    ##  Level 2 treatment: 50
    ##  Level 2 control: 20
    ## ---------------------------------------------------
    ## MDES = 0.2 (with power = 80)
    ## power = 0.799 (for ES = 0.2)
    ## ---------------------------------------------------
    ## []: point constrained (fixed)
    ## <<: bound constrained
    ## Regression discontinuity design

    # CRD w/ quadratic score variable interacting with the treatment
    cosa.crd2(order = 2, interaction = TRUE,
              constrain = "power", power = .80,
              cn1 = c(5, 2), cn2 = c(50, 20),
              es = .20, rho2 = .20,
              g2 = 1, r21 = .20, r22 = .30,
              p = .389, n1 = 24,  n2 = NULL)

    ##
    ## RDDE for normal distribution
    ##  based on population moments---------------------------------------
    ## Polynomial order = 2
    ## Interaction w/ treatment = TRUE
    ## Treat if score < cutoff = TRUE
    ## Cutoff = -0.282 | p = 0.389
    ## RDDE = 4.994
    ##
    ## Solution converged with SLSQP
    ##
    ## Rounded solution:
    ## ---------------------------------------------------
    ##  [n1]  n2   [p]  cost mdes 95%lcl 95%ucl [power]
    ##    24 689 0.389 74188  0.2   0.06   0.34     0.8
    ## ---------------------------------------------------
    ## Per unit marginal costs:
    ##  Level 1 treatment: 5
    ##  Level 1 control: 2
    ##  Level 2 treatment: 50
    ##  Level 2 control: 20
    ## ---------------------------------------------------
    ## MDES = 0.2 (with power = 80)
    ## power = 0.8 (for ES = 0.2)
    ## ---------------------------------------------------
    ## []: point constrained (fixed)
    ## <<: bound constrained
    ## Regression discontinuity design

–o–