diff --git a/demos_ch2/demo2_4.html b/demos_ch2/demo2_4.html
index 6deb7ec..0ad844e 100644
--- a/demos_ch2/demo2_4.html
+++ b/demos_ch2/demo2_4.html
@@ -11,10 +11,23 @@
-
+
Bayesian data analysis demo 2.4
+
@@ -241,7 +254,7 @@
$(this).detach().appendTo(div);
// add a show code button right above
- var showCodeText = $('' + (showThis ? 'Hide' : 'Code') + ' ');
+ var showCodeText = $('' + (showThis ? 'Hide' : 'Show') + ' ');
var showCodeButton = $(' ');
showCodeButton.append(showCodeText);
showCodeButton
@@ -267,7 +280,7 @@
// * Change text
// * add a class for intermediate states styling
div.on('hide.bs.collapse', function () {
- showCodeText.text('Code');
+ showCodeText.text('Show');
showCodeButton.addClass('btn-collapsing');
});
div.on('hidden.bs.collapse', function () {
@@ -394,8 +407,8 @@
border-radius: 4px;
}
-.tabset-dropdown > .nav-tabs > li.active:before {
- content: "";
+.tabset-dropdown > .nav-tabs > li.active:before, .tabset-dropdown > .nav-tabs.nav-tabs-open:before {
+ content: "\e259";
font-family: 'Glyphicons Halflings';
display: inline-block;
padding: 10px;
@@ -403,16 +416,9 @@
}
.tabset-dropdown > .nav-tabs.nav-tabs-open > li.active:before {
- content: "";
- border: none;
-}
-
-.tabset-dropdown > .nav-tabs.nav-tabs-open:before {
- content: "";
+ content: "\e258";
font-family: 'Glyphicons Halflings';
- display: inline-block;
- padding: 10px;
- border-right: 1px solid #ddd;
+ border: none;
}
.tabset-dropdown > .nav-tabs > li.active {
@@ -469,14 +475,14 @@
Bayesian data analysis demo 2.4
Aki Vehtari, Markus Paasiniemi
-2022-08-29
+2023-11-07
Probability of a girl birth given placenta previa (BDA3 p. 37).
-
Calculate the posterior distribution on a discrete grid of points by multiplying the likelihood and a non-conjugate prior at each point, and normalizing over the points. Simulate samples from the resulting non-standard posterior distribution using inverse cdf using the discrete grid.
+
Calculate the posterior distribution on a discrete grid of points by multiplying the likelihood and a non-conjugate prior at each point, and normalizing over the points. Simulate draws from the resulting non-standard posterior distribution using inverse cdf using the discrete grid.
ggplot2 and gridExtra are used for plotting, tidyr for manipulating data frames
library(ggplot2)
theme_set(theme_minimal())
@@ -490,7 +496,7 @@ Evaluating posterior with non-conjugate prior in grid
b <- 543
Evaluate densities at evenly spaced points between 0.1 and 1
df1 <- data.frame(theta = seq(0.1, 1, 0.001))
-df1$con <- dbeta(df1$theta, a, b)
+df1$con <- dbeta(df1$theta, a+1, b+1)
Compute the density of non-conjugate prior in discrete points, i.e. in a grid this non-conjugate prior is the same as in figure 2.4 in the book
pp <- rep(1, nrow(df1))
pi <- sapply(c(0.388, 0.488, 0.588), function(pi) which(df1$theta == pi))
@@ -500,7 +506,7 @@ Evaluating posterior with non-conjugate prior in grid
normalize the prior
df1$nc_p <- pp / sum(pp)
compute the un-normalized non-conjugate posterior in a grid
-po <- dbeta(df1$theta, a, b) * pp
+po <- dbinom(a, a+b, df1$theta) * pp
normalize the posterior
df1$nc_po <- po / sum(po)
Plot posterior with uniform prior, non-conjugate prior and the corresponding non-conjugate posterior
@@ -518,7 +524,7 @@ Evaluating posterior with non-conjugate prior in grid
coord_cartesian(xlim = c(0.35,0.6)) +
scale_y_continuous(breaks=NULL) +
labs(x = '', y = '')
-
+
Inverse cdf sampling
@@ -536,7 +542,7 @@
Inverse cdf sampling
# sapply function for each sample r. The returned values s are now
# random draws from the distribution.
s <- sapply(r, invcdf, df1)
-
Create three plots: p1 is the posterior, p2 is the cdf of the posterior and p3 is the histogram of posterior samples (drawn using inv-cdf)
+
Create three plots: p1 is the posterior, p2 is the cdf of the posterior and p3 is the histogram of posterior draws (drawn using inv-cdf)
p1 <- ggplot(data = df1) +
geom_line(aes(theta, nc_po)) +
coord_cartesian(xlim = c(0.35, 0.6)) +
@@ -550,15 +556,15 @@ Inverse cdf sampling
p3 <- ggplot() +
geom_histogram(aes(s), binwidth = 0.003) +
coord_cartesian(xlim = c(0.35, 0.6)) +
- labs(title = 'Histogram of posterior samples', x = '', y = '') +
+ labs(title = 'Histogram of posterior draws', x = '', y = '') +
scale_y_continuous(breaks = NULL)
# combine the plots
grid.arrange(p1, p2, p3)
-
+
-LS0tCnRpdGxlOiAiQmF5ZXNpYW4gZGF0YSBhbmFseXNpcyBkZW1vIDIuNCIKYXV0aG9yOiAiQWtpIFZlaHRhcmksIE1hcmt1cyBQYWFzaW5pZW1pIgpkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCkpYCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZTogcmVhZGFibGUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKLS0tCiMjIFByb2JhYmlsaXR5IG9mIGEgZ2lybCBiaXJ0aCBnaXZlbiBwbGFjZW50YSBwcmV2aWEgKEJEQTMgcC4gMzcpLgoKQ2FsY3VsYXRlIHRoZSBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uIG9uIGEgZGlzY3JldGUgZ3JpZCBvZiBwb2ludHMgYnkKbXVsdGlwbHlpbmcgdGhlIGxpa2VsaWhvb2QgYW5kIGEgbm9uLWNvbmp1Z2F0ZSBwcmlvciBhdCBlYWNoIHBvaW50LAphbmQgbm9ybWFsaXppbmcgb3ZlciB0aGUgcG9pbnRzLiBTaW11bGF0ZSBzYW1wbGVzIGZyb20gdGhlIHJlc3VsdGluZwpub24tc3RhbmRhcmQgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbiB1c2luZyBpbnZlcnNlIGNkZiB1c2luZyB0aGUKZGlzY3JldGUgZ3JpZC4KCmdncGxvdDIgYW5kIGdyaWRFeHRyYSBhcmUgdXNlZCBmb3IgcGxvdHRpbmcsIHRpZHlyIGZvciBtYW5pcHVsYXRpbmcgZGF0YSBmcmFtZXMKCmBgYHtyIHNldHVwLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShnZ3Bsb3QyKQp0aGVtZV9zZXQodGhlbWVfbWluaW1hbCgpKQpsaWJyYXJ5KGdyaWRFeHRyYSkKbGlicmFyeSh0aWR5cikKbGlicmFyeShkcGx5cikKYGBgCgojIyMgRXZhbHVhdGluZyBwb3N0ZXJpb3Igd2l0aCBub24tY29uanVnYXRlIHByaW9yIGluIGdyaWQKClBvc3RlcmlvciB3aXRoIG9ic2VydmF0aW9ucyAoNDM3LDU0MykgYW5kIHVuaWZvcm0gcHJpb3IgKEJldGEoMSwxKSkKCmBgYHtyIH0KYSA8LSA0MzcKYiA8LSA1NDMKYGBgCgpFdmFsdWF0ZSBkZW5zaXRpZXMgYXQgZXZlbmx5IHNwYWNlZCBwb2ludHMgYmV0d2VlbiAwLjEgYW5kIDEKCmBgYHtyIH0KZGYxIDwtIGRhdGEuZnJhbWUodGhldGEgPSBzZXEoMC4xLCAxLCAwLjAwMSkpCmRmMSRjb24gPC0gZGJldGEoZGYxJHRoZXRhLCBhLCBiKQpgYGAKCkNvbXB1dGUgdGhlIGRlbnNpdHkgb2Ygbm9uLWNvbmp1Z2F0ZSBwcmlvciBpbiBkaXNjcmV0ZSBwb2ludHMsIGkuZS4gaW4gYSBncmlkCnRoaXMgbm9uLWNvbmp1Z2F0ZSBwcmlvciBpcyB0aGUgc2FtZSBhcyBpbiBmaWd1cmUgMi40IGluIHRoZSBib29rCgpgYGB7ciB9CnBwIDwtIHJlcCgxLCBucm93KGRmMSkpCnBpIDwtIHNhcHBseShjKDAuMzg4LCAwLjQ4OCwgMC41ODgpLCBmdW5jdGlvbihwaSkgd2hpY2goZGYxJHRoZXRhID09IHBpKSkKcG0gPC0gMTEKcHBbcGlbMV06cGlbMl1dIDwtIHNlcSgxLCBwbSwgbGVuZ3RoLm91dCA9IGxlbmd0aChwaVsxXTpwaVsyXSkpCnBwW3BpWzNdOnBpWzJdXSA8LSBzZXEoMSwgcG0sIGxlbmd0aC5vdXQgPSBsZW5ndGgocGlbM106cGlbMl0pKQpgYGAKCm5vcm1hbGl6ZSB0aGUgcHJpb3IKCmBgYHtyIH0KZGYxJG5jX3AgPC0gcHAgLyBzdW0ocHApCmBgYAoKY29tcHV0ZSB0aGUgdW4tbm9ybWFsaXplZCBub24tY29uanVnYXRlIHBvc3RlcmlvciBpbiBhIGdyaWQKCmBgYHtyIH0KcG8gPC0gZGJldGEoZGYxJHRoZXRhLCBhLCBiKSAqIHBwCmBgYAoKbm9ybWFsaXplIHRoZSBwb3N0ZXJpb3IKCmBgYHtyIH0KZGYxJG5jX3BvIDwtIHBvIC8gc3VtKHBvKQpgYGAKClBsb3QgcG9zdGVyaW9yIHdpdGggdW5pZm9ybSBwcmlvciwgbm9uLWNvbmp1Z2F0ZQpwcmlvciBhbmQgdGhlIGNvcnJlc3BvbmRpbmcgbm9uLWNvbmp1Z2F0ZSBwb3N0ZXJpb3IKCmBgYHtyIH0KIyBwaXZvdCB0aGUgZGF0YSBmcmFtZSBpbnRvIGtleS12YWx1ZSBwYWlycwojIGFuZCBjaGFuZ2UgdmFyaWFibGUgbmFtZXMgZm9yIHBsb3R0aW5nCmRmMiA8LSBkZjEgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtdGhldGEsIG5hbWVzX3RvID0gImdycCIsIHZhbHVlc190byA9ICJwIikgJT4lCiAgbXV0YXRlKGdycCA9IGZhY3RvcihncnAsIGxhYmVscz1jKCdQb3N0ZXJpb3Igd2l0aCB1bmlmb3JtIHByaW9yJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ05vbi1jb25qdWdhdGUgcHJpb3InLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnTm9uLWNvbmp1Z2F0ZSBwb3N0ZXJpb3InKSkpCiMjIGxldmVscyhkZjIkZ3JwKSA8LSAKZ2dwbG90KGRhdGEgPSBkZjIpICsKICBnZW9tX2xpbmUoYWVzKHRoZXRhLCBwKSkgKwogIGZhY2V0X3dyYXAofmdycCwgbmNvbCA9IDEsIHNjYWxlcyA9ICdmcmVlX3knKSArCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDAuMzUsMC42KSkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3M9TlVMTCkgKwogIGxhYnMoeCA9ICcnLCB5ID0gJycpCmBgYAoKIyMjIEludmVyc2UgY2RmIHNhbXBsaW5nCgpjb21wdXRlIHRoZSBjdW11bGF0aXZlIGRlbnNpdHkgaW4gYSBncmlkCgpgYGB7ciB9CmRmMSRjc19wbyA8LSBjdW1zdW0oZGYxJG5jX3BvKQpgYGAKClNhbXBsZSBmcm9tIHVuaWZvcm0gZGlzdHJpYnV0aW9uIFUoMCwxKQoKYGBge3IgfQojIHNldC5zZWVkKHNlZWQpIGlzIHVzZWQgdG8gc2V0IHNlZWQgZm9yIHRoZSByYW5kb24gbnVtYmVyIGdlbmVyYXRvcgpzZXQuc2VlZCgyNjAxKQojIHJ1bmlmKGspIHJldHVybnMgayB1bmlmb3JtIHJhbmRvbSBudW1iZXJzIGZyb20gaW50ZXJ2YWwgWzAsMV0KciA8LSBydW5pZigxMDAwMCkKYGBgCgpJbnZlcnNlLWNkZiBzYW1wbGluZwoKYGBge3IgfQojIGZ1bmN0aW9uIHRvIGZpbmQgdGhlIHZhbHVlIHNtYWxsZXN0IHZhbHVlIHRoZXRhIGF0IHdoaWNoIHRoZSBjdW11bGF0aXZlCiMgc3VtIG9mIHRoZSBwb3N0ZXJpb3IgZGVuc2l0aWVzIGlzIGdyZWF0ZXIgdGhhbiByLgppbnZjZGYgPC0gZnVuY3Rpb24ociwgZGYpIGRmJHRoZXRhW3N1bShkZiRjc19wbyA8IHIpICsgMV0KIyBzYXBwbHkgZnVuY3Rpb24gZm9yIGVhY2ggc2FtcGxlIHIuIFRoZSByZXR1cm5lZCB2YWx1ZXMgcyBhcmUgbm93CiMgcmFuZG9tIGRyYXdzIGZyb20gdGhlIGRpc3RyaWJ1dGlvbi4KcyA8LSBzYXBwbHkociwgaW52Y2RmLCBkZjEpCmBgYAoKQ3JlYXRlIHRocmVlIHBsb3RzOiBwMSBpcyB0aGUgcG9zdGVyaW9yLCBwMiBpcyB0aGUgY2RmIG9mIHRoZSBwb3N0ZXJpb3IKYW5kIHAzIGlzIHRoZSBoaXN0b2dyYW0gb2YgcG9zdGVyaW9yIHNhbXBsZXMgKGRyYXduIHVzaW5nIGludi1jZGYpCgpgYGB7ciB9CnAxIDwtIGdncGxvdChkYXRhID0gZGYxKSArCiAgZ2VvbV9saW5lKGFlcyh0aGV0YSwgbmNfcG8pKSArCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDAuMzUsIDAuNikpICsKICBsYWJzKHRpdGxlID0gJ05vbi1jb25qdWdhdGUgcG9zdGVyaW9yJywgeCA9ICcnLCB5ID0gJycpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gTlVMTCkKcDIgPC0gZ2dwbG90KGRhdGEgPSBkZjEpICsKICBnZW9tX2xpbmUoYWVzKHRoZXRhLCBjc19wbykpICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMC4zNSwgMC42KSkgKwogIGxhYnModGl0bGUgPSAnUG9zdGVyaW9yLWNkZicsIHggPSAnJywgeSA9ICcnKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IE5VTEwpCnAzIDwtIGdncGxvdCgpICsKICBnZW9tX2hpc3RvZ3JhbShhZXMocyksIGJpbndpZHRoID0gMC4wMDMpICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMC4zNSwgMC42KSkgKwogIGxhYnModGl0bGUgPSAnSGlzdG9ncmFtIG9mIHBvc3RlcmlvciBzYW1wbGVzJywgeCA9ICcnLCB5ID0gJycpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gTlVMTCkKIyBjb21iaW5lIHRoZSBwbG90cwpncmlkLmFycmFuZ2UocDEsIHAyLCBwMykKYGBgCgo=
+LS0tCnRpdGxlOiAiQmF5ZXNpYW4gZGF0YSBhbmFseXNpcyBkZW1vIDIuNCIKYXV0aG9yOiAiQWtpIFZlaHRhcmksIE1hcmt1cyBQYWFzaW5pZW1pIgpkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCkpYCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZTogcmVhZGFibGUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKLS0tCiMjIFByb2JhYmlsaXR5IG9mIGEgZ2lybCBiaXJ0aCBnaXZlbiBwbGFjZW50YSBwcmV2aWEgKEJEQTMgcC4gMzcpLgoKQ2FsY3VsYXRlIHRoZSBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uIG9uIGEgZGlzY3JldGUgZ3JpZCBvZiBwb2ludHMgYnkKbXVsdGlwbHlpbmcgdGhlIGxpa2VsaWhvb2QgYW5kIGEgbm9uLWNvbmp1Z2F0ZSBwcmlvciBhdCBlYWNoIHBvaW50LAphbmQgbm9ybWFsaXppbmcgb3ZlciB0aGUgcG9pbnRzLiBTaW11bGF0ZSBkcmF3cyBmcm9tIHRoZSByZXN1bHRpbmcKbm9uLXN0YW5kYXJkIHBvc3RlcmlvciBkaXN0cmlidXRpb24gdXNpbmcgaW52ZXJzZSBjZGYgdXNpbmcgdGhlCmRpc2NyZXRlIGdyaWQuCgpnZ3Bsb3QyIGFuZCBncmlkRXh0cmEgYXJlIHVzZWQgZm9yIHBsb3R0aW5nLCB0aWR5ciBmb3IgbWFuaXB1bGF0aW5nIGRhdGEgZnJhbWVzCgpgYGB7ciBzZXR1cCwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoZ2dwbG90MikKdGhlbWVfc2V0KHRoZW1lX21pbmltYWwoKSkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZHBseXIpCmBgYAoKIyMjIEV2YWx1YXRpbmcgcG9zdGVyaW9yIHdpdGggbm9uLWNvbmp1Z2F0ZSBwcmlvciBpbiBncmlkCgpQb3N0ZXJpb3Igd2l0aCBvYnNlcnZhdGlvbnMgKDQzNyw1NDMpIGFuZCB1bmlmb3JtIHByaW9yIChCZXRhKDEsMSkpCgpgYGB7ciB9CmEgPC0gNDM3CmIgPC0gNTQzCmBgYAoKRXZhbHVhdGUgZGVuc2l0aWVzIGF0IGV2ZW5seSBzcGFjZWQgcG9pbnRzIGJldHdlZW4gMC4xIGFuZCAxCgpgYGB7ciB9CmRmMSA8LSBkYXRhLmZyYW1lKHRoZXRhID0gc2VxKDAuMSwgMSwgMC4wMDEpKQpkZjEkY29uIDwtIGRiZXRhKGRmMSR0aGV0YSwgYSsxLCBiKzEpCmBgYAoKQ29tcHV0ZSB0aGUgZGVuc2l0eSBvZiBub24tY29uanVnYXRlIHByaW9yIGluIGRpc2NyZXRlIHBvaW50cywgaS5lLiBpbiBhIGdyaWQKdGhpcyBub24tY29uanVnYXRlIHByaW9yIGlzIHRoZSBzYW1lIGFzIGluIGZpZ3VyZSAyLjQgaW4gdGhlIGJvb2sKCmBgYHtyIH0KcHAgPC0gcmVwKDEsIG5yb3coZGYxKSkKcGkgPC0gc2FwcGx5KGMoMC4zODgsIDAuNDg4LCAwLjU4OCksIGZ1bmN0aW9uKHBpKSB3aGljaChkZjEkdGhldGEgPT0gcGkpKQpwbSA8LSAxMQpwcFtwaVsxXTpwaVsyXV0gPC0gc2VxKDEsIHBtLCBsZW5ndGgub3V0ID0gbGVuZ3RoKHBpWzFdOnBpWzJdKSkKcHBbcGlbM106cGlbMl1dIDwtIHNlcSgxLCBwbSwgbGVuZ3RoLm91dCA9IGxlbmd0aChwaVszXTpwaVsyXSkpCmBgYAoKbm9ybWFsaXplIHRoZSBwcmlvcgoKYGBge3IgfQpkZjEkbmNfcCA8LSBwcCAvIHN1bShwcCkKYGBgCgpjb21wdXRlIHRoZSB1bi1ub3JtYWxpemVkIG5vbi1jb25qdWdhdGUgcG9zdGVyaW9yIGluIGEgZ3JpZAoKYGBge3IgfQpwbyA8LSBkYmlub20oYSwgYStiLCBkZjEkdGhldGEpICogcHAKYGBgCgpub3JtYWxpemUgdGhlIHBvc3RlcmlvcgoKYGBge3IgfQpkZjEkbmNfcG8gPC0gcG8gLyBzdW0ocG8pCmBgYAoKUGxvdCBwb3N0ZXJpb3Igd2l0aCB1bmlmb3JtIHByaW9yLCBub24tY29uanVnYXRlCnByaW9yIGFuZCB0aGUgY29ycmVzcG9uZGluZyBub24tY29uanVnYXRlIHBvc3RlcmlvcgoKYGBge3IgfQojIHBpdm90IHRoZSBkYXRhIGZyYW1lIGludG8ga2V5LXZhbHVlIHBhaXJzCiMgYW5kIGNoYW5nZSB2YXJpYWJsZSBuYW1lcyBmb3IgcGxvdHRpbmcKZGYyIDwtIGRmMSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IC10aGV0YSwgbmFtZXNfdG8gPSAiZ3JwIiwgdmFsdWVzX3RvID0gInAiKSAlPiUKICBtdXRhdGUoZ3JwID0gZmFjdG9yKGdycCwgbGFiZWxzPWMoJ1Bvc3RlcmlvciB3aXRoIHVuaWZvcm0gcHJpb3InLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnTm9uLWNvbmp1Z2F0ZSBwcmlvcicsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdOb24tY29uanVnYXRlIHBvc3RlcmlvcicpKSkKIyMgbGV2ZWxzKGRmMiRncnApIDwtIApnZ3Bsb3QoZGF0YSA9IGRmMikgKwogIGdlb21fbGluZShhZXModGhldGEsIHApKSArCiAgZmFjZXRfd3JhcCh+Z3JwLCBuY29sID0gMSwgc2NhbGVzID0gJ2ZyZWVfeScpICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMC4zNSwwLjYpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcz1OVUxMKSArCiAgbGFicyh4ID0gJycsIHkgPSAnJykKYGBgCgojIyMgSW52ZXJzZSBjZGYgc2FtcGxpbmcKCmNvbXB1dGUgdGhlIGN1bXVsYXRpdmUgZGVuc2l0eSBpbiBhIGdyaWQKCmBgYHtyIH0KZGYxJGNzX3BvIDwtIGN1bXN1bShkZjEkbmNfcG8pCmBgYAoKU2FtcGxlIGZyb20gdW5pZm9ybSBkaXN0cmlidXRpb24gVSgwLDEpCgpgYGB7ciB9CiMgc2V0LnNlZWQoc2VlZCkgaXMgdXNlZCB0byBzZXQgc2VlZCBmb3IgdGhlIHJhbmRvbiBudW1iZXIgZ2VuZXJhdG9yCnNldC5zZWVkKDI2MDEpCiMgcnVuaWYoaykgcmV0dXJucyBrIHVuaWZvcm0gcmFuZG9tIG51bWJlcnMgZnJvbSBpbnRlcnZhbCBbMCwxXQpyIDwtIHJ1bmlmKDEwMDAwKQpgYGAKCkludmVyc2UtY2RmIHNhbXBsaW5nCgpgYGB7ciB9CiMgZnVuY3Rpb24gdG8gZmluZCB0aGUgdmFsdWUgc21hbGxlc3QgdmFsdWUgdGhldGEgYXQgd2hpY2ggdGhlIGN1bXVsYXRpdmUKIyBzdW0gb2YgdGhlIHBvc3RlcmlvciBkZW5zaXRpZXMgaXMgZ3JlYXRlciB0aGFuIHIuCmludmNkZiA8LSBmdW5jdGlvbihyLCBkZikgZGYkdGhldGFbc3VtKGRmJGNzX3BvIDwgcikgKyAxXQojIHNhcHBseSBmdW5jdGlvbiBmb3IgZWFjaCBzYW1wbGUgci4gVGhlIHJldHVybmVkIHZhbHVlcyBzIGFyZSBub3cKIyByYW5kb20gZHJhd3MgZnJvbSB0aGUgZGlzdHJpYnV0aW9uLgpzIDwtIHNhcHBseShyLCBpbnZjZGYsIGRmMSkKYGBgCgpDcmVhdGUgdGhyZWUgcGxvdHM6IHAxIGlzIHRoZSBwb3N0ZXJpb3IsIHAyIGlzIHRoZSBjZGYgb2YgdGhlIHBvc3RlcmlvcgphbmQgcDMgaXMgdGhlIGhpc3RvZ3JhbSBvZiBwb3N0ZXJpb3IgZHJhd3MgKGRyYXduIHVzaW5nIGludi1jZGYpCgpgYGB7ciB9CnAxIDwtIGdncGxvdChkYXRhID0gZGYxKSArCiAgZ2VvbV9saW5lKGFlcyh0aGV0YSwgbmNfcG8pKSArCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDAuMzUsIDAuNikpICsKICBsYWJzKHRpdGxlID0gJ05vbi1jb25qdWdhdGUgcG9zdGVyaW9yJywgeCA9ICcnLCB5ID0gJycpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gTlVMTCkKcDIgPC0gZ2dwbG90KGRhdGEgPSBkZjEpICsKICBnZW9tX2xpbmUoYWVzKHRoZXRhLCBjc19wbykpICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMC4zNSwgMC42KSkgKwogIGxhYnModGl0bGUgPSAnUG9zdGVyaW9yLWNkZicsIHggPSAnJywgeSA9ICcnKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IE5VTEwpCnAzIDwtIGdncGxvdCgpICsKICBnZW9tX2hpc3RvZ3JhbShhZXMocyksIGJpbndpZHRoID0gMC4wMDMpICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMC4zNSwgMC42KSkgKwogIGxhYnModGl0bGUgPSAnSGlzdG9ncmFtIG9mIHBvc3RlcmlvciBkcmF3cycsIHggPSAnJywgeSA9ICcnKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IE5VTEwpCiMgY29tYmluZSB0aGUgcGxvdHMKZ3JpZC5hcnJhbmdlKHAxLCBwMiwgcDMpCmBgYAoK