1 Gaussian homoscedastic linear model

We observe \(n\) pairs of observations, \((y_i,x_i)\), such that \[ \mbox{data} = \{(y_1,x_1),\ldots,(y_n,x_n)\}. \] The model that relates \(y\)s and the \(x\)s is a Gaussian homoscedastic linear model: \[ y_i = \beta x_i + \varepsilon_i \qquad \varepsilon_i \sim N(0,\sigma^2), \] with \(E(\varepsilon_i\varepsilon_j)=0\) for all \(i \neq j\). The likelihood function can be written as \[\begin{eqnarray*} L(\beta,\sigma^2|\mbox{data}) &=& \prod_{i=1}^n \frac{1}{\sqrt{2\pi\sigma^2}}\exp\left\{-\frac12\frac{(y_i-\beta x_i)^2}{\sigma^2}\right\}\\ &\propto& (\sigma^2)^{-n/2}\exp\left\{-\frac12\frac{\sum_{i=1}^n (y_i-\beta x_i)^2}{\sigma^2}\right\} \end{eqnarray*}\]

2 Prior

In this model, the two unknown quantities are the slope parameter \(\beta\) and the residual variance, \(\sigma^2\). We will assume conditionally conjugate priors as follows: \[ \beta \sim N(b_0,V_0) \ \ \ \mbox{and} \ \ \ \sigma^2 \sim IG(c_0,d_0), \] such that \[ p(\beta,\sigma^2) = p(\beta)p(\sigma^2) = \left[\frac{1}{\sqrt{2\pi V_0}}\exp\left\{-0.5\frac{(\beta-b_0)^2}{V_0}\right\}\right] \left[ \frac{d_0^{c_0}}{\Gamma(c_0)}(\sigma^2)^{-(c_0+1)}\exp\left\{-\frac{d_0}{\sigma^2}\right\}\right]. \]

3 Posterior distribution

The posterior distribution of \((\beta,\sigma^2)\) \[ p(\beta,\sigma^2|\mbox{data}) \propto p(\beta)p(\sigma^2)L(\beta,\sigma^2|\mbox{data}), \] does not belong to any known family of bivariate distributions and, consequently, there are not closed form answers to questions such as the following:

4 Gibbs-assisted posterior inference

The Gibbs sampler is a Markov Chain Monte Carlo (MCMC) scheme that samples from the distribution of interest (aka target distribution), in our case the posterior \(p(\beta,\sigma^2|\mbox{data})\), by iteratively sampling from the full conditional distributions: \[ p(\beta|\sigma^2,\mbox{data}) \ \ \ \mbox{and} \ \ \ p(\sigma^2|\beta,\mbox{data}). \] The beauty of the Gibbs sampler, and therefore of all MCMC schemes, is that it essentially breaks down the complexicity of a given model into the complexities of smaller models where blocks of parameters are kept fixed.

4.1 \(p(\sigma^2|\beta,\mbox{data})\)

In this full conditional distribution, the parameter \(\beta\) is treated as known. Therefore, we could define \(z_i = y_i-\beta x_i\) and the model becomes \[ z_1,\ldots,z_n \ \ iid \ \ N(0,\sigma^2). \] In this case, \[ p(\sigma^2|z_1,\ldots,z_n) \propto (\sigma^2)^{-(c_0+1)}\exp\left\{-\frac{d_0}{\sigma^2}\right\} (\sigma^2)^{-n/2}\exp\left\{-\frac{\sum_{i=1}^n z_i^2/2}{\sigma^2}\right\}, \] which resembles an inverse gamma distribution with hyperparameters \[ c_1 = c_0+\frac{n}{2} \ \ \ \mbox{and} \ \ \ d_1 = d_0 + \frac{\sum_{i=1}^n z_i^2}{2} = d_0 + \frac{\sum_{i=1}^n (y_i-\beta x_i)^2}{2}, \] or \(\sigma^2|\beta,\mbox{data} \sim IG(c_1,d_1)\).

sample.sigma2 = function(beta,c0,d0,y,x){
  c1 = c0+n/2
  d1 = d0+sum((y-x*beta)^2)/2
  return(1/rgamma(1,c1,d1))
}

4.2 \(p(\beta|\sigma^2,\mbox{data})\)

Similarly, assuming that \(\sigma^2\) is known, we have a simpler model,i.e. a Gaussian regression model with an unknown slope, \(\beta\), but known residual variance, \(\sigma^2\). In this case, \[\begin{eqnarray*} p(\beta|\sigma^2,\mbox{data}) &\propto& \exp\{-0.5(\beta-b_0)^2/V_0\}\exp\left\{-0.5\sum_{i=1}^n (y_i-\beta x_i)^2/\sigma^2\right\}\\ &\propto& \exp\left\{-0.5\left[\beta^2/V_0-2\beta b_0/V_0+\beta^2s_x^2/\sigma^2 -2\beta s_{xy}/\sigma^2\right]\right\}\\ &\propto& \exp\left\{-0.5\left[\beta^2(1/V_0+s_x^2/\sigma^2)-2\beta(b_0/V_0+s_{xy}/\sigma^2) \right]\right\}, \end{eqnarray*}\] where \(s_x^2 = \sum_{i=1}^n x_i^2\) and \(s_{xy} = \sum_{i=1}^n y_i x_i\). It is now easy to see that \[ \beta|\sigma^2,\mbox{data} \sim N(b_1,V_1), \] where \(V_1=1/(1/V_0+s_x^2/\sigma^2)\) and \[ b_1 = V_1(b_0/V_0+s_{xy}/\sigma^2) \]

sample.beta = function(sigma2,b0,V0,sx2,sxy){
  V1 = 1/(1/V0+sx2/sigma2)
  b1 = V1*(b0/V0+sxy/sigma2)
  return(rnorm(1,b1,sqrt(V1)))
}

5 Turning the Bayesian crank

5.1 Simulating some data

n = 50
x = runif(n,0,3)
y = 0.75*x+rnorm(n)
plot(x,y)

sx2 = sum(x^2)
sxy = sum(x*y)

5.2 Setting up the hyperparameters

b0 = 0
V0 = 9
c0 = 1/2
d0 = 1/2

par(mfrow=c(1,2))
sig2 = seq(0.0001,10,length=1000)
plot(sig2,dgamma(1/sig2,c0,d0)/(sig2^2),xlab=expression(sigma^2),ylab="Prior density",type="l")
beta = seq(-10,10,length=1000)
plot(beta,dnorm(beta,b0,sqrt(V0)),xlab=expression(beta),ylab="Prior density",type="l")

5.3 Setting up the MCMC scheme

beta.initial = 0

n.burn  = 1000
n.draws = 1000
step    = 1
niter   = n.burn+n.draws*step

5.4 Running the Gibbs sampler

beta = beta.initial
draws = matrix(0,niter,2)
for (iter in 1:niter){
  sigma2 = sample.sigma2(beta,c0,d0,y,x)
  beta   = sample.beta(sigma2,b0,V0,sx2,sxy)
  draws[iter,] = c(beta,sqrt(sigma2))
}

5.5 MCMC output

par(mfrow=c(2,3))
ts.plot(draws[,1],ylab="",main=expression(beta),xlab="Iterations")
acf(draws[,1],main="")
hist(draws[,1],prob=TRUE,main="",xlab=expression(beta))

ts.plot(draws[,2],ylab="",main=expression(sigma),xlab="Iterations")
acf(draws[,2],main="")
hist(draws[,2],prob=TRUE,main="",xlab=expression(sigma))

5.6 Comparing priors and posteriors

beta = seq(-10,10,length=1000)
sig2 = seq(0.0001,10,length=1000)
par(mfrow=c(1,2))
plot(density(draws[,1]),xlab=expression(beta),main="",ylab="Density",lwd=2)
lines(beta,dnorm(beta,b0,sqrt(V0)),col=2,lwd=2)
abline(v=0.75,col=4,lwd=2)
plot(density(draws[,2]^2),xlab=expression(sigma^2),main="",ylab="Density",xlim=c(0,4),lwd=2)
lines(sig2,dgamma(1/sig2,c0,d0)/(sig2^2),col=2,lwd=2)
abline(v=1,col=4,lwd=2)
legend("topright",legend=c("Prior","Posterior","True value"),col=c(2,1,4),bty="n",lty=1,lwd=2)

5.7 What is \(E(\beta|\mbox{data})\)?

mean(draws[,1])
## [1] 0.6707462

5.8 What is \(Pr(\sigma>1|\mbox{data})\)?

mean(draws[,2]>1)
## [1] 0.707
LS0tCnRpdGxlOiAiQmF5ZXNpYW4gbGluZWFyIHJlZ3Jlc3Npb24iCnN1YnRpdGxlOiAiR2liYnMgc2FtcGxlciBpbiBhY3Rpb24iCmF1dGhvcjogIkhlZGliZXJ0IEZyZWl0YXMgTG9wZXMiCmRhdGU6ICI1LzI3LzIwMjMiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDIKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKYGBgCgojIEdhdXNzaWFuIGhvbW9zY2VkYXN0aWMgbGluZWFyIG1vZGVsCldlIG9ic2VydmUgJG4kIHBhaXJzIG9mIG9ic2VydmF0aW9ucywgJCh5X2kseF9pKSQsIHN1Y2ggdGhhdAokJApcbWJveHtkYXRhfSA9IFx7KHlfMSx4XzEpLFxsZG90cywoeV9uLHhfbilcfS4KJCQKVGhlIG1vZGVsIHRoYXQgcmVsYXRlcyAkeSRzIGFuZCB0aGUgJHgkcyBpcyBhIEdhdXNzaWFuIGhvbW9zY2VkYXN0aWMgbGluZWFyIG1vZGVsOgokJAp5X2kgPSBcYmV0YSB4X2kgKyBcdmFyZXBzaWxvbl9pIFxxcXVhZCBcdmFyZXBzaWxvbl9pIFxzaW0gTigwLFxzaWdtYV4yKSwKJCQKd2l0aCAkRShcdmFyZXBzaWxvbl9pXHZhcmVwc2lsb25faik9MCQgZm9yIGFsbCAkaSBcbmVxIGokLiAgVGhlIGxpa2VsaWhvb2QgZnVuY3Rpb24gY2FuIGJlIHdyaXR0ZW4gYXMKXGJlZ2lue2VxbmFycmF5Kn0KTChcYmV0YSxcc2lnbWFeMnxcbWJveHtkYXRhfSkgJj0mIFxwcm9kX3tpPTF9Xm4KXGZyYWN7MX17XHNxcnR7MlxwaVxzaWdtYV4yfX1cZXhwXGxlZnRcey1cZnJhYzEyXGZyYWN7KHlfaS1cYmV0YSB4X2kpXjJ9e1xzaWdtYV4yfVxyaWdodFx9XFwKJlxwcm9wdG8mIChcc2lnbWFeMileey1uLzJ9XGV4cFxsZWZ0XHstXGZyYWMxMlxmcmFje1xzdW1fe2k9MX1ebiAoeV9pLVxiZXRhIHhfaSleMn17XHNpZ21hXjJ9XHJpZ2h0XH0KXGVuZHtlcW5hcnJheSp9CgojIFByaW9yCkluIHRoaXMgbW9kZWwsIHRoZSB0d28gdW5rbm93biBxdWFudGl0aWVzIGFyZSB0aGUgc2xvcGUgcGFyYW1ldGVyICRcYmV0YSQgYW5kIHRoZSByZXNpZHVhbCB2YXJpYW5jZSwgJFxzaWdtYV4yJC4gIFdlIHdpbGwgYXNzdW1lIGNvbmRpdGlvbmFsbHkgY29uanVnYXRlIHByaW9ycyBhcyBmb2xsb3dzOgokJApcYmV0YSBcc2ltIE4oYl8wLFZfMCkgXCBcIFwgXG1ib3h7YW5kfSBcIFwgXCBcc2lnbWFeMiBcc2ltIElHKGNfMCxkXzApLAokJApzdWNoIHRoYXQgCiQkCnAoXGJldGEsXHNpZ21hXjIpID0gcChcYmV0YSlwKFxzaWdtYV4yKSA9IFxsZWZ0W1xmcmFjezF9e1xzcXJ0ezJccGkgVl8wfX1cZXhwXGxlZnRcey0wLjVcZnJhY3soXGJldGEtYl8wKV4yfXtWXzB9XHJpZ2h0XH1ccmlnaHRdIFxsZWZ0WwpcZnJhY3tkXzBee2NfMH19e1xHYW1tYShjXzApfShcc2lnbWFeMileey0oY18wKzEpfVxleHBcbGVmdFx7LVxmcmFje2RfMH17XHNpZ21hXjJ9XHJpZ2h0XH1ccmlnaHRdLgokJAoKIyBQb3N0ZXJpb3IgZGlzdHJpYnV0aW9uClRoZSBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uIG9mICQoXGJldGEsXHNpZ21hXjIpJCAKJCQKcChcYmV0YSxcc2lnbWFeMnxcbWJveHtkYXRhfSkgXHByb3B0byBwKFxiZXRhKXAoXHNpZ21hXjIpTChcYmV0YSxcc2lnbWFeMnxcbWJveHtkYXRhfSksCiQkCmRvZXMgbm90IGJlbG9uZyB0byBhbnkga25vd24gZmFtaWx5IG9mIGJpdmFyaWF0ZSBkaXN0cmlidXRpb25zIGFuZCwgY29uc2VxdWVudGx5LCB0aGVyZSBhcmUgbm90IGNsb3NlZCBmb3JtIGFuc3dlcnMgdG8gcXVlc3Rpb25zIHN1Y2ggYXMgdGhlIGZvbGxvd2luZzoKCiogV2hhdCBpcyAkRShcYmV0YXxcbWJveHtkYXRhfSkkPwoKKiBXaGF0IGlzICRQcihcc2lnbWE+MXxcbWJveHtkYXRhfSkkPwoKIyBHaWJicy1hc3Npc3RlZCBwb3N0ZXJpb3IgaW5mZXJlbmNlClRoZSBHaWJicyBzYW1wbGVyIGlzIGEgTWFya292IENoYWluIE1vbnRlIENhcmxvIChNQ01DKSBzY2hlbWUgdGhhdCBzYW1wbGVzIGZyb20gdGhlIGRpc3RyaWJ1dGlvbiBvZiBpbnRlcmVzdCAoYWthIHRhcmdldCBkaXN0cmlidXRpb24pLCBpbiBvdXIgY2FzZSB0aGUgcG9zdGVyaW9yICRwKFxiZXRhLFxzaWdtYV4yfFxtYm94e2RhdGF9KSQsIGJ5IGl0ZXJhdGl2ZWx5IHNhbXBsaW5nIGZyb20gdGhlIGZ1bGwgY29uZGl0aW9uYWwgZGlzdHJpYnV0aW9uczoKJCQKcChcYmV0YXxcc2lnbWFeMixcbWJveHtkYXRhfSkgXCBcIFwgXG1ib3h7YW5kfSBcIFwgXCAKcChcc2lnbWFeMnxcYmV0YSxcbWJveHtkYXRhfSkuCiQkClRoZSBiZWF1dHkgb2YgdGhlIEdpYmJzIHNhbXBsZXIsIGFuZCB0aGVyZWZvcmUgb2YgYWxsIE1DTUMgc2NoZW1lcywgaXMgdGhhdCBpdCBlc3NlbnRpYWxseSBicmVha3MgZG93biB0aGUgY29tcGxleGljaXR5IG9mIGEgZ2l2ZW4gbW9kZWwgaW50byB0aGUgY29tcGxleGl0aWVzIG9mIHNtYWxsZXIgbW9kZWxzIHdoZXJlIGJsb2NrcyBvZiBwYXJhbWV0ZXJzIGFyZSBrZXB0IGZpeGVkLgoKIyMgJHAoXHNpZ21hXjJ8XGJldGEsXG1ib3h7ZGF0YX0pJApJbiB0aGlzIGZ1bGwgY29uZGl0aW9uYWwgZGlzdHJpYnV0aW9uLCB0aGUgcGFyYW1ldGVyICRcYmV0YSQgaXMgdHJlYXRlZCBhcyBrbm93bi4gIFRoZXJlZm9yZSwgd2UgY291bGQgZGVmaW5lICR6X2kgPSB5X2ktXGJldGEgeF9pJCBhbmQgdGhlIG1vZGVsIGJlY29tZXMKJCQKel8xLFxsZG90cyx6X24gXCBcIGlpZCBcIFwgTigwLFxzaWdtYV4yKS4KJCQKSW4gdGhpcyBjYXNlLAokJApwKFxzaWdtYV4yfHpfMSxcbGRvdHMsel9uKSBccHJvcHRvIChcc2lnbWFeMileey0oY18wKzEpfVxleHBcbGVmdFx7LVxmcmFje2RfMH17XHNpZ21hXjJ9XHJpZ2h0XH0KKFxzaWdtYV4yKV57LW4vMn1cZXhwXGxlZnRcey1cZnJhY3tcc3VtX3tpPTF9Xm4gel9pXjIvMn17XHNpZ21hXjJ9XHJpZ2h0XH0sCiQkCndoaWNoIHJlc2VtYmxlcyBhbiBpbnZlcnNlIGdhbW1hIGRpc3RyaWJ1dGlvbiB3aXRoIGh5cGVycGFyYW1ldGVycwokJApjXzEgPSBjXzArXGZyYWN7bn17Mn0gXCBcIFwgXG1ib3h7YW5kfSBcIFwgXCBkXzEgPSBkXzAgKyBcZnJhY3tcc3VtX3tpPTF9Xm4gel9pXjJ9ezJ9Cj0gZF8wICsgXGZyYWN7XHN1bV97aT0xfV5uICh5X2ktXGJldGEgeF9pKV4yfXsyfSwKJCQKb3IgJFxzaWdtYV4yfFxiZXRhLFxtYm94e2RhdGF9IFxzaW0gSUcoY18xLGRfMSkkLgoKYGBge3J9CnNhbXBsZS5zaWdtYTIgPSBmdW5jdGlvbihiZXRhLGMwLGQwLHkseCl7CiAgYzEgPSBjMCtuLzIKICBkMSA9IGQwK3N1bSgoeS14KmJldGEpXjIpLzIKICByZXR1cm4oMS9yZ2FtbWEoMSxjMSxkMSkpCn0KYGBgCgoKIyMgJHAoXGJldGF8XHNpZ21hXjIsXG1ib3h7ZGF0YX0pJApTaW1pbGFybHksIGFzc3VtaW5nIHRoYXQgJFxzaWdtYV4yJCBpcyBrbm93biwgd2UgaGF2ZSBhIHNpbXBsZXIgbW9kZWwsaS5lLiBhIEdhdXNzaWFuIHJlZ3Jlc3Npb24gbW9kZWwgd2l0aCBhbiB1bmtub3duIHNsb3BlLCAkXGJldGEkLCBidXQga25vd24gcmVzaWR1YWwgdmFyaWFuY2UsICRcc2lnbWFeMiQuICBJbiB0aGlzIGNhc2UsClxiZWdpbntlcW5hcnJheSp9CnAoXGJldGF8XHNpZ21hXjIsXG1ib3h7ZGF0YX0pICZccHJvcHRvJiBcZXhwXHstMC41KFxiZXRhLWJfMCleMi9WXzBcfVxleHBcbGVmdFx7LTAuNVxzdW1fe2k9MX1ebiAoeV9pLVxiZXRhIHhfaSleMi9cc2lnbWFeMlxyaWdodFx9XFwKJlxwcm9wdG8mClxleHBcbGVmdFx7LTAuNVxsZWZ0W1xiZXRhXjIvVl8wLTJcYmV0YSBiXzAvVl8wK1xiZXRhXjJzX3heMi9cc2lnbWFeMiAtMlxiZXRhIHNfe3h5fS9cc2lnbWFeMlxyaWdodF1ccmlnaHRcfVxcCiZccHJvcHRvJiAKXGV4cFxsZWZ0XHstMC41XGxlZnRbXGJldGFeMigxL1ZfMCtzX3heMi9cc2lnbWFeMiktMlxiZXRhKGJfMC9WXzArc197eHl9L1xzaWdtYV4yKSBccmlnaHRdXHJpZ2h0XH0sClxlbmR7ZXFuYXJyYXkqfQp3aGVyZSAkc194XjIgPSBcc3VtX3tpPTF9Xm4geF9pXjIkIGFuZCAkc197eHl9ID0gXHN1bV97aT0xfV5uIHlfaSB4X2kkLiAgSXQgaXMgbm93IGVhc3kgdG8gc2VlIHRoYXQKJCQKXGJldGF8XHNpZ21hXjIsXG1ib3h7ZGF0YX0gXHNpbSBOKGJfMSxWXzEpLAokJAp3aGVyZSAkVl8xPTEvKDEvVl8wK3NfeF4yL1xzaWdtYV4yKSQgYW5kIAokJApiXzEgPSBWXzEoYl8wL1ZfMCtzX3t4eX0vXHNpZ21hXjIpCiQkCmBgYHtyfQpzYW1wbGUuYmV0YSA9IGZ1bmN0aW9uKHNpZ21hMixiMCxWMCxzeDIsc3h5KXsKICBWMSA9IDEvKDEvVjArc3gyL3NpZ21hMikKICBiMSA9IFYxKihiMC9WMCtzeHkvc2lnbWEyKQogIHJldHVybihybm9ybSgxLGIxLHNxcnQoVjEpKSkKfQpgYGAKCiMgVHVybmluZyB0aGUgQmF5ZXNpYW4gY3JhbmsKCiMjIFNpbXVsYXRpbmcgc29tZSBkYXRhCmBgYHtyIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTYsIGZpZy5hbGlnbj0nY2VudGVyJ30KbiA9IDUwCnggPSBydW5pZihuLDAsMykKeSA9IDAuNzUqeCtybm9ybShuKQpwbG90KHgseSkKCnN4MiA9IHN1bSh4XjIpCnN4eSA9IHN1bSh4KnkpCmBgYAoKCiMjIFNldHRpbmcgdXAgdGhlIGh5cGVycGFyYW1ldGVycwpgYGB7ciBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD00LCBmaWcuYWxpZ249J2NlbnRlcid9CmIwID0gMApWMCA9IDkKYzAgPSAxLzIKZDAgPSAxLzIKCnBhcihtZnJvdz1jKDEsMikpCnNpZzIgPSBzZXEoMC4wMDAxLDEwLGxlbmd0aD0xMDAwKQpwbG90KHNpZzIsZGdhbW1hKDEvc2lnMixjMCxkMCkvKHNpZzJeMikseGxhYj1leHByZXNzaW9uKHNpZ21hXjIpLHlsYWI9IlByaW9yIGRlbnNpdHkiLHR5cGU9ImwiKQpiZXRhID0gc2VxKC0xMCwxMCxsZW5ndGg9MTAwMCkKcGxvdChiZXRhLGRub3JtKGJldGEsYjAsc3FydChWMCkpLHhsYWI9ZXhwcmVzc2lvbihiZXRhKSx5bGFiPSJQcmlvciBkZW5zaXR5Iix0eXBlPSJsIikKYGBgCgojIyBTZXR0aW5nIHVwIHRoZSBNQ01DIHNjaGVtZQpgYGB7cn0KYmV0YS5pbml0aWFsID0gMAoKbi5idXJuICA9IDEwMDAKbi5kcmF3cyA9IDEwMDAKc3RlcCAgICA9IDEKbml0ZXIgICA9IG4uYnVybituLmRyYXdzKnN0ZXAKYGBgCgojIyBSdW5uaW5nIHRoZSBHaWJicyBzYW1wbGVyCmBgYHtyfQpiZXRhID0gYmV0YS5pbml0aWFsCmRyYXdzID0gbWF0cml4KDAsbml0ZXIsMikKZm9yIChpdGVyIGluIDE6bml0ZXIpewogIHNpZ21hMiA9IHNhbXBsZS5zaWdtYTIoYmV0YSxjMCxkMCx5LHgpCiAgYmV0YSAgID0gc2FtcGxlLmJldGEoc2lnbWEyLGIwLFYwLHN4MixzeHkpCiAgZHJhd3NbaXRlcixdID0gYyhiZXRhLHNxcnQoc2lnbWEyKSkKfQpgYGAKCiMjIE1DTUMgb3V0cHV0CmBgYHtyIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTYsIGZpZy5hbGlnbj0nY2VudGVyJ30KcGFyKG1mcm93PWMoMiwzKSkKdHMucGxvdChkcmF3c1ssMV0seWxhYj0iIixtYWluPWV4cHJlc3Npb24oYmV0YSkseGxhYj0iSXRlcmF0aW9ucyIpCmFjZihkcmF3c1ssMV0sbWFpbj0iIikKaGlzdChkcmF3c1ssMV0scHJvYj1UUlVFLG1haW49IiIseGxhYj1leHByZXNzaW9uKGJldGEpKQoKdHMucGxvdChkcmF3c1ssMl0seWxhYj0iIixtYWluPWV4cHJlc3Npb24oc2lnbWEpLHhsYWI9Ikl0ZXJhdGlvbnMiKQphY2YoZHJhd3NbLDJdLG1haW49IiIpCmhpc3QoZHJhd3NbLDJdLHByb2I9VFJVRSxtYWluPSIiLHhsYWI9ZXhwcmVzc2lvbihzaWdtYSkpCmBgYAoKIyMgQ29tcGFyaW5nIHByaW9ycyBhbmQgcG9zdGVyaW9ycwpgYGB7ciBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD00LCBmaWcuYWxpZ249J2NlbnRlcid9CmJldGEgPSBzZXEoLTEwLDEwLGxlbmd0aD0xMDAwKQpzaWcyID0gc2VxKDAuMDAwMSwxMCxsZW5ndGg9MTAwMCkKcGFyKG1mcm93PWMoMSwyKSkKcGxvdChkZW5zaXR5KGRyYXdzWywxXSkseGxhYj1leHByZXNzaW9uKGJldGEpLG1haW49IiIseWxhYj0iRGVuc2l0eSIsbHdkPTIpCmxpbmVzKGJldGEsZG5vcm0oYmV0YSxiMCxzcXJ0KFYwKSksY29sPTIsbHdkPTIpCmFibGluZSh2PTAuNzUsY29sPTQsbHdkPTIpCnBsb3QoZGVuc2l0eShkcmF3c1ssMl1eMikseGxhYj1leHByZXNzaW9uKHNpZ21hXjIpLG1haW49IiIseWxhYj0iRGVuc2l0eSIseGxpbT1jKDAsNCksbHdkPTIpCmxpbmVzKHNpZzIsZGdhbW1hKDEvc2lnMixjMCxkMCkvKHNpZzJeMiksY29sPTIsbHdkPTIpCmFibGluZSh2PTEsY29sPTQsbHdkPTIpCmxlZ2VuZCgidG9wcmlnaHQiLGxlZ2VuZD1jKCJQcmlvciIsIlBvc3RlcmlvciIsIlRydWUgdmFsdWUiKSxjb2w9YygyLDEsNCksYnR5PSJuIixsdHk9MSxsd2Q9MikKYGBgCgojIyBXaGF0IGlzICRFKFxiZXRhfFxtYm94e2RhdGF9KSQ/CmBgYHtyfQptZWFuKGRyYXdzWywxXSkKYGBgCgojIyBXaGF0IGlzICRQcihcc2lnbWE+MXxcbWJveHtkYXRhfSkkPwpgYGB7cn0KbWVhbihkcmF3c1ssMl0+MSkKYGBgCg==