Most randomised controlled trials (RCTs) use non-probability samples
and the goal is to estimate the sample average treatment effect (SATE).
The sample is the finite population of interest and something else needs
to be done to transfer or generalise the finding to other samples –
ideally a few decades of substantive theory built on basic research.
There’s still an inferential problem, even with the finite sample.
SATE is the average of each individual’s treatment effect (TEs), which
is defined as the difference between the individual’s potential outcome
following treatment and their potential outcome following control.
However, only one of those two potential outcomes is realised for an
individual, depending on whether they were randomised to treatment or
control.
The standard ANCOVA-style way to estimate SATE is to regress the
outcome on treatment group and covariates. This yields an unbiased
estimate of the SATE; however, the standard error is a little too big,
which means the confidence interval is a little too wide. The reason for
this is that the correct standard error depends on the correlation
between potential outcomes, but we cannot estimate this correlation
since each trial participant only gives us one of the two values we wish
to correlate.
Here’s the SE for a test without covariates (Reichardt & Gollob,
1999):
\[\sqrt{\frac{\sigma_X^2}{n_X} +
\frac{\sigma_Y^2}{n_Y}-\left[ \frac{(\sigma_X-\sigma_Y)^2}{N} +
\frac{2(1-\rho) \sigma_X \sigma_{Y}}{N} \right]}\]
where \(\sigma_X^2\) and \(\sigma_Y^2\) are the variances of the two
groups, \(n_X\) and \(n_Y\) are the observed group sample sizes,
and \(N\) is the total sample (the
finite population) size. The problem is \(\rho\), the unobservable correlation
between treat and control outcomes for each participant.
This problem was pointed out by Neyman (1923/1990). Reichardt and
Gollob (1999) independently rediscovered the problem and suggested a way
to get a less conservative standard error based on the reliability of
the outcome measure, which gives an upper bound on the correlation.
Aronow, Green, and Lee (2014) proved a result that puts bounds on the
correlation based on the observed marginal distribution of outcomes.
They also helpfully provided R code to do the sums; however, this
approach only works for a model without any covariates.
I’m excited by a new preprint by Mikhaeil and Green (2024) that
extends the approach to models with covariates and again provides R
code, in the {sharpvar}
package (currently on GitHub). Let’s give it a go.
Simulate data
#devtools::install_github("JonasMikhaeil/SharpVarianceBounds")
library(conflicted)
library(sharpvar)
library(tidyverse)
── Attaching core tidyverse packages ────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.1.4 ✔ readr 2.1.5
✔ forcats 1.0.0 ✔ stringr 1.5.1
✔ ggplot2 3.5.1 ✔ tibble 3.2.1
✔ lubridate 1.9.3 ✔ tidyr 1.3.1
✔ purrr 1.0.2
library(broom)
library(tictoc)
conflicts_prefer(dplyr::filter)
[conflicted] Will prefer dplyr::filter over any other package.
set.seed(42)
theN <- 100
sim_dat <- tibble(latent_magic = 50 + rnorm(theN, 0, sqrt(.6)),
y0 = round(latent_magic + rnorm(theN, 0, sqrt(.4)), 1),
y1 = round(latent_magic + 0.2 + rnorm(theN, 0, sqrt(.4)), 1),
x = latent_magic + rnorm(theN, mean = 0, sd = 1.5),
TE = y1 - y0) |>
select(-latent_magic)
sim_dat
sim_dat |>
select(-TE) |>
cor() |>
round(2)
y0 y1 x
y0 1.00 0.64 0.47
y1 0.64 1.00 0.41
x 0.47 0.41 1.00
This is the true SATE for this finite population:
trueSATE <- mean(sim_dat$TE)
trueSATE
[1] 0.252
Simulate some efficacy trials
This is a slightly convoluted way to implement complete randomisation
in which a fixed number of participants are randomised to treatment
(compare with Bernoulli randomisation, where the proportion is a
probability that may vary between trials).
completely_randomiser <- function(dat,
treat_var_name = "treat",
prop_treat = 0.5) {
treat_n <- ceiling(prop_treat * nrow(dat))
control_n <- nrow(dat) - treat_n
zero_ones <- c(rep(1, treat_n), rep(0, control_n))
dat |>
mutate(!!treat_var_name := sample(zero_ones))
}
This function will give us the realised potential outcome:
realise_potential <- function(dat, y_name = y, y0, y1, treat) {
dat |>
mutate(!!y_name := ifelse(treat == 1, y1, y0))
}
And a function to summarise the findings for the classic SE and the
new sharp bound on the SE:
summarise_mod <- function(mod, dat, treat_var = "treat") {
mod |>
tidy() |>
filter(term == treat_var) |>
mutate(
se_sharp = sharpvar(resid(mod), dat$treat, upper = TRUE) |> sqrt(),
df = df.residual(mod)
) |>
rename(se_classic = std.error) |>
select(-c(statistic, p.value)) |>
pivot_longer(
cols = starts_with("se_"),
names_prefix = "se_",
names_to = "type",
values_to = "se"
) |>
mutate(ci_lower = estimate + qt(.05/2, df) * se,
ci_upper = estimate + qt(1 - (.05/2), df) * se)
}
The pipeline we will replicate a few thousand times:
one_sim <- function(popn_dat) {
one_trial <- popn_dat |>
completely_randomiser() |>
realise_potential("y", y0, y1, treat)
the_mod <- lm(y ~ treat + x, data = one_trial)
summarise_mod(the_mod, one_trial)
}
Off we go:
tic()
res <- replicate(10000, one_sim(sim_dat), simplify = FALSE) |> list_rbind()
toc()
102.51 sec elapsed
Now what’s the coverage like?
tallied_res <- res |>
mutate(truth = trueSATE,
covered = between(truth, ci_lower, ci_upper)) |>
group_by(type) |>
summarise(`proportion 95% CI coverage` = mean(covered))
tallied_res
We see that the classic (and conservative) 95% confidence interval
covers the true SATE 97.58% of the time whereas Mikhaeil and Green’s
improved interval gives us 97.15% coverage.
It worked, the interval is a tiny bit closer to the 95% target!
References
Aronow, P. M., Green, D. P., & Lee, D. K. K. (2014). Sharp bounds on the
variance in randomized experiments. Annals of Statistics, 42,
850–871.
Mikhaeil, J. M., & Green, D. P. (2024). Sharp bounds on the variance of
general regression adjustment in randomized experiments. arXiv
preprint.
Neyman, J. (1923/1990). On the application of
probability theory to agricultural experiments. Essay on principles.
Section 9. Statistical Science, 5, 465–472.
Reichardt, C. S., & Gollob, H. F. (1999). Justifying
the Use and Increasing the Power of a t Test for a Randomized
Experiment With a Convenience Sample. Psychological
Methods, 4, 117–128.
LS0tDQp0aXRsZTogIlNoYXJwIHZhcmlhbmNlIGJvdW5kcyBmb3IgU0FURTogZ2l2aW5nIE1pa2hhZWlsIGFuZCBHcmVlbidzICgyMDI0KSB3b3JrIGEgdGVzdCBkcml2ZSINCmF1dGhvcjogQW5kaSBGdWdhcmQNCmRhdGU6IDkgTm92IDIwMjQNCm91dHB1dDogDQogIGh0bWxfbm90ZWJvb2s6IA0KICAgIGNvZGVfZm9sZGluZzogbm9uZQ0KLS0tDQoNCg0KTW9zdCByYW5kb21pc2VkIGNvbnRyb2xsZWQgdHJpYWxzIChSQ1RzKSB1c2Ugbm9uLXByb2JhYmlsaXR5IHNhbXBsZXMgYW5kIHRoZSBnb2FsIGlzIHRvIGVzdGltYXRlIHRoZSBzYW1wbGUgYXZlcmFnZSB0cmVhdG1lbnQgZWZmZWN0IChTQVRFKS4gVGhlIHNhbXBsZSBpcyB0aGUgZmluaXRlIHBvcHVsYXRpb24gb2YgaW50ZXJlc3QgYW5kIHNvbWV0aGluZyBlbHNlIG5lZWRzIHRvIGJlIGRvbmUgdG8gdHJhbnNmZXIgb3IgZ2VuZXJhbGlzZSB0aGUgZmluZGluZyB0byBvdGhlciBzYW1wbGVzIC0tIGlkZWFsbHkgYSBmZXcgZGVjYWRlcyBvZiBzdWJzdGFudGl2ZSB0aGVvcnkgYnVpbHQgb24gYmFzaWMgcmVzZWFyY2guDQoNClRoZXJlJ3Mgc3RpbGwgYW4gaW5mZXJlbnRpYWwgcHJvYmxlbSwgZXZlbiB3aXRoIHRoZSBmaW5pdGUgc2FtcGxlLiBTQVRFIGlzIHRoZSBhdmVyYWdlIG9mIGVhY2ggaW5kaXZpZHVhbCdzIHRyZWF0bWVudCBlZmZlY3QgKFRFcyksIHdoaWNoIGlzIGRlZmluZWQgYXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgaW5kaXZpZHVhbCdzIHBvdGVudGlhbCBvdXRjb21lIGZvbGxvd2luZyB0cmVhdG1lbnQgYW5kIHRoZWlyIHBvdGVudGlhbCBvdXRjb21lIGZvbGxvd2luZyBjb250cm9sLiBIb3dldmVyLCBvbmx5IG9uZSBvZiB0aG9zZSB0d28gcG90ZW50aWFsIG91dGNvbWVzIGlzIHJlYWxpc2VkIGZvciBhbiBpbmRpdmlkdWFsLCBkZXBlbmRpbmcgb24gd2hldGhlciB0aGV5IHdlcmUgcmFuZG9taXNlZCB0byB0cmVhdG1lbnQgb3IgY29udHJvbC4NCg0KVGhlIHN0YW5kYXJkIEFOQ09WQS1zdHlsZSB3YXkgdG8gZXN0aW1hdGUgU0FURSBpcyB0byByZWdyZXNzIHRoZSBvdXRjb21lIG9uIHRyZWF0bWVudCBncm91cCBhbmQgY292YXJpYXRlcy4gVGhpcyB5aWVsZHMgYW4gdW5iaWFzZWQgZXN0aW1hdGUgb2YgdGhlIFNBVEU7IGhvd2V2ZXIsIHRoZSBzdGFuZGFyZCBlcnJvciBpcyBhIGxpdHRsZSB0b28gYmlnLCB3aGljaCBtZWFucyB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbCBpcyBhIGxpdHRsZSB0b28gd2lkZS4gVGhlIHJlYXNvbiBmb3IgdGhpcyBpcyB0aGF0IHRoZSBjb3JyZWN0IHN0YW5kYXJkIGVycm9yIGRlcGVuZHMgb24gdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gcG90ZW50aWFsIG91dGNvbWVzLCBidXQgd2UgY2Fubm90IGVzdGltYXRlIHRoaXMgY29ycmVsYXRpb24gc2luY2UgZWFjaCB0cmlhbCBwYXJ0aWNpcGFudCBvbmx5IGdpdmVzIHVzIG9uZSBvZiB0aGUgdHdvIHZhbHVlcyB3ZSB3aXNoIHRvIGNvcnJlbGF0ZS4NCg0KSGVyZSdzIHRoZSBTRSBmb3IgYSB0ZXN0IHdpdGhvdXQgY292YXJpYXRlcyAoUmVpY2hhcmR0ICYgR29sbG9iLCAxOTk5KToNCg0KJCRcc3FydHtcZnJhY3tcc2lnbWFfWF4yfXtuX1h9ICsgXGZyYWN7XHNpZ21hX1leMn17bl9ZfS1cbGVmdFsgXGZyYWN7KFxzaWdtYV9YLVxzaWdtYV9ZKV4yfXtOfSArIFxmcmFjezIoMS1ccmhvKSBcc2lnbWFfWCBcc2lnbWFfe1l9fXtOfSBccmlnaHRdfSQkDQoNCndoZXJlICRcc2lnbWFfWF4yJCBhbmQgJFxzaWdtYV9ZXjIkIGFyZSB0aGUgdmFyaWFuY2VzIG9mIHRoZSB0d28gZ3JvdXBzLCAkbl9YJCBhbmQgJG5fWSQgYXJlIHRoZSBvYnNlcnZlZCBncm91cCBzYW1wbGUgc2l6ZXMsIGFuZCAkTiQgaXMgdGhlIHRvdGFsIHNhbXBsZSAodGhlIGZpbml0ZSBwb3B1bGF0aW9uKSBzaXplLiBUaGUgcHJvYmxlbSBpcyAkXHJobyQsIHRoZSB1bm9ic2VydmFibGUgY29ycmVsYXRpb24gYmV0d2VlbiB0cmVhdCBhbmQgY29udHJvbCBvdXRjb21lcyBmb3IgZWFjaCBwYXJ0aWNpcGFudC4NCg0KVGhpcyBwcm9ibGVtIHdhcyBwb2ludGVkIG91dCBieSBOZXltYW4gKDE5MjMvMTk5MCkuIFJlaWNoYXJkdCBhbmQgR29sbG9iICgxOTk5KSBpbmRlcGVuZGVudGx5IHJlZGlzY292ZXJlZCB0aGUgcHJvYmxlbSBhbmQgc3VnZ2VzdGVkIGEgd2F5IHRvIGdldCBhIGxlc3MgY29uc2VydmF0aXZlIHN0YW5kYXJkIGVycm9yIGJhc2VkIG9uIHRoZSByZWxpYWJpbGl0eSBvZiB0aGUgb3V0Y29tZSBtZWFzdXJlLCB3aGljaCBnaXZlcyBhbiB1cHBlciBib3VuZCBvbiB0aGUgY29ycmVsYXRpb24uICBBcm9ub3csIEdyZWVuLCBhbmQgTGVlICgyMDE0KSBwcm92ZWQgYSByZXN1bHQgdGhhdCBwdXRzIGJvdW5kcyBvbiB0aGUgY29ycmVsYXRpb24gYmFzZWQgb24gdGhlIG9ic2VydmVkIG1hcmdpbmFsIGRpc3RyaWJ1dGlvbiBvZiBvdXRjb21lcy4gVGhleSBhbHNvIGhlbHBmdWxseSBwcm92aWRlZCBSIGNvZGUgdG8gZG8gdGhlIHN1bXM7IGhvd2V2ZXIsIHRoaXMgYXBwcm9hY2ggb25seSB3b3JrcyBmb3IgYSBtb2RlbCB3aXRob3V0IGFueSBjb3ZhcmlhdGVzLg0KDQpJJ20gZXhjaXRlZCBieSBhIG5ldyBwcmVwcmludCBieSBNaWtoYWVpbCBhbmQgR3JlZW4gKDIwMjQpIHRoYXQgZXh0ZW5kcyB0aGUgYXBwcm9hY2ggdG8gbW9kZWxzIHdpdGggY292YXJpYXRlcyBhbmQgYWdhaW4gcHJvdmlkZXMgUiBjb2RlLCBpbiB0aGUge1tzaGFycHZhcl0oaHR0cHM6Ly9naXRodWIuY29tL0pvbmFzTWlraGFlaWwvU2hhcnBWYXJpYW5jZUJvdW5kcyl9IHBhY2thZ2UgKGN1cnJlbnRseSBvbiBHaXRIdWIpLiBMZXQncyBnaXZlIGl0IGEgZ28uDQoNCiMjIFNpbXVsYXRlIGRhdGENCg0KYGBge3J9DQojZGV2dG9vbHM6Omluc3RhbGxfZ2l0aHViKCJKb25hc01pa2hhZWlsL1NoYXJwVmFyaWFuY2VCb3VuZHMiKQ0KbGlicmFyeShjb25mbGljdGVkKQ0KbGlicmFyeShzaGFycHZhcikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShicm9vbSkNCmxpYnJhcnkodGljdG9jKQ0KY29uZmxpY3RzX3ByZWZlcihkcGx5cjo6ZmlsdGVyKQ0KYGBgDQoNCg0KYGBge3J9DQpzZXQuc2VlZCg0MikNCnRoZU4gPC0gMTAwDQoNCnNpbV9kYXQgPC0gdGliYmxlKGxhdGVudF9tYWdpYyA9IDUwICsgcm5vcm0odGhlTiwgMCwgc3FydCguNikpLA0KICAgICAgICAgICAgICAgICAgeTAgPSByb3VuZChsYXRlbnRfbWFnaWMgKyBybm9ybSh0aGVOLCAwLCBzcXJ0KC40KSksIDEpLA0KICAgICAgICAgICAgICAgICAgeTEgPSByb3VuZChsYXRlbnRfbWFnaWMgKyAwLjIgKyBybm9ybSh0aGVOLCAwLCBzcXJ0KC40KSksIDEpLA0KICAgICAgICAgICAgICAgICAgeCAgPSBsYXRlbnRfbWFnaWMgKyBybm9ybSh0aGVOLCBtZWFuID0gMCwgc2QgPSAxLjUpLA0KICAgICAgICAgICAgICAgICAgVEUgPSB5MSAtIHkwKSB8Pg0KICBzZWxlY3QoLWxhdGVudF9tYWdpYykNCmBgYA0KDQoNCmBgYHtyfQ0Kc2ltX2RhdA0KYGBgDQoNCmBgYHtyfQ0Kc2ltX2RhdCB8Pg0KICBzZWxlY3QoLVRFKSB8Pg0KICBjb3IoKSB8Pg0KICByb3VuZCgyKQ0KYGBgDQoNClRoaXMgaXMgdGhlIHRydWUgU0FURSBmb3IgdGhpcyBmaW5pdGUgcG9wdWxhdGlvbjoNCg0KYGBge3J9DQp0cnVlU0FURSA8LSBtZWFuKHNpbV9kYXQkVEUpDQp0cnVlU0FURQ0KYGBgDQoNCg0KIyMgU2ltdWxhdGUgc29tZSBlZmZpY2FjeSB0cmlhbHMNCg0KVGhpcyBpcyBhIHNsaWdodGx5IGNvbnZvbHV0ZWQgd2F5IHRvIGltcGxlbWVudCBjb21wbGV0ZSByYW5kb21pc2F0aW9uIGluIHdoaWNoIGEgZml4ZWQgbnVtYmVyIG9mIHBhcnRpY2lwYW50cyBhcmUgcmFuZG9taXNlZCB0byB0cmVhdG1lbnQgKGNvbXBhcmUgd2l0aCBCZXJub3VsbGkgcmFuZG9taXNhdGlvbiwgd2hlcmUgdGhlIHByb3BvcnRpb24gaXMgYSBwcm9iYWJpbGl0eSB0aGF0IG1heSB2YXJ5IGJldHdlZW4gdHJpYWxzKS4NCg0KYGBge3J9DQpjb21wbGV0ZWx5X3JhbmRvbWlzZXIgPC0gZnVuY3Rpb24oZGF0LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyZWF0X3Zhcl9uYW1lID0gInRyZWF0IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wX3RyZWF0ID0gMC41KSB7DQogIHRyZWF0X24gICA8LSBjZWlsaW5nKHByb3BfdHJlYXQgKiBucm93KGRhdCkpDQogIGNvbnRyb2xfbiA8LSBucm93KGRhdCkgLSB0cmVhdF9uDQogIHplcm9fb25lcyA8LSBjKHJlcCgxLCB0cmVhdF9uKSwgcmVwKDAsIGNvbnRyb2xfbikpDQogIGRhdCB8Pg0KICAgIG11dGF0ZSghIXRyZWF0X3Zhcl9uYW1lIDo9IHNhbXBsZSh6ZXJvX29uZXMpKQ0KfQ0KYGBgDQoNClRoaXMgZnVuY3Rpb24gd2lsbCBnaXZlIHVzIHRoZSByZWFsaXNlZCBwb3RlbnRpYWwgb3V0Y29tZToNCg0KYGBge3J9DQpyZWFsaXNlX3BvdGVudGlhbCA8LSBmdW5jdGlvbihkYXQsIHlfbmFtZSA9IHksIHkwLCB5MSwgdHJlYXQpIHsNCiAgZGF0IHw+DQogICAgbXV0YXRlKCEheV9uYW1lIDo9IGlmZWxzZSh0cmVhdCA9PSAxLCB5MSwgeTApKQ0KfQ0KYGBgDQoNCkFuZCBhIGZ1bmN0aW9uIHRvIHN1bW1hcmlzZSB0aGUgZmluZGluZ3MgZm9yIHRoZSBjbGFzc2ljIFNFIGFuZCB0aGUgbmV3IHNoYXJwIGJvdW5kIG9uIHRoZSBTRToNCg0KYGBge3J9DQpzdW1tYXJpc2VfbW9kIDwtIGZ1bmN0aW9uKG1vZCwgZGF0LCB0cmVhdF92YXIgPSAidHJlYXQiKSB7DQogIG1vZCB8Pg0KICAgIHRpZHkoKSB8Pg0KICAgIGZpbHRlcih0ZXJtID09IHRyZWF0X3ZhcikgfD4NCiAgICBtdXRhdGUoDQogICAgICBzZV9zaGFycCA9IHNoYXJwdmFyKHJlc2lkKG1vZCksIGRhdCR0cmVhdCwgdXBwZXIgPSBUUlVFKSB8PiBzcXJ0KCksDQogICAgICBkZiA9IGRmLnJlc2lkdWFsKG1vZCkNCiAgICApIHw+DQogICAgcmVuYW1lKHNlX2NsYXNzaWMgPSBzdGQuZXJyb3IpIHw+DQogICAgc2VsZWN0KC1jKHN0YXRpc3RpYywgcC52YWx1ZSkpIHw+DQogICAgcGl2b3RfbG9uZ2VyKA0KICAgICAgY29scyA9IHN0YXJ0c193aXRoKCJzZV8iKSwNCiAgICAgIG5hbWVzX3ByZWZpeCA9ICJzZV8iLA0KICAgICAgbmFtZXNfdG8gPSAidHlwZSIsDQogICAgICB2YWx1ZXNfdG8gPSAic2UiDQogICAgKSB8Pg0KICAgIG11dGF0ZShjaV9sb3dlciA9IGVzdGltYXRlICsgcXQoLjA1LzIsIGRmKSAqIHNlLA0KICAgICAgICAgICBjaV91cHBlciA9IGVzdGltYXRlICsgcXQoMSAtICguMDUvMiksIGRmKSAqIHNlKQ0KfQ0KYGBgDQoNCg0KVGhlIHBpcGVsaW5lIHdlIHdpbGwgcmVwbGljYXRlIGEgZmV3IHRob3VzYW5kIHRpbWVzOg0KDQpgYGB7cn0NCm9uZV9zaW0gPC0gZnVuY3Rpb24ocG9wbl9kYXQpIHsNCiAgb25lX3RyaWFsIDwtIHBvcG5fZGF0IHw+DQogICAgY29tcGxldGVseV9yYW5kb21pc2VyKCkgfD4NCiAgICByZWFsaXNlX3BvdGVudGlhbCgieSIsIHkwLCB5MSwgdHJlYXQpDQogIA0KICB0aGVfbW9kIDwtIGxtKHkgfiB0cmVhdCArIHgsIGRhdGEgPSBvbmVfdHJpYWwpDQogIA0KICBzdW1tYXJpc2VfbW9kKHRoZV9tb2QsIG9uZV90cmlhbCkNCn0NCmBgYA0KDQoNCg0KT2ZmIHdlIGdvOg0KDQpgYGB7cn0NCnRpYygpDQpyZXMgPC0gcmVwbGljYXRlKDEwMDAwLCBvbmVfc2ltKHNpbV9kYXQpLCBzaW1wbGlmeSA9IEZBTFNFKSB8PiBsaXN0X3JiaW5kKCkNCnRvYygpDQpgYGANCg0KTm93IHdoYXQncyB0aGUgY292ZXJhZ2UgbGlrZT8NCg0KDQpgYGB7cn0NCnRhbGxpZWRfcmVzIDwtIHJlcyB8Pg0KICBtdXRhdGUodHJ1dGggPSB0cnVlU0FURSwNCiAgICAgICAgIGNvdmVyZWQgPSBiZXR3ZWVuKHRydXRoLCBjaV9sb3dlciwgY2lfdXBwZXIpKSB8Pg0KICBncm91cF9ieSh0eXBlKSB8Pg0KICBzdW1tYXJpc2UoYHByb3BvcnRpb24gOTUlIENJIGNvdmVyYWdlYCA9IG1lYW4oY292ZXJlZCkpDQp0YWxsaWVkX3Jlcw0KYGBgDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQpnaW1tZV9yZXMgPC0gZnVuY3Rpb24od2hpY2gpIHsNCiAgdGhlX3Byb3AgPC0gdGFsbGllZF9yZXMgfD4gZmlsdGVyKHR5cGUgPT0gd2hpY2gpIHw+IHB1bGwoMikNCiAgcm91bmQoMTAwICogdGhlX3Byb3AsMikNCn0NCmBgYA0KDQpXZSBzZWUgdGhhdCB0aGUgY2xhc3NpYyAoYW5kIGNvbnNlcnZhdGl2ZSkgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgY292ZXJzIHRoZSB0cnVlIFNBVEUgYHIgZ2ltbWVfcmVzKCJjbGFzc2ljIilgJSBvZiB0aGUgdGltZSB3aGVyZWFzIE1pa2hhZWlsIGFuZCBHcmVlbidzIGltcHJvdmVkIGludGVydmFsIGdpdmVzIHVzIGByIGdpbW1lX3Jlcygic2hhcnAiKWAlIGNvdmVyYWdlLg0KDQpJdCB3b3JrZWQsIHRoZSBpbnRlcnZhbCBpcyBhIHRpbnkgYml0IGNsb3NlciB0byB0aGUgOTUlIHRhcmdldCENCg0KDQojIyBSZWZlcmVuY2VzDQoNCkFyb25vdywgUC4gTS4sIEdyZWVuLCBELiBQLiwgJiBMZWUsIEQuIEsuIEsuICgyMDE0KS4gW1NoYXJwIGJvdW5kcyBvbiB0aGUgdmFyaWFuY2UgaW4gcmFuZG9taXplZCBleHBlcmltZW50c10oaHR0cHM6Ly93d3cuanN0b3Iub3JnL3N0YWJsZS80MzU1NjMwOCkuIEFubmFscyBvZiBTdGF0aXN0aWNzLCA0MiwgODUwLS04NzEuDQoNCk1pa2hhZWlsLCBKLiBNLiwgJiBHcmVlbiwgRC4gUC4gKDIwMjQpLiBbU2hhcnAgYm91bmRzIG9uIHRoZSB2YXJpYW5jZSBvZiBnZW5lcmFsIHJlZ3Jlc3Npb24gYWRqdXN0bWVudCBpbiByYW5kb21pemVkIGV4cGVyaW1lbnRzXShodHRwczovL2FyeGl2Lm9yZy9hYnMvMjQxMS4wMDE5MSkuIGFyWGl2IHByZXByaW50Lg0KDQpOZXltYW4sIEouICgxOTIzLzE5OTApLiBbT24gdGhlIGFwcGxpY2F0aW9uIG9mIHByb2JhYmlsaXR5IHRoZW9yeSB0byBhZ3JpY3VsdHVyYWwgZXhwZXJpbWVudHMuIEVzc2F5IG9uIHByaW5jaXBsZXMuIFNlY3Rpb24gOS5dKGh0dHBzOi8vd3d3LmpzdG9yLm9yZy9zdGFibGUvMjI0NTM4MikgX1N0YXRpc3RpY2FsIFNjaWVuY2VfLCBfNV8sIDQ2NS0tNDcyLg0KDQpSZWljaGFyZHQsIEMuIFMuLCAmIEdvbGxvYiwgSC4gRi4gKDE5OTkpLiBbSnVzdGlmeWluZyB0aGUgVXNlIGFuZCBJbmNyZWFzaW5nIHRoZSBQb3dlciBvZiBhIF90XyBUZXN0IGZvciBhIFJhbmRvbWl6ZWQgRXhwZXJpbWVudCBXaXRoIGEgQ29udmVuaWVuY2UgU2FtcGxlXShodHRwczovL3BzeWNuZXQuYXBhLm9yZy9kb2kvMTAuMTAzNy8xMDgyLTk4OVguNC4xLjExNykuIF9Qc3ljaG9sb2dpY2FsIE1ldGhvZHNfLCBfNF8sIDExNy0tMTI4Lg0KDQo=