Fitting the model
Since the \(\beta\)’s are unknown population
parameters, we need to estimate them using the sample data. So how do
formulate their estimators?
\[\hat{\beta}_0 = b_0\]
\[\hat{\beta}_1 = b_1\]
The sample model is:
\[\hat{y}_i = b_0 + b_1 x_i\]
and
\[y_i = b_0 + b_1 x_i + e_i\]
where \(e_i\) is called the
residual, which is a prediction of the random error,
\(\varepsilon\):
\[\hat{\varepsilon}_i = e_i\]
We calculate the residual using the difference between the observed
value, \(y_i\), and the estimated
value, \(\hat{y}_i\):
\[e_i = y_i - \hat{y}_i\]
What is the best fitting line?
Estimating the line:
We can add the line of best fit to the scatterplot
created earlier (gg_cats) by adding
geom_smooth(method = 'lm'):
gg_cats_SLR <-
gg_cats +
geom_smooth(
method = 'lm',
formula = y ~ x,
se = F, # This removes a confidence band we'll look at later
color = 'orchid'
)
gg_cats_SLR

The red line above uses the sample model:
\[\hat{y}_i = b_0 + b_1 x_i\]
How do we find that line? That is to say, what are the estimators for
\(b_0\) and \(b_1\)?
Since we’ll be using the line of best fit for the remainder of the
script, let’s find \((b_0, b_1)\) and
discuss how they’re calculated.
The lm() function
Most functions in R that create a model use a
formula type object to define the explanatory and response
variables. The lm() function (short for linear
model) is no exception!
The code chunk below will fit the SLR model for us:
cats_lm <- lm(formula = Hwt ~ Bwt, data = cats)
cats_lm
##
## Call:
## lm(formula = Hwt ~ Bwt, data = cats)
##
## Coefficients:
## (Intercept) Bwt
## -0.3567 4.0341
The formula is coded as response ~ explanatory, which
reads as ‘The response variable by the explanatory variable’,
or Heart Weight by Body Weight.
The intercept is \(b_0 = -0.36\) and
\(b_1 = 4.03\). Why are those the
‘best’?
Which line is the best line?
Why is the purple line better than the added red line below?
gg_cats_SLR +
# Adding an arbitrary line:
geom_abline(
slope = 3,
intercept = mean(cats$Hwt) - 3*mean(cats$Bwt),
color = 'red',
linetype = 'dashed',
linewidth = 1
)

Visually we can tell that the red line is better than the blue line.
But how do we show that, statistically speaking?
We define some criteria that the line needs to meet to be the ‘best
line’:
- The predicted value of \(Y\) when
\(X\) is at the mean is the mean of
\(Y\):
\[\bar{y} = b_0 + b_1 \bar{x}
\]
or, in other words, the line must pass through the coordinate \((\bar{x}, \bar{y})\):
gg_cats_SLR +
# Adding an arbitrary line:
geom_abline(
slope = 3,
intercept = mean(cats$Hwt) - 3*mean(cats$Bwt),
color = 'red',
linetype = 'dashed',
linewidth = 1
) +
# Adding the 'center' of the plot
geom_vline(
mapping = aes(xintercept = mean(Bwt)),
linewidth = 1,
color = 'orange'
) +
geom_hline(
mapping = aes(yintercept = mean(Hwt)),
linewidth = 1,
color = 'steelblue'
)

Both the red and purple line pass through \((\bar{x}, \bar{y})\), so what other
criteria does the best line need to meet?
We want the line to be as close as possible to the points in the
data. One initially obvious choice is to try to minimize the
average residual, the vertical distance a point is from the
line:
# Creating a sample to calculate the residuals:
cats_res_sample <-
cats |>
slice(c(3, 40, 100, 130, 144))
# Adding the predicted heart weight:
cats_res_sample$Hwt_hat <- predict(cats_lm, newdata = cats_res_sample)
cats_res_sample
## Sex Bwt Hwt Hwt_hat
## 1 F 2.0 9.5 7.711463
## 2 F 2.7 8.5 10.535307
## 3 M 3.0 10.0 11.745526
## 4 M 3.4 14.4 13.359151
## 5 M 3.9 20.5 15.376182
# Visualizing the residuals for the 5 sample cats
ggplot(
data = cats_res_sample,
mapping = aes(
x = Bwt,
y = Hwt
)
) +
# Adding the 'center' of the plot
geom_vline(
data = cats,
mapping = aes(xintercept = mean(Bwt)),
linewidth = 1,
color = 'orange'
) +
geom_hline(
data = cats,
mapping = aes(yintercept = mean(Hwt)),
linewidth = 1,
color = 'steelblue'
) +
geom_segment(
mapping = aes(
xend = Bwt,
yend = Hwt_hat
),
linewidth = 1,
color = 'orchid',
linetype = 'dashed'
) +
geom_smooth(
data = cats,
se = F,
method = 'lm',
formula = y ~ x,
color = 'orchid'
) +
geom_point(size = 3)

Let’s calculate the average residual for our best fitting
line. You can ‘extract’ the residuals using cats_lm$res
round(cats_lm$residuals[1:10], 3)
## 1 2 3 4 5 6 7 8 9 10
## -0.711 -0.311 1.789 -0.915 -0.815 -0.515 -0.015 0.085 0.185 0.385
Let’s calculate the mean of the residuals, \(\bar{e}\):
mean(cats_lm$residuals)
## [1] -3.58901e-17
which is computationally 0.
How about our other line? What is the average residual of the red
line:
\[\widetilde{Hwt} = 2.46 + 3 \times
Bwt\]
Note: We use \(\widetilde{Hwt}\) to indicate that it is
different that the predicted heart weight from the best model, \(\widehat{Hwt}\)
cats |>
# Adding the predicted heart weight using the red line and the residual
mutate(
hwt_pred = mean(Hwt) - 3*mean(Bwt) + 3 * Bwt,
hwt_res = Hwt - hwt_pred
) |>
# Averaging the residuals:
summarize(
res_avg = mean(hwt_res)
)
## res_avg
## 1 -1.782109e-15
which is also computationally 0! So both lines have an average
residual of 0, therefore using that criteria would indicate that both
are equally good, despite what our eyes told us earlier.
In fact, any line that passes through \((\bar{x}, \bar{y})\) will have an average
residual of 0. That sounds weird at first, but you can demonstrate it
mathematically:
If a line passes through \((\bar{x},
\bar{y})\), then for any slope, \(b_1\),
\[b_0 = \bar{y} - b_1\bar{x}\]
which gives us the residual as:
\[e_i = y - (\bar{y} - b_1\bar{x} +
b_1x_i) \]
\[e_i = (y - \bar{y}) - b_1(x_i -
\bar{x})\]
Instead, we minimize the sum (or mean) of the squared
residuals!
The Sums of Squares Criterion and the Normal Equations
First, we’ll define the function \(Q\):
\[Q = \sum_{i = 1}^n [Y_i - (\beta_0 -
\beta_1X_i)]^2\]
We want to find the values of \((\beta_0,
\beta_1)\) that minimize \(Q\)!
Let’s compare the two models we have so far:
cats |>
# Adding the predicted heart weight using the red line and the residual
mutate(
hwt_hat = cats_lm$fit, # Preds from the best line
hwt_pred = mean(Hwt) - 3*mean(Bwt) + 3 * Bwt # Preds from other line
) |>
# Averaging the residuals:
summarize(
best_SSE = sum((Hwt - hwt_hat)^2),
not_as_good_SSE = sum((Hwt - hwt_pred)^2)
)
## best_SSE not_as_good_SSE
## 1 299.5331 335.5464
Notice that the sums of the squares of the residuals is smaller!
How do we find the values that minimize \(Q\)? Do we try every combination possible
and keep the one that makes the sums of squares the smallest?
While we theoretically could, there is a much more efficient way to
do that: calculus!
We’ll do the math on the board, but we can take the derivative of
\(Q\) with respect to the two \(\beta\)’s individually:
\[\frac{\partial Q}{\partial \beta_0} =
\sum_{i = 1}^n (-2)(Y_i - \beta_0 - \beta_1 X_i) \]
\[\frac{\partial Q}{\partial \beta_1} =
\sum_{i = 1}^n (-2X_i)(Y_i - \beta_0 - \beta_1 X_i) \]
To find the values of \((\beta_0,
\beta_1)\) that minimize Q, we take the partial derivatives, set
them equal to 0, then do a little simplification, we can create what we
call The Normal Equations:
\[\sum_{i = 1}^n (Y_i - b_0 - b_1 X_i) =
0\]
\[\sum_{i = 1}^n (Y_i - b_0 - b_1 X_i)X_i
= 0\]
We can solve the system of the Normal Equations to find the
estimators of our model parameters:
\[b_1 = \frac{\sum_{i = 1}^n(X_i -
\bar{X})(Y_i - \bar{Y})}{\sum_{i = 1}^n(X_i - \bar{X})^2}=
\frac{S_{XY}}{S_{XX}}\] where \(S_{XY}\) is the estimated covariance
between \(X, Y\) and \(S_{XX}\) is the estimated variance of \(X\)
and
\[b_0 = \bar{Y} - b_1\bar{X}\]
There are a couple of alternative ways we can write \(b_1\) that are easier to work with:
- \[b_1 = \frac{(\sum_{i = 1}^n X_iY_i) -
n\bar{X}\bar{Y}}{(\sum_{i = 1}^n X_i^2) - n\bar{X}^2}\]
which is often easier to use when calculating expected values and
variances of the estimates, which we’ll do later!
- \[b_1 = r\frac{s_Y}{s_X}\]
where \(r\) is the correlation
between \(X, Y\), \(s_X\) is the estimated standard deviation
of \(X\), and the same for \(Y\)
The fitted model:
Now that we have the functions for how to calculate \(b_0\) and \(b_1\), we can write our model as:
\[\hat{Y_i} = \bar{Y} +
r\frac{s_Y}{s_X}(X_i - \bar{X})\]
Calculating the estimates ‘by hand’
Next, let’s calculate the estimates, \(b_0\) and \(b_1\) using the equations above
cats |>
mutate(
dev_x = Bwt - mean(Bwt), # X - X_bar
dev_y = Hwt - mean(Hwt) # Y - Y_bar
) |>
# Calculating b1 and b0
summarize(
# Slope using the 'raw' data
b1_manual1 = sum(dev_x * dev_y) / sum(dev_x^2),
b1_manual2 = (sum(Bwt*Hwt) - n() * mean(Bwt)*mean(Hwt))/(sum(Bwt^2) - n() * mean(Bwt)^2),
b1_formula1 = cov(Bwt, Hwt) / var(Bwt), # S_XY / S_XX
b1_formula2 = cor(Bwt, Hwt) * sd(Hwt) / sd(Bwt), # r (s_Y / s_X)
# Calculating b0
b0_manual = mean(Hwt) - b1_manual1 * mean(Bwt)
)
## b1_manual1 b1_manual2 b1_formula1 b1_formula2 b0_manual
## 1 4.034063 4.034063 4.034063 4.034063 -0.3566624
and we can compare it to the estimates from lm() using
cats_lm$coef:
cats_lm$coef
## (Intercept) Bwt
## -0.3566624 4.0340627
They’re the same!
LS0tDQp0aXRsZTogJ0ludHJvZHVjdGlvbjogRml0dGluZyB0aGUgTGluZWFyIE1vZGVsIC0gQ2F0cyBleGFtcGxlJw0KYXV0aG9yOiAiQ2hhcHRlciAxIg0KZGF0ZTogIlNUQSA0MjEwIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGZpZ193aWR0aDogOA0KICAgIGZpZ19oZWlnaHQ6IDYNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiBubw0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIHNtb290aF9zY3JvbGw6IHllcw0KICAgIHRoZW1lOiBsdW1lbg0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgICAgIGZpZy5hbGlnbiA9ICdjZW50ZXInKQ0Kc2V0LnNlZWQoNDIxMCkNCiMgTG9hZGluZyBwYWNrYWdlcw0KbGlicmFyeSh0aWR5dmVyc2UpDQoNCiMgU2V0dGluZyB0aGUgZGVmYXVsdCB0aGVtZSB0byB0aGVtZV9idygpDQp0aGVtZV9zZXQodGhlbWVfYncoKSkNCmBgYA0KDQpMb2FkaW5nIHRoZSBkYXRhIGZyb20gdGhlIGBNQVNTYCBwYWNrYWdlDQoNCmBgYHtyfQ0KIyBHZXR0aW5nIHRoZSBkYXRhDQpjYXRzIDwtIE1BU1M6OmNhdHMNCmBgYA0KDQojIyBQbG90dGluZyB0aGUgZGF0YQ0KDQpBbnkgZ29vZCBleGFtaW5hdGlvbiBzdGFydHMgd2l0aCBleHBsb3JhdG9yeSBkYXRhIGFuYWx5c2lzLiBMZXQncyBjcmVhdGUgdGhlIHNjYXR0ZXJwbG90IGJldHdlZW4gYm9keSB3ZWlnaHQgYW5kIGhlYXJ0IHdlaWdodDoNCg0KYGBge3J9DQpnZ19jYXRzIDwtIA0KICBnZ3Bsb3QoDQogICAgZGF0YSA9IGNhdHMsDQogICAgbWFwcGluZyA9IGFlcygNCiAgICAgIHggPSBCd3QsDQogICAgICB5ID0gSHd0DQogICAgKQ0KICApICsgDQogICMgQWRkaW5nIHRoZSBwb2ludHMgdG8gdGhlIGdyYXBoOg0KICBnZW9tX3BvaW50KGNvbG9yID0gJ3N0ZWVsYmx1ZScpICsgDQogICMgQWRkaW5nIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIGJvZHkgYW5kIGhlYXJ0IHdlaWdodA0KICBhbm5vdGF0ZSgNCiAgICBnZW9tID0gJ3RleHQnLA0KICAgIGxhYmVsID0gcGFzdGUwKCdyID0gJywgcm91bmQoY29yKGNhdHMkQnd0LCBjYXRzJEh3dCksIDMpKSwNCiAgICB4ID0gMi4yLA0KICAgIHkgPSAxNy41LA0KICAgIHNpemUgPSA1LA0KICAgIGNvbG9yID0gJ3JlZCcNCiAgKSArDQogICMgQ2hhbmdpbmcgdGhlIHRoZW1lDQogIHRoZW1lX2J3KCkgKyANCiAgIyBBZGRpbmcgYSB0aXRsZSBhbmQgbGFiZWxpbmcgdGhlIGF4ZXMNCiAgbGFicygNCiAgICB0aXRsZSA9ICdDYXRzOiBCb2R5IHdlaWdodCB2cyBIZWFydCB3ZWlnaHQnLA0KICAgIHggPSAnQm9keSBXZWlnaHQgKGtnKScsDQogICAgeSA9ICdIZWFydCBXZWlnaHQgKGcpJw0KICApDQoNCg0KZ2dfY2F0cw0KYGBgDQoNCiMjIFN0YXRpbmcgdGhlIG1vZGVsOg0KDQpTaW5jZSB0aGUgYXNzb2NpYXRpb24gYmV0d2VlbiBib2R5IHdlaWdodCAoJFgkKSBhbmQgaGVhcnQgd2VpZ2h0ICgkWSQpIGlzIGxpbmVhciwgd2UgY2FuIG1vZGVsICRZJCB1c2luZyBhIGxpbmVhciBmdW5jdGlvbiBvZiAkWCQ6DQoNCiQkWV9pPSBcYmV0YV8wICsgXGJldGFfMSBYX2kgKyBcdmFyZXBzaWxvbl9pJCQNCg0KJCRFKFlfaXxYX2kpID0gXGJldGFfMCArIFxiZXRhXzEgWF9pJCQNCg0KKipOb3RlOiBGb3IgdGhlIHJlbWFpbmRlciBvZiB0aGlzIGV4YW1wbGUsICRZX2l8WF9pJCB3aWxsIGJlIHNob3J0ZW5lZCBqdXN0IGFzICRZX2kkIHVubGVzcyBzdGF0ZWQgb3RoZXJ3aXNlKioNCg0KV2UgYXBwbHkgdGhlICpkaXN0cmlidXRpb25hbCBhc3N1bXB0aW9uKiBvbiB0aGUgKipyYW5kb20gZXJyb3IqKiwgJFx2YXJlcHNpbG9uX2kkOg0KDQokJFx2YXJlcHNpbG9uX2kgXHNpbSBOKDAsIFxzaWdtYV4yKSQkDQoNCndoaWNoIGltcGxpZXMgYSBkaXN0cmlidXRpb24gZm9yICRZX2kkOg0KDQokJFx2YXJlcHNpbG9uX2kgXHNpbSBOKDAsIFxzaWdtYV4yKSBccmlnaHRhcnJvdyBZX2kgXHNpbSBOKFxiZXRhXzAgKyBcYmV0YV8xIFhfaSwgXHNpZ21hXjIgKSQkDQoNCiMjIEZpdHRpbmcgdGhlIG1vZGVsDQoNClNpbmNlIHRoZSAqKiRcYmV0YSQqKidzIGFyZSB1bmtub3duIHBvcHVsYXRpb24gcGFyYW1ldGVycywgd2UgbmVlZCB0byBlc3RpbWF0ZSB0aGVtIHVzaW5nIHRoZSBzYW1wbGUgZGF0YS4gU28gaG93IGRvIGZvcm11bGF0ZSB0aGVpciBlc3RpbWF0b3JzPw0KDQokJFxoYXR7XGJldGF9XzAgPSBiXzAkJA0KDQokJFxoYXR7XGJldGF9XzEgPSBiXzEkJA0KDQpUaGUgc2FtcGxlIG1vZGVsIGlzOg0KDQokJFxoYXR7eX1faSA9IGJfMCArIGJfMSB4X2kkJA0KDQphbmQgDQoNCiQkeV9pID0gYl8wICsgYl8xIHhfaSArIGVfaSQkDQoNCndoZXJlICRlX2kkIGlzIGNhbGxlZCB0aGUgKnJlc2lkdWFsKiwgd2hpY2ggaXMgYSBwcmVkaWN0aW9uIG9mIHRoZSAqcmFuZG9tIGVycm9yKiwgJFx2YXJlcHNpbG9uJDoNCg0KJCRcaGF0e1x2YXJlcHNpbG9ufV9pID0gZV9pJCQNCg0KV2UgY2FsY3VsYXRlIHRoZSByZXNpZHVhbCB1c2luZyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBvYnNlcnZlZCB2YWx1ZSwgJHlfaSQsIGFuZCB0aGUgZXN0aW1hdGVkIHZhbHVlLCAkXGhhdHt5fV9pJDoNCg0KJCRlX2kgPSB5X2kgLSBcaGF0e3l9X2kkJA0KDQpXaGF0IGlzIHRoZSBiZXN0IGZpdHRpbmcgbGluZT8NCg0KIyMjIEVzdGltYXRpbmcgdGhlIGxpbmU6DQoNCldlIGNhbiBhZGQgdGhlICoqbGluZSBvZiBiZXN0IGZpdCoqIHRvIHRoZSBzY2F0dGVycGxvdCBjcmVhdGVkIGVhcmxpZXIgKGBnZ19jYXRzYCkgYnkgYWRkaW5nIGBnZW9tX3Ntb290aChtZXRob2QgPSAnbG0nKWA6DQoNCmBgYHtyfQ0KZ2dfY2F0c19TTFIgPC0gDQogIGdnX2NhdHMgKyANCiAgZ2VvbV9zbW9vdGgoDQogICAgbWV0aG9kID0gJ2xtJywNCiAgICBmb3JtdWxhID0geSB+IHgsICANCiAgICBzZSA9IEYsICAgICAgICAgICAjIFRoaXMgcmVtb3ZlcyBhIGNvbmZpZGVuY2UgYmFuZCB3ZSdsbCBsb29rIGF0IGxhdGVyDQogICAgY29sb3IgPSAnb3JjaGlkJw0KICApDQoNCmdnX2NhdHNfU0xSDQpgYGANCg0KVGhlIHJlZCBsaW5lIGFib3ZlIHVzZXMgdGhlIHNhbXBsZSBtb2RlbDoNCg0KJCRcaGF0e3l9X2kgPSBiXzAgKyBiXzEgeF9pJCQNCg0KSG93IGRvIHdlIGZpbmQgdGhhdCBsaW5lPyBUaGF0IGlzIHRvIHNheSwgd2hhdCBhcmUgdGhlIGVzdGltYXRvcnMgZm9yICRiXzAkIGFuZCAkYl8xJD8NCg0KU2luY2Ugd2UnbGwgYmUgdXNpbmcgdGhlIGxpbmUgb2YgYmVzdCBmaXQgZm9yIHRoZSByZW1haW5kZXIgb2YgdGhlIHNjcmlwdCwgbGV0J3MgZmluZCAkKGJfMCwgYl8xKSQgYW5kIGRpc2N1c3MgaG93IHRoZXkncmUgY2FsY3VsYXRlZC4NCg0KIyMjIyBUaGUgYGxtKClgIGZ1bmN0aW9uDQoNCk1vc3QgZnVuY3Rpb25zIGluICoqUioqIHRoYXQgY3JlYXRlIGEgbW9kZWwgdXNlIGEgYGZvcm11bGFgIHR5cGUgb2JqZWN0IHRvIGRlZmluZSB0aGUgZXhwbGFuYXRvcnkgYW5kIHJlc3BvbnNlIHZhcmlhYmxlcy4gVGhlIGBsbSgpYCBmdW5jdGlvbiAoc2hvcnQgZm9yICpsaW5lYXIgbW9kZWwqKSBpcyBubyBleGNlcHRpb24hIA0KDQpUaGUgY29kZSBjaHVuayBiZWxvdyB3aWxsIGZpdCB0aGUgU0xSIG1vZGVsIGZvciB1czoNCg0KYGBge3IgY2F0c19TTFJfZml0fQ0KY2F0c19sbSA8LSBsbShmb3JtdWxhID0gSHd0IH4gQnd0LCBkYXRhID0gY2F0cykNCg0KY2F0c19sbQ0KYGBgDQoNClRoZSBmb3JtdWxhIGlzIGNvZGVkIGFzIGByZXNwb25zZSB+IGV4cGxhbmF0b3J5YCwgd2hpY2ggcmVhZHMgYXMgJ1RoZSByZXNwb25zZSB2YXJpYWJsZSAqYnkqIHRoZSBleHBsYW5hdG9yeSB2YXJpYWJsZScsIG9yIEhlYXJ0IFdlaWdodCBieSBCb2R5IFdlaWdodC4NCg0KVGhlIGludGVyY2VwdCBpcyAkYl8wID0gLTAuMzYkIGFuZCAkYl8xID0gNC4wMyQuIFdoeSBhcmUgdGhvc2UgdGhlICdiZXN0Jz8NCg0KIyMjIFdoaWNoIGxpbmUgaXMgdGhlIGJlc3QgbGluZT8NCg0KDQpXaHkgaXMgdGhlIHB1cnBsZSBsaW5lIGJldHRlciB0aGFuIHRoZSBhZGRlZCByZWQgbGluZSBiZWxvdz8NCg0KYGBge3J9DQpnZ19jYXRzX1NMUiArIA0KICAjIEFkZGluZyBhbiBhcmJpdHJhcnkgbGluZToNCiAgZ2VvbV9hYmxpbmUoDQogICAgc2xvcGUgPSAzLCANCiAgICBpbnRlcmNlcHQgPSBtZWFuKGNhdHMkSHd0KSAtIDMqbWVhbihjYXRzJEJ3dCksDQogICAgY29sb3IgPSAncmVkJywNCiAgICBsaW5ldHlwZSA9ICdkYXNoZWQnLA0KICAgIGxpbmV3aWR0aCA9IDENCiAgKQ0KYGBgDQoNClZpc3VhbGx5IHdlIGNhbiB0ZWxsIHRoYXQgdGhlIHJlZCBsaW5lIGlzIGJldHRlciB0aGFuIHRoZSBibHVlIGxpbmUuIEJ1dCBob3cgZG8gd2Ugc2hvdyB0aGF0LCBzdGF0aXN0aWNhbGx5IHNwZWFraW5nPw0KDQpXZSBkZWZpbmUgc29tZSBjcml0ZXJpYSB0aGF0IHRoZSBsaW5lIG5lZWRzIHRvIG1lZXQgdG8gYmUgdGhlICdiZXN0IGxpbmUnOg0KDQoxKSBUaGUgcHJlZGljdGVkIHZhbHVlIG9mICRZJCB3aGVuICRYJCBpcyBhdCB0aGUgbWVhbiBpcyB0aGUgbWVhbiBvZiAkWSQ6DQoNCiQkXGJhcnt5fSA9IGJfMCArIGJfMSBcYmFye3h9ICQkDQoNCm9yLCBpbiBvdGhlciB3b3JkcywgdGhlIGxpbmUgbXVzdCBwYXNzIHRocm91Z2ggdGhlIGNvb3JkaW5hdGUgJChcYmFye3h9LCBcYmFye3l9KSQ6DQoNCmBgYHtyfQ0KZ2dfY2F0c19TTFIgKyANCiAgIyBBZGRpbmcgYW4gYXJiaXRyYXJ5IGxpbmU6DQogIGdlb21fYWJsaW5lKA0KICAgIHNsb3BlID0gMywgDQogICAgaW50ZXJjZXB0ID0gbWVhbihjYXRzJEh3dCkgLSAzKm1lYW4oY2F0cyRCd3QpLA0KICAgIGNvbG9yID0gJ3JlZCcsDQogICAgbGluZXR5cGUgPSAnZGFzaGVkJywNCiAgICBsaW5ld2lkdGggPSAxDQogICkgKyANCiAgIyBBZGRpbmcgdGhlICdjZW50ZXInIG9mIHRoZSBwbG90DQogIGdlb21fdmxpbmUoDQogICAgbWFwcGluZyA9IGFlcyh4aW50ZXJjZXB0ID0gbWVhbihCd3QpKSwNCiAgICBsaW5ld2lkdGggPSAxLA0KICAgIGNvbG9yID0gJ29yYW5nZScNCiAgKSArIA0KICBnZW9tX2hsaW5lKA0KICAgIG1hcHBpbmcgPSBhZXMoeWludGVyY2VwdCA9IG1lYW4oSHd0KSksDQogICAgbGluZXdpZHRoID0gMSwNCiAgICBjb2xvciA9ICdzdGVlbGJsdWUnDQogICkNCmBgYA0KDQpCb3RoIHRoZSByZWQgYW5kIHB1cnBsZSBsaW5lIHBhc3MgdGhyb3VnaCAkKFxiYXJ7eH0sIFxiYXJ7eX0pJCwgc28gd2hhdCBvdGhlciBjcml0ZXJpYSBkb2VzIHRoZSBiZXN0IGxpbmUgbmVlZCB0byBtZWV0Pw0KDQpXZSB3YW50IHRoZSBsaW5lIHRvIGJlIGFzIGNsb3NlIGFzIHBvc3NpYmxlIHRvIHRoZSBwb2ludHMgaW4gdGhlIGRhdGEuIE9uZSBpbml0aWFsbHkgb2J2aW91cyBjaG9pY2UgaXMgdG8gdHJ5IHRvIG1pbmltaXplIHRoZSAqYXZlcmFnZSogcmVzaWR1YWwsIHRoZSB2ZXJ0aWNhbCBkaXN0YW5jZSBhIHBvaW50IGlzIGZyb20gdGhlIGxpbmU6DQoNCmBgYHtyfQ0KIyBDcmVhdGluZyBhIHNhbXBsZSB0byBjYWxjdWxhdGUgdGhlIHJlc2lkdWFsczoNCmNhdHNfcmVzX3NhbXBsZSA8LSANCiAgY2F0cyB8PiANCiAgc2xpY2UoYygzLCA0MCwgMTAwLCAxMzAsIDE0NCkpIA0KDQojIEFkZGluZyB0aGUgcHJlZGljdGVkIGhlYXJ0IHdlaWdodDoNCmNhdHNfcmVzX3NhbXBsZSRId3RfaGF0IDwtIHByZWRpY3QoY2F0c19sbSwgbmV3ZGF0YSA9IGNhdHNfcmVzX3NhbXBsZSkNCg0KY2F0c19yZXNfc2FtcGxlDQoNCiMgVmlzdWFsaXppbmcgdGhlIHJlc2lkdWFscyBmb3IgdGhlIDUgc2FtcGxlIGNhdHMNCmdncGxvdCgNCiAgZGF0YSA9IGNhdHNfcmVzX3NhbXBsZSwNCiAgbWFwcGluZyA9IGFlcygNCiAgICB4ID0gQnd0LA0KICAgIHkgPSBId3QNCiAgKQ0KKSArIA0KICAjIEFkZGluZyB0aGUgJ2NlbnRlcicgb2YgdGhlIHBsb3QNCiAgZ2VvbV92bGluZSgNCiAgICBkYXRhID0gY2F0cywNCiAgICBtYXBwaW5nID0gYWVzKHhpbnRlcmNlcHQgPSBtZWFuKEJ3dCkpLA0KICAgIGxpbmV3aWR0aCA9IDEsDQogICAgY29sb3IgPSAnb3JhbmdlJw0KICApICsgDQogIGdlb21faGxpbmUoDQogICAgZGF0YSA9IGNhdHMsDQogICAgbWFwcGluZyA9IGFlcyh5aW50ZXJjZXB0ID0gbWVhbihId3QpKSwNCiAgICBsaW5ld2lkdGggPSAxLA0KICAgIGNvbG9yID0gJ3N0ZWVsYmx1ZScNCiAgKSArIA0KICBnZW9tX3NlZ21lbnQoDQogICAgbWFwcGluZyA9IGFlcygNCiAgICAgIHhlbmQgPSBCd3QsDQogICAgICB5ZW5kID0gSHd0X2hhdA0KICAgICksIA0KICAgIGxpbmV3aWR0aCA9IDEsDQogICAgY29sb3IgPSAnb3JjaGlkJywNCiAgICBsaW5ldHlwZSA9ICdkYXNoZWQnDQogICkgKyANCiAgZ2VvbV9zbW9vdGgoDQogICAgZGF0YSA9IGNhdHMsDQogICAgc2UgPSBGLA0KICAgIG1ldGhvZCA9ICdsbScsDQogICAgZm9ybXVsYSA9IHkgfiB4LA0KICAgIGNvbG9yID0gJ29yY2hpZCcNCiAgKSArIA0KICBnZW9tX3BvaW50KHNpemUgPSAzKSANCiAgDQpgYGANCg0KTGV0J3MgY2FsY3VsYXRlIHRoZSAqYXZlcmFnZSogcmVzaWR1YWwgZm9yIG91ciBiZXN0IGZpdHRpbmcgbGluZS4gWW91IGNhbiAnZXh0cmFjdCcgdGhlIHJlc2lkdWFscyB1c2luZyBgY2F0c19sbSRyZXNgDQoNCmBgYHtyfQ0Kcm91bmQoY2F0c19sbSRyZXNpZHVhbHNbMToxMF0sIDMpDQpgYGANCg0KTGV0J3MgY2FsY3VsYXRlIHRoZSBtZWFuIG9mIHRoZSByZXNpZHVhbHMsICRcYmFye2V9JDoNCg0KYGBge3J9DQptZWFuKGNhdHNfbG0kcmVzaWR1YWxzKQ0KYGBgDQoNCndoaWNoIGlzIGNvbXB1dGF0aW9uYWxseSAwLiANCg0KSG93IGFib3V0IG91ciBvdGhlciBsaW5lPyBXaGF0IGlzIHRoZSBhdmVyYWdlIHJlc2lkdWFsIG9mIHRoZSByZWQgbGluZToNCg0KJCRcd2lkZXRpbGRle0h3dH0gPSAyLjQ2ICsgMyBcdGltZXMgQnd0JCQNCg0KKipOb3RlOiBXZSB1c2UgJFx3aWRldGlsZGV7SHd0fSQgdG8gaW5kaWNhdGUgdGhhdCBpdCBpcyBkaWZmZXJlbnQgdGhhdCB0aGUgcHJlZGljdGVkIGhlYXJ0IHdlaWdodCBmcm9tIHRoZSBiZXN0IG1vZGVsLCAgJFx3aWRlaGF0e0h3dH0kKioNCg0KYGBge3J9DQpjYXRzIHw+DQogICMgQWRkaW5nIHRoZSBwcmVkaWN0ZWQgaGVhcnQgd2VpZ2h0IHVzaW5nIHRoZSByZWQgbGluZSBhbmQgdGhlIHJlc2lkdWFsDQogIG11dGF0ZSgNCiAgICBod3RfcHJlZCA9IG1lYW4oSHd0KSAtIDMqbWVhbihCd3QpICsgMyAqIEJ3dCwNCiAgICBod3RfcmVzID0gSHd0IC0gaHd0X3ByZWQNCiAgKSB8Pg0KICAjIEF2ZXJhZ2luZyB0aGUgcmVzaWR1YWxzOg0KICBzdW1tYXJpemUoDQogICAgcmVzX2F2ZyA9IG1lYW4oaHd0X3JlcykNCiAgKQ0KYGBgDQoNCndoaWNoIGlzIGFsc28gY29tcHV0YXRpb25hbGx5IDAhIFNvIGJvdGggbGluZXMgaGF2ZSBhbiBhdmVyYWdlIHJlc2lkdWFsIG9mIDAsIHRoZXJlZm9yZSB1c2luZyB0aGF0IGNyaXRlcmlhIHdvdWxkIGluZGljYXRlIHRoYXQgYm90aCBhcmUgZXF1YWxseSBnb29kLCBkZXNwaXRlIHdoYXQgb3VyIGV5ZXMgdG9sZCB1cyBlYXJsaWVyLiANCg0KSW4gZmFjdCwgYW55IGxpbmUgdGhhdCBwYXNzZXMgdGhyb3VnaCAkKFxiYXJ7eH0sIFxiYXJ7eX0pJCB3aWxsIGhhdmUgYW4gYXZlcmFnZSByZXNpZHVhbCBvZiAwLiBUaGF0IHNvdW5kcyB3ZWlyZCBhdCBmaXJzdCwgYnV0IHlvdSBjYW4gZGVtb25zdHJhdGUgaXQgbWF0aGVtYXRpY2FsbHk6DQoNCklmIGEgbGluZSBwYXNzZXMgdGhyb3VnaCAkKFxiYXJ7eH0sIFxiYXJ7eX0pJCwgdGhlbiBmb3IgYW55IHNsb3BlLCAkYl8xJCwgDQoNCiQkYl8wID0gXGJhcnt5fSAtIGJfMVxiYXJ7eH0kJA0KDQp3aGljaCBnaXZlcyB1cyB0aGUgcmVzaWR1YWwgYXM6DQoNCiQkZV9pID0geSAtIChcYmFye3l9IC0gYl8xXGJhcnt4fSArIGJfMXhfaSkgJCQNCg0KJCRlX2kgPSAgKHkgLSBcYmFye3l9KSAtIGJfMSh4X2kgLSBcYmFye3h9KSQkDQoNCkluc3RlYWQsIHdlIG1pbmltaXplIHRoZSBzdW0gKG9yIG1lYW4pIG9mIHRoZSAqc3F1YXJlZCogcmVzaWR1YWxzIQ0KDQojIyMgVGhlIFN1bXMgb2YgU3F1YXJlcyBDcml0ZXJpb24gYW5kIHRoZSBOb3JtYWwgRXF1YXRpb25zDQoNCkZpcnN0LCB3ZSdsbCBkZWZpbmUgdGhlIGZ1bmN0aW9uICRRJDoNCg0KJCRRID0gXHN1bV97aSA9IDF9Xm4gW1lfaSAtIChcYmV0YV8wIC0gXGJldGFfMVhfaSldXjIkJA0KDQpXZSB3YW50IHRvIGZpbmQgdGhlIHZhbHVlcyBvZiAkKFxiZXRhXzAsIFxiZXRhXzEpJCB0aGF0IG1pbmltaXplICRRJCENCg0KTGV0J3MgY29tcGFyZSB0aGUgdHdvIG1vZGVscyB3ZSBoYXZlIHNvIGZhcjoNCg0KYGBge3IgU1NFX2NvbXBhcmV9IA0KY2F0cyB8Pg0KICAjIEFkZGluZyB0aGUgcHJlZGljdGVkIGhlYXJ0IHdlaWdodCB1c2luZyB0aGUgcmVkIGxpbmUgYW5kIHRoZSByZXNpZHVhbA0KICBtdXRhdGUoDQogICAgaHd0X2hhdCAgPSBjYXRzX2xtJGZpdCwgICAgICAgICAgICAgICAgICAgICAgICAjIFByZWRzIGZyb20gdGhlIGJlc3QgbGluZQ0KICAgIGh3dF9wcmVkID0gbWVhbihId3QpIC0gMyptZWFuKEJ3dCkgKyAzICogQnd0ICAgIyBQcmVkcyBmcm9tIG90aGVyIGxpbmUNCiAgKSB8Pg0KICAjIEF2ZXJhZ2luZyB0aGUgcmVzaWR1YWxzOg0KICBzdW1tYXJpemUoDQogICAgYmVzdF9TU0UgPSBzdW0oKEh3dCAtIGh3dF9oYXQpXjIpLA0KICAgIG5vdF9hc19nb29kX1NTRSA9IHN1bSgoSHd0IC0gaHd0X3ByZWQpXjIpDQogICkNCmBgYA0KDQpOb3RpY2UgdGhhdCB0aGUgc3VtcyBvZiB0aGUgc3F1YXJlcyBvZiB0aGUgcmVzaWR1YWxzIGlzIHNtYWxsZXIhDQoNCkhvdyBkbyB3ZSBmaW5kIHRoZSB2YWx1ZXMgdGhhdCBtaW5pbWl6ZSAkUSQ/IERvIHdlIHRyeSBldmVyeSBjb21iaW5hdGlvbiBwb3NzaWJsZSBhbmQga2VlcCB0aGUgb25lIHRoYXQgbWFrZXMgdGhlIHN1bXMgb2Ygc3F1YXJlcyB0aGUgc21hbGxlc3Q/DQoNCldoaWxlIHdlIHRoZW9yZXRpY2FsbHkgY291bGQsIHRoZXJlIGlzIGEgbXVjaCBtb3JlIGVmZmljaWVudCB3YXkgdG8gZG8gdGhhdDogY2FsY3VsdXMhDQoNCldlJ2xsIGRvIHRoZSBtYXRoIG9uIHRoZSBib2FyZCwgYnV0IHdlIGNhbiB0YWtlIHRoZSBkZXJpdmF0aXZlIG9mICRRJCB3aXRoIHJlc3BlY3QgdG8gdGhlIHR3byAkXGJldGEkJ3MgaW5kaXZpZHVhbGx5Og0KDQokJFxmcmFje1xwYXJ0aWFsIFF9e1xwYXJ0aWFsIFxiZXRhXzB9ID0gXHN1bV97aSA9IDF9Xm4gKC0yKShZX2kgLSBcYmV0YV8wIC0gXGJldGFfMSBYX2kpICQkDQoNCiQkXGZyYWN7XHBhcnRpYWwgUX17XHBhcnRpYWwgXGJldGFfMX0gPSBcc3VtX3tpID0gMX1ebiAoLTJYX2kpKFlfaSAtIFxiZXRhXzAgLSBcYmV0YV8xIFhfaSkgJCQNCg0KVG8gZmluZCB0aGUgdmFsdWVzIG9mICQoXGJldGFfMCwgXGJldGFfMSkkIHRoYXQgbWluaW1pemUgUSwgd2UgdGFrZSB0aGUgcGFydGlhbCBkZXJpdmF0aXZlcywgc2V0IHRoZW0gZXF1YWwgdG8gMCwgdGhlbiBkbyBhIGxpdHRsZSBzaW1wbGlmaWNhdGlvbiwgd2UgY2FuIGNyZWF0ZSB3aGF0IHdlIGNhbGwgKipUaGUgTm9ybWFsIEVxdWF0aW9ucyoqOg0KDQokJFxzdW1fe2kgPSAxfV5uIChZX2kgLSBiXzAgLSBiXzEgWF9pKSA9IDAkJA0KDQokJFxzdW1fe2kgPSAxfV5uIChZX2kgLSBiXzAgLSBiXzEgWF9pKVhfaSA9IDAkJA0KDQpXZSBjYW4gc29sdmUgdGhlIHN5c3RlbSBvZiB0aGUgTm9ybWFsIEVxdWF0aW9ucyB0byBmaW5kIHRoZSBlc3RpbWF0b3JzIG9mIG91ciBtb2RlbCBwYXJhbWV0ZXJzOg0KDQokJGJfMSA9IFxmcmFje1xzdW1fe2kgPSAxfV5uKFhfaSAtIFxiYXJ7WH0pKFlfaSAtIFxiYXJ7WX0pfXtcc3VtX3tpID0gMX1ebihYX2kgLSBcYmFye1h9KV4yfT0gXGZyYWN7U197WFl9fXtTX3tYWH19JCQNCndoZXJlICRTX3tYWX0kIGlzIHRoZSBlc3RpbWF0ZWQgY292YXJpYW5jZSBiZXR3ZWVuICRYLCBZJCBhbmQgJFNfe1hYfSQgaXMgdGhlIGVzdGltYXRlZCB2YXJpYW5jZSBvZiAkWCQNCg0KDQoNCmFuZA0KDQokJGJfMCA9IFxiYXJ7WX0gLSBiXzFcYmFye1h9JCQNCg0KDQoNClRoZXJlIGFyZSBhIGNvdXBsZSBvZiBhbHRlcm5hdGl2ZSB3YXlzIHdlIGNhbiB3cml0ZSAkYl8xJCB0aGF0IGFyZSBlYXNpZXIgdG8gd29yayB3aXRoOg0KDQoxKSAkJGJfMSA9IFxmcmFjeyhcc3VtX3tpID0gMX1ebiBYX2lZX2kpIC0gblxiYXJ7WH1cYmFye1l9fXsoXHN1bV97aSA9IDF9Xm4gWF9pXjIpIC0gblxiYXJ7WH1eMn0kJA0KDQp3aGljaCBpcyBvZnRlbiBlYXNpZXIgdG8gdXNlIHdoZW4gY2FsY3VsYXRpbmcgZXhwZWN0ZWQgdmFsdWVzIGFuZCB2YXJpYW5jZXMgb2YgdGhlIGVzdGltYXRlcywgd2hpY2ggd2UnbGwgZG8gbGF0ZXIhDQoNCg0KDQoyKSAkJGJfMSA9IHJcZnJhY3tzX1l9e3NfWH0kJA0KDQp3aGVyZSAkciQgaXMgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gJFgsIFkkLCAkc19YJCBpcyB0aGUgZXN0aW1hdGVkIHN0YW5kYXJkIGRldmlhdGlvbiBvZiAkWCQsIGFuZCB0aGUgc2FtZSBmb3IgJFkkDQoNCg0KIyMjIFRoZSBmaXR0ZWQgbW9kZWw6DQoNCk5vdyB0aGF0IHdlIGhhdmUgdGhlIGZ1bmN0aW9ucyBmb3IgaG93IHRvIGNhbGN1bGF0ZSAkYl8wJCBhbmQgJGJfMSQsIHdlIGNhbiB3cml0ZSBvdXIgbW9kZWwgYXM6DQoNCiQkXGhhdHtZX2l9ID0gXGJhcntZfSArIHJcZnJhY3tzX1l9e3NfWH0oWF9pIC0gXGJhcntYfSkkJA0KDQojIyMgQ2FsY3VsYXRpbmcgdGhlIGVzdGltYXRlcyAnYnkgaGFuZCcNCg0KTmV4dCwgbGV0J3MgY2FsY3VsYXRlIHRoZSBlc3RpbWF0ZXMsICRiXzAkIGFuZCAkYl8xJCB1c2luZyB0aGUgZXF1YXRpb25zIGFib3ZlDQoNCmBgYHtyfQ0KY2F0cyB8Pg0KICBtdXRhdGUoDQogICAgZGV2X3ggPSBCd3QgLSBtZWFuKEJ3dCksICAjIFggLSBYX2Jhcg0KICAgIGRldl95ID0gSHd0IC0gbWVhbihId3QpICAgIyBZIC0gWV9iYXINCiAgKSB8Pg0KICANCiAgIyBDYWxjdWxhdGluZyBiMSBhbmQgYjANCiAgc3VtbWFyaXplKA0KICAgICMgU2xvcGUgdXNpbmcgdGhlICdyYXcnIGRhdGENCiAgICBiMV9tYW51YWwxICA9IHN1bShkZXZfeCAqIGRldl95KSAvIHN1bShkZXZfeF4yKSwNCiAgICBiMV9tYW51YWwyICA9IChzdW0oQnd0Kkh3dCkgLSBuKCkgKiBtZWFuKEJ3dCkqbWVhbihId3QpKS8oc3VtKEJ3dF4yKSAtIG4oKSAqIG1lYW4oQnd0KV4yKSwNCiAgICBiMV9mb3JtdWxhMSA9IGNvdihCd3QsIEh3dCkgLyB2YXIoQnd0KSwgICAgICAgICAgICAjIFNfWFkgLyBTX1hYDQogICAgYjFfZm9ybXVsYTIgPSBjb3IoQnd0LCBId3QpICogc2QoSHd0KSAvIHNkKEJ3dCksICAgIyByIChzX1kgLyBzX1gpDQogICAgDQogICAgIyBDYWxjdWxhdGluZyBiMA0KICAgIGIwX21hbnVhbCA9IG1lYW4oSHd0KSAtIGIxX21hbnVhbDEgKiBtZWFuKEJ3dCkNCiAgKQ0KICANCmBgYA0KDQphbmQgd2UgY2FuIGNvbXBhcmUgaXQgdG8gdGhlIGVzdGltYXRlcyBmcm9tIGBsbSgpYCB1c2luZyBgY2F0c19sbSRjb2VmYDoNCg0KYGBge3J9DQpjYXRzX2xtJGNvZWYNCmBgYA0KDQpUaGV5J3JlIHRoZSBzYW1lIQ0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg==