1 Introduction

Here we use a banana-shape posterior distribution to illustrate the how Bayesian computation via Monte Carlo strategies allows for more flexible Bayesian inference in non-conjugate, non-Gaussian and non-linear cases. The Source of the banana-shape joint posterior is the article Recursive Pathways to Marginal Likelihood Estimation with Prior-Sensitivity Analysis, by Ewan Cameron and Anthony Pettitt, published in the journal Statistical Science in 2014 (Volume 29, Number3, Pages 397-419).

2 Univariate example

Let us assume that \[ p(\theta|\mbox{data}) \propto p(\theta)L(\theta|\mbox{data})=\left(\frac{1}{1.5}\right) \exp\left\{-25(0.45-\theta)^2-400(0.065-\theta^4)^2\right\}, \] where \(\theta \in (-0.5,1.0)\). In other words, the prior for \(\theta\) is \(U(-0.5,1)\) and the likelihood function is nonlinear on \(\theta\). Below, we use a grid with 10,000 points between \(-0.5\) and \(1.0\) in order to approximate the normalizing constant (also known as predictive density) and posterior moments of \(\theta\).

prior.likelihood = function(theta){
  prior=1/1.5
  likelihood=exp(-25*(0.45-theta)^2-(20*(0.065-theta^4))^2)
  return(prior*likelihood)
}

N     = 10000
theta = seq(-0.5,1,length=N)
post  = prior.likelihood(theta)
h     = theta[2]-theta[1]
py    = sum(post*h)
post  = post/py

2.1 Predictive density and posterior moments on a grid

E = sum(theta*post*h)
E2 = sum(theta^2*post*h) 
V = E2 - E^2
S = sqrt(V)
c(E,S,py)
## [1] 0.45189309 0.08907801 0.11782328
plot(theta,post,type="l",xlab=expression(theta),main="Posterior density",ylab="Density")
abline(v=E,col=2)
abline(v=E-2*S,col=2,lty=2)
abline(v=E+2*S,col=2,lty=2)

2.2 MC-based posterior approximation via SIR

# Step 1:  Sampling from proposal
M      = 1000
thetas = runif(M,-0.5,1)

# Step 2: Computing resampling weights
w      = prior.likelihood(thetas)
w      = w/sum(w)
plot(thetas,w,pch=16,cex=0.5,xlab=expression(theta),ylab="Weights")

# Step 3: Resampling
thetas.post = sample(thetas,size=M,replace=TRUE,prob=w)


E.sir = mean(thetas.post)
S.sir = sqrt(var(thetas.post))

c(E,E.sir)
## [1] 0.4518931 0.4610462
c(S,S.sir)
## [1] 0.08907801 0.08076191
hist(thetas.post,prob=TRUE,breaks=seq(-0.5,1,length=40),xlab=expression(theta),main="")
lines(theta,post,col=2,lwd=2)
title("Posterior: grid vs SIR")

2.3 How good (or bad) is the MC approximation?

Ms = c(seq(10,100,by=10),seq(200,1000,by=1000),
       seq(2000,10000,by=1000),seq(20000,100000,by=10000),seq(200000,1000000,by=100000))
nM = length(Ms)
E.sir = rep(0,nM)
for (i in 1:nM){
  thetas = runif(Ms[i],-0.5,1)
  w      = prior.likelihood(thetas)
  thetas.post = sample(thetas,size=M,replace=TRUE,prob=w)
  E.sir[i] = mean(thetas.post)
}


plot(log10(Ms),E.sir,ylab="Posterior mean",xlab="Monte Carlo size (log10)",type="b",pch=16)
abline(h=E,col=2,lwd=2)
title("Monte Carlo approximation of posterior mean")

3 Bivariate example

\[ p(\theta|\mbox{data}) \propto p(\theta)L(\theta|\mbox{data})=\left(\frac{1}{1.5}\right)^2 \exp\left\{-25(0.45-\theta)^2-400(\theta_2-\theta^4)^2\right\}, \] where \(\theta=(\theta_1,\theta_2)\), the prior of \(\theta_1\) is \(U(-0.5,1)\) and the prior of \(\theta_2\) is \(U(-0.5,1)\), with \(\theta_1\) and \(\theta_2\) independent a priori

prior.likelihood = function(theta1,theta2){
  prior=(1/1.5)^2
  likelihood=exp(-(10*(0.45-theta1))^2/4-(20*(theta2/2-theta1^4))^2)
  return(prior*likelihood)
}

N      = 200
theta1 = seq(-0.5,1,length=N)
theta2 = seq(-0.5,1,length=N)

post = matrix(0,N,N)
for (i in 1:N)
  for (j in 1:N)
    post[i,j] = prior.likelihood(theta1[i],theta2[j])

h = theta1[2]-theta1[1]
py = sum(apply(post*h^2,1,sum))
post = post/py

E1 = sum(t(post)%*%theta1*h^2)
E2 = sum(post%*%theta2*h^2)

c(E1,E2,py)
## [1] 0.44872266 0.12973071 0.02784243
par(mfrow=c(1,1))
contour(theta1,theta2,post,nlevels=15,xlab=expression(theta[1]),ylab=expression(theta[2]),
drawlabels=FALSE,main="Posterior")

3.1 Sampling importance resampling

# Step 1:  Sampling from proposal
M = 100000
theta1.prior = runif(M,-0.5,1)
theta2.prior = runif(M,-0.5,1)

# Step 2: Computing resampling weights
w = rep(0,M)
for (i in 1:M)
  w[i] = prior.likelihood(theta1.prior[i],theta2.prior[i])
  
# Step 3: Resampling
ind = sample(1:M,size=M,replace=TRUE,prob=w)
theta1.post = theta1.prior[ind]
theta2.post = theta2.prior[ind]

# Computing normalizing constant (prior predictive)
py.mc = mean(w)


par(mfrow=c(2,2))
plot(theta1.prior,theta2.prior,xlab=expression(theta[1]),ylab=expression(theta[2]),
     main="Prior draws vs posterior evaluations",pch=".")
contour(theta1,theta2,post,nlevels=15,drawlabels=FALSE,add=TRUE,col=3,lwd=2)
plot(theta1.post,theta2.post,xlim=range(theta1.prior),ylim=range(theta2.prior),
     xlab=expression(theta[1]),ylab=expression(theta[2]),pch=".",
     main="Posterior draws vs posterior evaluations")
contour(theta1,theta2,post,nlevels=15,drawlabels=FALSE,add=TRUE,col=3,lwd=2)
hist(theta1.post,prob=TRUE,xlab=expression(theta[1]),main="",xlim=c(-0.5,1),col=3)
title("Marginal posterior")
abline(h=1/1.5,col=2,lwd=3)
hist(theta2.post,prob=TRUE,xlab=expression(theta[2]),main="",xlim=c(-0.5,1),col=3)
title("Marginal posterior")
abline(h=1/1.5,col=2,lwd=3)

# Marginal priors and posteriors
tab = rbind(
summary(theta1.prior),
summary(theta2.prior),
summary(theta1.post),
summary(theta2.post))
rownames(tab) = c("Prior theta1","Prior theta2","Posterior theta1","Posterior theta2")
round(tab,3)
##                    Min. 1st Qu. Median  Mean 3rd Qu.  Max.
## Prior theta1     -0.500  -0.124  0.251 0.251   0.625 1.000
## Prior theta2     -0.500  -0.124  0.248 0.250   0.627 1.000
## Posterior theta1 -0.260   0.355  0.449 0.449   0.542 0.858
## Posterior theta2 -0.281   0.024  0.097 0.129   0.194 1.000
E1.mc = mean(theta1.post)
E2.mc = mean(theta2.post)


c(E1,E1.mc)
## [1] 0.4487227 0.4488311
c(E2,E2.mc)
## [1] 0.1297307 0.1289639
c(py,py.mc)
## [1] 0.02784243 0.01254233
LS0tCnRpdGxlOiAiQmFuYW5hLXNoYXBlIHBvc3RlcmlvciIKc3VidGl0bGU6ICJNQy1iYXNlZCBwb3N0ZXJpb3IgaW5mZXJlbmNlIgphdXRob3I6ICJIZWRpYmVydCBGcmVpdGFzIExvcGVzIgpkYXRlOiAiNS83LzIwMjQiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDMKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdG9jX2NvbGxhcHNlZDogdHJ1ZQogICAgY29kZV9kb3dubG9hZDogeWVzCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRoZW1lOiBsdW1lbgotLS0KCgoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKYGBgCgojIEludHJvZHVjdGlvbgpIZXJlIHdlIHVzZSBhIGJhbmFuYS1zaGFwZSBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uIHRvIGlsbHVzdHJhdGUgdGhlIGhvdyBCYXllc2lhbiBjb21wdXRhdGlvbiB2aWEgTW9udGUgQ2FybG8gc3RyYXRlZ2llcyBhbGxvd3MgZm9yIG1vcmUgZmxleGlibGUgQmF5ZXNpYW4gaW5mZXJlbmNlIGluIG5vbi1jb25qdWdhdGUsIG5vbi1HYXVzc2lhbiBhbmQgbm9uLWxpbmVhciBjYXNlcy4gIFRoZSBTb3VyY2Ugb2YgdGhlIGJhbmFuYS1zaGFwZSBqb2ludCBwb3N0ZXJpb3IgaXMgdGhlIGFydGljbGUgKlJlY3Vyc2l2ZSBQYXRod2F5cyB0byBNYXJnaW5hbCBMaWtlbGlob29kIEVzdGltYXRpb24gd2l0aCBQcmlvci1TZW5zaXRpdml0eSBBbmFseXNpcyosIGJ5IEV3YW4gQ2FtZXJvbiBhbmQgQW50aG9ueSBQZXR0aXR0LCBwdWJsaXNoZWQgaW4gdGhlIGpvdXJuYWwgKlN0YXRpc3RpY2FsIFNjaWVuY2UqIGluIDIwMTQgKFZvbHVtZSAyOSwgTnVtYmVyMywgUGFnZXMgMzk3LTQxOSkuCgoKIyBVbml2YXJpYXRlIGV4YW1wbGUKCkxldCB1cyBhc3N1bWUgdGhhdCAKJCQKcChcdGhldGF8XG1ib3h7ZGF0YX0pIFxwcm9wdG8gcChcdGhldGEpTChcdGhldGF8XG1ib3h7ZGF0YX0pPVxsZWZ0KFxmcmFjezF9ezEuNX1ccmlnaHQpClxleHBcbGVmdFx7LTI1KDAuNDUtXHRoZXRhKV4yLTQwMCgwLjA2NS1cdGhldGFeNCleMlxyaWdodFx9LAokJAp3aGVyZSAkXHRoZXRhIFxpbiAoLTAuNSwxLjApJC4KSW4gb3RoZXIgd29yZHMsIHRoZSBwcmlvciBmb3IgJFx0aGV0YSQgaXMgJFUoLTAuNSwxKSQgYW5kIHRoZSBsaWtlbGlob29kIGZ1bmN0aW9uIGlzIG5vbmxpbmVhciBvbiAkXHRoZXRhJC4gIEJlbG93LCB3ZSB1c2UgYSBncmlkIHdpdGggMTAsMDAwIHBvaW50cyBiZXR3ZWVuICQtMC41JCBhbmQgJDEuMCQgaW4gb3JkZXIgdG8gYXBwcm94aW1hdGUgdGhlIG5vcm1hbGl6aW5nIGNvbnN0YW50IChhbHNvIGtub3duIGFzIHByZWRpY3RpdmUgZGVuc2l0eSkgYW5kIHBvc3RlcmlvciBtb21lbnRzIG9mICRcdGhldGEkLgoKYGBge3J9CnByaW9yLmxpa2VsaWhvb2QgPSBmdW5jdGlvbih0aGV0YSl7CiAgcHJpb3I9MS8xLjUKICBsaWtlbGlob29kPWV4cCgtMjUqKDAuNDUtdGhldGEpXjItKDIwKigwLjA2NS10aGV0YV40KSleMikKICByZXR1cm4ocHJpb3IqbGlrZWxpaG9vZCkKfQoKTiAgICAgPSAxMDAwMAp0aGV0YSA9IHNlcSgtMC41LDEsbGVuZ3RoPU4pCnBvc3QgID0gcHJpb3IubGlrZWxpaG9vZCh0aGV0YSkKaCAgICAgPSB0aGV0YVsyXS10aGV0YVsxXQpweSAgICA9IHN1bShwb3N0KmgpCnBvc3QgID0gcG9zdC9weQpgYGAKCiMjIFByZWRpY3RpdmUgZGVuc2l0eSBhbmQgcG9zdGVyaW9yIG1vbWVudHMgb24gYSBncmlkCmBgYHtyIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTUsIGZpZy5hbGlnbj0nY2VudGVyJ30KRSA9IHN1bSh0aGV0YSpwb3N0KmgpCkUyID0gc3VtKHRoZXRhXjIqcG9zdCpoKSAKViA9IEUyIC0gRV4yClMgPSBzcXJ0KFYpCmMoRSxTLHB5KQoKcGxvdCh0aGV0YSxwb3N0LHR5cGU9ImwiLHhsYWI9ZXhwcmVzc2lvbih0aGV0YSksbWFpbj0iUG9zdGVyaW9yIGRlbnNpdHkiLHlsYWI9IkRlbnNpdHkiKQphYmxpbmUodj1FLGNvbD0yKQphYmxpbmUodj1FLTIqUyxjb2w9MixsdHk9MikKYWJsaW5lKHY9RSsyKlMsY29sPTIsbHR5PTIpCgpgYGAKCiMjIE1DLWJhc2VkIHBvc3RlcmlvciBhcHByb3hpbWF0aW9uIHZpYSBTSVIKYGBge3IgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9NSwgZmlnLmFsaWduPSdjZW50ZXInfQojIFN0ZXAgMTogIFNhbXBsaW5nIGZyb20gcHJvcG9zYWwKTSAgICAgID0gMTAwMAp0aGV0YXMgPSBydW5pZihNLC0wLjUsMSkKCiMgU3RlcCAyOiBDb21wdXRpbmcgcmVzYW1wbGluZyB3ZWlnaHRzCncgICAgICA9IHByaW9yLmxpa2VsaWhvb2QodGhldGFzKQp3ICAgICAgPSB3L3N1bSh3KQpwbG90KHRoZXRhcyx3LHBjaD0xNixjZXg9MC41LHhsYWI9ZXhwcmVzc2lvbih0aGV0YSkseWxhYj0iV2VpZ2h0cyIpCgojIFN0ZXAgMzogUmVzYW1wbGluZwp0aGV0YXMucG9zdCA9IHNhbXBsZSh0aGV0YXMsc2l6ZT1NLHJlcGxhY2U9VFJVRSxwcm9iPXcpCgoKRS5zaXIgPSBtZWFuKHRoZXRhcy5wb3N0KQpTLnNpciA9IHNxcnQodmFyKHRoZXRhcy5wb3N0KSkKCmMoRSxFLnNpcikKYyhTLFMuc2lyKQoKaGlzdCh0aGV0YXMucG9zdCxwcm9iPVRSVUUsYnJlYWtzPXNlcSgtMC41LDEsbGVuZ3RoPTQwKSx4bGFiPWV4cHJlc3Npb24odGhldGEpLG1haW49IiIpCmxpbmVzKHRoZXRhLHBvc3QsY29sPTIsbHdkPTIpCnRpdGxlKCJQb3N0ZXJpb3I6IGdyaWQgdnMgU0lSIikKYGBgCgojIyBIb3cgZ29vZCAob3IgYmFkKSBpcyB0aGUgTUMgYXBwcm94aW1hdGlvbj8KYGBge3IgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9NSwgZmlnLmFsaWduPSdjZW50ZXInfQpNcyA9IGMoc2VxKDEwLDEwMCxieT0xMCksc2VxKDIwMCwxMDAwLGJ5PTEwMDApLAogICAgICAgc2VxKDIwMDAsMTAwMDAsYnk9MTAwMCksc2VxKDIwMDAwLDEwMDAwMCxieT0xMDAwMCksc2VxKDIwMDAwMCwxMDAwMDAwLGJ5PTEwMDAwMCkpCm5NID0gbGVuZ3RoKE1zKQpFLnNpciA9IHJlcCgwLG5NKQpmb3IgKGkgaW4gMTpuTSl7CiAgdGhldGFzID0gcnVuaWYoTXNbaV0sLTAuNSwxKQogIHcgICAgICA9IHByaW9yLmxpa2VsaWhvb2QodGhldGFzKQogIHRoZXRhcy5wb3N0ID0gc2FtcGxlKHRoZXRhcyxzaXplPU0scmVwbGFjZT1UUlVFLHByb2I9dykKICBFLnNpcltpXSA9IG1lYW4odGhldGFzLnBvc3QpCn0KCgpwbG90KGxvZzEwKE1zKSxFLnNpcix5bGFiPSJQb3N0ZXJpb3IgbWVhbiIseGxhYj0iTW9udGUgQ2FybG8gc2l6ZSAobG9nMTApIix0eXBlPSJiIixwY2g9MTYpCmFibGluZShoPUUsY29sPTIsbHdkPTIpCnRpdGxlKCJNb250ZSBDYXJsbyBhcHByb3hpbWF0aW9uIG9mIHBvc3RlcmlvciBtZWFuIikKYGBgCgojIEJpdmFyaWF0ZSBleGFtcGxlCiQkCnAoXHRoZXRhfFxtYm94e2RhdGF9KSBccHJvcHRvIHAoXHRoZXRhKUwoXHRoZXRhfFxtYm94e2RhdGF9KT1cbGVmdChcZnJhY3sxfXsxLjV9XHJpZ2h0KV4yClxleHBcbGVmdFx7LTI1KDAuNDUtXHRoZXRhKV4yLTQwMChcdGhldGFfMi1cdGhldGFeNCleMlxyaWdodFx9LAokJAp3aGVyZSAkXHRoZXRhPShcdGhldGFfMSxcdGhldGFfMikkLCB0aGUgcHJpb3Igb2YgJFx0aGV0YV8xJCBpcyAkVSgtMC41LDEpJCBhbmQgdGhlIHByaW9yIG9mICRcdGhldGFfMiQgaXMgJFUoLTAuNSwxKSQsIHdpdGggJFx0aGV0YV8xJCBhbmQgJFx0aGV0YV8yJCBpbmRlcGVuZGVudCAqYSBwcmlvcmkqCgpgYGB7ciBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD01LCBmaWcuYWxpZ249J2NlbnRlcid9CnByaW9yLmxpa2VsaWhvb2QgPSBmdW5jdGlvbih0aGV0YTEsdGhldGEyKXsKICBwcmlvcj0oMS8xLjUpXjIKICBsaWtlbGlob29kPWV4cCgtKDEwKigwLjQ1LXRoZXRhMSkpXjIvNC0oMjAqKHRoZXRhMi8yLXRoZXRhMV40KSleMikKICByZXR1cm4ocHJpb3IqbGlrZWxpaG9vZCkKfQoKTiAgICAgID0gMjAwCnRoZXRhMSA9IHNlcSgtMC41LDEsbGVuZ3RoPU4pCnRoZXRhMiA9IHNlcSgtMC41LDEsbGVuZ3RoPU4pCgpwb3N0ID0gbWF0cml4KDAsTixOKQpmb3IgKGkgaW4gMTpOKQogIGZvciAoaiBpbiAxOk4pCiAgICBwb3N0W2ksal0gPSBwcmlvci5saWtlbGlob29kKHRoZXRhMVtpXSx0aGV0YTJbal0pCgpoID0gdGhldGExWzJdLXRoZXRhMVsxXQpweSA9IHN1bShhcHBseShwb3N0KmheMiwxLHN1bSkpCnBvc3QgPSBwb3N0L3B5CgpFMSA9IHN1bSh0KHBvc3QpJSoldGhldGExKmheMikKRTIgPSBzdW0ocG9zdCUqJXRoZXRhMipoXjIpCgpjKEUxLEUyLHB5KQoKcGFyKG1mcm93PWMoMSwxKSkKY29udG91cih0aGV0YTEsdGhldGEyLHBvc3QsbmxldmVscz0xNSx4bGFiPWV4cHJlc3Npb24odGhldGFbMV0pLHlsYWI9ZXhwcmVzc2lvbih0aGV0YVsyXSksCmRyYXdsYWJlbHM9RkFMU0UsbWFpbj0iUG9zdGVyaW9yIikKYGBgCgojIyBTYW1wbGluZyBpbXBvcnRhbmNlIHJlc2FtcGxpbmcKYGBge3IgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9OCwgZmlnLmFsaWduPSdjZW50ZXInfQojIFN0ZXAgMTogIFNhbXBsaW5nIGZyb20gcHJvcG9zYWwKTSA9IDEwMDAwMAp0aGV0YTEucHJpb3IgPSBydW5pZihNLC0wLjUsMSkKdGhldGEyLnByaW9yID0gcnVuaWYoTSwtMC41LDEpCgojIFN0ZXAgMjogQ29tcHV0aW5nIHJlc2FtcGxpbmcgd2VpZ2h0cwp3ID0gcmVwKDAsTSkKZm9yIChpIGluIDE6TSkKICB3W2ldID0gcHJpb3IubGlrZWxpaG9vZCh0aGV0YTEucHJpb3JbaV0sdGhldGEyLnByaW9yW2ldKQogIAojIFN0ZXAgMzogUmVzYW1wbGluZwppbmQgPSBzYW1wbGUoMTpNLHNpemU9TSxyZXBsYWNlPVRSVUUscHJvYj13KQp0aGV0YTEucG9zdCA9IHRoZXRhMS5wcmlvcltpbmRdCnRoZXRhMi5wb3N0ID0gdGhldGEyLnByaW9yW2luZF0KCiMgQ29tcHV0aW5nIG5vcm1hbGl6aW5nIGNvbnN0YW50IChwcmlvciBwcmVkaWN0aXZlKQpweS5tYyA9IG1lYW4odykKCgpwYXIobWZyb3c9YygyLDIpKQpwbG90KHRoZXRhMS5wcmlvcix0aGV0YTIucHJpb3IseGxhYj1leHByZXNzaW9uKHRoZXRhWzFdKSx5bGFiPWV4cHJlc3Npb24odGhldGFbMl0pLAogICAgIG1haW49IlByaW9yIGRyYXdzIHZzIHBvc3RlcmlvciBldmFsdWF0aW9ucyIscGNoPSIuIikKY29udG91cih0aGV0YTEsdGhldGEyLHBvc3QsbmxldmVscz0xNSxkcmF3bGFiZWxzPUZBTFNFLGFkZD1UUlVFLGNvbD0zLGx3ZD0yKQpwbG90KHRoZXRhMS5wb3N0LHRoZXRhMi5wb3N0LHhsaW09cmFuZ2UodGhldGExLnByaW9yKSx5bGltPXJhbmdlKHRoZXRhMi5wcmlvciksCiAgICAgeGxhYj1leHByZXNzaW9uKHRoZXRhWzFdKSx5bGFiPWV4cHJlc3Npb24odGhldGFbMl0pLHBjaD0iLiIsCiAgICAgbWFpbj0iUG9zdGVyaW9yIGRyYXdzIHZzIHBvc3RlcmlvciBldmFsdWF0aW9ucyIpCmNvbnRvdXIodGhldGExLHRoZXRhMixwb3N0LG5sZXZlbHM9MTUsZHJhd2xhYmVscz1GQUxTRSxhZGQ9VFJVRSxjb2w9Myxsd2Q9MikKaGlzdCh0aGV0YTEucG9zdCxwcm9iPVRSVUUseGxhYj1leHByZXNzaW9uKHRoZXRhWzFdKSxtYWluPSIiLHhsaW09YygtMC41LDEpLGNvbD0zKQp0aXRsZSgiTWFyZ2luYWwgcG9zdGVyaW9yIikKYWJsaW5lKGg9MS8xLjUsY29sPTIsbHdkPTMpCmhpc3QodGhldGEyLnBvc3QscHJvYj1UUlVFLHhsYWI9ZXhwcmVzc2lvbih0aGV0YVsyXSksbWFpbj0iIix4bGltPWMoLTAuNSwxKSxjb2w9MykKdGl0bGUoIk1hcmdpbmFsIHBvc3RlcmlvciIpCmFibGluZShoPTEvMS41LGNvbD0yLGx3ZD0zKQoKCgojIE1hcmdpbmFsIHByaW9ycyBhbmQgcG9zdGVyaW9ycwp0YWIgPSByYmluZCgKc3VtbWFyeSh0aGV0YTEucHJpb3IpLApzdW1tYXJ5KHRoZXRhMi5wcmlvciksCnN1bW1hcnkodGhldGExLnBvc3QpLApzdW1tYXJ5KHRoZXRhMi5wb3N0KSkKcm93bmFtZXModGFiKSA9IGMoIlByaW9yIHRoZXRhMSIsIlByaW9yIHRoZXRhMiIsIlBvc3RlcmlvciB0aGV0YTEiLCJQb3N0ZXJpb3IgdGhldGEyIikKcm91bmQodGFiLDMpCgoKRTEubWMgPSBtZWFuKHRoZXRhMS5wb3N0KQpFMi5tYyA9IG1lYW4odGhldGEyLnBvc3QpCgoKYyhFMSxFMS5tYykKYyhFMixFMi5tYykKYyhweSxweS5tYykKCmBgYAo=