Impact Evaluations and in particular randomized controlled trials have increasingly gained prominence in the field of development economics. In our paper “From What Works to Specific Decisions,” we argue that Bayesian analysis is often more appropriate than a frequentist analysis when the primary audience of an evaluation is a specific decision-maker.

In this notebook, we provide code for the first example in the working paper. In that example, a policyaker must decide between two programs which seek to increase income of farming households and conducts a randomized controlled trial to test which of the programmes is more effective.

To view the other examples from the working paper as well as instructions on how to get started with Stan and RStan click here.

Step 1 - Input fake data

We first input fake data which we will use to fit our model.

# Input fake data and save as a list for use in Stan model
y <- c(0.739, 2.392, 2.034, 4.566, 1.433, 0.504, 0.556, 0.813, 0.916, 1.542, 4.246, 2.772, 2.646, 1.684, 3.478, 1.146, 3.04, 3.148, -0.801, 1.023, 4.054, 2.272, 1.893, 3.322, 2.722, 1.752, 4.487, 1.953, 1.434, 2.424, 2.284, 0.959, 3.542, 0.774, 3.851, 1.793, 1.861, 2.866, 3.043, 2.275, 2.435, 3.091, 2.707, 2.573, 3.391, 3.548, -0.138, 3.432, 3.127, 1.018, 2.915, 3.123, 4.761, 2.462, 2.139, 0.31, 4.092, 3.197, 1.27, 5.5)
t1 <- rep(c(0,1,0), each = 20)
t2 <- rep(c(0,0,1), each = 20)
stan_data <- list(N = 60, y = y, t1 = t1, t2 = t2)

Step 2 - Specify model in Stan

We next specify our model in Stan and save this as an R string. The Stan code below encodes the following likelihood and priors.

\[ y_i \sim N(\alpha+\beta_1t1_i+\beta_2t2_i,\sigma_y^2) \] \[ p(\alpha)\sim N(0,100); p(\beta1)\sim N(0,100); p(\beta2)\sim N(0,100); p(\sigma) \sim Uniform(0,100) \]

# Create Stan model as a string 
stan_model_string <- "
data {
  int<lower=0> N;  // number of observations
  real y[N];  // outcome variable
  vector[N] t1;
  vector[N] t2;
}
parameters {
  // note that since we don't specify any priors Stan uses a uniform prior.
  // In the case of sigma, since we specify a lower bound, the uniform prior is over (0, infinity)
  real alpha;
  real beta1;
  real beta2;
  real <lower=0, upper=100> sigma;
}


model {
  alpha~normal(0,10);
  beta1~normal(0,10);
  beta2~normal(0,10);
  y ~ normal(alpha + beta1*t1+ beta2*t2,sigma);
}
"

Step 3 - Fit the model in Stan

# Import rstan library, fit the model to the data, and extract the posterior draws from the fit object
library(rstan)

fit <- stan(model_code = stan_model_string, data = stan_data, iter = 5000, chains = 4, refresh = 0)
extracted_values <- extract(fit, permute = TRUE)

Step 4 - Examine output and test for convergence

Before using the Stan output, it is useful to check that Stan “converged” – i.e. that the algorithm was successful in approximating the posterior. One useful way to do that is to make sure that the \(\hat R\) values reported for each parameter after a call to print(fit) are less than 1.1 and, ideally, right around 1.

library(ggplot2)

# Print a summary table of the fit
# Rhat should be close to 1 if Stan was able to successfully converge. 
print(fit)
Inference for Stan model: d7a54556ad68bca1214cca2e961e118b.
4 chains, each with iter=5000; warmup=2500; thin=1; 
post-warmup draws per chain=2500, total post-warmup draws=10000.

        mean se_mean   sd   2.5%    25%    50%    75%  97.5% n_eff Rhat
alpha   1.89    0.00 0.29   1.32   1.70   1.89   2.08   2.47  4109    1
beta1   0.59    0.01 0.42  -0.22   0.32   0.59   0.86   1.41  4612    1
beta2   0.86    0.01 0.41   0.06   0.58   0.86   1.14   1.65  4751    1
sigma   1.29    0.00 0.13   1.07   1.20   1.28   1.37   1.56  7323    1
lp__  -44.31    0.02 1.50 -48.02 -45.08 -43.95 -43.19 -42.46  4187    1

Samples were drawn using NUTS(diag_e) at Mon Feb 10 19:10:58 2020.
For each parameter, n_eff is a crude measure of effective sample size,
and Rhat is the potential scale reduction factor on split chains (at 
convergence, Rhat=1).
# Print a traceplot of each parameter (useful for checking whether samples are autocorrelated and chains mixed well)
# Note that the shinystan package provides a lot more graphs.
traceplot(fit,  pars = c("alpha" ,"beta1", "beta2"))

Step 5 - Test model fit using a test quantity

A key step in conducting Bayesian analysis is testing the fit of the model. One obvious way to do this is to perform the analysis using several different priors to test the sensitivity of results to different priors.

Here we demonstrate another way to test model fit through the use of a “test quantity” (Gelman et al, chapter 6). Broadly, Bayesian test quantities are used to compare actual data to simulated data from the model. To evaluate model fit using a test quantity, we perform X steps.

  1. Define a test quantity
  2. Calculate the value of the test quantity for the actual data
  3. For each simulated draw from the posterior of the parameters…
    1. Generate a complete new dataset using these values of the parameters and the likelihood
    2. Calculate the value of the test quantity on the simulated dataset
  4. calculate the proportion of times the value of the test quantity for the actual data is larger than the value of the test quantity from the simulated datasets.

In contrast to frequentist test statistics, Bayesian test quantities may be functions of parameters themselves. For these example, we choose the following test quantity.

\[ T(y)=max(y_{iϵc} )-min(y_{iϵc} )+max(y_{iϵt1})-min(y_{iϵt1})+max(y_{iϵt2})-min(y_{iϵt}) \] There is nothing special about this particular test quantity. We chose this test quantity because it, hopefully, will show if our likelihood is adequately capturing the tails of our data. If the test quantity is rejected, we may consider a likelihood model with fatter tails such as a multivariate t distribution.

df <- data.frame(y, t1, t2)

# calculate the test quantity for the actual data
control_y <- y[df$t1 ==0 & df$t2 == 0] 
t1_y <- y[df$t1 ==1]
t2_y <- y[df$t2 ==1]
observed_quantity <- max(control_y)-min(control_y)+max(t1_y)-min(t1_y)+max(t2_y)-min(t2_y)
print("Value of the test quantity for actual data:")
[1] "Value of the test quantity for actual data:"
print(observed_quantity)
[1] 14.718
draws <- data.frame(extracted_values)

count <- 0
for (i in 1:nrow(draws)){
  # generate simulated data using the sampling distribution
  alpha_sim <- draws$alpha[i]
  b1_sim <- draws$beta1[i]
  b2_sim <- draws$beta2[i]
  sig_sims <- draws$sigma[i]
  
  means <- c(rep(alpha_sim,20), rep(alpha_sim+b1_sim,20), rep(alpha_sim+b2_sim,20))
  y_sim <- means + rnorm(60, mean = 0, sd = sig_sims)
  
  control_y <- y_sim[1:20]
  t1_y <- y_sim[21:40]
  t2_y <- y_sim[41:60]
  
  test <- max(control_y)-min(control_y)+max(t1_y)-min(t1_y)+max(t2_y)-min(t2_y)
  if (test > observed_quantity) {
    count <- count+1
  }
}

print("Bayesian p-value is:")
[1] "Bayesian p-value is:"
print(count/nrow(draws))
[1] 0.4267

Step 6 - Perform inference using Stan output

To estimate the probability that the effect of the second intervention is larger than the first, we calculate the proportion of draws for which the simulated value for beta2 is greater than the simulated value for beta1.

print("Probability from Stan model that beta 2 is greater than beta 1")
[1] "Probability from Stan model that beta 2 is greater than beta 1"
print(mean(extracted_values$beta2 > extracted_values$beta1))
[1] 0.7468
print("Probability from Stan model that beta 1 - beta 2 <= .1")
[1] "Probability from Stan model that beta 1 - beta 2 <= .1"
print(mean((extracted_values$beta2+.1) > extracted_values$beta1))
[1] 0.8175

Step 7 - Compare results withl maximum likelihood estimates

It is useful to compare our results with the results we would have obtained if we naively used the output from maximum likelihood as if it was a posterior. In this case, since our priors were uninformative, the results are nearly identical.

# Fit a maximum likelihood model to the data.  
df <- data.frame(y, t1, t2)
reg_fit <- lm(y ~ t1+ t2, data = df)
# Calculate probability beta2 > beta1 by treating output from max likelihood as posterior
vc <- vcov(reg_fit)
test_equal_se <- (vc[2,2]+vc[3,3]-2*vc[3,2])^.5
diff <- coef(reg_fit)[2]-coef(reg_fit)[3]
print("Probability from max likelihood model that beta 2 is greater than beta 1")
[1] "Probability from max likelihood model that beta 2 is greater than beta 1"
print(pnorm(0, diff, test_equal_se))
[1] 0.7505165
LS0tDQp0aXRsZTogIkV4YW1wbGUgMSAtIGhlYWQgdG8gaGVhZCBjb21wYXJpc29uIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KSW1wYWN0IEV2YWx1YXRpb25zIGFuZCBpbiBwYXJ0aWN1bGFyIHJhbmRvbWl6ZWQgY29udHJvbGxlZCB0cmlhbHMgaGF2ZSBpbmNyZWFzaW5nbHkgZ2FpbmVkIHByb21pbmVuY2UgaW4gdGhlIGZpZWxkIG9mIGRldmVsb3BtZW50IGVjb25vbWljcy4gICBJbiBvdXIgcGFwZXIgIkZyb20gV2hhdCBXb3JrcyB0byBTcGVjaWZpYyBEZWNpc2lvbnMsIiB3ZSBhcmd1ZSB0aGF0IEJheWVzaWFuIGFuYWx5c2lzIGlzIG9mdGVuIG1vcmUgYXBwcm9wcmlhdGUgdGhhbiBhIGZyZXF1ZW50aXN0IGFuYWx5c2lzIHdoZW4gdGhlIHByaW1hcnkgYXVkaWVuY2Ugb2YgYW4gZXZhbHVhdGlvbiBpcyBhIHNwZWNpZmljIGRlY2lzaW9uLW1ha2VyLiANCg0KSW4gdGhpcyBub3RlYm9vaywgd2UgcHJvdmlkZSBjb2RlIGZvciB0aGUgZmlyc3QgZXhhbXBsZSBpbiB0aGUgd29ya2luZyBwYXBlci4gSW4gdGhhdCBleGFtcGxlLCBhIHBvbGljeWFrZXIgbXVzdCBkZWNpZGUgYmV0d2VlbiB0d28gcHJvZ3JhbXMgd2hpY2ggc2VlayB0byBpbmNyZWFzZSBpbmNvbWUgb2YgZmFybWluZyBob3VzZWhvbGRzIGFuZCBjb25kdWN0cyBhIHJhbmRvbWl6ZWQgY29udHJvbGxlZCB0cmlhbCB0byB0ZXN0IHdoaWNoIG9mIHRoZSBwcm9ncmFtbWVzIGlzIG1vcmUgZWZmZWN0aXZlLiANCg0KVG8gdmlldyB0aGUgb3RoZXIgZXhhbXBsZXMgZnJvbSB0aGUgd29ya2luZyBwYXBlciBhcyB3ZWxsIGFzIGluc3RydWN0aW9ucyBvbiBob3cgdG8gZ2V0IHN0YXJ0ZWQgd2l0aCBTdGFuIGFuZCBSU3RhbiBjbGljayBbaGVyZV0oaHR0cHM6Ly9naXRodWIuY29tL2RvdWdqODkyL2llNGRmZXMpLg0KDQoNCg0KIyMgU3RlcCAxIC0gSW5wdXQgZmFrZSBkYXRhDQpXZSBmaXJzdCBpbnB1dCBmYWtlIGRhdGEgd2hpY2ggd2Ugd2lsbCB1c2UgdG8gZml0IG91ciBtb2RlbC4gDQoNCmBgYHtyfQ0KIyBJbnB1dCBmYWtlIGRhdGEgYW5kIHNhdmUgYXMgYSBsaXN0IGZvciB1c2UgaW4gU3RhbiBtb2RlbA0KeSA8LSBjKDAuNzM5LCAyLjM5MiwgMi4wMzQsIDQuNTY2LCAxLjQzMywgMC41MDQsIDAuNTU2LCAwLjgxMywgMC45MTYsIDEuNTQyLCA0LjI0NiwgMi43NzIsIDIuNjQ2LCAxLjY4NCwgMy40NzgsIDEuMTQ2LCAzLjA0LCAzLjE0OCwgLTAuODAxLCAxLjAyMywgNC4wNTQsIDIuMjcyLCAxLjg5MywgMy4zMjIsIDIuNzIyLCAxLjc1MiwgNC40ODcsIDEuOTUzLCAxLjQzNCwgMi40MjQsIDIuMjg0LCAwLjk1OSwgMy41NDIsIDAuNzc0LCAzLjg1MSwgMS43OTMsIDEuODYxLCAyLjg2NiwgMy4wNDMsIDIuMjc1LCAyLjQzNSwgMy4wOTEsIDIuNzA3LCAyLjU3MywgMy4zOTEsIDMuNTQ4LCAtMC4xMzgsIDMuNDMyLCAzLjEyNywgMS4wMTgsIDIuOTE1LCAzLjEyMywgNC43NjEsIDIuNDYyLCAyLjEzOSwgMC4zMSwgNC4wOTIsIDMuMTk3LCAxLjI3LCA1LjUpDQp0MSA8LSByZXAoYygwLDEsMCksIGVhY2ggPSAyMCkNCnQyIDwtIHJlcChjKDAsMCwxKSwgZWFjaCA9IDIwKQ0Kc3Rhbl9kYXRhIDwtIGxpc3QoTiA9IDYwLCB5ID0geSwgdDEgPSB0MSwgdDIgPSB0MikNCmBgYA0KDQojIyBTdGVwIDIgLSBTcGVjaWZ5IG1vZGVsIGluIFN0YW4NCldlIG5leHQgc3BlY2lmeSBvdXIgbW9kZWwgaW4gU3RhbiBhbmQgc2F2ZSB0aGlzIGFzIGFuIFIgc3RyaW5nLiBUaGUgU3RhbiBjb2RlIGJlbG93IGVuY29kZXMgdGhlIGZvbGxvd2luZyBsaWtlbGlob29kIGFuZCBwcmlvcnMuDQoNCiQkIHlfaSBcc2ltIE4oXGFscGhhK1xiZXRhXzF0MV9pK1xiZXRhXzJ0Ml9pLFxzaWdtYV95XjIpICQkDQokJCBwKFxhbHBoYSlcc2ltIE4oMCwxMDApOyBwKFxiZXRhMSlcc2ltIE4oMCwxMDApOyBwKFxiZXRhMilcc2ltIE4oMCwxMDApOyBwKFxzaWdtYSkgXHNpbSBVbmlmb3JtKDAsMTAwKSAkJA0KDQoNCmBgYHtyfQ0KIyBDcmVhdGUgU3RhbiBtb2RlbCBhcyBhIHN0cmluZyANCnN0YW5fbW9kZWxfc3RyaW5nIDwtICINCmRhdGEgew0KICBpbnQ8bG93ZXI9MD4gTjsgIC8vIG51bWJlciBvZiBvYnNlcnZhdGlvbnMNCiAgcmVhbCB5W05dOyAgLy8gb3V0Y29tZSB2YXJpYWJsZQ0KICB2ZWN0b3JbTl0gdDE7DQogIHZlY3RvcltOXSB0MjsNCn0NCnBhcmFtZXRlcnMgew0KICAvLyBub3RlIHRoYXQgc2luY2Ugd2UgZG9uJ3Qgc3BlY2lmeSBhbnkgcHJpb3JzIFN0YW4gdXNlcyBhIHVuaWZvcm0gcHJpb3IuDQogIC8vIEluIHRoZSBjYXNlIG9mIHNpZ21hLCBzaW5jZSB3ZSBzcGVjaWZ5IGEgbG93ZXIgYm91bmQsIHRoZSB1bmlmb3JtIHByaW9yIGlzIG92ZXIgKDAsIGluZmluaXR5KQ0KICByZWFsIGFscGhhOw0KICByZWFsIGJldGExOw0KICByZWFsIGJldGEyOw0KICByZWFsIDxsb3dlcj0wLCB1cHBlcj0xMDA+IHNpZ21hOw0KfQ0KDQoNCm1vZGVsIHsNCiAgYWxwaGF+bm9ybWFsKDAsMTApOw0KICBiZXRhMX5ub3JtYWwoMCwxMCk7DQogIGJldGEyfm5vcm1hbCgwLDEwKTsNCiAgeSB+IG5vcm1hbChhbHBoYSArIGJldGExKnQxKyBiZXRhMip0MixzaWdtYSk7DQp9DQoiDQpgYGANCg0KDQojIyBTdGVwIDMgLSBGaXQgdGhlIG1vZGVsIGluIFN0YW4NCg0KYGBge3J9DQojIEltcG9ydCByc3RhbiBsaWJyYXJ5LCBmaXQgdGhlIG1vZGVsIHRvIHRoZSBkYXRhLCBhbmQgZXh0cmFjdCB0aGUgcG9zdGVyaW9yIGRyYXdzIGZyb20gdGhlIGZpdCBvYmplY3QNCmxpYnJhcnkocnN0YW4pDQoNCmZpdCA8LSBzdGFuKG1vZGVsX2NvZGUgPSBzdGFuX21vZGVsX3N0cmluZywgZGF0YSA9IHN0YW5fZGF0YSwgaXRlciA9IDUwMDAsIGNoYWlucyA9IDQsIHJlZnJlc2ggPSAwKQ0KZXh0cmFjdGVkX3ZhbHVlcyA8LSBleHRyYWN0KGZpdCwgcGVybXV0ZSA9IFRSVUUpDQoNCmBgYA0KDQojIyBTdGVwIDQgLSBFeGFtaW5lIG91dHB1dCBhbmQgdGVzdCBmb3IgY29udmVyZ2VuY2UNCkJlZm9yZSB1c2luZyB0aGUgU3RhbiBvdXRwdXQsIGl0IGlzIHVzZWZ1bCB0byBjaGVjayB0aGF0IFN0YW4gImNvbnZlcmdlZCIgLS0gaS5lLiB0aGF0IHRoZSBhbGdvcml0aG0gd2FzIHN1Y2Nlc3NmdWwgaW4gYXBwcm94aW1hdGluZyB0aGUgcG9zdGVyaW9yLiBPbmUgdXNlZnVsIHdheSB0byBkbyB0aGF0IGlzIHRvIG1ha2Ugc3VyZSB0aGF0IHRoZSAkXGhhdCBSJCB2YWx1ZXMgcmVwb3J0ZWQgZm9yIGVhY2ggcGFyYW1ldGVyIGFmdGVyIGEgY2FsbCB0byBwcmludChmaXQpIGFyZSBsZXNzIHRoYW4gMS4xIGFuZCwgaWRlYWxseSwgcmlnaHQgYXJvdW5kIDEuDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KDQojIFByaW50IGEgc3VtbWFyeSB0YWJsZSBvZiB0aGUgZml0DQojIFJoYXQgc2hvdWxkIGJlIGNsb3NlIHRvIDEgaWYgU3RhbiB3YXMgYWJsZSB0byBzdWNjZXNzZnVsbHkgY29udmVyZ2UuIA0KcHJpbnQoZml0KQ0KDQojIFByaW50IGEgdHJhY2VwbG90IG9mIGVhY2ggcGFyYW1ldGVyICh1c2VmdWwgZm9yIGNoZWNraW5nIHdoZXRoZXIgc2FtcGxlcyBhcmUgYXV0b2NvcnJlbGF0ZWQgYW5kIGNoYWlucyBtaXhlZCB3ZWxsKQ0KIyBOb3RlIHRoYXQgdGhlIHNoaW55c3RhbiBwYWNrYWdlIHByb3ZpZGVzIGEgbG90IG1vcmUgZ3JhcGhzLg0KdHJhY2VwbG90KGZpdCwgIHBhcnMgPSBjKCJhbHBoYSIgLCJiZXRhMSIsICJiZXRhMiIpKQ0KDQojIFByaW50IGEgZm9yZXN0IHBsb3Qgb2YgYWxsIHBhcmFtZXRlcnMNCnBsb3QoZml0KQ0KDQoNCg0KIyBEZW5zaXR5IGdyYXBoIG9mIGJldGEyIC0gYmV0YTENCmRpZmYgPC0gZXh0cmFjdGVkX3ZhbHVlcyRiZXRhMiAtIGV4dHJhY3RlZF92YWx1ZXMkYmV0YTENCnAgPC0gZ2dwbG90KGRhdGEuZnJhbWUoZGlmZiksIGFlcyh4PWRpZmYpKSsgZ2VvbV9kZW5zaXR5KCkNCnANCg0KIyBnZ3NhdmUoZmlsZS5wYXRoKG91dHB1dF9kaXIsICJleGFtcGxlIDEgLSBiZXRhIDEgYW5kIGJldGEgMiBwb3N0ZXJpb3IucG5nIiksIHApDQoNCmBgYA0KIyMgU3RlcCA1IC0gVGVzdCBtb2RlbCBmaXQgdXNpbmcgYSB0ZXN0IHF1YW50aXR5DQpBIGtleSBzdGVwIGluIGNvbmR1Y3RpbmcgQmF5ZXNpYW4gYW5hbHlzaXMgaXMgdGVzdGluZyB0aGUgZml0IG9mIHRoZSBtb2RlbC4gT25lIG9idmlvdXMgd2F5IHRvIGRvIHRoaXMgaXMgdG8gcGVyZm9ybSB0aGUgYW5hbHlzaXMgdXNpbmcgc2V2ZXJhbCBkaWZmZXJlbnQgcHJpb3JzIHRvIHRlc3QgdGhlIHNlbnNpdGl2aXR5IG9mIHJlc3VsdHMgdG8gZGlmZmVyZW50IHByaW9ycy4gIA0KDQpIZXJlIHdlIGRlbW9uc3RyYXRlIGFub3RoZXIgd2F5IHRvIHRlc3QgbW9kZWwgZml0IHRocm91Z2ggdGhlIHVzZSBvZiBhICJ0ZXN0IHF1YW50aXR5IiAoR2VsbWFuIGV0IGFsLCBjaGFwdGVyIDYpLiBCcm9hZGx5LCBCYXllc2lhbiB0ZXN0IHF1YW50aXRpZXMgYXJlIHVzZWQgdG8gY29tcGFyZSBhY3R1YWwgZGF0YSB0byBzaW11bGF0ZWQgZGF0YSBmcm9tIHRoZSBtb2RlbC4gIFRvIGV2YWx1YXRlIG1vZGVsIGZpdCB1c2luZyBhIHRlc3QgcXVhbnRpdHksIHdlIHBlcmZvcm0gWCBzdGVwcy4NCg0KMS4gRGVmaW5lIGEgdGVzdCBxdWFudGl0eSANCjIuIENhbGN1bGF0ZSB0aGUgdmFsdWUgb2YgdGhlIHRlc3QgcXVhbnRpdHkgZm9yIHRoZSBhY3R1YWwgZGF0YQ0KMy4gRm9yIGVhY2ggc2ltdWxhdGVkIGRyYXcgZnJvbSB0aGUgcG9zdGVyaW9yIG9mIHRoZSBwYXJhbWV0ZXJzLi4uDQogICAgMS4gR2VuZXJhdGUgYSBjb21wbGV0ZSBuZXcgZGF0YXNldCB1c2luZyB0aGVzZSB2YWx1ZXMgb2YgdGhlIHBhcmFtZXRlcnMgYW5kIHRoZSBsaWtlbGlob29kDQogICAgMi4gQ2FsY3VsYXRlIHRoZSB2YWx1ZSBvZiB0aGUgdGVzdCBxdWFudGl0eSBvbiB0aGUgc2ltdWxhdGVkIGRhdGFzZXQNCjQuIGNhbGN1bGF0ZSB0aGUgcHJvcG9ydGlvbiBvZiB0aW1lcyB0aGUgdmFsdWUgb2YgdGhlIHRlc3QgcXVhbnRpdHkgZm9yIHRoZSBhY3R1YWwgZGF0YSBpcyBsYXJnZXIgdGhhbiB0aGUgdmFsdWUgb2YgdGhlIHRlc3QgcXVhbnRpdHkgZnJvbSB0aGUgc2ltdWxhdGVkIGRhdGFzZXRzLg0KDQpJbiBjb250cmFzdCB0byBmcmVxdWVudGlzdCB0ZXN0IHN0YXRpc3RpY3MsIEJheWVzaWFuIHRlc3QgcXVhbnRpdGllcyBtYXkgYmUgZnVuY3Rpb25zIG9mIHBhcmFtZXRlcnMgdGhlbXNlbHZlcy4gRm9yIHRoZXNlIGV4YW1wbGUsIHdlIGNob29zZSB0aGUgZm9sbG93aW5nIHRlc3QgcXVhbnRpdHkuICAgDQoNCiQkIFQoeSk9bWF4KHlfe2nPtWN9ICktbWluKHlfe2nPtWN9ICkrbWF4KHlfe2nPtXQxfSktbWluKHlfe2nPtXQxfSkrbWF4KHlfe2nPtXQyfSktbWluKHlfe2nPtXR9KSAkJCANClRoZXJlIGlzIG5vdGhpbmcgc3BlY2lhbCBhYm91dCB0aGlzIHBhcnRpY3VsYXIgdGVzdCBxdWFudGl0eS4gIFdlIGNob3NlIHRoaXMgdGVzdCBxdWFudGl0eSBiZWNhdXNlIGl0LCBob3BlZnVsbHksIHdpbGwgc2hvdyBpZiBvdXIgbGlrZWxpaG9vZCBpcyBhZGVxdWF0ZWx5IGNhcHR1cmluZyB0aGUgdGFpbHMgb2Ygb3VyIGRhdGEuICBJZiB0aGUgdGVzdCBxdWFudGl0eSBpcyByZWplY3RlZCwgd2UgbWF5IGNvbnNpZGVyIGEgbGlrZWxpaG9vZCBtb2RlbCB3aXRoIGZhdHRlciB0YWlscyBzdWNoIGFzIGEgbXVsdGl2YXJpYXRlIHQgZGlzdHJpYnV0aW9uLg0KDQoNCmBgYHtyfQ0KZGYgPC0gZGF0YS5mcmFtZSh5LCB0MSwgdDIpDQoNCiMgY2FsY3VsYXRlIHRoZSB0ZXN0IHF1YW50aXR5IGZvciB0aGUgYWN0dWFsIGRhdGENCmNvbnRyb2xfeSA8LSB5W2RmJHQxID09MCAmIGRmJHQyID09IDBdIA0KdDFfeSA8LSB5W2RmJHQxID09MV0NCnQyX3kgPC0geVtkZiR0MiA9PTFdDQpvYnNlcnZlZF9xdWFudGl0eSA8LSBtYXgoY29udHJvbF95KS1taW4oY29udHJvbF95KSttYXgodDFfeSktbWluKHQxX3kpK21heCh0Ml95KS1taW4odDJfeSkNCnByaW50KCJWYWx1ZSBvZiB0aGUgdGVzdCBxdWFudGl0eSBmb3IgYWN0dWFsIGRhdGE6IikNCnByaW50KG9ic2VydmVkX3F1YW50aXR5KQ0KDQpkcmF3cyA8LSBkYXRhLmZyYW1lKGV4dHJhY3RlZF92YWx1ZXMpDQoNCmNvdW50IDwtIDANCmZvciAoaSBpbiAxOm5yb3coZHJhd3MpKXsNCiAgIyBnZW5lcmF0ZSBzaW11bGF0ZWQgZGF0YSB1c2luZyB0aGUgc2FtcGxpbmcgZGlzdHJpYnV0aW9uDQogIGFscGhhX3NpbSA8LSBkcmF3cyRhbHBoYVtpXQ0KICBiMV9zaW0gPC0gZHJhd3MkYmV0YTFbaV0NCiAgYjJfc2ltIDwtIGRyYXdzJGJldGEyW2ldDQogIHNpZ19zaW1zIDwtIGRyYXdzJHNpZ21hW2ldDQogIA0KICBtZWFucyA8LSBjKHJlcChhbHBoYV9zaW0sMjApLCByZXAoYWxwaGFfc2ltK2IxX3NpbSwyMCksIHJlcChhbHBoYV9zaW0rYjJfc2ltLDIwKSkNCiAgeV9zaW0gPC0gbWVhbnMgKyBybm9ybSg2MCwgbWVhbiA9IDAsIHNkID0gc2lnX3NpbXMpDQogIA0KICBjb250cm9sX3kgPC0geV9zaW1bMToyMF0NCiAgdDFfeSA8LSB5X3NpbVsyMTo0MF0NCiAgdDJfeSA8LSB5X3NpbVs0MTo2MF0NCiAgDQogIHRlc3QgPC0gbWF4KGNvbnRyb2xfeSktbWluKGNvbnRyb2xfeSkrbWF4KHQxX3kpLW1pbih0MV95KSttYXgodDJfeSktbWluKHQyX3kpDQogIGlmICh0ZXN0ID4gb2JzZXJ2ZWRfcXVhbnRpdHkpIHsNCiAgICBjb3VudCA8LSBjb3VudCsxDQogIH0NCn0NCg0KcHJpbnQoIkJheWVzaWFuIHAtdmFsdWUgaXM6IikNCnByaW50KGNvdW50L25yb3coZHJhd3MpKQ0KDQpgYGANCg0KDQojIyBTdGVwIDYgLSBQZXJmb3JtIGluZmVyZW5jZSB1c2luZyBTdGFuIG91dHB1dA0KVG8gZXN0aW1hdGUgdGhlIHByb2JhYmlsaXR5IHRoYXQgdGhlIGVmZmVjdCBvZiB0aGUgc2Vjb25kIGludGVydmVudGlvbiBpcyBsYXJnZXIgdGhhbiB0aGUgZmlyc3QsIHdlIGNhbGN1bGF0ZSB0aGUgcHJvcG9ydGlvbiBvZiBkcmF3cyBmb3Igd2hpY2ggdGhlIHNpbXVsYXRlZCB2YWx1ZSBmb3IgYmV0YTIgaXMgZ3JlYXRlciB0aGFuIHRoZSBzaW11bGF0ZWQgdmFsdWUgZm9yIGJldGExLg0KDQpgYGB7cn0NCnByaW50KCJQcm9iYWJpbGl0eSBmcm9tIFN0YW4gbW9kZWwgdGhhdCBiZXRhIDIgaXMgZ3JlYXRlciB0aGFuIGJldGEgMSIpDQpwcmludChtZWFuKGV4dHJhY3RlZF92YWx1ZXMkYmV0YTIgPiBleHRyYWN0ZWRfdmFsdWVzJGJldGExKSkNCg0KcHJpbnQoIlByb2JhYmlsaXR5IGZyb20gU3RhbiBtb2RlbCB0aGF0IGJldGEgMSAtIGJldGEgMiA8PSAuMSIpDQpwcmludChtZWFuKChleHRyYWN0ZWRfdmFsdWVzJGJldGEyKy4xKSA+IGV4dHJhY3RlZF92YWx1ZXMkYmV0YTEpKQ0KYGBgDQoNCg0KIyMgU3RlcCA3IC0gQ29tcGFyZSByZXN1bHRzIHdpdGhsIG1heGltdW0gbGlrZWxpaG9vZCBlc3RpbWF0ZXMNCkl0IGlzIHVzZWZ1bCB0byBjb21wYXJlIG91ciByZXN1bHRzIHdpdGggdGhlIHJlc3VsdHMgd2Ugd291bGQgaGF2ZSBvYnRhaW5lZCBpZiB3ZSBuYWl2ZWx5IHVzZWQgdGhlIG91dHB1dCBmcm9tIG1heGltdW0gbGlrZWxpaG9vZCBhcyBpZiBpdCB3YXMgYSBwb3N0ZXJpb3IuICBJbiB0aGlzIGNhc2UsIHNpbmNlIG91ciBwcmlvcnMgd2VyZSB1bmluZm9ybWF0aXZlLCB0aGUgcmVzdWx0cyBhcmUgbmVhcmx5IGlkZW50aWNhbC4NCg0KYGBge3J9DQojIEZpdCBhIG1heGltdW0gbGlrZWxpaG9vZCBtb2RlbCB0byB0aGUgZGF0YS4gIA0KZGYgPC0gZGF0YS5mcmFtZSh5LCB0MSwgdDIpDQpyZWdfZml0IDwtIGxtKHkgfiB0MSsgdDIsIGRhdGEgPSBkZikNCiMgQ2FsY3VsYXRlIHByb2JhYmlsaXR5IGJldGEyID4gYmV0YTEgYnkgdHJlYXRpbmcgb3V0cHV0IGZyb20gbWF4IGxpa2VsaWhvb2QgYXMgcG9zdGVyaW9yDQp2YyA8LSB2Y292KHJlZ19maXQpDQp0ZXN0X2VxdWFsX3NlIDwtICh2Y1syLDJdK3ZjWzMsM10tMip2Y1szLDJdKV4uNQ0KZGlmZiA8LSBjb2VmKHJlZ19maXQpWzJdLWNvZWYocmVnX2ZpdClbM10NCnByaW50KCJQcm9iYWJpbGl0eSBmcm9tIG1heCBsaWtlbGlob29kIG1vZGVsIHRoYXQgYmV0YSAyIGlzIGdyZWF0ZXIgdGhhbiBiZXRhIDEiKQ0KcHJpbnQocG5vcm0oMCwgZGlmZiwgdGVzdF9lcXVhbF9zZSkpDQoNCmBgYA0K