Normal, Cauchy and Laplace priors
A parameter \(\beta\) is standard normal, Cauchy (standard Student’s \(t\) with one degree of freedom) or standard double-exponential (aka Laplace) if \[\begin{eqnarray*}
p(\beta) &=& \frac{1}{\sqrt{2\pi}}\exp\{-0.5\beta^2\}, \ \ \mbox{or} \\
p(\beta) &=& \frac{1}{\pi(1+\beta^2)}, \ \ \mbox{or} \\
p(\beta) &=& \frac12 \exp\{-|\beta|\},
\end{eqnarray*}\] respectively, for \(\beta \in \Re\).
betas = seq(-5,5,length=1000)
plot(betas,dnorm(betas),type="l",ylim=c(0,0.5),xlab=expression(beta),ylab="Density",lwd=2)
lines(betas,dt(betas,1),col=2,lwd=2)
lines(betas,0.5*exp(-abs(betas)),col=3,lwd=2)
legend("topleft",legend=c("N(0,1)","t(1)","DE(1)"),col=1:3,lwd=2,lty=1,bty="n")
Bayesian inference via MCI
One of the main (computation) problems faced by applied Bayesian modelers/scientists is the computation of integrals, such as the normalizing constant \[
p(y|x) = \int_{-\infty}^\infty \left[\prod_{i=1}^n p_N(y_i|x_i\beta,1)\right]p(\beta)d\beta,
\] or the posterior mean, \[
E(\beta|y,x) = \frac{\int_{-\infty}^\infty \beta \left[\prod_{i=1}^n p_N(y_i|x_i\beta,1)\right]p(\beta)d\beta}{p(y|x)},
\] or even \(Pr(\beta<0.75|y,x)\), \[
Pr(\beta<0.75|y,x) = \frac{\int_{-\infty}^\infty 1(\beta<0.75) \left[\prod_{i=1}^n p_N(y_i|x_i\beta,1)\right]p(\beta)d\beta}{p(y|x)}.
\] Basically, Monte Carlo integration approximates the integral \[
I = \int h(\beta)g(\beta)d\beta = \int \left[\frac{h(\beta)g(\beta)}{q(\beta)}\right]q(\beta)d\beta,
\] based on draws \(\{\beta^{(i)}\}_{i=1}^M\) from \(g(\beta)\) or based on draws \(\{{\tilde \beta}^{(i)}\}_{i=1}^M\) from \(q(\beta)\) (proposal/candidate/importance distribution), as \[\begin{eqnarray*}
{\hat I}_1 &=& \frac{1}{M} \sum_{i=1}^M h(\beta^{(i)})\\
{\hat I}_2 &=& \frac{1}{M} \sum_{i=1}^M \frac{h({\tilde \beta}^{(i)})g({\tilde \beta}^{(i)})}{q({\tilde \beta}^{(i)})}.
\end{eqnarray*}\] As \(M \longrightarrow \infty\), both \({\hat I}_1\) and \({\hat I}_2\) converge to \(I\).
Below we use a uniform distribution in the interval $(-5,5) as our proposal \(q(\beta)\).
M = 10000
b.draws = runif(M,-5,5)
hist(b.draws,prob=TRUE,main="Draws from the proposal U(-5,5)",xlab=expression(beta))
Computing prior predictives
Here we compute \(p(y|x)\), the prior predictive density, based on each one of the three prior specifications of \(\beta\) (Gaussian, Student’s \(t\) and double-exponential).
like = rep(0,M)
for (i in 1:M)
like[i] = prod(dnorm(y,x*b.draws[i],1))
k.n = mean(like*dnorm(b.draws)/(1/10))
k.t = mean(like*dt(b.draws,df=1)/(1/10))
k.l = mean(like*0.5*exp(-abs(b.draws))/(1/10))
c(k.n,k.t,k.l)
## [1] 4.475916e-07 3.650963e-07 4.087623e-07
The only one we can obtain in closed-form is under the normal prior, \(\beta \sim N(0,1)\): \[
p(y|x,\mbox{normal prior}) = p_N(y|0,xx'+I_n)
\]
#install.packages("mvtnorm")
library("mvtnorm")
XtX = x%*%t(x)+diag(1,n)
k.n.exact = dmvnorm(y,rep(0,n),XtX,log=FALSE)
c(k.n.exact,k.n)
## [1] 4.484789e-07 4.475916e-07
Computing posterior means
E.n = mean(b.draws*like*dnorm(b.draws)/(1/10))/k.n
E.t = mean(b.draws*like*dt(b.draws,df=1)/(1/10))/k.t
E.l = mean(b.draws*like*0.5*exp(-abs(b.draws))/(1/10))/k.l
c(E.n,E.t,E.l)
## [1] 1.429081 1.516261 1.499867
The only one we can obtain in closed-form is under the normal prior, i.e. \[
E(\beta|y,x,\mbox{normal prior}) = \frac{\sum_{i=1}^n y_ix_i}{\sum_{i=1}^n x_i^2}.
\]
E.n.exact = sum(y*x)/(sum(x^2)+1)
c(E.n.exact,E.n)
## [1] 1.431680 1.429081
Computing posterior tails
P.n = mean((b.draws<0.75)*like*dnorm(b.draws)/(1/10))/k.n
P.t = mean((b.draws<0.75)*like*dt(b.draws,df=1)/(1/10))/k.t
P.l = mean((b.draws<0.75)*like*0.5*exp(-abs(b.draws))/(1/10))/k.l
c(P.n,P.t,P.l)
## [1] 0.03483404 0.03008621 0.03181092
The only one we can obtain in closed-form is under the normal prior
P.n.exact = pnorm(0.75,E.n.exact,sqrt(1/(sum(x^2)+1)))
c(P.n.exact,P.n)
## [1] 0.03431329 0.03483404
Priors, likelihood and posteriors
likelihood = rep(0,1000)
for (i in 1:1000)
likelihood[i] = prod(dnorm(y,x*betas[i],1))
post.n = dnorm(betas)*likelihood/k.n
post.t = dt(betas,df=1)*likelihood/k.t
post.l = 0.5*exp(-abs(betas))*likelihood/k.l
plot(betas,post.n,type="l",col=2,lwd=2,xlab=expression(beta),ylab="Density")
lines(betas,post.t,col=3,lwd=2)
lines(betas,post.l,col=4,lwd=2)
lines(betas,dnorm(betas),lty=2,col=2,lwd=2)
lines(betas,dt(betas,1),col=3,lty=2,lwd=2)
lines(betas,0.5*exp(-abs(betas)),col=4,lty=2,lwd=2)
lines(betas,dnorm(betas,beta.mle,se.beta),lwd=2)
legend("topleft",legend=c("N(0,1) prior","t(1) prior","DE(1) prior","Likelihood"),
col=c(2:4,1),lwd=2,lty=c(2,2,2,1),bty="n")
abline(v=0.75,lty=2)
Quality of MC approximation
M = 100000
b.draws = runif(M,-5,5)
like = rep(0,M)
for (i in 1:M)
like[i] = prod(dnorm(y,x*b.draws[i],1))
M1 = c(seq(100,1000,by=100),seq(2000,10000,by=1000),seq(20000,M,by=10000))
P.n = NULL
for (m in M1){
k.n = mean(like[1:m]*dnorm(b.draws[1:m])/(1/10))
P.n = c(P.n,mean((b.draws[1:m]<0.75)*like[1:m]*dnorm(b.draws[1:m])/(1/10))/k.n)
}
plot(M1/100,P.n,xlab="Monte Carlo size (x100)",ylab="Integral",type="b")
abline(h=P.n.exact,col=2)
Monte Carlo simulation via SIR
Draws from a candidate distribution \(q(\beta)\) can be reweighted and resampled in order to approximate draws from a target distribution \(p(\beta)\). This is the SIR scheme, one of the most popular MC sampling method for situations where dim(\(\beta\)) is small, say less than 10. SIR comprises three simple steps:
- Step 1: Draw \(\{{\tilde \beta}^{(i)}\}_{i=1}^M\) from the proposal/candidate/importance distribution \(q(\beta)\).
- Step 2: For \(i=1,\ldots,M\), compute (unnormalized) weights \[
\omega^{(i)} = \frac{p({\tilde \beta}^{(i)})}{q({\tilde \beta}^{(i)})}.
\]
- Step 3: \(\{\beta^{(i)}\}_{i=1}^M\) from \(\{{\tilde \beta}^{(i)}\}_{i=1}^M\) with weights \(\{\omega^{(i)}\}_{i=1}^M\).
Notice that, one only need to be able to evaluate both \(p(\cdot)\) and \(q(\cdot)\) up to normalizing constants since when the weights are normalized these constants cancel out. Additionally, one needs to easily sample from \(q(\cdot)\).
SIR for linear regression
Usually, \(p(\beta)\) is proportional to the product of the prior \(\pi(\beta)\) and the likelihood \(L(\beta;\mbox{data})\), i.e. \[
p(\beta) = \kappa \pi(\beta)L(\beta;y,x),
\] where \(k\) is the normalizing constant. If, in addition, one decides to use the prior as proposal (not a smart idea in most cases!), i.e. \(q(\beta) = \pi(\beta)\), it is easy to see that the SIR weights are \[
\omega^{(i)} = L({\tilde \beta}^{(i)};y,x).
\] Let us now use SIR to sample from the posterior of \(\beta\) in our regression example when using the double exponential prior
Step 1 - Drawing from proposal
Here we will use the \(U(-5,5)\) as \(q(\beta)\).
M = 20000
b.draws = runif(M,-5,5)
Step 2 - Computing weights
w = rep(0,M)
for (i in 1:M)
w[i] = prod(dnorm(y,x*b.draws[i],1))*0.5*exp(-abs(b.draws[i]))/(1/10)
Step 3 - Resampling
beta.post = sample(b.draws,size=M,replace=TRUE,prob=w)
hist(beta.post,prob=TRUE,xlab=expression(beta),ylab="Density",main="")
lines(betas,post.l,col=2,lwd=2)
Now we can compare the MC integration with the MC simulation approximations to the three quantities of interest from the posterior \(p(\beta|y,x)\)
c(E.l,mean(beta.post))
## [1] 1.499867 1.501845
c(k.l,mean(w))
## [1] 4.087623e-07 4.133555e-07
c(P.l,mean(beta.post<0.75))
## [1] 0.03181092 0.03260000
LS0tCnRpdGxlOiAiTW9udGUgQ2FybG8gaW50ZWdyYXRpb24iCnN1YnRpdGxlOiAiU2ltcGxlIGxpbmVhciByZWdyZXNzaW9uIgphdXRob3I6ICJIZWRpYmVydCBGcmVpdGFzIExvcGVzIgpkYXRlOiAiNS8xMS8yMDIyIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICB0b2NfZGVwdGg6IDIKICAgIHRvY19mbG9hdDogCiAgICAgIGNvbGxhcHNlZDogZmFsc2UKICAgICAgc21vb3RoX3Njcm9sbDogZmFsc2UKICAgIGNvZGVfZG93bmxvYWQ6IHllcwotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmBgYAoKCgojIE5vcm1hbCwgQ2F1Y2h5IGFuZCBMYXBsYWNlIHByaW9ycwoKQSBwYXJhbWV0ZXIgJFxiZXRhJCBpcyBzdGFuZGFyZCBub3JtYWwsIENhdWNoeSAoc3RhbmRhcmQgU3R1ZGVudCdzICR0JCB3aXRoIG9uZSBkZWdyZWUgb2YgZnJlZWRvbSkgb3Igc3RhbmRhcmQgZG91YmxlLWV4cG9uZW50aWFsIChha2EgTGFwbGFjZSkgaWYKXGJlZ2lue2VxbmFycmF5Kn0KcChcYmV0YSkgJj0mIFxmcmFjezF9e1xzcXJ0ezJccGl9fVxleHBcey0wLjVcYmV0YV4yXH0sIFwgXCBcbWJveHtvcn0gXFwKcChcYmV0YSkgJj0mIFxmcmFjezF9e1xwaSgxK1xiZXRhXjIpfSwgXCBcIFxtYm94e29yfSBcXApwKFxiZXRhKSAmPSYgXGZyYWMxMiBcZXhwXHstfFxiZXRhfFx9LApcZW5ke2VxbmFycmF5Kn0KcmVzcGVjdGl2ZWx5LCBmb3IgJFxiZXRhIFxpbiBcUmUkLgoKYGBge3IgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Nn0KYmV0YXMgPSBzZXEoLTUsNSxsZW5ndGg9MTAwMCkKcGxvdChiZXRhcyxkbm9ybShiZXRhcyksdHlwZT0ibCIseWxpbT1jKDAsMC41KSx4bGFiPWV4cHJlc3Npb24oYmV0YSkseWxhYj0iRGVuc2l0eSIsbHdkPTIpCmxpbmVzKGJldGFzLGR0KGJldGFzLDEpLGNvbD0yLGx3ZD0yKQpsaW5lcyhiZXRhcywwLjUqZXhwKC1hYnMoYmV0YXMpKSxjb2w9Myxsd2Q9MikKbGVnZW5kKCJ0b3BsZWZ0IixsZWdlbmQ9YygiTigwLDEpIiwidCgxKSIsIkRFKDEpIiksY29sPTE6Myxsd2Q9MixsdHk9MSxidHk9Im4iKQpgYGAKCiMgQSBzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24gZXhhbXBsZQoKYGBge3IgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Nn0Kc2V0LnNlZWQoMTIzNDUpCm4gICAgPSAxMApiZXRhID0gMgp4ICAgID0gcm5vcm0obikKeSAgICA9IGJldGEqeCArIHJub3JtKG4pCgpwbG90KHgseSkKYWJsaW5lKGxtKHl+eC0xKSxjb2w9MikKYWJsaW5lKGg9MCxsdHk9MikKYWJsaW5lKHY9MCxsdHk9MikKYGBgCgojIyBNYXhpbXVtIGxpa2VsaWhvb2QgZXN0aW1hdGUKVGhlIG1heGltdW0gbGlrZWxpaG9vZCBlc3RpbWF0aW9uIG9mIHRoZSBzaW1wbGUgR2F1c3NpYW4gbGluZWFyIHJlZ3Jlc3Npb24gdGhyb3VnaCB0aGUgb3JpZ2luCiQkCnlfaXx4X2ksXGJldGEgXHNpbSBOKFxiZXRhIHhfaSwxKSwKJCQKZm9yICRpPTEsXGxkb3RzLG4kLCBpcyBzdHJhaWdodGZvcndhcmQKJCQKe1x3aWRlaGF0IFxiZXRhfV97bWxlfSA9IFxmcmFje1xzdW1fe2k9MX1ebiB5X2l4X2l9e1xzdW1fe2k9MX1ebiB4X2leMn0sCiQkCnN1Y2ggdGhhdCAke1x3aWRlaGF0IFxiZXRhfV97bWxlfXxcYmV0YSBcc2ltIE4oXGJldGEsdl4yKSQsIHdoZXJlICR2XjI9XGZyYWN7MX17XHN1bV97aT0xfV5uIHhfaV4yfSQuCgoKCmBgYHtyfQpiZXRhLm1sZSA9IHN1bSh4KnkpL3N1bSh4XjIpCnNlLmJldGEgID0gMS9zcXJ0KHN1bSh4XjIpKQpjKGJldGEubWxlLHNlLmJldGEpCmBgYAoKIyBCYXllc2lhbiBpbmZlcmVuY2UgdmlhIE1DSQpPbmUgb2YgdGhlIG1haW4gKGNvbXB1dGF0aW9uKSBwcm9ibGVtcyBmYWNlZCBieSBhcHBsaWVkIEJheWVzaWFuIG1vZGVsZXJzL3NjaWVudGlzdHMgaXMgdGhlIGNvbXB1dGF0aW9uIG9mIGludGVncmFscywgc3VjaCBhcyB0aGUgbm9ybWFsaXppbmcgY29uc3RhbnQKJCQKcCh5fHgpID0gXGludF97LVxpbmZ0eX1eXGluZnR5IFxsZWZ0W1xwcm9kX3tpPTF9Xm4gcF9OKHlfaXx4X2lcYmV0YSwxKVxyaWdodF1wKFxiZXRhKWRcYmV0YSwKJCQKb3IgdGhlIHBvc3RlcmlvciBtZWFuLAokJApFKFxiZXRhfHkseCkgPSBcZnJhY3tcaW50X3stXGluZnR5fV5caW5mdHkgXGJldGEgXGxlZnRbXHByb2Rfe2k9MX1ebiBwX04oeV9pfHhfaVxiZXRhLDEpXHJpZ2h0XXAoXGJldGEpZFxiZXRhfXtwKHl8eCl9LAokJApvciBldmVuICRQcihcYmV0YTwwLjc1fHkseCkkLAokJApQcihcYmV0YTwwLjc1fHkseCkgPSBcZnJhY3tcaW50X3stXGluZnR5fV5caW5mdHkgMShcYmV0YTwwLjc1KSBcbGVmdFtccHJvZF97aT0xfV5uIHBfTih5X2l8eF9pXGJldGEsMSlccmlnaHRdcChcYmV0YSlkXGJldGF9e3AoeXx4KX0uCiQkCkJhc2ljYWxseSwgTW9udGUgQ2FybG8gaW50ZWdyYXRpb24gYXBwcm94aW1hdGVzIHRoZSBpbnRlZ3JhbAokJApJID0gXGludCBoKFxiZXRhKWcoXGJldGEpZFxiZXRhID0gXGludCBcbGVmdFtcZnJhY3toKFxiZXRhKWcoXGJldGEpfXtxKFxiZXRhKX1ccmlnaHRdcShcYmV0YSlkXGJldGEsCiQkCmJhc2VkIG9uIGRyYXdzICRce1xiZXRhXnsoaSl9XH1fe2k9MX1eTSQgZnJvbSAkZyhcYmV0YSkkIG9yIGJhc2VkIG9uIGRyYXdzICRce3tcdGlsZGUgXGJldGF9XnsoaSl9XH1fe2k9MX1eTSQgZnJvbSAkcShcYmV0YSkkIChwcm9wb3NhbC9jYW5kaWRhdGUvaW1wb3J0YW5jZSBkaXN0cmlidXRpb24pLCBhcwpcYmVnaW57ZXFuYXJyYXkqfQp7XGhhdCBJfV8xICY9JiBcZnJhY3sxfXtNfSBcc3VtX3tpPTF9Xk0gaChcYmV0YV57KGkpfSlcXAp7XGhhdCBJfV8yICY9JiBcZnJhY3sxfXtNfSBcc3VtX3tpPTF9Xk0gXGZyYWN7aCh7XHRpbGRlIFxiZXRhfV57KGkpfSlnKHtcdGlsZGUgXGJldGF9XnsoaSl9KX17cSh7XHRpbGRlIFxiZXRhfV57KGkpfSl9LgpcZW5ke2VxbmFycmF5Kn0KQXMgJE0gXGxvbmdyaWdodGFycm93IFxpbmZ0eSQsIGJvdGggJHtcaGF0IEl9XzEkIGFuZCAke1xoYXQgSX1fMiQgY29udmVyZ2UgdG8gJEkkLgoKQmVsb3cgd2UgdXNlIGEgdW5pZm9ybSBkaXN0cmlidXRpb24gaW4gdGhlIGludGVydmFsICQoLTUsNSkgYXMgb3VyIHByb3Bvc2FsICRxKFxiZXRhKSQuCgoKYGBge3IgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Nn0KTSAgICAgICA9IDEwMDAwCmIuZHJhd3MgPSBydW5pZihNLC01LDUpCmhpc3QoYi5kcmF3cyxwcm9iPVRSVUUsbWFpbj0iRHJhd3MgZnJvbSB0aGUgcHJvcG9zYWwgVSgtNSw1KSIseGxhYj1leHByZXNzaW9uKGJldGEpKQpgYGAKCiMjIENvbXB1dGluZyBwcmlvciBwcmVkaWN0aXZlcwoKSGVyZSB3ZSBjb21wdXRlICRwKHl8eCkkLCB0aGUgcHJpb3IgcHJlZGljdGl2ZSBkZW5zaXR5LCBiYXNlZCBvbiBlYWNoIG9uZSBvZiB0aGUgdGhyZWUgcHJpb3Igc3BlY2lmaWNhdGlvbnMgb2YgJFxiZXRhJCAoR2F1c3NpYW4sIFN0dWRlbnQncyAkdCQgYW5kIGRvdWJsZS1leHBvbmVudGlhbCkuCgpgYGB7cn0KbGlrZSA9IHJlcCgwLE0pCmZvciAoaSBpbiAxOk0pCiAgbGlrZVtpXSA9IHByb2QoZG5vcm0oeSx4KmIuZHJhd3NbaV0sMSkpCmsubiA9IG1lYW4obGlrZSpkbm9ybShiLmRyYXdzKS8oMS8xMCkpCmsudCA9IG1lYW4obGlrZSpkdChiLmRyYXdzLGRmPTEpLygxLzEwKSkKay5sID0gbWVhbihsaWtlKjAuNSpleHAoLWFicyhiLmRyYXdzKSkvKDEvMTApKQpjKGsubixrLnQsay5sKQpgYGAKClRoZSBvbmx5IG9uZSB3ZSBjYW4gb2J0YWluIGluIGNsb3NlZC1mb3JtIGlzIHVuZGVyIHRoZSBub3JtYWwgcHJpb3IsICRcYmV0YSBcc2ltIE4oMCwxKSQ6CiQkCnAoeXx4LFxtYm94e25vcm1hbCBwcmlvcn0pID0gcF9OKHl8MCx4eCcrSV9uKQokJAoKYGBge3J9CiNpbnN0YWxsLnBhY2thZ2VzKCJtdnRub3JtIikKbGlicmFyeSgibXZ0bm9ybSIpClh0WCA9IHglKiV0KHgpK2RpYWcoMSxuKQprLm4uZXhhY3QgPSBkbXZub3JtKHkscmVwKDAsbiksWHRYLGxvZz1GQUxTRSkKYyhrLm4uZXhhY3Qsay5uKQpgYGAKCiMjIENvbXB1dGluZyBwb3N0ZXJpb3IgbWVhbnMKCmBgYHtyfQpFLm4gPSBtZWFuKGIuZHJhd3MqbGlrZSpkbm9ybShiLmRyYXdzKS8oMS8xMCkpL2subgpFLnQgPSBtZWFuKGIuZHJhd3MqbGlrZSpkdChiLmRyYXdzLGRmPTEpLygxLzEwKSkvay50CkUubCA9IG1lYW4oYi5kcmF3cypsaWtlKjAuNSpleHAoLWFicyhiLmRyYXdzKSkvKDEvMTApKS9rLmwKYyhFLm4sRS50LEUubCkKYGBgCgpUaGUgb25seSBvbmUgd2UgY2FuIG9idGFpbiBpbiBjbG9zZWQtZm9ybSBpcyB1bmRlciB0aGUgbm9ybWFsIHByaW9yLCBpLmUuCiQkCkUoXGJldGF8eSx4LFxtYm94e25vcm1hbCBwcmlvcn0pID0gXGZyYWN7XHN1bV97aT0xfV5uIHlfaXhfaX17XHN1bV97aT0xfV5uIHhfaV4yfS4KJCQKYGBge3J9CkUubi5leGFjdCA9IHN1bSh5KngpLyhzdW0oeF4yKSsxKQpjKEUubi5leGFjdCxFLm4pCmBgYAoKIyMgQ29tcHV0aW5nIHBvc3RlcmlvciB0YWlscwoKYGBge3J9ClAubiA9IG1lYW4oKGIuZHJhd3M8MC43NSkqbGlrZSpkbm9ybShiLmRyYXdzKS8oMS8xMCkpL2subgpQLnQgPSBtZWFuKChiLmRyYXdzPDAuNzUpKmxpa2UqZHQoYi5kcmF3cyxkZj0xKS8oMS8xMCkpL2sudApQLmwgPSBtZWFuKChiLmRyYXdzPDAuNzUpKmxpa2UqMC41KmV4cCgtYWJzKGIuZHJhd3MpKS8oMS8xMCkpL2subApjKFAubixQLnQsUC5sKQpgYGAKClRoZSBvbmx5IG9uZSB3ZSBjYW4gb2J0YWluIGluIGNsb3NlZC1mb3JtIGlzIHVuZGVyIHRoZSBub3JtYWwgcHJpb3IKCmBgYHtyfQpQLm4uZXhhY3QgPSBwbm9ybSgwLjc1LEUubi5leGFjdCxzcXJ0KDEvKHN1bSh4XjIpKzEpKSkKYyhQLm4uZXhhY3QsUC5uKQpgYGAKCiMjIFByaW9ycywgbGlrZWxpaG9vZCBhbmQgcG9zdGVyaW9ycwoKYGBge3IgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Nn0KbGlrZWxpaG9vZCA9IHJlcCgwLDEwMDApCmZvciAoaSBpbiAxOjEwMDApCiAgbGlrZWxpaG9vZFtpXSA9IHByb2QoZG5vcm0oeSx4KmJldGFzW2ldLDEpKQpwb3N0Lm4gPSBkbm9ybShiZXRhcykqbGlrZWxpaG9vZC9rLm4KcG9zdC50ID0gZHQoYmV0YXMsZGY9MSkqbGlrZWxpaG9vZC9rLnQKcG9zdC5sID0gMC41KmV4cCgtYWJzKGJldGFzKSkqbGlrZWxpaG9vZC9rLmwKCnBsb3QoYmV0YXMscG9zdC5uLHR5cGU9ImwiLGNvbD0yLGx3ZD0yLHhsYWI9ZXhwcmVzc2lvbihiZXRhKSx5bGFiPSJEZW5zaXR5IikKbGluZXMoYmV0YXMscG9zdC50LGNvbD0zLGx3ZD0yKQpsaW5lcyhiZXRhcyxwb3N0LmwsY29sPTQsbHdkPTIpCmxpbmVzKGJldGFzLGRub3JtKGJldGFzKSxsdHk9Mixjb2w9Mixsd2Q9MikKbGluZXMoYmV0YXMsZHQoYmV0YXMsMSksY29sPTMsbHR5PTIsbHdkPTIpCmxpbmVzKGJldGFzLDAuNSpleHAoLWFicyhiZXRhcykpLGNvbD00LGx0eT0yLGx3ZD0yKQpsaW5lcyhiZXRhcyxkbm9ybShiZXRhcyxiZXRhLm1sZSxzZS5iZXRhKSxsd2Q9MikKbGVnZW5kKCJ0b3BsZWZ0IixsZWdlbmQ9YygiTigwLDEpIHByaW9yIiwidCgxKSBwcmlvciIsIkRFKDEpIHByaW9yIiwiTGlrZWxpaG9vZCIpLAogICAgICAgY29sPWMoMjo0LDEpLGx3ZD0yLGx0eT1jKDIsMiwyLDEpLGJ0eT0ibiIpCmFibGluZSh2PTAuNzUsbHR5PTIpICAgICAgIApgYGAgICAgICAgCgoKIyMgUXVhbGl0eSBvZiBNQyBhcHByb3hpbWF0aW9uCgpgYGB7ciBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD02fQpNICAgICAgID0gMTAwMDAwCmIuZHJhd3MgPSBydW5pZihNLC01LDUpCmxpa2UgPSByZXAoMCxNKQpmb3IgKGkgaW4gMTpNKQogIGxpa2VbaV0gPSBwcm9kKGRub3JtKHkseCpiLmRyYXdzW2ldLDEpKQpNMSA9IGMoc2VxKDEwMCwxMDAwLGJ5PTEwMCksc2VxKDIwMDAsMTAwMDAsYnk9MTAwMCksc2VxKDIwMDAwLE0sYnk9MTAwMDApKQpQLm4gPSBOVUxMCmZvciAobSBpbiBNMSl7CiAgay5uID0gbWVhbihsaWtlWzE6bV0qZG5vcm0oYi5kcmF3c1sxOm1dKS8oMS8xMCkpCiAgUC5uID0gYyhQLm4sbWVhbigoYi5kcmF3c1sxOm1dPDAuNzUpKmxpa2VbMTptXSpkbm9ybShiLmRyYXdzWzE6bV0pLygxLzEwKSkvay5uKQp9CnBsb3QoTTEvMTAwLFAubix4bGFiPSJNb250ZSBDYXJsbyBzaXplICh4MTAwKSIseWxhYj0iSW50ZWdyYWwiLHR5cGU9ImIiKQphYmxpbmUoaD1QLm4uZXhhY3QsY29sPTIpCmBgYAoKCiMgTW9udGUgQ2FybG8gc2ltdWxhdGlvbiB2aWEgU0lSCkRyYXdzIGZyb20gYSBjYW5kaWRhdGUgZGlzdHJpYnV0aW9uICRxKFxiZXRhKSQgY2FuIGJlIHJld2VpZ2h0ZWQgYW5kIHJlc2FtcGxlZCBpbiBvcmRlciB0byBhcHByb3hpbWF0ZSBkcmF3cyBmcm9tIGEgdGFyZ2V0IGRpc3RyaWJ1dGlvbiAkcChcYmV0YSkkLiAgVGhpcyBpcyB0aGUgU0lSIHNjaGVtZSwgb25lIG9mIHRoZSBtb3N0IHBvcHVsYXIgTUMgc2FtcGxpbmcgbWV0aG9kIGZvciBzaXR1YXRpb25zIHdoZXJlIGRpbSgkXGJldGEkKSBpcyBzbWFsbCwgc2F5IGxlc3MgdGhhbiAxMC4gIFNJUiBjb21wcmlzZXMgdGhyZWUgc2ltcGxlIHN0ZXBzOgoKKiBTdGVwIDE6IERyYXcgJFx7e1x0aWxkZSBcYmV0YX1eeyhpKX1cfV97aT0xfV5NJCBmcm9tIHRoZSBwcm9wb3NhbC9jYW5kaWRhdGUvaW1wb3J0YW5jZSBkaXN0cmlidXRpb24gJHEoXGJldGEpJC4KKiBTdGVwIDI6IEZvciAkaT0xLFxsZG90cyxNJCwgY29tcHV0ZSAodW5ub3JtYWxpemVkKSB3ZWlnaHRzIAokJApcb21lZ2FeeyhpKX0gPSBcZnJhY3twKHtcdGlsZGUgXGJldGF9XnsoaSl9KX17cSh7XHRpbGRlIFxiZXRhfV57KGkpfSl9LgokJAoqIFN0ZXAgMzogJFx7XGJldGFeeyhpKX1cfV97aT0xfV5NJCBmcm9tICRce3tcdGlsZGUgXGJldGF9XnsoaSl9XH1fe2k9MX1eTSQgd2l0aCB3ZWlnaHRzCiRce1xvbWVnYV57KGkpfVx9X3tpPTF9Xk0kLgoKTm90aWNlIHRoYXQsIG9uZSBvbmx5IG5lZWQgdG8gYmUgYWJsZSB0byBldmFsdWF0ZSBib3RoICRwKFxjZG90KSQgYW5kICRxKFxjZG90KSQgdXAgdG8gbm9ybWFsaXppbmcgY29uc3RhbnRzIHNpbmNlIHdoZW4gdGhlIHdlaWdodHMgYXJlIG5vcm1hbGl6ZWQgdGhlc2UgY29uc3RhbnRzIGNhbmNlbCBvdXQuICBBZGRpdGlvbmFsbHksIG9uZSBuZWVkcyB0byBlYXNpbHkgc2FtcGxlIGZyb20gJHEoXGNkb3QpJC4KCgojIyBTSVIgZm9yIGxpbmVhciByZWdyZXNzaW9uClVzdWFsbHksICRwKFxiZXRhKSQgaXMgcHJvcG9ydGlvbmFsIHRvIHRoZSBwcm9kdWN0IG9mIHRoZSBwcmlvciAkXHBpKFxiZXRhKSQgYW5kIHRoZSBsaWtlbGlob29kICRMKFxiZXRhO1xtYm94e2RhdGF9KSQsIGkuZS4KJCQKcChcYmV0YSkgPSBca2FwcGEgXHBpKFxiZXRhKUwoXGJldGE7eSx4KSwKJCQKd2hlcmUgJGskIGlzIHRoZSBub3JtYWxpemluZyBjb25zdGFudC4gIElmLCBpbiBhZGRpdGlvbiwgb25lIGRlY2lkZXMgdG8gdXNlIHRoZSBwcmlvciBhcyBwcm9wb3NhbCAobm90IGEgc21hcnQgaWRlYSBpbiBtb3N0IGNhc2VzISksIGkuZS4gJHEoXGJldGEpID0gXHBpKFxiZXRhKSQsIGl0IGlzIGVhc3kgdG8gc2VlIHRoYXQgdGhlIFNJUiB3ZWlnaHRzIGFyZQokJApcb21lZ2FeeyhpKX0gPSBMKHtcdGlsZGUgXGJldGF9XnsoaSl9O3kseCkuCiQkCkxldCB1cyBub3cgdXNlIFNJUiB0byBzYW1wbGUgZnJvbSB0aGUgcG9zdGVyaW9yIG9mICRcYmV0YSQgaW4gb3VyIHJlZ3Jlc3Npb24gZXhhbXBsZSB3aGVuIHVzaW5nIHRoZSBkb3VibGUgZXhwb25lbnRpYWwgcHJpb3IKCiMjIyBTdGVwIDEgLSBEcmF3aW5nIGZyb20gcHJvcG9zYWwKSGVyZSB3ZSB3aWxsIHVzZSB0aGUgJFUoLTUsNSkkIGFzICRxKFxiZXRhKSQuCmBgYHtyfQpNICAgICAgID0gMjAwMDAKYi5kcmF3cyA9IHJ1bmlmKE0sLTUsNSkKYGBgCgojIyMgU3RlcCAyIC0gQ29tcHV0aW5nIHdlaWdodHMKYGBge3J9CncgPSByZXAoMCxNKQpmb3IgKGkgaW4gMTpNKQogIHdbaV0gPSBwcm9kKGRub3JtKHkseCpiLmRyYXdzW2ldLDEpKSowLjUqZXhwKC1hYnMoYi5kcmF3c1tpXSkpLygxLzEwKQpgYGAKCiMjIyBTdGVwIDMgLSBSZXNhbXBsaW5nCmBgYHtyIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTZ9CmJldGEucG9zdCA9IHNhbXBsZShiLmRyYXdzLHNpemU9TSxyZXBsYWNlPVRSVUUscHJvYj13KQpoaXN0KGJldGEucG9zdCxwcm9iPVRSVUUseGxhYj1leHByZXNzaW9uKGJldGEpLHlsYWI9IkRlbnNpdHkiLG1haW49IiIpCmxpbmVzKGJldGFzLHBvc3QubCxjb2w9Mixsd2Q9MikKYGBgCgpOb3cgd2UgY2FuIGNvbXBhcmUgdGhlIE1DIGludGVncmF0aW9uIHdpdGggdGhlIE1DIHNpbXVsYXRpb24gYXBwcm94aW1hdGlvbnMgdG8gdGhlIHRocmVlIHF1YW50aXRpZXMgb2YgaW50ZXJlc3QgZnJvbSB0aGUgcG9zdGVyaW9yICRwKFxiZXRhfHkseCkkCmBgYHtyfQpjKEUubCxtZWFuKGJldGEucG9zdCkpCmMoay5sLG1lYW4odykpCmMoUC5sLG1lYW4oYmV0YS5wb3N0PDAuNzUpKQoKYGBgCgo=