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:

  1. Sample (large) \(M\) draws from a proposal density \(q(\theta)\): \(\{\widetilde{\theta}^{(1)},\ldots,\widetilde{\theta}^{(M)}\}\);

  2. Evalute the weights \(\omega^{(i)} \propto \frac{p(\widetilde{\theta}^{(i)})}{q(\widetilde{\theta}^{(i)})}\);

  3. Resample \(N \leq M\) from the discrete set \(\{\widetilde{\theta}^{(1)},\ldots,\widetilde{\theta}^{(M)}\}\) with probabilities \(\{\omega^{(1)},\ldots,\omega^{(M)}\}\).

  4. 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=