Scale Dependence

Generate data

set.seed(12345)
n <- 10000
inoffice <- rbinom(n, size = 1, prob = .50)
mentor <- rbinom(n, size = 1, prob = .10)

# Probability of quitting
latent_quit <- - 2.9 + inoffice*2.7 - mentor*1.2 + inoffice*mentor*0.7


logit <- function(x) {
  exp(x)/(1 + exp(x))
}

prob_quit <- logit(latent_quit)
quit <- rbinom(n, size = 1, prob = prob_quit)
  
office <- data.frame(inoffice, mentor, quit)

Model

in brms

library(brms)
whoquits <- brm(quit ~ mentor*inoffice, 
               data = office, 
               family = bernoulli,
               chains = 4, file = "models/whoquits.rds")
summary(whoquits)
##  Family: bernoulli 
##   Links: mu = logit 
## Formula: quit ~ mentor * inoffice 
##    Data: office (Number of observations: 10000) 
## Samples: 4 chains, each with iter = 2000; warmup = 1000; thin = 1;
##          total post-warmup samples = 4000
## 
## Population-Level Effects: 
##                 Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## Intercept          -3.06      0.07    -3.21    -2.91 1.00     1873     1680
## mentor             -1.45      0.42    -2.33    -0.73 1.00     1327     1826
## inoffice            2.90      0.08     2.75     3.06 1.00     1993     1742
## mentor:inoffice     0.86      0.43     0.09     1.75 1.00     1435     1802
## 
## Samples were drawn using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).

Frequentist analysis in base R for comparison

summary(glm(quit ~ mentor*inoffice, 
            data = office, 
            family = binomial))
## 
## Call:
## glm(formula = quit ~ mentor * inoffice, family = binomial, data = office)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -1.1100  -0.8799  -0.3033  -0.1537   2.9815  
## 
## Coefficients:
##                 Estimate Std. Error z value Pr(>|z|)    
## (Intercept)     -3.05589    0.07236 -42.234  < 2e-16 ***
## mentor          -1.37691    0.41643  -3.306 0.000945 ***
## inoffice         2.89528    0.07823  37.012  < 2e-16 ***
## mentor:inoffice  0.78828    0.42865   1.839 0.065916 .  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 11151.2  on 9999  degrees of freedom
## Residual deviance:  8592.2  on 9996  degrees of freedom
## AIC: 8600.2
## 
## Number of Fisher Scoring iterations: 6

Get the percentages directly from the coefficients

not_inoffice_no_mentoring <- logit(fixef(whoquits)["Intercept", 1])
not_inoffice_mentoring <- logit(fixef(whoquits)["Intercept", 1] + fixef(whoquits)["mentor", 1])

not_inoffice_no_mentoring - not_inoffice_mentoring
## [1] 0.03397337
inoffice_no_mentoring <- logit(fixef(whoquits)["Intercept", 1] + fixef(whoquits)["inoffice", 1])
inoffice_mentoring <- logit(fixef(whoquits)["Intercept", 1] + fixef(whoquits)["inoffice", 1]
                      + fixef(whoquits)["mentor", 1] + fixef(whoquits)["mentor:inoffice", 1])
inoffice_no_mentoring - inoffice_mentoring
## [1] 0.1395221

Get the percentages with credible intervals from the posterior

# Helper function
fix_var <- function(input, variable, value) {
  # Function takes a dataframe, a variable name, and a specific value
  # Returns the dataframe but with the given variable set to the
  # specific value
  input[, variable] <- value
  return(input)
}

predictions <- function(data_no_mentoring, data_mentoring, modelfit) {
  # Takes a list of two dataframes and a model
  # Returns margins, average marginal effect, relative risk
  library(brms)
  
  pred1 <- predict(modelfit, newdata = data_no_mentoring, summary = FALSE)
  pred2 <- predict(modelfit, newdata = data_mentoring, summary = FALSE)
  
  # Margins
  averages1 <- rowMeans(pred1)
  averages2 <- rowMeans(pred2)
  
  nonmentors <- c(mean(averages1), quantile(averages1, probs = c(.50, .025, .975)))
  mentors <- c(mean(averages2), quantile(averages2, probs = c(.50, .025, .975)))
  margins <- rbind(nonmentors, mentors)
  
  # Average Effect
  diff <- pred2 - pred1
  average_diff <- rowMeans(diff)
  ame <- c(mean(average_diff), quantile(average_diff, probs = c(.50, .025, .975)))
  
  # Relative risk
  relative <- c(mean(rowMeans(pred2)/rowMeans(pred1)),
                quantile(rowMeans(pred2)/rowMeans(pred1),
                         probs = c(.5, .025, .975)))
  
  # Return all results
  all_results <- list(margins, ame, relative)
  names(all_results) <- c("Predictive margins", "Average marginal effect", "Relative risk")
  return(all_results)
  
}

comparison <- function(data_no_mentoring_1, data_mentoring_1, 
                       data_no_mentoring_2, data_mentoring_2, modelfit) {
  # Takes a list of four dataframes and a model
  # Compare average marginal effects and relative risks 
  # Difference is group2 - group1
  
  library(brms)
  
  pred1 <- predict(modelfit, newdata = data_no_mentoring_1, summary = FALSE)
  pred2 <- predict(modelfit, newdata = data_mentoring_1, summary = FALSE)
  pred3 <- predict(modelfit, newdata = data_no_mentoring_2, summary = FALSE)
  pred4 <- predict(modelfit, newdata = data_mentoring_2, summary = FALSE)
  
  # Average Effect
  diff1 <- pred2 - pred1 # mentor effect group 1
  diff2 <- pred4 - pred3 # mentor effect group 2
  
  # Difference in the effects
  diff3 <- diff2 - diff1
  average_diff <- rowMeans(diff3)
  
  # Summarize
  difference_prob <- c(mean(average_diff), quantile(average_diff, probs = c(.50, .025, .975)))
  
  
  # Relative risk
  relative1 <- rowMeans(pred2)/rowMeans(pred1)
  relative2 <- rowMeans(pred4)/rowMeans(pred3)
  
  rel_diffs <- relative2 - relative1
  
  difference_rr <- c(mean(rel_diffs),
                     quantile(rel_diffs,
                              probs = c(.5, .025, .975)))
  
  # Return all results
  all_results <- list(difference_prob, difference_rr)
  names(all_results) <- c("Difference in AME", "Difference in RR")
  return(all_results)
  
}

# Not inoffice
pred_no_inoffice <- predictions(fix_var(fix_var(office, "mentor", 0), "inoffice", 0),
                              fix_var(fix_var(office, "mentor", 1), "inoffice", 0),
                              whoquits)

# inoffice
pred_inoffice <- predictions(fix_var(fix_var(office, "mentor", 0), "inoffice", 1),
                              fix_var(fix_var(office, "mentor", 1), "inoffice", 1),
                              whoquits)

# Comparison
comp <- comparison(fix_var(fix_var(office, "mentor", 0), "inoffice", 0),
                   fix_var(fix_var(office, "mentor", 1), "inoffice", 0),
                   fix_var(fix_var(office, "mentor", 0), "inoffice", 1),
                   fix_var(fix_var(office, "mentor", 1), "inoffice", 1),
                   whoquits)

Plot log function

logit <- function(x) {
  exp(x)/(1 + exp(x))
}

library(ggplot2)

# Intercept
intercept <- summary(whoquits)$fixed[1, "Estimate"]

# mentor
mentor <- summary(whoquits)$fixed[2, "Estimate"]

# inoffice
inoffice <- summary(whoquits)$fixed[3, "Estimate"]

# Interaction
interact <- summary(whoquits)$fixed[4, "Estimate"]

theme_set(theme_bw())
ggplot(data = data.frame(x = 0), mapping = aes(x = x)) +
  xlim(-5, 5) +
  stat_function(fun = logit) +
  xlab("Logit") +
  ylab("Probability of quitting") +
  geom_point(aes(x = intercept, 
                 y = logit(intercept)), color = "blue") +
  geom_point(aes(x = intercept + mentor, 
                 y = logit(intercept + mentor)), color = "blue") +
  
  # Horizontal
  geom_segment(aes(x = intercept, 
                   xend = intercept + mentor, 
                   y = 0, 
                   yend = 0), color = "blue", size = 2) +
  geom_segment(aes(x = intercept, xend = intercept, 
                   y = logit(intercept), yend = 0), linetype = "dashed", color = "grey") +
  geom_segment(aes(x = intercept + mentor, xend = intercept + mentor, 
                   y = logit(intercept + mentor), yend = 0), linetype = "dashed", color = "grey") +
  
  # Vertical
  geom_segment(aes(x = -5, xend = -5, y = logit(intercept), 
                   yend = logit(intercept + mentor)), color = "blue", size = 2) +
  geom_segment(aes(x = -5, xend = intercept, 
                   y = logit(intercept), yend = logit(intercept)), linetype = "dashed", color = "grey") +
  geom_segment(aes(x = -5, xend = intercept + mentor, 
                   y = logit(intercept + mentor), 
                   yend = logit(intercept + mentor)), linetype = "dashed", color = "grey") +
  
  geom_point(aes(x = intercept + inoffice, 
                 y = logit(intercept + inoffice)), color = "red") +
  geom_point(aes(x = intercept + mentor + inoffice + interact, 
                 y = logit(intercept + mentor + inoffice + interact)), color = "red") +
  
  # Horizontal
  geom_segment(aes(x = intercept + inoffice, 
                   xend = intercept + mentor + inoffice + interact, y = 0, yend = 0), color = "red", size = 2) +
  geom_segment(aes(x = intercept + inoffice, xend = intercept + inoffice, 
                   y = logit(intercept + inoffice), yend = 0), linetype = "dashed", color = "grey") +
  geom_segment(aes(x = intercept + mentor + inoffice + interact, 
                   xend = intercept + mentor + inoffice + interact, 
                   y = logit(intercept + mentor + inoffice + interact), yend = 0), 
               linetype = "dashed", color = "grey") +
  
  # Vertical
  geom_segment(aes(x = -5, xend = -5, y = logit(intercept + inoffice), 
                   yend = logit(intercept + mentor + inoffice + interact)), color = "red", size = 2) +
  geom_segment(aes(x = -5, xend = intercept + inoffice, 
                   y = logit(intercept + inoffice), yend = logit(intercept + inoffice)), linetype = "dashed", color = "grey") +
  geom_segment(aes(x = -5, xend = intercept + mentor + inoffice + interact, 
                   y = logit(intercept + mentor + inoffice + interact), 
                   yend = logit(intercept + mentor + inoffice + interact)), linetype = "dashed", color = "grey") +
  annotate("text", x = -4, y = 0.5, label = "On-site", color = "red") +
  annotate("text", x = -4, y = 0.09, label = "Remote", color = "blue") +
  theme(panel.border = element_blank(), panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(), axis.line = element_line(colour = "black"))

ggsave("plots/log_function.png", width = 4, height = 3)
ggsave("plots/log_function.pdf", width = 4, height = 3)
IyBTY2FsZSBEZXBlbmRlbmNlCgojIyBHZW5lcmF0ZSBkYXRhCmBgYHtyfQpzZXQuc2VlZCgxMjM0NSkKbiA8LSAxMDAwMAppbm9mZmljZSA8LSByYmlub20obiwgc2l6ZSA9IDEsIHByb2IgPSAuNTApCm1lbnRvciA8LSByYmlub20obiwgc2l6ZSA9IDEsIHByb2IgPSAuMTApCgojIFByb2JhYmlsaXR5IG9mIHF1aXR0aW5nCmxhdGVudF9xdWl0IDwtIC0gMi45ICsgaW5vZmZpY2UqMi43IC0gbWVudG9yKjEuMiArIGlub2ZmaWNlKm1lbnRvciowLjcKCgpsb2dpdCA8LSBmdW5jdGlvbih4KSB7CiAgZXhwKHgpLygxICsgZXhwKHgpKQp9Cgpwcm9iX3F1aXQgPC0gbG9naXQobGF0ZW50X3F1aXQpCnF1aXQgPC0gcmJpbm9tKG4sIHNpemUgPSAxLCBwcm9iID0gcHJvYl9xdWl0KQogIApvZmZpY2UgPC0gZGF0YS5mcmFtZShpbm9mZmljZSwgbWVudG9yLCBxdWl0KQpgYGAKCgojIyBNb2RlbAojIyMgaW4gYnJtcwpgYGB7cn0KbGlicmFyeShicm1zKQp3aG9xdWl0cyA8LSBicm0ocXVpdCB+IG1lbnRvcippbm9mZmljZSwgCiAgICAgICAgICAgICAgIGRhdGEgPSBvZmZpY2UsIAogICAgICAgICAgICAgICBmYW1pbHkgPSBiZXJub3VsbGksCiAgICAgICAgICAgICAgIGNoYWlucyA9IDQsIGZpbGUgPSAibW9kZWxzL3dob3F1aXRzLnJkcyIpCnN1bW1hcnkod2hvcXVpdHMpCmBgYAoKIyMjIEZyZXF1ZW50aXN0IGFuYWx5c2lzIGluIGJhc2UgUiBmb3IgY29tcGFyaXNvbgpgYGB7cn0Kc3VtbWFyeShnbG0ocXVpdCB+IG1lbnRvcippbm9mZmljZSwgCiAgICAgICAgICAgIGRhdGEgPSBvZmZpY2UsIAogICAgICAgICAgICBmYW1pbHkgPSBiaW5vbWlhbCkpCmBgYAoKCiMjIyBHZXQgdGhlIHBlcmNlbnRhZ2VzIGRpcmVjdGx5IGZyb20gdGhlIGNvZWZmaWNpZW50cwpgYGB7cn0Kbm90X2lub2ZmaWNlX25vX21lbnRvcmluZyA8LSBsb2dpdChmaXhlZih3aG9xdWl0cylbIkludGVyY2VwdCIsIDFdKQpub3RfaW5vZmZpY2VfbWVudG9yaW5nIDwtIGxvZ2l0KGZpeGVmKHdob3F1aXRzKVsiSW50ZXJjZXB0IiwgMV0gKyBmaXhlZih3aG9xdWl0cylbIm1lbnRvciIsIDFdKQoKbm90X2lub2ZmaWNlX25vX21lbnRvcmluZyAtIG5vdF9pbm9mZmljZV9tZW50b3JpbmcKCmlub2ZmaWNlX25vX21lbnRvcmluZyA8LSBsb2dpdChmaXhlZih3aG9xdWl0cylbIkludGVyY2VwdCIsIDFdICsgZml4ZWYod2hvcXVpdHMpWyJpbm9mZmljZSIsIDFdKQppbm9mZmljZV9tZW50b3JpbmcgPC0gbG9naXQoZml4ZWYod2hvcXVpdHMpWyJJbnRlcmNlcHQiLCAxXSArIGZpeGVmKHdob3F1aXRzKVsiaW5vZmZpY2UiLCAxXQogICAgICAgICAgICAgICAgICAgICAgKyBmaXhlZih3aG9xdWl0cylbIm1lbnRvciIsIDFdICsgZml4ZWYod2hvcXVpdHMpWyJtZW50b3I6aW5vZmZpY2UiLCAxXSkKaW5vZmZpY2Vfbm9fbWVudG9yaW5nIC0gaW5vZmZpY2VfbWVudG9yaW5nCmBgYAoKIyMjIEdldCB0aGUgcGVyY2VudGFnZXMgd2l0aCBjcmVkaWJsZSBpbnRlcnZhbHMgZnJvbSB0aGUgcG9zdGVyaW9yCmBgYHtyfQojIEhlbHBlciBmdW5jdGlvbgpmaXhfdmFyIDwtIGZ1bmN0aW9uKGlucHV0LCB2YXJpYWJsZSwgdmFsdWUpIHsKICAjIEZ1bmN0aW9uIHRha2VzIGEgZGF0YWZyYW1lLCBhIHZhcmlhYmxlIG5hbWUsIGFuZCBhIHNwZWNpZmljIHZhbHVlCiAgIyBSZXR1cm5zIHRoZSBkYXRhZnJhbWUgYnV0IHdpdGggdGhlIGdpdmVuIHZhcmlhYmxlIHNldCB0byB0aGUKICAjIHNwZWNpZmljIHZhbHVlCiAgaW5wdXRbLCB2YXJpYWJsZV0gPC0gdmFsdWUKICByZXR1cm4oaW5wdXQpCn0KCnByZWRpY3Rpb25zIDwtIGZ1bmN0aW9uKGRhdGFfbm9fbWVudG9yaW5nLCBkYXRhX21lbnRvcmluZywgbW9kZWxmaXQpIHsKICAjIFRha2VzIGEgbGlzdCBvZiB0d28gZGF0YWZyYW1lcyBhbmQgYSBtb2RlbAogICMgUmV0dXJucyBtYXJnaW5zLCBhdmVyYWdlIG1hcmdpbmFsIGVmZmVjdCwgcmVsYXRpdmUgcmlzawogIGxpYnJhcnkoYnJtcykKICAKICBwcmVkMSA8LSBwcmVkaWN0KG1vZGVsZml0LCBuZXdkYXRhID0gZGF0YV9ub19tZW50b3JpbmcsIHN1bW1hcnkgPSBGQUxTRSkKICBwcmVkMiA8LSBwcmVkaWN0KG1vZGVsZml0LCBuZXdkYXRhID0gZGF0YV9tZW50b3JpbmcsIHN1bW1hcnkgPSBGQUxTRSkKICAKICAjIE1hcmdpbnMKICBhdmVyYWdlczEgPC0gcm93TWVhbnMocHJlZDEpCiAgYXZlcmFnZXMyIDwtIHJvd01lYW5zKHByZWQyKQogIAogIG5vbm1lbnRvcnMgPC0gYyhtZWFuKGF2ZXJhZ2VzMSksIHF1YW50aWxlKGF2ZXJhZ2VzMSwgcHJvYnMgPSBjKC41MCwgLjAyNSwgLjk3NSkpKQogIG1lbnRvcnMgPC0gYyhtZWFuKGF2ZXJhZ2VzMiksIHF1YW50aWxlKGF2ZXJhZ2VzMiwgcHJvYnMgPSBjKC41MCwgLjAyNSwgLjk3NSkpKQogIG1hcmdpbnMgPC0gcmJpbmQobm9ubWVudG9ycywgbWVudG9ycykKICAKICAjIEF2ZXJhZ2UgRWZmZWN0CiAgZGlmZiA8LSBwcmVkMiAtIHByZWQxCiAgYXZlcmFnZV9kaWZmIDwtIHJvd01lYW5zKGRpZmYpCiAgYW1lIDwtIGMobWVhbihhdmVyYWdlX2RpZmYpLCBxdWFudGlsZShhdmVyYWdlX2RpZmYsIHByb2JzID0gYyguNTAsIC4wMjUsIC45NzUpKSkKICAKICAjIFJlbGF0aXZlIHJpc2sKICByZWxhdGl2ZSA8LSBjKG1lYW4ocm93TWVhbnMocHJlZDIpL3Jvd01lYW5zKHByZWQxKSksCiAgICAgICAgICAgICAgICBxdWFudGlsZShyb3dNZWFucyhwcmVkMikvcm93TWVhbnMocHJlZDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgcHJvYnMgPSBjKC41LCAuMDI1LCAuOTc1KSkpCiAgCiAgIyBSZXR1cm4gYWxsIHJlc3VsdHMKICBhbGxfcmVzdWx0cyA8LSBsaXN0KG1hcmdpbnMsIGFtZSwgcmVsYXRpdmUpCiAgbmFtZXMoYWxsX3Jlc3VsdHMpIDwtIGMoIlByZWRpY3RpdmUgbWFyZ2lucyIsICJBdmVyYWdlIG1hcmdpbmFsIGVmZmVjdCIsICJSZWxhdGl2ZSByaXNrIikKICByZXR1cm4oYWxsX3Jlc3VsdHMpCiAgCn0KCmNvbXBhcmlzb24gPC0gZnVuY3Rpb24oZGF0YV9ub19tZW50b3JpbmdfMSwgZGF0YV9tZW50b3JpbmdfMSwgCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YV9ub19tZW50b3JpbmdfMiwgZGF0YV9tZW50b3JpbmdfMiwgbW9kZWxmaXQpIHsKICAjIFRha2VzIGEgbGlzdCBvZiBmb3VyIGRhdGFmcmFtZXMgYW5kIGEgbW9kZWwKICAjIENvbXBhcmUgYXZlcmFnZSBtYXJnaW5hbCBlZmZlY3RzIGFuZCByZWxhdGl2ZSByaXNrcyAKICAjIERpZmZlcmVuY2UgaXMgZ3JvdXAyIC0gZ3JvdXAxCiAgCiAgbGlicmFyeShicm1zKQogIAogIHByZWQxIDwtIHByZWRpY3QobW9kZWxmaXQsIG5ld2RhdGEgPSBkYXRhX25vX21lbnRvcmluZ18xLCBzdW1tYXJ5ID0gRkFMU0UpCiAgcHJlZDIgPC0gcHJlZGljdChtb2RlbGZpdCwgbmV3ZGF0YSA9IGRhdGFfbWVudG9yaW5nXzEsIHN1bW1hcnkgPSBGQUxTRSkKICBwcmVkMyA8LSBwcmVkaWN0KG1vZGVsZml0LCBuZXdkYXRhID0gZGF0YV9ub19tZW50b3JpbmdfMiwgc3VtbWFyeSA9IEZBTFNFKQogIHByZWQ0IDwtIHByZWRpY3QobW9kZWxmaXQsIG5ld2RhdGEgPSBkYXRhX21lbnRvcmluZ18yLCBzdW1tYXJ5ID0gRkFMU0UpCiAgCiAgIyBBdmVyYWdlIEVmZmVjdAogIGRpZmYxIDwtIHByZWQyIC0gcHJlZDEgIyBtZW50b3IgZWZmZWN0IGdyb3VwIDEKICBkaWZmMiA8LSBwcmVkNCAtIHByZWQzICMgbWVudG9yIGVmZmVjdCBncm91cCAyCiAgCiAgIyBEaWZmZXJlbmNlIGluIHRoZSBlZmZlY3RzCiAgZGlmZjMgPC0gZGlmZjIgLSBkaWZmMQogIGF2ZXJhZ2VfZGlmZiA8LSByb3dNZWFucyhkaWZmMykKICAKICAjIFN1bW1hcml6ZQogIGRpZmZlcmVuY2VfcHJvYiA8LSBjKG1lYW4oYXZlcmFnZV9kaWZmKSwgcXVhbnRpbGUoYXZlcmFnZV9kaWZmLCBwcm9icyA9IGMoLjUwLCAuMDI1LCAuOTc1KSkpCiAgCiAgCiAgIyBSZWxhdGl2ZSByaXNrCiAgcmVsYXRpdmUxIDwtIHJvd01lYW5zKHByZWQyKS9yb3dNZWFucyhwcmVkMSkKICByZWxhdGl2ZTIgPC0gcm93TWVhbnMocHJlZDQpL3Jvd01lYW5zKHByZWQzKQogIAogIHJlbF9kaWZmcyA8LSByZWxhdGl2ZTIgLSByZWxhdGl2ZTEKICAKICBkaWZmZXJlbmNlX3JyIDwtIGMobWVhbihyZWxfZGlmZnMpLAogICAgICAgICAgICAgICAgICAgICBxdWFudGlsZShyZWxfZGlmZnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2JzID0gYyguNSwgLjAyNSwgLjk3NSkpKQogIAogICMgUmV0dXJuIGFsbCByZXN1bHRzCiAgYWxsX3Jlc3VsdHMgPC0gbGlzdChkaWZmZXJlbmNlX3Byb2IsIGRpZmZlcmVuY2VfcnIpCiAgbmFtZXMoYWxsX3Jlc3VsdHMpIDwtIGMoIkRpZmZlcmVuY2UgaW4gQU1FIiwgIkRpZmZlcmVuY2UgaW4gUlIiKQogIHJldHVybihhbGxfcmVzdWx0cykKICAKfQoKIyBOb3QgaW5vZmZpY2UKcHJlZF9ub19pbm9mZmljZSA8LSBwcmVkaWN0aW9ucyhmaXhfdmFyKGZpeF92YXIob2ZmaWNlLCAibWVudG9yIiwgMCksICJpbm9mZmljZSIsIDApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaXhfdmFyKGZpeF92YXIob2ZmaWNlLCAibWVudG9yIiwgMSksICJpbm9mZmljZSIsIDApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aG9xdWl0cykKCiMgaW5vZmZpY2UKcHJlZF9pbm9mZmljZSA8LSBwcmVkaWN0aW9ucyhmaXhfdmFyKGZpeF92YXIob2ZmaWNlLCAibWVudG9yIiwgMCksICJpbm9mZmljZSIsIDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaXhfdmFyKGZpeF92YXIob2ZmaWNlLCAibWVudG9yIiwgMSksICJpbm9mZmljZSIsIDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aG9xdWl0cykKCiMgQ29tcGFyaXNvbgpjb21wIDwtIGNvbXBhcmlzb24oZml4X3ZhcihmaXhfdmFyKG9mZmljZSwgIm1lbnRvciIsIDApLCAiaW5vZmZpY2UiLCAwKSwKICAgICAgICAgICAgICAgICAgIGZpeF92YXIoZml4X3ZhcihvZmZpY2UsICJtZW50b3IiLCAxKSwgImlub2ZmaWNlIiwgMCksCiAgICAgICAgICAgICAgICAgICBmaXhfdmFyKGZpeF92YXIob2ZmaWNlLCAibWVudG9yIiwgMCksICJpbm9mZmljZSIsIDEpLAogICAgICAgICAgICAgICAgICAgZml4X3ZhcihmaXhfdmFyKG9mZmljZSwgIm1lbnRvciIsIDEpLCAiaW5vZmZpY2UiLCAxKSwKICAgICAgICAgICAgICAgICAgIHdob3F1aXRzKQpgYGAKCgoKIyMgUGxvdCBsb2cgZnVuY3Rpb24KYGBge3J9CmxvZ2l0IDwtIGZ1bmN0aW9uKHgpIHsKICBleHAoeCkvKDEgKyBleHAoeCkpCn0KCmxpYnJhcnkoZ2dwbG90MikKCiMgSW50ZXJjZXB0CmludGVyY2VwdCA8LSBzdW1tYXJ5KHdob3F1aXRzKSRmaXhlZFsxLCAiRXN0aW1hdGUiXQoKIyBtZW50b3IKbWVudG9yIDwtIHN1bW1hcnkod2hvcXVpdHMpJGZpeGVkWzIsICJFc3RpbWF0ZSJdCgojIGlub2ZmaWNlCmlub2ZmaWNlIDwtIHN1bW1hcnkod2hvcXVpdHMpJGZpeGVkWzMsICJFc3RpbWF0ZSJdCgojIEludGVyYWN0aW9uCmludGVyYWN0IDwtIHN1bW1hcnkod2hvcXVpdHMpJGZpeGVkWzQsICJFc3RpbWF0ZSJdCgp0aGVtZV9zZXQodGhlbWVfYncoKSkKZ2dwbG90KGRhdGEgPSBkYXRhLmZyYW1lKHggPSAwKSwgbWFwcGluZyA9IGFlcyh4ID0geCkpICsKICB4bGltKC01LCA1KSArCiAgc3RhdF9mdW5jdGlvbihmdW4gPSBsb2dpdCkgKwogIHhsYWIoIkxvZ2l0IikgKwogIHlsYWIoIlByb2JhYmlsaXR5IG9mIHF1aXR0aW5nIikgKwogIGdlb21fcG9pbnQoYWVzKHggPSBpbnRlcmNlcHQsIAogICAgICAgICAgICAgICAgIHkgPSBsb2dpdChpbnRlcmNlcHQpKSwgY29sb3IgPSAiYmx1ZSIpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gaW50ZXJjZXB0ICsgbWVudG9yLCAKICAgICAgICAgICAgICAgICB5ID0gbG9naXQoaW50ZXJjZXB0ICsgbWVudG9yKSksIGNvbG9yID0gImJsdWUiKSArCiAgCiAgIyBIb3Jpem9udGFsCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gaW50ZXJjZXB0LCAKICAgICAgICAgICAgICAgICAgIHhlbmQgPSBpbnRlcmNlcHQgKyBtZW50b3IsIAogICAgICAgICAgICAgICAgICAgeSA9IDAsIAogICAgICAgICAgICAgICAgICAgeWVuZCA9IDApLCBjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDIpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSBpbnRlcmNlcHQsIHhlbmQgPSBpbnRlcmNlcHQsIAogICAgICAgICAgICAgICAgICAgeSA9IGxvZ2l0KGludGVyY2VwdCksIHllbmQgPSAwKSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiZ3JleSIpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSBpbnRlcmNlcHQgKyBtZW50b3IsIHhlbmQgPSBpbnRlcmNlcHQgKyBtZW50b3IsIAogICAgICAgICAgICAgICAgICAgeSA9IGxvZ2l0KGludGVyY2VwdCArIG1lbnRvciksIHllbmQgPSAwKSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiZ3JleSIpICsKICAKICAjIFZlcnRpY2FsCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gLTUsIHhlbmQgPSAtNSwgeSA9IGxvZ2l0KGludGVyY2VwdCksIAogICAgICAgICAgICAgICAgICAgeWVuZCA9IGxvZ2l0KGludGVyY2VwdCArIG1lbnRvcikpLCBjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDIpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAtNSwgeGVuZCA9IGludGVyY2VwdCwgCiAgICAgICAgICAgICAgICAgICB5ID0gbG9naXQoaW50ZXJjZXB0KSwgeWVuZCA9IGxvZ2l0KGludGVyY2VwdCkpLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmV5IikgKwogIGdlb21fc2VnbWVudChhZXMoeCA9IC01LCB4ZW5kID0gaW50ZXJjZXB0ICsgbWVudG9yLCAKICAgICAgICAgICAgICAgICAgIHkgPSBsb2dpdChpbnRlcmNlcHQgKyBtZW50b3IpLCAKICAgICAgICAgICAgICAgICAgIHllbmQgPSBsb2dpdChpbnRlcmNlcHQgKyBtZW50b3IpKSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiZ3JleSIpICsKICAKICBnZW9tX3BvaW50KGFlcyh4ID0gaW50ZXJjZXB0ICsgaW5vZmZpY2UsIAogICAgICAgICAgICAgICAgIHkgPSBsb2dpdChpbnRlcmNlcHQgKyBpbm9mZmljZSkpLCBjb2xvciA9ICJyZWQiKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGludGVyY2VwdCArIG1lbnRvciArIGlub2ZmaWNlICsgaW50ZXJhY3QsIAogICAgICAgICAgICAgICAgIHkgPSBsb2dpdChpbnRlcmNlcHQgKyBtZW50b3IgKyBpbm9mZmljZSArIGludGVyYWN0KSksIGNvbG9yID0gInJlZCIpICsKICAKICAjIEhvcml6b250YWwKICBnZW9tX3NlZ21lbnQoYWVzKHggPSBpbnRlcmNlcHQgKyBpbm9mZmljZSwgCiAgICAgICAgICAgICAgICAgICB4ZW5kID0gaW50ZXJjZXB0ICsgbWVudG9yICsgaW5vZmZpY2UgKyBpbnRlcmFjdCwgeSA9IDAsIHllbmQgPSAwKSwgY29sb3IgPSAicmVkIiwgc2l6ZSA9IDIpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSBpbnRlcmNlcHQgKyBpbm9mZmljZSwgeGVuZCA9IGludGVyY2VwdCArIGlub2ZmaWNlLCAKICAgICAgICAgICAgICAgICAgIHkgPSBsb2dpdChpbnRlcmNlcHQgKyBpbm9mZmljZSksIHllbmQgPSAwKSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiZ3JleSIpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSBpbnRlcmNlcHQgKyBtZW50b3IgKyBpbm9mZmljZSArIGludGVyYWN0LCAKICAgICAgICAgICAgICAgICAgIHhlbmQgPSBpbnRlcmNlcHQgKyBtZW50b3IgKyBpbm9mZmljZSArIGludGVyYWN0LCAKICAgICAgICAgICAgICAgICAgIHkgPSBsb2dpdChpbnRlcmNlcHQgKyBtZW50b3IgKyBpbm9mZmljZSArIGludGVyYWN0KSwgeWVuZCA9IDApLCAKICAgICAgICAgICAgICAgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiZ3JleSIpICsKICAKICAjIFZlcnRpY2FsCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gLTUsIHhlbmQgPSAtNSwgeSA9IGxvZ2l0KGludGVyY2VwdCArIGlub2ZmaWNlKSwgCiAgICAgICAgICAgICAgICAgICB5ZW5kID0gbG9naXQoaW50ZXJjZXB0ICsgbWVudG9yICsgaW5vZmZpY2UgKyBpbnRlcmFjdCkpLCBjb2xvciA9ICJyZWQiLCBzaXplID0gMikgKwogIGdlb21fc2VnbWVudChhZXMoeCA9IC01LCB4ZW5kID0gaW50ZXJjZXB0ICsgaW5vZmZpY2UsIAogICAgICAgICAgICAgICAgICAgeSA9IGxvZ2l0KGludGVyY2VwdCArIGlub2ZmaWNlKSwgeWVuZCA9IGxvZ2l0KGludGVyY2VwdCArIGlub2ZmaWNlKSksIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gImdyZXkiKSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gLTUsIHhlbmQgPSBpbnRlcmNlcHQgKyBtZW50b3IgKyBpbm9mZmljZSArIGludGVyYWN0LCAKICAgICAgICAgICAgICAgICAgIHkgPSBsb2dpdChpbnRlcmNlcHQgKyBtZW50b3IgKyBpbm9mZmljZSArIGludGVyYWN0KSwgCiAgICAgICAgICAgICAgICAgICB5ZW5kID0gbG9naXQoaW50ZXJjZXB0ICsgbWVudG9yICsgaW5vZmZpY2UgKyBpbnRlcmFjdCkpLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmV5IikgKwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IC00LCB5ID0gMC41LCBsYWJlbCA9ICJPbi1zaXRlIiwgY29sb3IgPSAicmVkIikgKwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IC00LCB5ID0gMC4wOSwgbGFiZWwgPSAiUmVtb3RlIiwgY29sb3IgPSAiYmx1ZSIpICsKICB0aGVtZShwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJibGFjayIpKQpnZ3NhdmUoInBsb3RzL2xvZ19mdW5jdGlvbi5wbmciLCB3aWR0aCA9IDQsIGhlaWdodCA9IDMpCmdnc2F2ZSgicGxvdHMvbG9nX2Z1bmN0aW9uLnBkZiIsIHdpZHRoID0gNCwgaGVpZ2h0ID0gMykKYGBgCg==