Introduction

Paper - Aki Vehtari, Daniel Simpson, Andrew Gelman, Yuling Yao, and Jonah Gabry (2022). Pareto smoothed importance sampling. arXiv preprint arXiv:1507.02646

presents Pareto smoothed importance sampling, but also Pareto-\(\hat{k}\) diagnostic that can be used when estimating any mean based on finite sample. Recently Noa Kallioinen added this diagnostic to posterior package. This short notebook illustrates the use.

Load posterior

library(posterior)
options(pillar.neg = FALSE, pillar.subtle=FALSE, pillar.sigfig=2)

Simulated data

Generate xn a simulated MCMC sample with 4 chains each with 1000 iterations using AR process with marginal normal(0,1)

N=1000
phi=0.3
set.seed(6534)
dr<-array(data=replicate(4,as.numeric(arima.sim(n = N,
                                                list(ar = c(phi)),
                                                sd = sqrt((1-phi^2))))),
         dim=c(N,4,1)) |>
  as_draws_df() |>
  set_variables('xn')

Transform xn via cdf-inverse-cdf so that we have variables that have marginally distributions \(t_3\), \(t_{2.5}\), \(t_2\), \(t_{1.5}\), and \(t_1\). These all have thick tails. In addition \(t_2\), \(t_{1.5}\), and \(t_1\) have infinite variance, and \(t_1\) (aka Cauchy) has infinite mean.

drt <- dr |>
  mutate_variables(xt3=qt(pnorm(xn), df=3),
                   xt2_5=qt(pnorm(xn), df=2.5),
                   xt2=qt(pnorm(xn), df=2),
                   xt1_5=qt(pnorm(xn), df=1.5),
                   xt1=qt(pnorm(xn), df=1))

MCMC convergence diagnostics

We examine the draws with the default summarise_draws().

drt |> summarise_draws()
# A tibble: 6 × 10
  variable  mean  median    sd   mad    q5   q95  rhat ess_bulk ess_tail
  <chr>    <dbl>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>    <dbl>    <dbl>
1 xn       0.010 0.00094  0.99  0.99  -1.6   1.6   1.0    2284.    3189.
2 xt3      0.025 0.0010   1.6   1.1   -2.3   2.3   1.0    2284.    3189.
3 xt2_5    0.031 0.0010   2.0   1.1   -2.5   2.5   1.0    2284.    3189.
4 xt2      0.046 0.0011   2.9   1.2   -2.8   2.9   1.0    2284.    3189.
5 xt1_5    0.092 0.0011   7.6   1.3   -3.5   3.6   1.0    2284.    3189.
6 xt1      0.33  0.0012  93.    1.5   -5.8   6.1   1.0    2284.    3189.

All the usual convergence diagnostics \(\widehat{R}\), Bulk-ESS, and Tail-ESS look good, which is fine as they have been designed to work also with infinite variance (Vehtari et al., 2021).

If these variables would present variables of interest for which we would like to estimate means, we would be also interested in Monte Carlo standard error (MCSE, see case study How many iterations to run and how many digits to report).

drt |>
  summarise_draws(mean, sd, mcse_mean, ess_bulk, ess_basic)
# A tibble: 6 × 6
  variable  mean    sd mcse_mean ess_bulk ess_basic
  <chr>    <dbl> <dbl>     <dbl>    <dbl>     <dbl>
1 xn       0.010  0.99     0.021    2284.     2280.
2 xt3      0.025  1.6      0.033    2284.     2452.
3 xt2_5    0.031  2.0      0.039    2284.     2584.
4 xt2      0.046  2.9      0.054    2284.     2903.
5 xt1_5    0.092  7.6      0.13     2284.     3553.
6 xt1      0.33  93.       1.5      2284.     3976.

Here MCSE for mean is based on standard deviation and Basic-ESS, but these assume finite variance. We did sample also from distributions with infinite variance, but given a finite sample size, the empirical variance estimates are finite, and thus we get overoptimistic MCSE.

Pareto-\(\hat{k}\)

To diagnose whether our variables of interest may have infinite variance and even infinite mean, we can use Pareto-\(\hat{k}\) diagnostic.

drt |>
  summarise_draws(mean, sd, mcse_mean, ess_basic, pareto_khat)
# A tibble: 6 × 6
  variable  mean    sd mcse_mean ess_basic   khat
  <chr>    <dbl> <dbl>     <dbl>     <dbl>  <dbl>
1 xn       0.010  0.99     0.021     2280. -0.072
2 xt3      0.025  1.6      0.033     2452.  0.33 
3 xt2_5    0.031  2.0      0.039     2584.  0.41 
4 xt2      0.046  2.9      0.054     2903.  0.52 
5 xt1_5    0.092  7.6      0.13      3553.  0.69 
6 xt1      0.33  93.       1.5       3976.  1.0  

\(\hat{k} \leq 0\) indicates that all moments exist, and the inverse of positive \(\hat{k}\) tells estimate for the number of finite (fractional) moments. Thus, \(\hat{k}\geq 1/2\) indicates infinite variance, and \(\hat{k}\geq 1\) indicates infinite mean. Sometimes very thick distribution tails may affect also sampling, but assuming sampling did go well, and we would be interested only in quantiles, infinite variance and mean are not a problem. But if we are interested in mean, then we need to care about the number of (fractional) moments. Here we see \(\hat{k} \geq 1/2\) for \(t_2\), \(t_{1.5}\), and \(t_{1}\), and we should not trust their mcse_mean values.

Pareto smoothing

If we really do need those mean estimates, we can improve trustworthiness by Pareto smoothing, which replaces extreme tail draws with expected ordered statistics of Pareto distribution fitted to the tails of the distribution. Pareto smoothed mean estimate (computed using Pareto smoothed draws) has finite variance with a cost of some bias which we know when it is negligible. As a thumb rule when \(\hat{k}<0.7\), the bias is negligible.

We Pareto smooth all the variables.

drts <- drt |> 
  mutate_variables(xt3_s=pareto_smooth(xt3),
                   xt2_5_s=pareto_smooth(xt2_5),
                   xt2_s=pareto_smooth(xt2),
                   xt1_5_s=pareto_smooth(xt1_5),
                   xt1_s=pareto_smooth(xt1)) |>
  subset_draws(variable="_s", regex=TRUE)

Now the mcse_mean values are more trustworthy when \(\hat{k} < 0.7\). When \(\hat{k}>0.7\) both bias and variance grow so fast that Pareto smoothing rarely helps.

drts |> summarise_draws(mean, mcse_mean, ess_basic, pareto_khat)
# A tibble: 5 × 5
  variable  mean mcse_mean ess_basic  khat
  <chr>    <dbl>     <dbl>     <dbl> <dbl>
1 xt3_s    0.026     0.033     2436.  0.34
2 xt2_5_s  0.034     0.038     2533.  0.41
3 xt2_s    0.053     0.051     2756.  0.52
4 xt1_5_s  0.13      0.10      3281.  0.68
5 xt1_s    1.0       0.79      3902.  1.0 

Minimum sample size required

The bias and variance depend on the sample size, and we can use additional diagnostic min_ss which tells the minimum sample size needed so that mcse_mean can be trusted.

drt |> summarise_draws(mean, mcse_mean, ess_basic,
                       pareto_khat, min_ss=pareto_min_ss)
# A tibble: 6 × 6
  variable  mean mcse_mean ess_basic   khat min_ss
  <chr>    <dbl>     <dbl>     <dbl>  <dbl>  <dbl>
1 xn       0.010     0.021     2280. -0.072    10 
2 xt3      0.025     0.033     2452.  0.33     31.
3 xt2_5    0.031     0.039     2584.  0.41     48.
4 xt2      0.046     0.054     2903.  0.52    116.
5 xt1_5    0.092     0.13      3553.  0.69   1735.
6 xt1      0.33      1.5       3976.  1.0     Inf 

Here required min_ss is smaller than ess_basic for all except \(t_1\), for which there is no hope.

Convergence rate

Given finite variance, central limit theorem states that to halve MCSE we need four times bigger sample size. With Pareto smoothing, we can go further, but the convergence rate decreases when \(\hat{k}\) increases.

drt |> summarise_draws(mean, mcse_mean, ess_basic,
                       pareto_khat, min_ss=pareto_min_ss,
                       convergence_rate=pareto_convergence_rate)
# A tibble: 6 × 7
  variable  mean mcse_mean ess_basic   khat min_ss convergence_rate
  <chr>    <dbl>     <dbl>     <dbl>  <dbl>  <dbl>            <dbl>
1 xn       0.010     0.021     2280. -0.072    10              1   
2 xt3      0.025     0.033     2452.  0.33     31.             0.98
3 xt2_5    0.031     0.039     2584.  0.41     48.             0.95
4 xt2      0.046     0.054     2903.  0.52    116.             0.86
5 xt1_5    0.092     0.13      3553.  0.69   1735.             0.60
6 xt1      0.33      1.5       3976.  1.0     Inf              0   

We see that with \(t_2\), \(t_{1.5}\), and \(t_1\) we need \(4^{1/0.86}\approx 5\), \(4^{1/0.60}\approx 10\), and \(4^{1/0}\approx \infty\) bigger sample sizes to halve MCSE for mean.

Pareto-\(\hat{k}\)-threshold

The final Pareto diagnostic, \(\hat{k}\)-threshold, is useful for smaller sample sizes. Here we select only 100 iterations per chain to get total of 400 draws.

drt |> subset_draws(iteration=1:100) |>
  summarise_draws(mean, mcse_mean, ess_basic,
                  pareto_khat, min_ss=pareto_min_ss,
                  khat_thres=pareto_khat_threshold,
                  converg_rate=pareto_convergence_rate)
# A tibble: 6 × 8
  variable   mean mcse_mean ess_basic   khat min_ss khat_threshold
  <chr>     <dbl>     <dbl>     <dbl>  <dbl>  <dbl>          <dbl>
1 xn        0.038     0.066      244. -0.012 1  e 1           0.62
2 xt3       0.054     0.11       237.  0.32  3.0e 1           0.62
3 xt2_5     0.057     0.13       237.  0.38  4.2e 1           0.62
4 xt2       0.063     0.17       243.  0.48  8.3e 1           0.62
5 xt1_5     0.061     0.31       271.  0.64  5.6e 2           0.62
6 xt1      -0.26      1.6        344.  0.95  2.2e18           0.62
# ℹ 1 more variable: convergence_rate <dbl>

With only 400 draws, we can trust the Pareto smoothed result only when \(\hat{k}<0.62\). For \(t_{1.5}\) \(\hat{k}\approx 0.64\), and min_ss reveals we would probably need more than 560 draws to be on the safe side.

Pareto diagnostics

We can get all these diagnostics with pareto_diags(), and it’s easy to compute these also for derived quantities.

drt |> mutate_variables(xt2_5_sq=xt2_5^2) |> subset_draws(variable="xt2_5_sq") |>
  summarise_draws(mean, mcse_mean,
                  pareto_diags)
# A tibble: 1 × 7
  variable  mean mcse_mean  khat min_ss khat_threshold convergence_rate
  <chr>    <dbl>     <dbl> <dbl>  <dbl>          <dbl>            <dbl>
1 xt2_5_sq   3.9      0.56  0.67  1124.           0.72             0.63

Discussion

All these diagnostics are presented in Section 3 and summarized in Table 1 in PSIS paper (Vehtari et al., 2022).

If you don’t need to estimate means of thick tailed distributions, and there are no sampling issues due to thick tails, then you don’t need to check existence of finite variance, and thus there is no need to check Pareto-\(\hat{k}\) for all the parameters and derived quantities.

Pareto smoothing can significantly reduce Monte Carlo error in mean and extreme quantile estimates. but we’ll return to that in other notebook.

References

Vehtari, A., Gelman, A., Simpson, D., Carpenter, B. and Bürkner, P.-C. (2021) ‘Rank-normalization, folding, and localization: An improved \(\widehat{R}\) for assessing convergence of MCMC’, Bayesian Analysis, 16, pp. 667–718.

Vehtari, A., Simpson, D., Gelman, A., Yao, Y. and Gabry, J. (2022) ‘Pareto smoothed importance sampling’, arXiv preprint arXiv:1507.02646. Available at: https://arxiv.org/abs/1507.02646v6.

Licenses

  • Code © 2023, Aki Vehtari, licensed under BSD-3.
  • Text © 2023, Aki Vehtari, licensed under CC-BY-NC 4.0.
LS0tCnRpdGxlOiAiUGFyZXRvLWtoYXQgZGlhZ25vc3RpY3MiCmF1dGhvcjogIkFraSBWZWh0YXJpIgpkYXRlOiAiRmlyc3QgdmVyc2lvbiAyMDIzLTExLTIwLiBMYXN0IG1vZGlmaWVkIGByIGZvcm1hdChTeXMuRGF0ZSgpKWAuIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRoZW1lOiByZWFkYWJsZQogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDIKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQpiaWJsaW9ncmFwaHk6IHBhcmV0by5iaWIKY3NsOiBoYXJ2YXJkLWNpdGUtdGhlbS1yaWdodC5jc2wKbGluay1jaXRhdGlvbnM6IHllcwotLS0KCiMjIEludHJvZHVjdGlvbgoKUGFwZXIKICAtIEFraSBWZWh0YXJpLCBEYW5pZWwgU2ltcHNvbiwgQW5kcmV3IEdlbG1hbiwgWXVsaW5nIFlhbywgYW5kCiAgICBKb25haCBHYWJyeSAoMjAyMikuIFBhcmV0byBzbW9vdGhlZCBpbXBvcnRhbmNlIHNhbXBsaW5nLiBbYXJYaXYKICAgIHByZXByaW50IGFyWGl2OjE1MDcuMDI2NDZdKGh0dHBzOi8vYXJ4aXYub3JnL2Ficy8xNTA3LjAyNjQ2djgpCgpwcmVzZW50cyBQYXJldG8gc21vb3RoZWQgaW1wb3J0YW5jZSBzYW1wbGluZywgYnV0IGFsc28KUGFyZXRvLSRcaGF0e2t9JCBkaWFnbm9zdGljIHRoYXQgY2FuIGJlIHVzZWQgd2hlbiBlc3RpbWF0aW5nIGFueQptZWFuIGJhc2VkIG9uIGZpbml0ZSBzYW1wbGUuIFJlY2VudGx5IE5vYSBLYWxsaW9pbmVuIGFkZGVkIHRoaXMKZGlhZ25vc3RpYyB0byBbYHBvc3RlcmlvcmAKcGFja2FnZV0oaHR0cHM6Ly9tYy1zdGFuLm9yZy9wb3N0ZXJpb3IvaW5kZXguaHRtbCkuIFRoaXMgc2hvcnQKbm90ZWJvb2sgaWxsdXN0cmF0ZXMgdGhlIHVzZS4KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQobWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGNvbW1lbnQ9TkEsIGNhY2hlPUZBTFNFKQpgYGAKCkxvYWQgYHBvc3RlcmlvcmAKCmBgYHtyfQpsaWJyYXJ5KHBvc3RlcmlvcikKb3B0aW9ucyhwaWxsYXIubmVnID0gRkFMU0UsIHBpbGxhci5zdWJ0bGU9RkFMU0UsIHBpbGxhci5zaWdmaWc9MikKYGBgCgojIyBTaW11bGF0ZWQgZGF0YQoKR2VuZXJhdGUgYHhuYCBhIHNpbXVsYXRlZCBNQ01DIHNhbXBsZSB3aXRoIDQgY2hhaW5zIGVhY2ggd2l0aCAxMDAwCml0ZXJhdGlvbnMgdXNpbmcgQVIgcHJvY2VzcyB3aXRoIG1hcmdpbmFsIG5vcm1hbCgwLDEpCgpgYGB7cn0KTj0xMDAwCnBoaT0wLjMKc2V0LnNlZWQoNjUzNCkKZHI8LWFycmF5KGRhdGE9cmVwbGljYXRlKDQsYXMubnVtZXJpYyhhcmltYS5zaW0obiA9IE4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3QoYXIgPSBjKHBoaSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZCA9IHNxcnQoKDEtcGhpXjIpKSkpKSwKICAgICAgICAgZGltPWMoTiw0LDEpKSB8PgogIGFzX2RyYXdzX2RmKCkgfD4KICBzZXRfdmFyaWFibGVzKCd4bicpCmBgYAoKVHJhbnNmb3JtIGB4bmAgdmlhIGNkZi1pbnZlcnNlLWNkZiBzbyB0aGF0IHdlIGhhdmUgdmFyaWFibGVzIHRoYXQKaGF2ZSBtYXJnaW5hbGx5IGRpc3RyaWJ1dGlvbnMgJHRfMyQsICR0X3syLjV9JCwgJHRfMiQsICR0X3sxLjV9JCwKYW5kICR0XzEkLiBUaGVzZSBhbGwgaGF2ZSB0aGljayB0YWlscy4gSW4gYWRkaXRpb24gJHRfMiQsCiR0X3sxLjV9JCwgYW5kICR0XzEkIGhhdmUgaW5maW5pdGUgdmFyaWFuY2UsIGFuZCAkdF8xJCAoYWthIENhdWNoeSkKaGFzIGluZmluaXRlIG1lYW4uCgpgYGB7cn0KZHJ0IDwtIGRyIHw+CiAgbXV0YXRlX3ZhcmlhYmxlcyh4dDM9cXQocG5vcm0oeG4pLCBkZj0zKSwKICAgICAgICAgICAgICAgICAgIHh0Ml81PXF0KHBub3JtKHhuKSwgZGY9Mi41KSwKICAgICAgICAgICAgICAgICAgIHh0Mj1xdChwbm9ybSh4biksIGRmPTIpLAogICAgICAgICAgICAgICAgICAgeHQxXzU9cXQocG5vcm0oeG4pLCBkZj0xLjUpLAogICAgICAgICAgICAgICAgICAgeHQxPXF0KHBub3JtKHhuKSwgZGY9MSkpCmBgYAoKIyMgTUNNQyBjb252ZXJnZW5jZSBkaWFnbm9zdGljcwoKV2UgZXhhbWluZSB0aGUgZHJhd3Mgd2l0aCB0aGUgZGVmYXVsdCBgc3VtbWFyaXNlX2RyYXdzKClgLgoKYGBge3J9CmRydCB8PiBzdW1tYXJpc2VfZHJhd3MoKQpgYGAKCkFsbCB0aGUgdXN1YWwgY29udmVyZ2VuY2UgZGlhZ25vc3RpY3MgJFx3aWRlaGF0e1J9JCwgQnVsay1FU1MsIGFuZApUYWlsLUVTUyBsb29rIGdvb2QsIHdoaWNoIGlzIGZpbmUgYXMgdGhleSBoYXZlIGJlZW4gZGVzaWduZWQgdG8Kd29yayBhbHNvIHdpdGggaW5maW5pdGUgdmFyaWFuY2UgW0BWZWh0YXJpK2V0YWw6MjAyMTpSaGF0XS4KCklmIHRoZXNlIHZhcmlhYmxlcyB3b3VsZCBwcmVzZW50IHZhcmlhYmxlcyBvZiBpbnRlcmVzdCBmb3Igd2hpY2gKd2Ugd291bGQgbGlrZSB0byBlc3RpbWF0ZSBtZWFucywgd2Ugd291bGQgYmUgYWxzbyBpbnRlcmVzdGVkIGluCk1vbnRlIENhcmxvIHN0YW5kYXJkIGVycm9yIChNQ1NFLCBzZWUgY2FzZSBzdHVkeSBbSG93IG1hbnkKaXRlcmF0aW9ucyB0byBydW4gYW5kIGhvdyBtYW55IGRpZ2l0cyB0bwpyZXBvcnRdKGh0dHBzOi8vdXNlcnMuYWFsdG8uZmkvfmF2ZS9jYXNlc3R1ZGllcy9EaWdpdHMvZGlnaXRzLmh0bWwpKS4KCmBgYHtyfQpkcnQgfD4KICBzdW1tYXJpc2VfZHJhd3MobWVhbiwgc2QsIG1jc2VfbWVhbiwgZXNzX2J1bGssIGVzc19iYXNpYykKYGBgCgpIZXJlIE1DU0UgZm9yIG1lYW4gaXMgYmFzZWQgb24gc3RhbmRhcmQgZGV2aWF0aW9uIGFuZCBCYXNpYy1FU1MsCmJ1dCB0aGVzZSBhc3N1bWUgZmluaXRlIHZhcmlhbmNlLiBXZSBkaWQgc2FtcGxlIGFsc28gZnJvbQpkaXN0cmlidXRpb25zIHdpdGggaW5maW5pdGUgdmFyaWFuY2UsIGJ1dCBnaXZlbiBhIGZpbml0ZSBzYW1wbGUgc2l6ZSwgdGhlCmVtcGlyaWNhbCB2YXJpYW5jZSBlc3RpbWF0ZXMgYXJlIGZpbml0ZSwgYW5kIHRodXMgd2UgZ2V0Cm92ZXJvcHRpbWlzdGljIE1DU0UuCgojIyBQYXJldG8tJFxoYXR7a30kCgpUbyBkaWFnbm9zZSB3aGV0aGVyIG91ciB2YXJpYWJsZXMgb2YgaW50ZXJlc3QgbWF5IGhhdmUgaW5maW5pdGUKdmFyaWFuY2UgYW5kIGV2ZW4gaW5maW5pdGUgbWVhbiwgd2UgY2FuIHVzZSBQYXJldG8tJFxoYXR7a30kCmRpYWdub3N0aWMuCgpgYGB7cn0KZHJ0IHw+CiAgc3VtbWFyaXNlX2RyYXdzKG1lYW4sIHNkLCBtY3NlX21lYW4sIGVzc19iYXNpYywgcGFyZXRvX2toYXQpCmBgYAoKJFxoYXR7a30gXGxlcSAwJCBpbmRpY2F0ZXMgdGhhdCBhbGwgbW9tZW50cyBleGlzdCwgYW5kIHRoZSBpbnZlcnNlCm9mIHBvc2l0aXZlICRcaGF0e2t9JCB0ZWxscyBlc3RpbWF0ZSBmb3IgdGhlIG51bWJlciBvZiBmaW5pdGUgKGZyYWN0aW9uYWwpCm1vbWVudHMuIFRodXMsICRcaGF0e2t9XGdlcSAxLzIkIGluZGljYXRlcyBpbmZpbml0ZSB2YXJpYW5jZSwKYW5kICRcaGF0e2t9XGdlcSAxJCBpbmRpY2F0ZXMgaW5maW5pdGUgbWVhbi4gU29tZXRpbWVzIHZlcnkgdGhpY2sKZGlzdHJpYnV0aW9uIHRhaWxzIG1heSBhZmZlY3QgYWxzbyBzYW1wbGluZywgYnV0IGFzc3VtaW5nIHNhbXBsaW5nCmRpZCBnbyB3ZWxsLCBhbmQgd2Ugd291bGQgYmUgaW50ZXJlc3RlZCBvbmx5IGluIHF1YW50aWxlcywgaW5maW5pdGUKdmFyaWFuY2UgYW5kIG1lYW4gYXJlIG5vdCBhIHByb2JsZW0uIEJ1dCBpZiB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBtZWFuLAp0aGVuIHdlIG5lZWQgdG8gY2FyZSBhYm91dCB0aGUgbnVtYmVyIG9mIChmcmFjdGlvbmFsKSBtb21lbnRzLiBIZXJlIHdlCnNlZSAkXGhhdHtrfSBcZ2VxIDEvMiQgZm9yICR0XzIkLCAkdF97MS41fSQsIGFuZCAkdF97MX0kLCBhbmQKd2Ugc2hvdWxkIG5vdCB0cnVzdCB0aGVpciBgbWNzZV9tZWFuYCB2YWx1ZXMuCgojIyBQYXJldG8gc21vb3RoaW5nCgpJZiB3ZSByZWFsbHkgZG8gbmVlZCB0aG9zZSBtZWFuIGVzdGltYXRlcywgd2UgY2FuIGltcHJvdmUKdHJ1c3R3b3J0aGluZXNzIGJ5IFBhcmV0byBzbW9vdGhpbmcsICB3aGljaCByZXBsYWNlcwpleHRyZW1lIHRhaWwgZHJhd3Mgd2l0aCBleHBlY3RlZCBvcmRlcmVkIHN0YXRpc3RpY3Mgb2YgUGFyZXRvCmRpc3RyaWJ1dGlvbiBmaXR0ZWQgdG8gdGhlIHRhaWxzIG9mIHRoZSBkaXN0cmlidXRpb24uIFBhcmV0bwpzbW9vdGhlZCBtZWFuIGVzdGltYXRlIChjb21wdXRlZCB1c2luZyBQYXJldG8gc21vb3RoZWQgZHJhd3MpIGhhcwpmaW5pdGUgdmFyaWFuY2Ugd2l0aCBhIGNvc3Qgb2Ygc29tZSBiaWFzIHdoaWNoIHdlIGtub3cgd2hlbiBpdCBpcwpuZWdsaWdpYmxlLiBBcyBhIHRodW1iIHJ1bGUgd2hlbiAkXGhhdHtrfTwwLjckLCB0aGUgYmlhcyBpcwpuZWdsaWdpYmxlLgoKV2UgUGFyZXRvIHNtb290aCBhbGwgdGhlIHZhcmlhYmxlcy4KCmBgYHtyfQpkcnRzIDwtIGRydCB8PiAKICBtdXRhdGVfdmFyaWFibGVzKHh0M19zPXBhcmV0b19zbW9vdGgoeHQzKSwKICAgICAgICAgICAgICAgICAgIHh0Ml81X3M9cGFyZXRvX3Ntb290aCh4dDJfNSksCiAgICAgICAgICAgICAgICAgICB4dDJfcz1wYXJldG9fc21vb3RoKHh0MiksCiAgICAgICAgICAgICAgICAgICB4dDFfNV9zPXBhcmV0b19zbW9vdGgoeHQxXzUpLAogICAgICAgICAgICAgICAgICAgeHQxX3M9cGFyZXRvX3Ntb290aCh4dDEpKSB8PgogIHN1YnNldF9kcmF3cyh2YXJpYWJsZT0iX3MiLCByZWdleD1UUlVFKQpgYGAKCk5vdyB0aGUgYG1jc2VfbWVhbmAgdmFsdWVzIGFyZSBtb3JlIHRydXN0d29ydGh5IHdoZW4gJFxoYXR7a30gPCAwLjckLgpXaGVuICRcaGF0e2t9PjAuNyQgYm90aCBiaWFzIGFuZCB2YXJpYW5jZSBncm93IHNvIGZhc3QgdGhhdCBQYXJldG8gc21vb3RoaW5nCnJhcmVseSBoZWxwcy4KCmBgYHtyfQpkcnRzIHw+IHN1bW1hcmlzZV9kcmF3cyhtZWFuLCBtY3NlX21lYW4sIGVzc19iYXNpYywgcGFyZXRvX2toYXQpCmBgYAoKCiMjIE1pbmltdW0gc2FtcGxlIHNpemUgcmVxdWlyZWQKClRoZSBiaWFzIGFuZCB2YXJpYW5jZSBkZXBlbmQgb24gdGhlIHNhbXBsZSBzaXplLCBhbmQgd2UgY2FuCnVzZSBhZGRpdGlvbmFsIGRpYWdub3N0aWMgYG1pbl9zc2Agd2hpY2ggdGVsbHMgdGhlIG1pbmltdW0gc2FtcGxlIHNpemUgbmVlZGVkCnNvIHRoYXQgYG1jc2VfbWVhbmAgY2FuIGJlIHRydXN0ZWQuCgpgYGB7cn0KZHJ0IHw+IHN1bW1hcmlzZV9kcmF3cyhtZWFuLCBtY3NlX21lYW4sIGVzc19iYXNpYywKICAgICAgICAgICAgICAgICAgICAgICBwYXJldG9fa2hhdCwgbWluX3NzPXBhcmV0b19taW5fc3MpCmBgYAoKSGVyZSByZXF1aXJlZCBgbWluX3NzYCBpcyBzbWFsbGVyIHRoYW4gYGVzc19iYXNpY2AgZm9yIGFsbCBleGNlcHQgJHRfMSQsIGZvcgp3aGljaCB0aGVyZSBpcyBubyBob3BlLgoKIyMgQ29udmVyZ2VuY2UgcmF0ZQoKR2l2ZW4gZmluaXRlIHZhcmlhbmNlLCBjZW50cmFsIGxpbWl0IHRoZW9yZW0gc3RhdGVzIHRoYXQgdG8gaGFsdmUKTUNTRSB3ZSBuZWVkIGZvdXIgdGltZXMgYmlnZ2VyIHNhbXBsZSBzaXplLiBXaXRoIFBhcmV0byBzbW9vdGhpbmcsCndlIGNhbiBnbyBmdXJ0aGVyLCBidXQgdGhlIGNvbnZlcmdlbmNlIHJhdGUgZGVjcmVhc2VzIHdoZW4gJFxoYXR7a30kIGluY3JlYXNlcy4KCmBgYHtyfQpkcnQgfD4gc3VtbWFyaXNlX2RyYXdzKG1lYW4sIG1jc2VfbWVhbiwgZXNzX2Jhc2ljLAogICAgICAgICAgICAgICAgICAgICAgIHBhcmV0b19raGF0LCBtaW5fc3M9cGFyZXRvX21pbl9zcywKICAgICAgICAgICAgICAgICAgICAgICBjb252ZXJnZW5jZV9yYXRlPXBhcmV0b19jb252ZXJnZW5jZV9yYXRlKQpgYGAKCldlIHNlZSB0aGF0IHdpdGggJHRfMiQsICR0X3sxLjV9JCwgYW5kICR0XzEkICB3ZSBuZWVkICQ0XnsxLzAuODZ9XGFwcHJveCA1JCwKJDReezEvMC42MH1cYXBwcm94IDEwJCwgYW5kICQ0XnsxLzB9XGFwcHJveCBcaW5mdHkkIGJpZ2dlciBzYW1wbGUgc2l6ZXMgdG8KaGFsdmUgTUNTRSBmb3IgbWVhbi4KCiMjIFBhcmV0by0kXGhhdHtrfSQtdGhyZXNob2xkCgpUaGUgZmluYWwgUGFyZXRvIGRpYWdub3N0aWMsICRcaGF0e2t9JC10aHJlc2hvbGQsIGlzIHVzZWZ1bCBmb3Igc21hbGxlciBzYW1wbGUgc2l6ZXMuIEhlcmUgd2Ugc2VsZWN0IG9ubHkgMTAwIGl0ZXJhdGlvbnMgcGVyIGNoYWluIHRvIGdldCB0b3RhbCBvZiA0MDAgZHJhd3MuCgpgYGB7cn0KZHJ0IHw+IHN1YnNldF9kcmF3cyhpdGVyYXRpb249MToxMDApIHw+CiAgc3VtbWFyaXNlX2RyYXdzKG1lYW4sIG1jc2VfbWVhbiwgZXNzX2Jhc2ljLAogICAgICAgICAgICAgICAgICBwYXJldG9fa2hhdCwgbWluX3NzPXBhcmV0b19taW5fc3MsCiAgICAgICAgICAgICAgICAgIGtoYXRfdGhyZXM9cGFyZXRvX2toYXRfdGhyZXNob2xkLAogICAgICAgICAgICAgICAgICBjb252ZXJnX3JhdGU9cGFyZXRvX2NvbnZlcmdlbmNlX3JhdGUpCmBgYAoKV2l0aCBvbmx5IDQwMCBkcmF3cywgd2UgY2FuIHRydXN0IHRoZSBQYXJldG8gc21vb3RoZWQgcmVzdWx0IG9ubHkgd2hlbgokXGhhdHtrfTwwLjYyJC4gRm9yICR0X3sxLjV9JCAkXGhhdHtrfVxhcHByb3ggMC42NCQsIGFuZCBgbWluX3NzYCByZXZlYWxzCndlIHdvdWxkIHByb2JhYmx5IG5lZWQgbW9yZSB0aGFuIDU2MCBkcmF3cyB0byBiZSBvbiB0aGUgc2FmZSBzaWRlLgoKIyMgUGFyZXRvIGRpYWdub3N0aWNzCgpXZSBjYW4gZ2V0IGFsbCB0aGVzZSBkaWFnbm9zdGljcyB3aXRoIGBwYXJldG9fZGlhZ3MoKWAsIGFuZCBpdCdzCmVhc3kgdG8gY29tcHV0ZSB0aGVzZSBhbHNvIGZvciBkZXJpdmVkIHF1YW50aXRpZXMuCgpgYGB7cn0KZHJ0IHw+IG11dGF0ZV92YXJpYWJsZXMoeHQyXzVfc3E9eHQyXzVeMikgfD4gc3Vic2V0X2RyYXdzKHZhcmlhYmxlPSJ4dDJfNV9zcSIpIHw+CiAgc3VtbWFyaXNlX2RyYXdzKG1lYW4sIG1jc2VfbWVhbiwKICAgICAgICAgICAgICAgICAgcGFyZXRvX2RpYWdzKQpgYGAKCiMjIERpc2N1c3Npb24KCkFsbCB0aGVzZSBkaWFnbm9zdGljcyBhcmUgcHJlc2VudGVkIGluIFNlY3Rpb24gMyBhbmQgc3VtbWFyaXplZCBpbgpUYWJsZSAxIGluIFBTSVMgcGFwZXIgW0BWZWh0YXJpK2V0YWw6UFNJUzoyMDIyXS4KCklmIHlvdSBkb24ndCBuZWVkIHRvIGVzdGltYXRlIG1lYW5zIG9mIHRoaWNrIHRhaWxlZCBkaXN0cmlidXRpb25zLAphbmQgdGhlcmUgYXJlIG5vIHNhbXBsaW5nIGlzc3VlcyBkdWUgdG8gdGhpY2sgdGFpbHMsIHRoZW4geW91IGRvbid0Cm5lZWQgdG8gY2hlY2sgZXhpc3RlbmNlIG9mIGZpbml0ZSB2YXJpYW5jZSwgYW5kIHRodXMgdGhlcmUgaXMgbm8KbmVlZCB0byBjaGVjayBQYXJldG8tJFxoYXR7a30kIGZvciBhbGwgdGhlIHBhcmFtZXRlcnMgYW5kIGRlcml2ZWQKcXVhbnRpdGllcy4KClBhcmV0byBzbW9vdGhpbmcgY2FuIHNpZ25pZmljYW50bHkgcmVkdWNlIE1vbnRlIENhcmxvIGVycm9yIGluIG1lYW4KYW5kIGV4dHJlbWUgcXVhbnRpbGUgZXN0aW1hdGVzLiBidXQgd2UnbGwgcmV0dXJuIHRvIHRoYXQgaW4gb3RoZXIgbm90ZWJvb2suCgoKIyMgUmVmZXJlbmNlcyB7LnVubnVtYmVyZWR9Cgo8ZGl2IGlkPSJyZWZzIj48L2Rpdj4KCiMjIExpY2Vuc2VzIHsudW5udW1iZXJlZH0KCiogQ29kZSAmY29weTsgMjAyMywgQWtpIFZlaHRhcmksIGxpY2Vuc2VkIHVuZGVyIEJTRC0zLgoqIFRleHQgJmNvcHk7IDIwMjMsIEFraSBWZWh0YXJpLCBsaWNlbnNlZCB1bmRlciBDQy1CWS1OQyA0LjAuCgo=