In this note we’re going to demonstrate how we can use linear algebra to compute the standard errors of regression coefficients. We’re going to start by defining the variance covariance matrix: We denote a variance covariance matrix of a random variable \(Y\) with \(\mathbb{V}[Y]=\Sigma\) with entries: \[\Sigma_{ij}=\mathbb{C}[y_{i},y_{j}]\] In the cases we have been studying: \[\mathbb{C}[y_{i},y_{i}]=\mathbb{V}[y_{i}]=\sigma^{2}\] \[\begin{align}\mathbb{C}[y_{i},y_{j}]=0 & & \forall & i\not=j\end{align}\] Thus, \(\mathbb{V}[Y]=\sigma^{2}I\)

Variance of a linear combination. A useful matrix algebra result is that \[\mathbb{V}[AY]=A\mathbb{V}[Y]A^{T}\] For example if \(y_{1}\) and \(y_{2}\) are independent, both with variance \(\sigma^{2}\): \[\mathbb{V}[y_{1}+y_{2}]=\mathbb{V}\left\{\begin{pmatrix}1&1\end{pmatrix}\underbrace{\begin{pmatrix}y_{1}\\y_{2}\end{pmatrix}}_{Y}\right\}=\begin{pmatrix}1&1\end{pmatrix}\sigma^{2}I\begin{pmatrix}1\\1\end{pmatrix}\] LSE Standard Errors:

Note that \(\hat{\beta}\) is a linear combination of \(Y\): \[\begin{align}\hat{\beta}&=(X^{T}X)^{-1}X^{T}Y\\ \mathbb{V}[\hat{\beta}]&=\mathbb{V}\{X^{T}X)^{-1}X^{T}Y\}=\\ &=(X^{T}X)^{-1}X^{T}\sigma^{2}I\{(X^{T}X)^{-1}X^{T}\}^{T}=\\ &=\sigma^{2}(X^{T}X)^{-1}X^{T}X(X^{T}X)^{-1}=\\ &=\sigma^{2}(X^{T}X)^{-1}\end{align}\] Linear Combination of Estimates

Commonly we want to compute the standard deviations of a linear estimation of estimates such as

\[\hat{\beta_{1}}-\hat{\beta_{2}}=\begin{pmatrix}0&1&-1&0&...&0\end{pmatrix}\begin{pmatrix}\hat{\beta}_{0}\\ \hat{\beta}_{1}\\ \hat{\beta}_{2}\\ \vdots \\ \hat{\beta}_{p}\end{pmatrix}\] We know how to compute the variance covariance matrix of \(\hat{\beta}\)

The standard approach to writing linear models either assume the \(X\) are fixed or that we are conditioning on them. Thus \(X\beta\) has no variance as the \(X\) is considered fixed. This is why we write \(\mathbb{V}[y_{i}]=\mathbb{V}[e_{i}]=\sigma^{2}\). This can cause confusion in practice because if you, for example, compute the following:

# install.packages("UsingR")
# library(UsingR)
x =  father.son$fheight
beta =  c(34,0.5)
var(beta[1]+beta[2]*x)
[1] 1.883576

it is nowhere near 0. This is an example in which we have to be careful in distinguishing code from math. The function var is simply computing the variance of the list we feed it, while the mathematical use of var is considering only quantities that are random variables. In the R code above \(x\) is not fixed at all: we are letting it vary but when we write \(\mathbb{V}[y_{i}]=\sigma^{2}\) we are imposing, mathematically, \(x\) to be fixed. Similarly if we use R to compute the variance of \(Y\) in our object dropping example we obtain something very different than \(\sigma^{2}=1\) (the known variance):

g <- 9.8 
h.0 <- 56.67
v.0 <- 0
N <- 25
tt <- seq(0,3.4,len=N)
y = h.0 + v.0*tt  - 0.5*g*tt^2 + rnorm(N,sd=1)
var(y)
[1] 314.3813

Again, this is because we are not fixing tt.

Exercises:

In the previous assessment, we used a Monte Carlo technique to see that the linear model coefficients are random variables when the data is a random sample. Now we will use the matrix algebra from the previous lesson to try to estimate the standard error of the linear model coefficients. Again, take a random sample of the father.son heights data:

#library(UsingR)
x <- father.son$fheight
y <- father.son$sheight
n <- length(y)
N <- 50
set.seed(1)
index <- sample(n,N) #Sample function gives a sample of N values in n.
sampledat <- father.son[index,]
x.s <- sampledat$fheight
y.s <- sampledat$sheight
beta.hat <- lm(y.s~x.s)$coef

The formula for the standard error in the previous lesson was

\[\begin{align} SE(\hat{\beta})&=\sqrt{\mathbb{V}(\hat{\beta})}\\ \mathbb{V}(\hat{\beta})&=\sigma^{2}(X^{T}X)^{-1} \end{align}\] We will estimate or calculate each part of this equation and then combine them.

First, we want to estimate \(\sigma^{2}\), the variance of \(Y\). As we have seen in the previous unit, the random part of \(Y\) only come from \(\varepsilon\) because we assume \(X\beta\) is fixed. So we can try to estimate the variance of the epsilons from the residuals, the \(Y\) minus the fitted values from the linear model.

Standard Errors Exercises #1

Note that the fitted values \(\hat{Y}\) from a linear model can be obtained with:

fit <- lm(y.s ~ x.s) # Estimates parameters for a given model from a set of data.
fit$fitted.values
       1        2        3        4        5        6        7        8        9 
69.27033 68.11931 69.09869 68.52856 66.48068 68.01818 67.79780 68.20419 68.04929 
      10       11       12       13       14       15       16       17       18 
68.50890 67.59336 67.40100 67.71831 66.27646 68.48256 67.80804 69.25742 69.11139 
      19       20       21       22       23       24       25       26       27 
68.76791 67.57585 66.65584 68.72140 67.55598 69.01422 68.62526 67.33597 68.92766 
      28       29       30       31       32       33       34       35       36 
68.94045 66.37204 66.58197 67.63505 68.03238 67.87915 69.69109 68.03458 68.47743 
      37       38       39       40       41       42       43       44       45 
68.71055 67.38635 68.88510 69.01250 68.61522 68.27404 69.71375 68.47982 70.01991 
      46       47       48       49       50 
67.87682 68.33042 67.88145 70.01590 68.81012 

What is the sum of the squared residuals (where residuals are given by \(r_{i}=y_{i}-\hat{y}_{i}\)?

y.hat<-fit$fitted.values
r<-y.s-y.hat
SSR<-t(r)%*%r
SSR
         [,1]
[1,] 331.2952

Our estimate of \(\sigma^{2}\) will be the sum of squared residuals divided by \((N-p)\) ), the sample size minus the number of terms in the model. Since we have a sample of 50 and 2 terms in the model (an intercept and a slope), our estimate of \(\sigma^{2}\) will be the sum of squared residuals divided by 48 Save this to a variable sigma2:

sigma2 <- SSR / 48
sigma2
         [,1]
[1,] 6.901984

where SSR is the answer to the previous question.

Standard Errors Exercises #2

Form the design matrix \(X\) (note: use a capital \(X\)!). This can be done by combining a column of 1’s with a column of \(x\) the father’s heights.

X <- cbind(rep(1,N), x.s)

Now calculate \((X^{T}X)^{-1}\) the inverse of \(X\) transpose times \(X\) use the solve() function to the inverse and t() for transpose. What is the element in the first row, first column?

Var.X<-solve(t(X)%*%X)
Var.X[1,1]
[1] 14.5639

Standard Errors Exercises #3

Now we are one step away from the standard error of \(\hat{\beta}\). Take the diagonals from \((X^{T}X)^{-1}\) the matrix above, using the diag() function. Now multiply our estimate of \(\sigma^{2}\) and the diagonals of this matrix. This is the estimated variance of \(\hat{\beta}\) so take the square root of this. You should end up with two numbers, the standard error for the intercept and the standard error for the slope.

What is the standard error for the slope?

diagonal<-diag(Var.X)
diagonal
                      x.s 
14.563903878  0.003169572 
sqrt(diagonal[2]*sigma2)
          [,1]
[1,] 0.1479065
LS0tCnRpdGxlOiAiSU5GRVJFTkNFIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpJbiB0aGlzIG5vdGUgd2UncmUgZ29pbmcgdG8gZGVtb25zdHJhdGUgaG93IHdlIGNhbiB1c2UgbGluZWFyIGFsZ2VicmEgdG8gY29tcHV0ZSB0aGUgc3RhbmRhcmQgZXJyb3JzIG9mIHJlZ3Jlc3Npb24gY29lZmZpY2llbnRzLiBXZSdyZSBnb2luZyB0byBzdGFydCBieSBkZWZpbmluZyB0aGUgdmFyaWFuY2UgY292YXJpYW5jZSBtYXRyaXg6CldlIGRlbm90ZSBhIHZhcmlhbmNlIGNvdmFyaWFuY2UgbWF0cml4IG9mIGEgcmFuZG9tIHZhcmlhYmxlICRZJCB3aXRoICRcbWF0aGJie1Z9W1ldPVxTaWdtYSQgd2l0aCBlbnRyaWVzOgokJFxTaWdtYV97aWp9PVxtYXRoYmJ7Q31beV97aX0seV97an1dJCQKSW4gdGhlIGNhc2VzIHdlIGhhdmUgYmVlbiBzdHVkeWluZzoKJCRcbWF0aGJie0N9W3lfe2l9LHlfe2l9XT1cbWF0aGJie1Z9W3lfe2l9XT1cc2lnbWFeezJ9JCQKJCRcYmVnaW57YWxpZ259XG1hdGhiYntDfVt5X3tpfSx5X3tqfV09MCAmICYgXGZvcmFsbCAmIGlcbm90PWpcZW5ke2FsaWdufSQkClRodXMsICRcbWF0aGJie1Z9W1ldPVxzaWdtYV57Mn1JJAoKVmFyaWFuY2Ugb2YgYSBsaW5lYXIgY29tYmluYXRpb24uCkEgdXNlZnVsIG1hdHJpeCBhbGdlYnJhIHJlc3VsdCBpcyB0aGF0CiQkXG1hdGhiYntWfVtBWV09QVxtYXRoYmJ7Vn1bWV1BXntUfSQkCkZvciBleGFtcGxlIGlmICR5X3sxfSQgYW5kICR5X3syfSQgYXJlIGluZGVwZW5kZW50LCBib3RoIHdpdGggdmFyaWFuY2UgJFxzaWdtYV57Mn0kOgokJFxtYXRoYmJ7Vn1beV97MX0reV97Mn1dPVxtYXRoYmJ7Vn1cbGVmdFx7XGJlZ2lue3BtYXRyaXh9MSYxXGVuZHtwbWF0cml4fVx1bmRlcmJyYWNle1xiZWdpbntwbWF0cml4fXlfezF9XFx5X3syfVxlbmR7cG1hdHJpeH19X3tZfVxyaWdodFx9PVxiZWdpbntwbWF0cml4fTEmMVxlbmR7cG1hdHJpeH1cc2lnbWFeezJ9SVxiZWdpbntwbWF0cml4fTFcXDFcZW5ke3BtYXRyaXh9JCQKTFNFIFN0YW5kYXJkIEVycm9yczoKCk5vdGUgdGhhdCAkXGhhdHtcYmV0YX0kIGlzIGEgbGluZWFyIGNvbWJpbmF0aW9uIG9mICRZJDoKJCRcYmVnaW57YWxpZ259XGhhdHtcYmV0YX0mPShYXntUfVgpXnstMX1YXntUfVlcXCBcbWF0aGJie1Z9W1xoYXR7XGJldGF9XSY9XG1hdGhiYntWfVx7WF57VH1YKV57LTF9WF57VH1ZXH09XFwgJj0oWF57VH1YKV57LTF9WF57VH1cc2lnbWFeezJ9SVx7KFhee1R9WCleey0xfVhee1R9XH1ee1R9PVxcICY9XHNpZ21hXnsyfShYXntUfVgpXnstMX1YXntUfVgoWF57VH1YKV57LTF9PVxcICY9XHNpZ21hXnsyfShYXntUfVgpXnstMX1cZW5ke2FsaWdufSQkCkxpbmVhciBDb21iaW5hdGlvbiBvZiBFc3RpbWF0ZXMKCkNvbW1vbmx5IHdlIHdhbnQgdG8gY29tcHV0ZSB0aGUgc3RhbmRhcmQgZGV2aWF0aW9ucyBvZiBhIGxpbmVhciBlc3RpbWF0aW9uIG9mIGVzdGltYXRlcyBzdWNoIGFzCgokJFxoYXR7XGJldGFfezF9fS1caGF0e1xiZXRhX3syfX09XGJlZ2lue3BtYXRyaXh9MCYxJi0xJjAmLi4uJjBcZW5ke3BtYXRyaXh9XGJlZ2lue3BtYXRyaXh9XGhhdHtcYmV0YX1fezB9XFwgXGhhdHtcYmV0YX1fezF9XFwgXGhhdHtcYmV0YX1fezJ9XFwgXHZkb3RzIFxcIFxoYXR7XGJldGF9X3twfVxlbmR7cG1hdHJpeH0kJApXZSBrbm93IGhvdyB0byBjb21wdXRlIHRoZSB2YXJpYW5jZSBjb3ZhcmlhbmNlIG1hdHJpeCBvZiAkXGhhdHtcYmV0YX0kCgpUaGUgc3RhbmRhcmQgYXBwcm9hY2ggdG8gd3JpdGluZyBsaW5lYXIgbW9kZWxzIGVpdGhlciBhc3N1bWUgdGhlICRYJCBhcmUgZml4ZWQgb3IgdGhhdCB3ZSBhcmUgY29uZGl0aW9uaW5nIG9uIHRoZW0uIFRodXMgJFhcYmV0YSQgaGFzIG5vIHZhcmlhbmNlIGFzIHRoZSAkWCQgaXMgY29uc2lkZXJlZCBmaXhlZC4gVGhpcyBpcyB3aHkgd2Ugd3JpdGUgJFxtYXRoYmJ7Vn1beV97aX1dPVxtYXRoYmJ7Vn1bZV97aX1dPVxzaWdtYV57Mn0kLiBUaGlzIGNhbiBjYXVzZSBjb25mdXNpb24gaW4gcHJhY3RpY2UgYmVjYXVzZSBpZiB5b3UsIGZvciBleGFtcGxlLCBjb21wdXRlIHRoZSBmb2xsb3dpbmc6CgpgYGB7cn0KIyBpbnN0YWxsLnBhY2thZ2VzKCJVc2luZ1IiKQojIGxpYnJhcnkoVXNpbmdSKQp4ID0gIGZhdGhlci5zb24kZmhlaWdodApiZXRhID0gIGMoMzQsMC41KQp2YXIoYmV0YVsxXStiZXRhWzJdKngpCmBgYAppdCBpcyBub3doZXJlIG5lYXIgMC4gVGhpcyBpcyBhbiBleGFtcGxlIGluIHdoaWNoIHdlIGhhdmUgdG8gYmUgY2FyZWZ1bCBpbiBkaXN0aW5ndWlzaGluZyBjb2RlIGZyb20gbWF0aC4gVGhlIGZ1bmN0aW9uIHZhciBpcyBzaW1wbHkgY29tcHV0aW5nIHRoZSB2YXJpYW5jZSBvZiB0aGUgbGlzdCB3ZSBmZWVkIGl0LCB3aGlsZSB0aGUgbWF0aGVtYXRpY2FsIHVzZSBvZiB2YXIgaXMgY29uc2lkZXJpbmcgb25seSBxdWFudGl0aWVzIHRoYXQgYXJlIHJhbmRvbSB2YXJpYWJsZXMuIEluIHRoZSBSIGNvZGUgYWJvdmUgJHgkIGlzIG5vdCBmaXhlZCBhdCBhbGw6IHdlIGFyZSBsZXR0aW5nIGl0IHZhcnkgYnV0IHdoZW4gd2Ugd3JpdGUgJFxtYXRoYmJ7Vn1beV97aX1dPVxzaWdtYV57Mn0kIHdlIGFyZSBpbXBvc2luZywgbWF0aGVtYXRpY2FsbHksICR4JCB0byBiZSBmaXhlZC4gU2ltaWxhcmx5IGlmIHdlIHVzZSBSIHRvIGNvbXB1dGUgdGhlIHZhcmlhbmNlIG9mICRZJCBpbiBvdXIgb2JqZWN0IGRyb3BwaW5nIGV4YW1wbGUgd2Ugb2J0YWluIHNvbWV0aGluZyB2ZXJ5IGRpZmZlcmVudCB0aGFuICRcc2lnbWFeezJ9PTEkICh0aGUga25vd24gdmFyaWFuY2UpOgpgYGB7cn0KZyA8LSA5LjggCmguMCA8LSA1Ni42Nwp2LjAgPC0gMApOIDwtIDI1CnR0IDwtIHNlcSgwLDMuNCxsZW49TikKeSA9IGguMCArIHYuMCp0dCAgLSAwLjUqZyp0dF4yICsgcm5vcm0oTixzZD0xKQp2YXIoeSkKYGBgCkFnYWluLCB0aGlzIGlzIGJlY2F1c2Ugd2UgYXJlIG5vdCBmaXhpbmcgdHQuCgoKRXhlcmNpc2VzOgoKSW4gdGhlIHByZXZpb3VzIGFzc2Vzc21lbnQsIHdlIHVzZWQgYSBNb250ZSBDYXJsbyB0ZWNobmlxdWUgdG8gc2VlIHRoYXQgdGhlIGxpbmVhciBtb2RlbCBjb2VmZmljaWVudHMgYXJlIHJhbmRvbSB2YXJpYWJsZXMgd2hlbiB0aGUgZGF0YSBpcyBhIHJhbmRvbSBzYW1wbGUuIE5vdyB3ZSB3aWxsIHVzZSB0aGUgbWF0cml4IGFsZ2VicmEgZnJvbSB0aGUgcHJldmlvdXMgbGVzc29uIHRvIHRyeSB0byBlc3RpbWF0ZSB0aGUgc3RhbmRhcmQgZXJyb3Igb2YgdGhlIGxpbmVhciBtb2RlbCBjb2VmZmljaWVudHMuIEFnYWluLCB0YWtlIGEgcmFuZG9tIHNhbXBsZSBvZiB0aGUgZmF0aGVyLnNvbiBoZWlnaHRzIGRhdGE6CgpgYGB7cn0KI2xpYnJhcnkoVXNpbmdSKQp4IDwtIGZhdGhlci5zb24kZmhlaWdodAp5IDwtIGZhdGhlci5zb24kc2hlaWdodApuIDwtIGxlbmd0aCh5KQpOIDwtIDUwCnNldC5zZWVkKDEpCmluZGV4IDwtIHNhbXBsZShuLE4pICNTYW1wbGUgZnVuY3Rpb24gZ2l2ZXMgYSBzYW1wbGUgb2YgTiB2YWx1ZXMgaW4gbi4Kc2FtcGxlZGF0IDwtIGZhdGhlci5zb25baW5kZXgsXQp4LnMgPC0gc2FtcGxlZGF0JGZoZWlnaHQKeS5zIDwtIHNhbXBsZWRhdCRzaGVpZ2h0CmJldGEuaGF0IDwtIGxtKHkuc354LnMpJGNvZWYKYGBgCgpUaGUgZm9ybXVsYSBmb3IgdGhlIHN0YW5kYXJkIGVycm9yIGluIHRoZSBwcmV2aW91cyBsZXNzb24gd2FzCgokJFxiZWdpbnthbGlnbn0gIFNFKFxoYXR7XGJldGF9KSY9XHNxcnR7XG1hdGhiYntWfShcaGF0e1xiZXRhfSl9XFwgIFxtYXRoYmJ7Vn0oXGhhdHtcYmV0YX0pJj1cc2lnbWFeezJ9KFhee1R9WCleey0xfSBcZW5ke2FsaWdufSQkCldlIHdpbGwgZXN0aW1hdGUgb3IgY2FsY3VsYXRlIGVhY2ggcGFydCBvZiB0aGlzIGVxdWF0aW9uIGFuZCB0aGVuIGNvbWJpbmUgdGhlbS4KCkZpcnN0LCB3ZSB3YW50IHRvIGVzdGltYXRlICRcc2lnbWFeezJ9JCwgdGhlIHZhcmlhbmNlIG9mICRZJC4gQXMgd2UgaGF2ZSBzZWVuIGluIHRoZSBwcmV2aW91cyB1bml0LCB0aGUgcmFuZG9tIHBhcnQgb2YgJFkkIG9ubHkgY29tZSBmcm9tICRcdmFyZXBzaWxvbiQgYmVjYXVzZSB3ZSBhc3N1bWUgJFhcYmV0YSQgaXMgZml4ZWQuIFNvIHdlIGNhbiB0cnkgdG8gZXN0aW1hdGUgdGhlIHZhcmlhbmNlIG9mIHRoZSBlcHNpbG9ucyBmcm9tIHRoZSByZXNpZHVhbHMsIHRoZSAkWSQgbWludXMgdGhlIGZpdHRlZCB2YWx1ZXMgZnJvbSB0aGUgbGluZWFyIG1vZGVsLgoKU3RhbmRhcmQgRXJyb3JzIEV4ZXJjaXNlcyAjMQoKTm90ZSB0aGF0IHRoZSBmaXR0ZWQgdmFsdWVzICRcaGF0e1l9JCBmcm9tIGEgbGluZWFyIG1vZGVsIGNhbiBiZSBvYnRhaW5lZCB3aXRoOgoKYGBge3J9CmZpdCA8LSBsbSh5LnMgfiB4LnMpICMgRXN0aW1hdGVzIHBhcmFtZXRlcnMgZm9yIGEgZ2l2ZW4gbW9kZWwgZnJvbSBhIHNldCBvZiBkYXRhLgpmaXQkZml0dGVkLnZhbHVlcwpgYGAKV2hhdCBpcyB0aGUgc3VtIG9mIHRoZSBzcXVhcmVkIHJlc2lkdWFscyAod2hlcmUgcmVzaWR1YWxzIGFyZSBnaXZlbiBieSAkcl97aX09eV97aX0tXGhhdHt5fV97aX0kPwoKYGBge3J9CnkuaGF0PC1maXQkZml0dGVkLnZhbHVlcwpyPC15LnMteS5oYXQKU1NSPC10KHIpJSolcgpTU1IKYGBgCk91ciBlc3RpbWF0ZSBvZiAkXHNpZ21hXnsyfSQgd2lsbCBiZSB0aGUgc3VtIG9mIHNxdWFyZWQgcmVzaWR1YWxzIGRpdmlkZWQgYnkgJChOLXApJCApLCB0aGUgc2FtcGxlIHNpemUgbWludXMgdGhlIG51bWJlciBvZiB0ZXJtcyBpbiB0aGUgbW9kZWwuIFNpbmNlIHdlIGhhdmUgYSBzYW1wbGUgb2YgNTAgYW5kIDIgdGVybXMgaW4gdGhlIG1vZGVsIChhbiBpbnRlcmNlcHQgYW5kIGEgc2xvcGUpLCBvdXIgZXN0aW1hdGUgb2YgJFxzaWdtYV57Mn0kIHdpbGwgYmUgdGhlIHN1bSBvZiBzcXVhcmVkIHJlc2lkdWFscyBkaXZpZGVkIGJ5IDQ4IFNhdmUgdGhpcyB0byBhIHZhcmlhYmxlIHNpZ21hMjoKYGBge3J9CnNpZ21hMiA8LSBTU1IgLyA0OApzaWdtYTIKYGBgCndoZXJlIFNTUiBpcyB0aGUgYW5zd2VyIHRvIHRoZSBwcmV2aW91cyBxdWVzdGlvbi4KClN0YW5kYXJkIEVycm9ycyBFeGVyY2lzZXMgIzIKCkZvcm0gdGhlIGRlc2lnbiBtYXRyaXggJFgkICAobm90ZTogdXNlIGEgY2FwaXRhbCAkWCQhKS4gVGhpcyBjYW4gYmUgZG9uZSBieSBjb21iaW5pbmcgYSBjb2x1bW4gb2YgMSdzIHdpdGggYSBjb2x1bW4gb2YgJHgkIHRoZSBmYXRoZXIncyBoZWlnaHRzLgoKYGBge3J9ClggPC0gY2JpbmQocmVwKDEsTiksIHgucykKYGBgCgpOb3cgY2FsY3VsYXRlICQoWF57VH1YKV57LTF9JCB0aGUgaW52ZXJzZSBvZiAkWCQgdHJhbnNwb3NlIHRpbWVzICRYJCB1c2UgdGhlIHNvbHZlKCkgZnVuY3Rpb24gdG8gdGhlIGludmVyc2UgYW5kIHQoKSBmb3IgdHJhbnNwb3NlLiBXaGF0IGlzIHRoZSBlbGVtZW50IGluIHRoZSBmaXJzdCByb3csIGZpcnN0IGNvbHVtbj8KYGBge3J9ClZhci5YPC1zb2x2ZSh0KFgpJSolWCkKVmFyLlhbMSwxXQpgYGAKClN0YW5kYXJkIEVycm9ycyBFeGVyY2lzZXMgIzMKCk5vdyB3ZSBhcmUgb25lIHN0ZXAgYXdheSBmcm9tIHRoZSBzdGFuZGFyZCBlcnJvciBvZiAkXGhhdHtcYmV0YX0kLiBUYWtlIHRoZSBkaWFnb25hbHMgZnJvbSAgJChYXntUfVgpXnstMX0kICB0aGUgbWF0cml4IGFib3ZlLCB1c2luZyB0aGUgZGlhZygpIGZ1bmN0aW9uLiBOb3cgbXVsdGlwbHkgb3VyIGVzdGltYXRlIG9mICRcc2lnbWFeezJ9JCAgYW5kIHRoZSBkaWFnb25hbHMgb2YgdGhpcyBtYXRyaXguIFRoaXMgaXMgdGhlIGVzdGltYXRlZCB2YXJpYW5jZSBvZiAkXGhhdHtcYmV0YX0kIHNvIHRha2UgdGhlIHNxdWFyZSByb290IG9mIHRoaXMuIFlvdSBzaG91bGQgZW5kIHVwIHdpdGggdHdvIG51bWJlcnMsIHRoZSBzdGFuZGFyZCBlcnJvciBmb3IgdGhlIGludGVyY2VwdCBhbmQgdGhlIHN0YW5kYXJkIGVycm9yIGZvciB0aGUgc2xvcGUuCgpXaGF0IGlzIHRoZSBzdGFuZGFyZCBlcnJvciBmb3IgdGhlIHNsb3BlPwoKYGBge3J9CmRpYWdvbmFsPC1kaWFnKFZhci5YKQpkaWFnb25hbApzcXJ0KGRpYWdvbmFsWzJdKnNpZ21hMikKYGBgCgoKCgoKCgoKCgoKCgoKCg==