PROBLEM 1: Grid approximation
Here we wanto to compute \(E(\theta)\), \(E(\theta^2)\) and \(Pr(\theta<0)\), when the unnormalized
density of \(\theta\) is \[
p(\theta) \propto \exp\{-0.5(\theta-1)^2\}(1+0.25\theta^2)^{-2.5} \qquad
\theta \in \Re.
\] We construct a grid from \(-5\) to \(5\) with one million points, so the
distance between two consecutive points is about \(0.00001\). The figure below show that the
variation of \(\theta\) is roughly
between \(-4\) and \(4\), so our grid is quite conservative. We
compare the performance of the grid approximation for various sizes of
the grid, from 10 points to 1,000,000 points.
theta = seq(-5,5,length=1000000)
h = theta[2]-theta[1]
post = exp(-0.5*(theta-1)^2)*(1+0.25*theta^2)^(-2.5)
plot(theta,post,type="l",xlab=expression(theta),
ylab="Unnormalized density")

Ms = c(seq(10,100,by=10),1000,10000,100000,1000000)
summaries = NULL
for (M in Ms){
theta = seq(-5,5,length=M)
post = exp(-0.5*(theta-1)^2)*(1+0.25*theta^2)^(-2.5)
denominator = sum(post)
E = sum(theta*post)/denominator
E2 = sum((theta-E)^2*post)/denominator
Prob = sum(ifelse(theta<0,1,0)*post)/denominator
summaries=rbind(summaries,round(c(E,E2,Prob),10))
}
tab = cbind(Ms,summaries)
colnames(tab) = c("M","Mean","Mean2","Prob(theta<0)")
tab
## M Mean Mean2 Prob(theta<0)
## [1,] 1e+01 0.5376929 0.5508078 0.2065551
## [2,] 2e+01 0.5319219 0.5572364 0.2314653
## [3,] 3e+01 0.5319216 0.5572353 0.2345890
## [4,] 4e+01 0.5319214 0.5572344 0.2355990
## [5,] 5e+01 0.5319212 0.5572338 0.2360507
## [6,] 6e+01 0.5319211 0.5572334 0.2362914
## [7,] 7e+01 0.5319211 0.5572331 0.2364347
## [8,] 8e+01 0.5319210 0.5572328 0.2365270
## [9,] 9e+01 0.5319210 0.5572326 0.2365898
## [10,] 1e+02 0.5319209 0.5572325 0.2366346
## [11,] 1e+03 0.5319206 0.5572311 0.2368208
## [12,] 1e+04 0.5319206 0.5572309 0.2368227
## [13,] 1e+05 0.5319206 0.5572309 0.2368227
## [14,] 1e+06 0.5319206 0.5572309 0.2368227
PROBLEM 2: Monte Carlo integration
In this example, we want to compute \(Pr(\theta>0.7)\) when \(\theta \sim N(0,1)\) by using Monte Carlo
integration based on \(M\) draws from
\(N(0,1)\). More precisely, the
integral we want to compute is \[
I = \int_\Re I(\theta>0.7)p(\theta)d\theta.
\] The Monte Carlo integration approximation is \[
\widehat{I}_{MC} = \frac{1}{M} \sum_{i=1}^M I(\theta^{(i)}>0.7),
\] where \(\theta^{(1)},\ldots,\theta^{(M)}\) is a
random sample of \(N(0,1)\). It is easy
to see, based on frequentist asymptotic results, that \[
\widehat{I}_{MC} \longrightarrow I \qquad \mbox{when} \ \ \
M \longrightarrow \infty.
\] An important feature of Monte Carlo methods is the computation
of the Monte Carlo error \[
V(\widehat{I}_{MC}) \approx \frac{1}{M^2} \sum_{i=1}^M
(\theta^{(i)}-\widehat{I}_{MC})^2.
\] The figure below illustrates the above asymptotic result by
showing the improvement of the MC approximation as \(M\) increases from \(500\) to \(10,000\). The MC error descreases as the
sample increases.
set.seed(314159)
M = 10000
theta.draw = rnorm(M,0,1)
I.mc = cumsum(ifelse(theta.draw>0.7,1,0))/1:M
mc.error = sqrt(mean(theta.draw-I.mc)^2/(1:M))
bands = cbind(I.mc-2*mc.error,I.mc,I.mc+2*mc.error)
M0 = 500
par(mfrow=c(1,1))
plot(M0:M,bands[M0:M,2],type="l",xlab="Monte Carlo size",
ylab="MC approximation",ylim=c(0.2,0.3),axes=FALSE)
axis(2);axis(1,at=seq(M0,M,by=1000))
lines(M0:M,bands[M0:M,1],col=2)
lines(M0:M,bands[M0:M,3],col=2)
abline(h=1-pnorm(0.7),lty=2,col=4)

Replication exercise
In this replication exercise, commonly known as a Monte Carlo
exercise, we see the decreasing size of the Monte Carlo error.
set.seed(314159)
par(mfrow=c(1,1))
plot(M0:M,I.mc[M0:M],type="l",xlab="Monte Carlo size",
ylab="MC approximation",ylim=c(0.2,0.3),col=grey(0.8),
axes=FALSE)
axis(2);axis(1,at=seq(M0,M,by=1000))
for (i in 1:100){
theta.draw = rnorm(M,0,1)
I.mc = cumsum(ifelse(theta.draw>0.7,1,0))/(1:M)
lines(M0:M,I.mc[M0:M],col=grey(0.8))
}
abline(h=1-pnorm(0.7),lwd=3)
title("100 replications")

PROBLEM 3: MCIS
Monte Carlo integration (or simulation) via importance sampling is a
very popular strategy when one is not able to directly sample from the
target distribution, \(p(\theta)\). The
importance sampling samples from a proposal distribution, \(q(\theta)\).
Here, we want to compute \(Pr(\theta>0.7)\) when \(\theta \sim N(0,1)\) using Monte Carlo
integration based on \(M\) draws from
the proposal distribution \(U(-20,20)\).
M = 10000
theta.draw = runif(M,-20,20)
I.mcis = mean(ifelse(theta.draw>0.7,1,0)*dnorm(theta.draw)/(1/40))
c(I.mc[M],I.mcis)
## [1] 0.2421000 0.2469929
PROBLEM 1 (CONTINUING)
Computing \(Pr(\theta<0)\) by
Monte Carlo via Importance Sampling (MCIS) where the proposal density is
\(N(0,4)\).
M = 100000
theta.draw = rnorm(M,0,2)
denominator = exp(-0.5*(theta.draw-1)^2)*(1+0.25*theta.draw^2)^(-2.5)/dnorm(theta.draw,0,2)
numerator = ifelse(theta.draw<0,1,0)*denominator
I.mc = mean(numerator)/mean(denominator)
paste("Exact value = ",round(Prob,5),sep="")
## [1] "Exact value = 0.23682"
paste("MCIS approximation = ",round(I.mc,5),sep="")
## [1] "MCIS approximation = 0.23632"
PROBLEM 4: Rejection method
Approximating the constant \(\pi\)
via rejection method.
set.seed(3141593)
M = 10000
x = runif(M)
y = runif(M)
ind = order(x)
x=x[ind]
y=y[ind]
cond = (x^2+y^2)<1
plot(x,y,pch=16,cex=0.5)
points(x[cond],y[cond],pch=16,cex=0.5,col=2)
lines(x,sqrt(1-x^2))

pi.mc = 4*sum(cond)/M
pi.mc
## [1] 3.1312
PROBLEM 5: SIR
Sampling from the target distribution, \(N(0,1)\), based on draws from the proposal
density, \(Cauchy(0,1)\) via Sampling
Importance Resampling (SIR) and approximating the following few
summaries:
\(Pr(\theta<1)\)
\(E(|\theta|)\)
2.5% quantile
Recall that the SIR algorithm works as follows:
Sample (large) \(M\) draws from
a proposal density \(q(\theta)\): \(\{\widetilde{\theta}^{(1)},\ldots,\widetilde{\theta}^{(M)}\}\);
Evalute the weights \(\omega^{(i)}
\propto
\frac{p(\widetilde{\theta}^{(i)})}{q(\widetilde{\theta}^{(i)})}\);
Resample \(N \leq M\) from the
discrete set \(\{\widetilde{\theta}^{(1)},\ldots,\widetilde{\theta}^{(M)}\}\)
with probabilities \(\{\omega^{(1)},\ldots,\omega^{(M)}\}\).
The final sampled set, say \(\{\theta^{(1)},\ldots,\theta^{(N)}\}\)
approximates a sample from \(p(\theta)\).
More details about Monte Carlo integration, MC simulation, SIR and
other Monte Carlo schemes, can be found in my course notes here.
M = 100000
N = 50000
theta = rt(M,df=1)
w = exp(-theta^2/2)*(1+theta^2)
theta.new = sample(theta,size=N,replace=TRUE,prob=w)
par(mfrow=c(1,2))
hist(theta[abs(theta)<15],breaks=seq(-15,15,length=40),
prob=TRUE, xlab=expression(theta),main="")
title("Draws from proposal: Cauchy(0,1)")
legend("topleft",legend=paste("Tails = ",
100*round(1-sum(abs(theta)<15)/M,4),"%",sep=""),bty="n")
hist(theta.new,prob=TRUE,xlab=expression(theta),main="")
title("Draws from target: N(0,1)")
thetas = seq(-5,5,length=100)
lines(thetas,dnorm(thetas),col=2,lwd=3)

tab = cbind(c(pnorm(1),mean(theta.new<1)),
c(sqrt(2/pi),mean(abs(theta.new))),
c(qnorm(0.025),quantile(theta.new,0.025)))
rownames(tab) = c("Exact","SIR")
colnames(tab) =
c("Pr(theta<1)","E(|theta|)","2.5% quant")
round(tab,4)
## Pr(theta<1) E(|theta|) 2.5% quant
## Exact 0.8413 0.7979 -1.9600
## SIR 0.8415 0.7984 -1.9525
LS0tCnRpdGxlOiAiTW9udGUgQ2FybG8gSW50ZWdyYXRpb24gYW5kIFNpbXVsYXRpb24iCnN1YnRpdGxlOiAiRml2ZSBpbGx1c3RyYXRpdmUgZXhhbXBsZXMiCmF1dGhvcjogIkhlZGliZXJ0IEZyZWl0YXMgTG9wZXMiCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZTogcGFwZXIKICAgIGhpZ2hsaWdodDogcHlnbWVudHMKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiAzCiAgICB0b2NfY29sbGFwc2VkOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgICNudW1iZXJfc2VjdGlvbnM6IHRydWUKLS0tCgoKCiMgUFJPQkxFTSAxOiBHcmlkIGFwcHJveGltYXRpb24KCkhlcmUgd2Ugd2FudG8gdG8gY29tcHV0ZSAkRShcdGhldGEpJCwgJEUoXHRoZXRhXjIpJCBhbmQgJFByKFx0aGV0YTwwKSQsIHdoZW4gdGhlIHVubm9ybWFsaXplZCBkZW5zaXR5IG9mICRcdGhldGEkIGlzCiQkCnAoXHRoZXRhKSBccHJvcHRvIFxleHBcey0wLjUoXHRoZXRhLTEpXjJcfSgxKzAuMjVcdGhldGFeMileey0yLjV9IFxxcXVhZCBcdGhldGEgXGluIFxSZS4KJCQKV2UgY29uc3RydWN0IGEgZ3JpZCBmcm9tICQtNSQgdG8gJDUkIHdpdGggb25lIG1pbGxpb24gcG9pbnRzLCBzbyB0aGUgZGlzdGFuY2UgYmV0d2VlbiB0d28gY29uc2VjdXRpdmUgcG9pbnRzIGlzIGFib3V0ICQwLjAwMDAxJC4gIFRoZSBmaWd1cmUgYmVsb3cgc2hvdyB0aGF0IHRoZSB2YXJpYXRpb24gb2YgJFx0aGV0YSQgaXMgcm91Z2hseSBiZXR3ZWVuICQtNCQgYW5kICQ0JCwgc28gb3VyIGdyaWQgaXMgcXVpdGUgY29uc2VydmF0aXZlLiAgV2UgY29tcGFyZSB0aGUgcGVyZm9ybWFuY2Ugb2YgdGhlIGdyaWQgYXBwcm94aW1hdGlvbiBmb3IgdmFyaW91cyAgc2l6ZXMgb2YgdGhlIGdyaWQsIGZyb20gMTAgcG9pbnRzIHRvIDEsMDAwLDAwMCBwb2ludHMuCgpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTV9CnRoZXRhID0gc2VxKC01LDUsbGVuZ3RoPTEwMDAwMDApCmggICAgID0gdGhldGFbMl0tdGhldGFbMV0KcG9zdCAgPSBleHAoLTAuNSoodGhldGEtMSleMikqKDErMC4yNSp0aGV0YV4yKV4oLTIuNSkKcGxvdCh0aGV0YSxwb3N0LHR5cGU9ImwiLHhsYWI9ZXhwcmVzc2lvbih0aGV0YSksCiAgICAgeWxhYj0iVW5ub3JtYWxpemVkIGRlbnNpdHkiKQoKCk1zID0gYyhzZXEoMTAsMTAwLGJ5PTEwKSwxMDAwLDEwMDAwLDEwMDAwMCwxMDAwMDAwKQpzdW1tYXJpZXMgPSBOVUxMCmZvciAoTSBpbiBNcyl7CiAgdGhldGEgPSBzZXEoLTUsNSxsZW5ndGg9TSkKICBwb3N0ICA9IGV4cCgtMC41Kih0aGV0YS0xKV4yKSooMSswLjI1KnRoZXRhXjIpXigtMi41KQogIGRlbm9taW5hdG9yID0gc3VtKHBvc3QpCiAgRSA9IHN1bSh0aGV0YSpwb3N0KS9kZW5vbWluYXRvcgogIEUyID0gc3VtKCh0aGV0YS1FKV4yKnBvc3QpL2Rlbm9taW5hdG9yCiAgUHJvYiA9IHN1bShpZmVsc2UodGhldGE8MCwxLDApKnBvc3QpL2Rlbm9taW5hdG9yCiAgc3VtbWFyaWVzPXJiaW5kKHN1bW1hcmllcyxyb3VuZChjKEUsRTIsUHJvYiksMTApKQp9CnRhYiA9IGNiaW5kKE1zLHN1bW1hcmllcykKY29sbmFtZXModGFiKSA9IGMoIk0iLCJNZWFuIiwiTWVhbjIiLCJQcm9iKHRoZXRhPDApIikKdGFiCmBgYAoKIyBQUk9CTEVNIDI6IE1vbnRlIENhcmxvIGludGVncmF0aW9uCgpJbiB0aGlzIGV4YW1wbGUsIHdlIHdhbnQgdG8gY29tcHV0ZSAkUHIoXHRoZXRhPjAuNykkIAp3aGVuICRcdGhldGEgXHNpbSBOKDAsMSkkIGJ5IHVzaW5nIE1vbnRlIENhcmxvIGludGVncmF0aW9uIApiYXNlZCBvbiAkTSQgZHJhd3MgZnJvbSAkTigwLDEpJC4gIE1vcmUgcHJlY2lzZWx5LCB0aGUgaW50ZWdyYWwgd2Ugd2FudCB0byBjb21wdXRlIGlzCiQkCkkgPSBcaW50X1xSZSBJKFx0aGV0YT4wLjcpcChcdGhldGEpZFx0aGV0YS4KJCQKVGhlIE1vbnRlIENhcmxvIGludGVncmF0aW9uIGFwcHJveGltYXRpb24gaXMKJCQKXHdpZGVoYXR7SX1fe01DfSA9IFxmcmFjezF9e019IFxzdW1fe2k9MX1eTSBJKFx0aGV0YV57KGkpfT4wLjcpLAokJAp3aGVyZSAkXHRoZXRhXnsoMSl9LFxsZG90cyxcdGhldGFeeyhNKX0kIGlzIGEgcmFuZG9tIHNhbXBsZSBvZiAkTigwLDEpJC4gIEl0IGlzIGVhc3kgdG8gc2VlLCBiYXNlZCBvbiBmcmVxdWVudGlzdCBhc3ltcHRvdGljIHJlc3VsdHMsIHRoYXQgCiQkClx3aWRlaGF0e0l9X3tNQ30gXGxvbmdyaWdodGFycm93IEkgXHFxdWFkIFxtYm94e3doZW59IFwgXCBcIApNIFxsb25ncmlnaHRhcnJvdyBcaW5mdHkuCiQkCkFuIGltcG9ydGFudCBmZWF0dXJlIG9mIE1vbnRlIENhcmxvIG1ldGhvZHMgaXMgdGhlIGNvbXB1dGF0aW9uIG9mIHRoZSBNb250ZSBDYXJsbyBlcnJvcgokJApWKFx3aWRlaGF0e0l9X3tNQ30pIFxhcHByb3ggXGZyYWN7MX17TV4yfSBcc3VtX3tpPTF9Xk0gCihcdGhldGFeeyhpKX0tXHdpZGVoYXR7SX1fe01DfSleMi4KJCQKVGhlIGZpZ3VyZSBiZWxvdyBpbGx1c3RyYXRlcyB0aGUgYWJvdmUgYXN5bXB0b3RpYyByZXN1bHQgYnkgc2hvd2luZyB0aGUgaW1wcm92ZW1lbnQgb2YgdGhlIE1DIGFwcHJveGltYXRpb24gYXMgJE0kIGluY3JlYXNlcyBmcm9tICQ1MDAkIHRvICQxMCwwMDAkLiAgVGhlIE1DIGVycm9yIGRlc2NyZWFzZXMgYXMgdGhlIHNhbXBsZSBpbmNyZWFzZXMuCgpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTV9CnNldC5zZWVkKDMxNDE1OSkKTSA9IDEwMDAwCnRoZXRhLmRyYXcgPSBybm9ybShNLDAsMSkKSS5tYyAgICAgICA9IGN1bXN1bShpZmVsc2UodGhldGEuZHJhdz4wLjcsMSwwKSkvMTpNCm1jLmVycm9yICAgPSBzcXJ0KG1lYW4odGhldGEuZHJhdy1JLm1jKV4yLygxOk0pKQpiYW5kcyA9IGNiaW5kKEkubWMtMiptYy5lcnJvcixJLm1jLEkubWMrMiptYy5lcnJvcikKCk0wID0gNTAwCnBhcihtZnJvdz1jKDEsMSkpCnBsb3QoTTA6TSxiYW5kc1tNMDpNLDJdLHR5cGU9ImwiLHhsYWI9Ik1vbnRlIENhcmxvIHNpemUiLAogICAgIHlsYWI9Ik1DIGFwcHJveGltYXRpb24iLHlsaW09YygwLjIsMC4zKSxheGVzPUZBTFNFKQpheGlzKDIpO2F4aXMoMSxhdD1zZXEoTTAsTSxieT0xMDAwKSkKbGluZXMoTTA6TSxiYW5kc1tNMDpNLDFdLGNvbD0yKQpsaW5lcyhNMDpNLGJhbmRzW00wOk0sM10sY29sPTIpCmFibGluZShoPTEtcG5vcm0oMC43KSxsdHk9Mixjb2w9NCkKYGBgCgojIyBSZXBsaWNhdGlvbiBleGVyY2lzZQoKSW4gdGhpcyByZXBsaWNhdGlvbiBleGVyY2lzZSwgY29tbW9ubHkga25vd24gYXMgYSBNb250ZSBDYXJsbyBleGVyY2lzZSwgd2Ugc2VlIHRoZSBkZWNyZWFzaW5nIHNpemUgb2YgdGhlIE1vbnRlIENhcmxvIGVycm9yLgoKYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD01fQpzZXQuc2VlZCgzMTQxNTkpCnBhcihtZnJvdz1jKDEsMSkpCnBsb3QoTTA6TSxJLm1jW00wOk1dLHR5cGU9ImwiLHhsYWI9Ik1vbnRlIENhcmxvIHNpemUiLAogICAgIHlsYWI9Ik1DIGFwcHJveGltYXRpb24iLHlsaW09YygwLjIsMC4zKSxjb2w9Z3JleSgwLjgpLAogICAgIGF4ZXM9RkFMU0UpCmF4aXMoMik7YXhpcygxLGF0PXNlcShNMCxNLGJ5PTEwMDApKQpmb3IgKGkgaW4gMToxMDApewogIHRoZXRhLmRyYXcgPSBybm9ybShNLDAsMSkKICBJLm1jID0gY3Vtc3VtKGlmZWxzZSh0aGV0YS5kcmF3PjAuNywxLDApKS8oMTpNKQogIGxpbmVzKE0wOk0sSS5tY1tNMDpNXSxjb2w9Z3JleSgwLjgpKQp9CmFibGluZShoPTEtcG5vcm0oMC43KSxsd2Q9MykKdGl0bGUoIjEwMCByZXBsaWNhdGlvbnMiKQpgYGAKCgojIFBST0JMRU0gMzogTUNJUyAKTW9udGUgQ2FybG8gaW50ZWdyYXRpb24gKG9yIHNpbXVsYXRpb24pIHZpYSBpbXBvcnRhbmNlIHNhbXBsaW5nIGlzIGEgdmVyeSBwb3B1bGFyIHN0cmF0ZWd5IHdoZW4gb25lIGlzIG5vdCBhYmxlIHRvIGRpcmVjdGx5IHNhbXBsZSBmcm9tIHRoZSB0YXJnZXQgZGlzdHJpYnV0aW9uLCAkcChcdGhldGEpJC4gIFRoZSBpbXBvcnRhbmNlIHNhbXBsaW5nIHNhbXBsZXMgZnJvbSBhIHByb3Bvc2FsIGRpc3RyaWJ1dGlvbiwgJHEoXHRoZXRhKSQuCgpIZXJlLCB3ZSB3YW50IHRvIGNvbXB1dGUgJFByKFx0aGV0YT4wLjcpJCAKd2hlbiAkXHRoZXRhIFxzaW0gTigwLDEpJCB1c2luZyBNb250ZSBDYXJsbyBpbnRlZ3JhdGlvbiAKYmFzZWQgb24gJE0kIGRyYXdzIGZyb20gdGhlIHByb3Bvc2FsIGRpc3RyaWJ1dGlvbiAKJFUoLTIwLDIwKSQuCgpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTV9Ck0gPSAxMDAwMAp0aGV0YS5kcmF3ID0gcnVuaWYoTSwtMjAsMjApCkkubWNpcyA9IG1lYW4oaWZlbHNlKHRoZXRhLmRyYXc+MC43LDEsMCkqZG5vcm0odGhldGEuZHJhdykvKDEvNDApKQpjKEkubWNbTV0sSS5tY2lzKQpgYGAKCiMgUFJPQkxFTSAxIChDT05USU5VSU5HKQoKQ29tcHV0aW5nICRQcihcdGhldGE8MCkkIGJ5IE1vbnRlIENhcmxvIHZpYSBJbXBvcnRhbmNlIFNhbXBsaW5nIChNQ0lTKQp3aGVyZSB0aGUgcHJvcG9zYWwgZGVuc2l0eSBpcyAkTigwLDQpJC4KCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NX0KTSA9IDEwMDAwMAp0aGV0YS5kcmF3ICA9IHJub3JtKE0sMCwyKQpkZW5vbWluYXRvciA9IGV4cCgtMC41Kih0aGV0YS5kcmF3LTEpXjIpKigxKzAuMjUqdGhldGEuZHJhd14yKV4oLTIuNSkvZG5vcm0odGhldGEuZHJhdywwLDIpCm51bWVyYXRvciAgID0gaWZlbHNlKHRoZXRhLmRyYXc8MCwxLDApKmRlbm9taW5hdG9yCkkubWMgPSBtZWFuKG51bWVyYXRvcikvbWVhbihkZW5vbWluYXRvcikKCnBhc3RlKCJFeGFjdCB2YWx1ZSA9ICIscm91bmQoUHJvYiw1KSxzZXA9IiIpCnBhc3RlKCJNQ0lTIGFwcHJveGltYXRpb24gPSAiLHJvdW5kKEkubWMsNSksc2VwPSIiKQpgYGAKCiMgUFJPQkxFTSA0OiBSZWplY3Rpb24gbWV0aG9kCgpBcHByb3hpbWF0aW5nIHRoZSBjb25zdGFudCAkXHBpJCB2aWEgcmVqZWN0aW9uIG1ldGhvZC4KCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9N30Kc2V0LnNlZWQoMzE0MTU5MykKTSA9IDEwMDAwCnggPSBydW5pZihNKQp5ID0gcnVuaWYoTSkKaW5kID0gb3JkZXIoeCkKeD14W2luZF0KeT15W2luZF0KY29uZCA9ICh4XjIreV4yKTwxCnBsb3QoeCx5LHBjaD0xNixjZXg9MC41KQpwb2ludHMoeFtjb25kXSx5W2NvbmRdLHBjaD0xNixjZXg9MC41LGNvbD0yKQpsaW5lcyh4LHNxcnQoMS14XjIpKQpwaS5tYyA9IDQqc3VtKGNvbmQpL00KcGkubWMKYGBgCgojIFBST0JMRU0gNTogU0lSCgpTYW1wbGluZyBmcm9tIHRoZSB0YXJnZXQgZGlzdHJpYnV0aW9uLCAkTigwLDEpJCwgYmFzZWQgb24gZHJhd3MgZnJvbSB0aGUgcHJvcG9zYWwgZGVuc2l0eSwgJENhdWNoeSgwLDEpJCB2aWEgU2FtcGxpbmcgSW1wb3J0YW5jZSBSZXNhbXBsaW5nICAoU0lSKSBhbmQgYXBwcm94aW1hdGluZyB0aGUgZm9sbG93aW5nIApmZXcgc3VtbWFyaWVzOgoKKiAkUHIoXHRoZXRhPDEpJAoKKiAkRSh8XHRoZXRhfCkkCgoqIDIuNVwlIHF1YW50aWxlCgpSZWNhbGwgdGhhdCB0aGUgU0lSIGFsZ29yaXRobSB3b3JrcyBhcyBmb2xsb3dzOgoKMSkgU2FtcGxlIChsYXJnZSkgJE0kIGRyYXdzIGZyb20gYSBwcm9wb3NhbCBkZW5zaXR5ICRxKFx0aGV0YSkkOgokXHtcd2lkZXRpbGRle1x0aGV0YX1eeygxKX0sXGxkb3RzLFx3aWRldGlsZGV7XHRoZXRhfV57KE0pfVx9JDsKCjIpIEV2YWx1dGUgdGhlIHdlaWdodHMgJFxvbWVnYV57KGkpfSBccHJvcHRvIFxmcmFje3AoXHdpZGV0aWxkZXtcdGhldGF9XnsoaSl9KX17cShcd2lkZXRpbGRle1x0aGV0YX1eeyhpKX0pfSQ7CgozKSBSZXNhbXBsZSAkTiBcbGVxIE0kIGZyb20gdGhlIGRpc2NyZXRlIHNldCAkXHtcd2lkZXRpbGRle1x0aGV0YX1eeygxKX0sXGxkb3RzLFx3aWRldGlsZGV7XHRoZXRhfV57KE0pfVx9JCAgd2l0aCBwcm9iYWJpbGl0aWVzICRce1xvbWVnYV57KDEpfSxcbGRvdHMsXG9tZWdhXnsoTSl9XH0kLgoKNCkgVGhlIGZpbmFsIHNhbXBsZWQgc2V0LCBzYXkgCiRce1x0aGV0YV57KDEpfSxcbGRvdHMsXHRoZXRhXnsoTil9XH0kCmFwcHJveGltYXRlcyBhIHNhbXBsZSBmcm9tICRwKFx0aGV0YSkkLiAgCgpNb3JlIGRldGFpbHMgYWJvdXQgTW9udGUgQ2FybG8gaW50ZWdyYXRpb24sIE1DIHNpbXVsYXRpb24sIFNJUiBhbmQgb3RoZXIgTW9udGUgQ2FybG8gc2NoZW1lcywgY2FuIGJlIGZvdW5kIGluIG15IGNvdXJzZSBub3RlcyBbaGVyZV0oaHR0cHM6Ly9oZWRpYmVydC5vcmcvd3AtY29udGVudC91cGxvYWRzLzIwMjAvMDEvYXByZW5kaXphZ2VtYmF5ZXNpYW5hLWJheWVzaWFuY29tcHV0YXRpb24ucGRmKS4KCgoKCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NX0KTSA9IDEwMDAwMApOID0gNTAwMDAKdGhldGEgPSBydChNLGRmPTEpCncgPSBleHAoLXRoZXRhXjIvMikqKDErdGhldGFeMikKdGhldGEubmV3ID0gc2FtcGxlKHRoZXRhLHNpemU9TixyZXBsYWNlPVRSVUUscHJvYj13KQoKcGFyKG1mcm93PWMoMSwyKSkKaGlzdCh0aGV0YVthYnModGhldGEpPDE1XSxicmVha3M9c2VxKC0xNSwxNSxsZW5ndGg9NDApLApwcm9iPVRSVUUsIHhsYWI9ZXhwcmVzc2lvbih0aGV0YSksbWFpbj0iIikKdGl0bGUoIkRyYXdzIGZyb20gcHJvcG9zYWw6IENhdWNoeSgwLDEpIikKbGVnZW5kKCJ0b3BsZWZ0IixsZWdlbmQ9cGFzdGUoIlRhaWxzID0gIiwKMTAwKnJvdW5kKDEtc3VtKGFicyh0aGV0YSk8MTUpL00sNCksIiUiLHNlcD0iIiksYnR5PSJuIikKCmhpc3QodGhldGEubmV3LHByb2I9VFJVRSx4bGFiPWV4cHJlc3Npb24odGhldGEpLG1haW49IiIpCnRpdGxlKCJEcmF3cyBmcm9tIHRhcmdldDogTigwLDEpIikKdGhldGFzID0gc2VxKC01LDUsbGVuZ3RoPTEwMCkKbGluZXModGhldGFzLGRub3JtKHRoZXRhcyksY29sPTIsbHdkPTMpCgp0YWIgPSBjYmluZChjKHBub3JtKDEpLG1lYW4odGhldGEubmV3PDEpKSwKYyhzcXJ0KDIvcGkpLG1lYW4oYWJzKHRoZXRhLm5ldykpKSwKYyhxbm9ybSgwLjAyNSkscXVhbnRpbGUodGhldGEubmV3LDAuMDI1KSkpCnJvd25hbWVzKHRhYikgPSBjKCJFeGFjdCIsIlNJUiIpCmNvbG5hbWVzKHRhYikgPSAKYygiUHIodGhldGE8MSkiLCJFKHx0aGV0YXwpIiwiMi41JSBxdWFudCIpCnJvdW5kKHRhYiw0KQpgYGA=