View the
latest recording of this lecture
In a multiple regression model there are a variety of hypotheses that
we might wish to test. For example:
- Is the mean response related to any of the predictors?
- Does a given predictor provide additional information about the
response over and above that provided by the other predictors?
In this lecture we shall look at the methodology for testing question
1 above.
The F Test for Overall Fit of a Multiple Regression
Model
For any given model: \(Y_i = \beta_0 +
\beta_1 x_{i1} + \ldots + \beta_p x_{ip}
+ \varepsilon_i\) where i=1,2,…,n.
We ask: Is the mean response (linearly) related to any of the
predictors?
We test:
H0: \(\beta_1 = \beta_2
= \ldots = \beta_p = 0\) i.e. mean response is not linearly
related to any of the predictors
against
H1: \(\beta_1, \beta_2,
\ldots, \beta_p~\mbox{not all zero}\) i.e. mean response is
linearly related to at least one of the predictors.
Testing H0 versus H1 is
equivalent to comparing two different models:
M0: \(Y_i = \beta_0 +
\varepsilon_i\) and
M1: \(Y_i = \beta_0 + \beta_1
x_{i1} + \ldots + \beta_p x_{ip} + \varepsilon_i\) where
i=1,2,…,n.
Model M0 corresponds to H0; Model
M1 corresponds to H1.
General Thoughts on Choosing Between Models
In choosing between models, statisticians have two aims:
- to choose a simple (i.e. not too complex) model;
- to choose a model that fits the data well.
We can measure the complexity of a linear regression model by the
number of regression parameters, p+1. The greater this value,
the more complex the model.
We can measure the closeness of fit of the model to data using the
residual sum of squares.
Think of model comparison like clothes shopping — is it worth
spending more (parameters) in order to get a better (model) fit?
F-Tests for Overall Fit (again)
We want to compare:
Model M0 — cheap (just 1 regression parameter) but may fit
badly (residual sum of squares, RSSM0, may be
large).
Model M1 — more expensive (p+1 regression
parameters) but will fit better (residual sum of squares,
RSSM1, smaller).
So we calculate residual sum of squares (RSS) for each model and
compute the following F test statistic:
\[F = \frac{[RSS_{M0} -
RSS_{M1}]/p}{RSS_{M1}/(n-p-1)}\]
- Intuitively, this F statistic measures (a standardised
version of) improvement in fit per “unit cost” (i.e. per extra
parameter).
Large values of F suggests that we should prefer M1
to M0. Intuitively, improvement in fit of model is worth the
cost.
How large is “large”?
If model M0 is correct (i.e. H0 is
correct) then the F test statistic has an F
distribution with p,(n-p-1) degrees of freedom, often denoted
Fp,n-p-1.
We use these facts to calculate the P-value for the
F statistic, and hence test H0 versus
H1.
Aside: The F Distribution
An F distribution is defined by two degrees of freedom.
Random variables from the F distribution take only
non-negative values.
Some examples of the density of various F distributions are
displayed. The shape depends on the numerator and denominator degrees of
freedom…
… but large values of x are always unlikely to be observed
by chance alone.
As a rough guide, the median of an F distribution is always
<1. So if you get an F value less than one, then it is not going to
be significant.
If you get an F value greater than ten it definitely is very
significant.
ANOVA table
In most Statistical programs (but not R) it is common to represent
the result of a regression with an Analysis of Variance table. It is a
useful way to keep track of things. (We’ll soon see how R summarises
this table.)
Regression |
\(SS_{regn}\) |
p |
\(MS_{regn} =
\frac{SS_{regn}}{p}\) |
F=\(\frac{MS_{regn}}{MS_{resid}}\) |
Residuals |
\(SS_{resid}\) |
n-p-1 |
\(MS_{resid}=\frac{SS_{resid}
}{n-p-1}\) |
|
Total |
\(SS_{Tot}\) |
n-1 |
|
|
where \(MS_{total} = \sum( Y -\bar
Y)^2\), \(~~MS_{error} = \sum( Y -\hat
Y)^2\) , p= number of regression parameters (predictors, not
including the intercept) the model formula and \(n-p-1\) is the residual df.
Note the First two SS add up to the total SS. So this illustrates how
regression separates the different sources of variation or “analyses the
variance”.
The df add up as well: p + n-p-1= n-1.
The F is the ratio of the Mean Squared errors.
Analysis of Variance table for Climate data
N.B.
Download Climate.csv
to be able to run the examples below.
For the climate data we have
Climate = read.csv(file = "../../data/Climate.csv", header = TRUE, row.names = 1)
Climate.lm0 = lm(MnJlyTemp ~ 1, data = Climate)
Climate.lm1 = lm(MnJlyTemp ~ ., data = Climate)
anova(Climate.lm0, Climate.lm1)
Analysis of Variance Table
Model 1: MnJlyTemp ~ 1
Model 2: MnJlyTemp ~ Lat + Long + MnJanTemp + Rain + Sun + Height + Sea +
NorthIsland
Res.Df RSS Df Sum of Sq F Pr(>F)
1 35 270.330
2 27 25.022 8 245.31 33.087 5.255e-12 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Note that we have explicitly created the null model
Climate.lm0
with no predictor variables.
The use of the anova()
command has compared two models
here. We show that this way of using anova()
is unnecessary
below, but we do make frequent use of the anova()
command
with reference to two (or more) models a lot when working with
regression models.
Omnibus F Test Statistics in R
The above test of whether the response is related to any of the
explanatory variables is sometimes called an omnibus
F test, while others refer to it as a test of model
utility.
We do not have to do the test by hand, or by fitting the null model
because R provides the F statistic and corresponding
P-value for this test as a standard part of the
summary()
output for a linear model.
Back to Climate example
Climate.lm1.sum = summary(Climate.lm1)
Climate.lm1.sum
Call:
lm(formula = MnJlyTemp ~ ., data = Climate)
Residuals:
Min 1Q Median 3Q Max
-1.2213 -0.5257 -0.2620 0.3796 3.3033
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 5.2829167 24.0200695 0.220 0.82757
Lat -0.3655501 0.1638323 -2.231 0.03416 *
Long 0.1012667 0.1253184 0.808 0.42611
MnJanTemp -0.0380083 0.2901840 -0.131 0.89676
Rain 0.0002901 0.0002971 0.977 0.33744
Sun -0.0006941 0.0011596 -0.599 0.55442
Height -0.0049986 0.0014557 -3.434 0.00194 **
Sea 1.7298287 0.5472228 3.161 0.00386 **
NorthIsland 1.3589549 0.8087868 1.680 0.10445
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 0.9627 on 27 degrees of freedom
Multiple R-squared: 0.9074, Adjusted R-squared: 0.88
F-statistic: 33.09 on 8 and 27 DF, p-value: 5.255e-12
[1] "call" "terms" "residuals" "coefficients"
[5] "aliased" "sigma" "df" "r.squared"
[9] "adj.r.squared" "fstatistic" "cov.unscaled"
Climate.lm1.sum$r.squared
[1] 0.9074375
Climate.lm1.sum$fstatistic
value numdf dendf
33.08687 8.00000 27.00000
These figures are the same as were seen earlier when we used the
anova()
command.
LS0tDQp0aXRsZTogIkxlY3R1cmUgMTA6IFRlc3RpbmcgaW4gTXVsdGlwbGUgUmVncmVzc2lvbiBNb2RlbHMgKDEpIg0Kc3VidGl0bGU6IDE2MS4yNTEgUmVncmVzc2lvbiBNb2RlbGxpbmcNCmF1dGhvcjogIlByZXNlbnRlZCBieSBKb25hdGhhbiBHb2RmcmV5IDxhLmouZ29kZnJleUBtYXNzZXkuYWMubno+IiAgDQpkYXRlOiAiV2VlayA0IG9mIFNlbWVzdGVyIDIsIGByIGx1YnJpZGF0ZTo6eWVhcihsdWJyaWRhdGU6Om5vdygpKWAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHRoZW1lOiB5ZXRpDQogICAgaGlnaGxpZ2h0OiB0YW5nbw0KICBodG1sX25vdGVib29rOg0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICB0aGVtZTogeWV0aQ0KICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgaW9zbGlkZXNfcHJlc2VudGF0aW9uOg0KICAgIHdpZGVzY3JlZW46IHRydWUNCiAgICBzbWFsbGVyOiB0cnVlDQogIHdvcmRfZG9jdW1lbnQ6IGRlZmF1bHQNCiAgc2xpZHlfcHJlc2VudGF0aW9uOiANCiAgICB0aGVtZTogeWV0aQ0KICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KDQoNCg0KDQpbVmlldyB0aGUgbGF0ZXN0IHJlY29yZGluZyBvZiB0aGlzIGxlY3R1cmVdKGh0dHBzOi8vUi1SZXNvdXJjZXMubWFzc2V5LmFjLm56L3ZpZGVvcy8yNTFMMTAubXA0KQ0KPCEtLS0gRGF0YSBpcyBvbg0KaHR0cHM6Ly9yLXJlc291cmNlcy5tYXNzZXkuYWMubnovZGF0YS8xNjEyNTEvDQotLS0+DQoNCmBgYHtyIHNldHVwLCBwdXJsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQ0KbGlicmFyeShrbml0cikNCm9wdHNfY2h1bmskc2V0KGRldj1jKCJwbmciLCAicGRmIikpDQpvcHRzX2NodW5rJHNldChmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD03LCBmaWcucGF0aD0iRmlndXJlcy8iLCBmaWcuYWx0PSJ1bmxhYmVsbGVkIikNCm9wdHNfY2h1bmskc2V0KGNvbW1lbnQ9IiIsIGZpZy5hbGlnbj0iY2VudGVyIiwgdGlkeT1UUlVFKQ0Kb3B0aW9ucyhrbml0ci5rYWJsZS5OQSA9ICcnKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGJyb29tKQ0KYGBgDQoNCg0KPCEtLS0gRG8gbm90IGVkaXQgYW55dGhpbmcgYWJvdmUgdGhpcyBsaW5lLiAtLS0+DQoNCkluIGEgbXVsdGlwbGUgcmVncmVzc2lvbiBtb2RlbCB0aGVyZSBhcmUgYSB2YXJpZXR5IG9mIGh5cG90aGVzZXMNCiAgICB0aGF0IHdlIG1pZ2h0IHdpc2ggdG8gdGVzdC4gRm9yIGV4YW1wbGU6DQoNCjEuICBJcyB0aGUgbWVhbiByZXNwb25zZSByZWxhdGVkIHRvIGFueSBvZiB0aGUgcHJlZGljdG9ycz8NCjIuICBEb2VzIGEgZ2l2ZW4gcHJlZGljdG9yIHByb3ZpZGUgYWRkaXRpb25hbCBpbmZvcm1hdGlvbiBhYm91dCB0aGUNCiAgICAgICAgcmVzcG9uc2Ugb3ZlciBhbmQgYWJvdmUgdGhhdCBwcm92aWRlZCBieSB0aGUgb3RoZXIgcHJlZGljdG9ycz8NCg0KSW4gdGhpcyBsZWN0dXJlIHdlIHNoYWxsIGxvb2sgYXQgdGhlIG1ldGhvZG9sb2d5IGZvciB0ZXN0aW5nIHF1ZXN0aW9uICAxIGFib3ZlLg0KDQojIyBUaGUgKkYqIFRlc3QgZm9yIE92ZXJhbGwgRml0IG9mIGEgTXVsdGlwbGUgUmVncmVzc2lvbiBNb2RlbA0KDQpGb3IgYW55IGdpdmVuIG1vZGVsOiAkWV9pID0gXGJldGFfMCArIFxiZXRhXzEgeF97aTF9ICsgXGxkb3RzICsgXGJldGFfcCB4X3tpcH0NCisgXHZhcmVwc2lsb25faSQgd2hlcmUgKmk9MSwyLC4uLixuKi4NCg0KV2UgYXNrOiBJcyB0aGUgbWVhbiByZXNwb25zZSAobGluZWFybHkpIHJlbGF0ZWQgdG8gYW55IG9mIHRoZSBwcmVkaWN0b3JzPw0KDQoNCldlIHRlc3Q6ICANCg0KKkh+MH4qOiAkXGJldGFfMSA9IFxiZXRhXzIgPSBcbGRvdHMgPSBcYmV0YV9wID0gMCQgaS5lLiBtZWFuIHJlc3BvbnNlIGlzDQpub3QgbGluZWFybHkgcmVsYXRlZCB0byBhbnkgb2YgdGhlIHByZWRpY3RvcnMNCg0KYWdhaW5zdA0KDQoqSH4xfio6ICRcYmV0YV8xLCBcYmV0YV8yLCBcbGRvdHMsIFxiZXRhX3B+XG1ib3h7bm90IGFsbCB6ZXJvfSQgaS5lLiBtZWFuDQpyZXNwb25zZSBpcyBsaW5lYXJseSByZWxhdGVkIHRvIGF0IGxlYXN0IG9uZSBvZiB0aGUgcHJlZGljdG9ycy4NCg0KVGVzdGluZyAqSH4wfiogdmVyc3VzICpIfjF+KiBpcyBlcXVpdmFsZW50IHRvIGNvbXBhcmluZyB0d28gZGlmZmVyZW50DQptb2RlbHM6IA0KDQoqTTAqOiAkWV9pID0gXGJldGFfMCArIFx2YXJlcHNpbG9uX2kkIGFuZCANCg0KKk0xKjogJFlfaSA9IFxiZXRhXzAgKyBcYmV0YV8xIHhfe2kxfSArIFxsZG90cyArIFxiZXRhX3AgeF97aXB9ICsgIFx2YXJlcHNpbG9uX2kkIHdoZXJlICppPTEsMiwuLi4sbiouDQoNCg0KDQpNb2RlbCAqTTAqIGNvcnJlc3BvbmRzIHRvICpIfjB+KjsgTW9kZWwgKk0xKiBjb3JyZXNwb25kcyB0byAqSH4xfiouDQoNCiMjIEdlbmVyYWwgVGhvdWdodHMgb24gQ2hvb3NpbmcgQmV0d2VlbiBNb2RlbHMNCg0KSW4gY2hvb3NpbmcgYmV0d2VlbiBtb2RlbHMsIHN0YXRpc3RpY2lhbnMgaGF2ZSB0d28gYWltczoNCiAgICANCi0gdG8gY2hvb3NlIGEgc2ltcGxlIChpLmUuIG5vdCB0b28gY29tcGxleCkgbW9kZWw7DQotIHRvIGNob29zZSBhIG1vZGVsIHRoYXQgZml0cyB0aGUgZGF0YSB3ZWxsLg0KDQpXZSBjYW4gbWVhc3VyZSB0aGUgY29tcGxleGl0eSBvZiBhIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIGJ5IHRoZQ0KICAgIG51bWJlciBvZiByZWdyZXNzaW9uIHBhcmFtZXRlcnMsICpwKzEqLiBUaGUgZ3JlYXRlciB0aGlzIHZhbHVlLA0KICAgIHRoZSBtb3JlIGNvbXBsZXggdGhlIG1vZGVsLg0KDQpXZSBjYW4gbWVhc3VyZSB0aGUgY2xvc2VuZXNzIG9mIGZpdCBvZiB0aGUgbW9kZWwgdG8gZGF0YSB1c2luZyB0aGUNCiAgICByZXNpZHVhbCBzdW0gb2Ygc3F1YXJlcy4NCg0KVGhpbmsgb2YgbW9kZWwgY29tcGFyaXNvbiBsaWtlIGNsb3RoZXMgc2hvcHBpbmcgLS0tIGlzIGl0IHdvcnRoDQogICAgc3BlbmRpbmcgbW9yZSAocGFyYW1ldGVycykgaW4gb3JkZXIgdG8gZ2V0IGEgYmV0dGVyIChtb2RlbCkgZml0Pw0KDQojIyBGLVRlc3RzIGZvciBPdmVyYWxsIEZpdCAoYWdhaW4pDQoNCldlIHdhbnQgdG8gY29tcGFyZToNCg0KTW9kZWwgKk0wKiAtLS0gY2hlYXAgKGp1c3QgMSByZWdyZXNzaW9uIHBhcmFtZXRlcikgYnV0IG1heQ0KICAgICAgICBmaXQgYmFkbHkgKHJlc2lkdWFsIHN1bSBvZiBzcXVhcmVzLCAqUlNTfk0wfiosIG1heSBiZSBsYXJnZSkuDQoNCk1vZGVsICpNMSogLS0tIG1vcmUgZXhwZW5zaXZlICgqcCsxKiByZWdyZXNzaW9uIHBhcmFtZXRlcnMpDQogICAgICAgIGJ1dCB3aWxsIGZpdCBiZXR0ZXIgKHJlc2lkdWFsIHN1bSBvZiBzcXVhcmVzLCAqUlNTfk0xfiosDQogICAgICAgIHNtYWxsZXIpLg0KDQpTbyB3ZSBjYWxjdWxhdGUgcmVzaWR1YWwgc3VtIG9mIHNxdWFyZXMgKFJTUykgZm9yIGVhY2ggbW9kZWwgYW5kDQogICAgY29tcHV0ZSB0aGUgZm9sbG93aW5nICoqKkYgdGVzdCBzdGF0aXN0aWMqKio6DQoNCiQkRiA9IFxmcmFje1tSU1Nfe00wfSAtIFJTU197TTF9XS9wfXtSU1Nfe00xfS8obi1wLTEpfSQkDQoNCi0gSW50dWl0aXZlbHksIHRoaXMgKkYqIHN0YXRpc3RpYyBtZWFzdXJlcyAoYSBzdGFuZGFyZGlzZWQgdmVyc2lvbg0KICAgIG9mKSBpbXByb3ZlbWVudCBpbiBmaXQgcGVyICJ1bml0IGNvc3QiIChpLmUuIHBlciBleHRyYSBwYXJhbWV0ZXIpLg0KDQpMYXJnZSB2YWx1ZXMgb2YgKkYqIHN1Z2dlc3RzIHRoYXQgd2Ugc2hvdWxkIHByZWZlciAqTTEqIHRvICpNMCouIEludHVpdGl2ZWx5LCBpbXByb3ZlbWVudCBpbiBmaXQgb2YgbW9kZWwgaXMgd29ydGggdGhlIGNvc3QuDQoNCkhvdyBsYXJnZSBpcyAibGFyZ2UiPw0KDQpJZiBtb2RlbCAqTTAqIGlzIGNvcnJlY3QgKGkuZS4gKkh+MH4qIGlzIGNvcnJlY3QpIHRoZW4gdGhlICpGKiB0ZXN0IHN0YXRpc3RpYyBoYXMgYW4gKkYqIGRpc3RyaWJ1dGlvbiB3aXRoICpwLChuLXAtMSkqIGRlZ3JlZXMgb2YgZnJlZWRvbSwgb2Z0ZW4gZGVub3RlZCAqRn5wLG4tcC0xfiouDQoNCldlIHVzZSB0aGVzZSBmYWN0cyB0byBjYWxjdWxhdGUgdGhlICpQKi12YWx1ZSBmb3IgdGhlICpGKiBzdGF0aXN0aWMsIGFuZA0KICAgIGhlbmNlIHRlc3QgKkh+MH4qIHZlcnN1cyAqSH4xfiouDQoNCiMjIEFzaWRlOiBUaGUgKkYqIERpc3RyaWJ1dGlvbg0KDQoNCkFuICpGKiBkaXN0cmlidXRpb24gaXMgZGVmaW5lZCBieSB0d28gZGVncmVlcyBvZiBmcmVlZG9tLg0KDQpSYW5kb20gdmFyaWFibGVzIGZyb20gdGhlICpGKiBkaXN0cmlidXRpb24gdGFrZSBvbmx5IG5vbi1uZWdhdGl2ZSB2YWx1ZXMuDQoNClNvbWUgZXhhbXBsZXMgb2YgdGhlIGRlbnNpdHkgb2YgdmFyaW91cyAqRiogZGlzdHJpYnV0aW9ucyBhcmUgZGlzcGxheWVkLiBUaGUgc2hhcGUgZGVwZW5kcyBvbiB0aGUgbnVtZXJhdG9yIGFuZCBkZW5vbWluYXRvciBkZWdyZWVzIG9mIGZyZWVkb20uLi4NCg0KDQpgYGB7ciBGRGlzdHJpYnV0aW9ucywgZWNobz1GQUxTRSwgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9NywgZmlnLmNhcD0iUHJvYmFiaWxpdHkgZGVuc2l0eSBmdW5jdGlvbnMgZm9yIEYgZGlzdHJpYnV0aW9ucyB3aXRoIG51bWVyYXRvciBkZiBvZiAzIChsZWZ0KSBhbmQgMTAgKHJpZ2h0KSwgYW5kIGRlbm9taW5hdG9yIGRmIG9mICgxMCAodXBwZXIpIGFuZCAzMCAobG93ZXIpIn0NCnBhcihtZnJvdz1jKDIsMikpDQp4PSgwOjI1MCkvMTANCnkxID0gZGYoeCwzLDEwKQ0KcGxvdCh4LCB5MSwgeWxhYj0iZih4KSIsIHlsaW09YygwLDAuOCksIHR5cGU9ImwiKQ0KeTIgPSBkZih4LDEwLDEwKQ0KcGxvdCh4LCB5MiwgeWxhYj0iZih4KSIsIHlsaW09YygwLDAuOCksIHR5cGU9ImwiKQ0KeTMgPSBkZih4LDMsMzApDQpwbG90KHgsIHkzLCB5bGFiPSJmKHgpIiwgeWxpbT1jKDAsMC44KSwgdHlwZT0ibCIpDQp5NCA9IGRmKHgsMTAsMzApDQpwbG90KHgsIHk0LCB5bGFiPSJmKHgpIiwgeWxpbT1jKDAsMC44KSwgdHlwZT0ibCIpDQpgYGANCg0KLi4uIGJ1dCBsYXJnZSB2YWx1ZXMgb2YgKngqIGFyZSBhbHdheXMgdW5saWtlbHkgdG8gYmUgb2JzZXJ2ZWQgYnkgY2hhbmNlIGFsb25lLg0KDQoNCkFzIGEgcm91Z2ggZ3VpZGUsICB0aGUgbWVkaWFuIG9mIGFuICpGKiBkaXN0cmlidXRpb24gaXMgYWx3YXlzIDwxLiBTbyBpZiB5b3UgZ2V0IGFuIEYgdmFsdWUgbGVzcyB0aGFuIG9uZSwgIHRoZW4gaXQgaXMgbm90IGdvaW5nIHRvIGJlIHNpZ25pZmljYW50LiAgDQpJZiB5b3UgZ2V0IGFuIEYgdmFsdWUgZ3JlYXRlciB0aGFuIHRlbiBpdCBkZWZpbml0ZWx5IGlzIHZlcnkgc2lnbmlmaWNhbnQuIA0KDQojIyBBTk9WQSB0YWJsZSANCg0KSW4gbW9zdCBTdGF0aXN0aWNhbCBwcm9ncmFtcyAoYnV0IG5vdCBSKSBpdCBpcyBjb21tb24gdG8gcmVwcmVzZW50IHRoZSByZXN1bHQgb2YgYSByZWdyZXNzaW9uIHdpdGggYW4gQW5hbHlzaXMgb2YgVmFyaWFuY2UgdGFibGUuICAgSXQgaXMgYSB1c2VmdWwgd2F5IHRvIGtlZXAgdHJhY2sgb2YgdGhpbmdzLiAoV2UnbGwgc29vbiBzZWUgaG93IFIgc3VtbWFyaXNlcyB0aGlzIHRhYmxlLikNCg0KDQoNClNvdXJjZSB8IFN1bSBvZiBzcXVhcmVzIHwgZGYgfCBNZWFuIFNxdWFyZSB8IEYgDQotLS0gfCAtLS0gfCAtLS0gfCAtLS0gfCAtLS0NClJlZ3Jlc3Npb24gfCAkU1Nfe3JlZ259JHwgcCB8ICRNU197cmVnbn0gPSBcZnJhY3tTU197cmVnbn19e3B9JHwgRj0kXGZyYWN7TVNfe3JlZ259fXtNU197cmVzaWR9fSQNClJlc2lkdWFsc3wgJFNTX3tyZXNpZH0kIHwgbi1wLTEgIHwgJE1TX3tyZXNpZH09XGZyYWN7U1Nfe3Jlc2lkfQ0KfXtuLXAtMX0kIHwgDQpUb3RhbCB8JFNTX3tUb3R9JHxuLTEgIHwgfA0KDQoNCndoZXJlICAkTVNfe3RvdGFsfSA9IFxzdW0oIFkgLVxiYXIgWSleMiQsICAkfn5NU197ZXJyb3J9ID0gIFxzdW0oIFkgLVxoYXQgWSleMiQgICwgIHA9IG51bWJlciBvZiByZWdyZXNzaW9uIHBhcmFtZXRlcnMgKHByZWRpY3RvcnMsIG5vdCBpbmNsdWRpbmcgdGhlIGludGVyY2VwdCkNCnRoZSBtb2RlbCBmb3JtdWxhIGFuZCAkbi1wLTEkIGlzIHRoZSByZXNpZHVhbCBkZi4gDQoNCk5vdGUgdGhlIEZpcnN0IHR3byBTUyBhZGQgdXAgdG8gdGhlIHRvdGFsIFNTLiAgU28gdGhpcyBpbGx1c3RyYXRlcyBob3cgcmVncmVzc2lvbiBzZXBhcmF0ZXMgdGhlIGRpZmZlcmVudCBzb3VyY2VzIG9mIHZhcmlhdGlvbiBvciAiYW5hbHlzZXMgdGhlIHZhcmlhbmNlIi4gDQoNClRoZSBkZiBhZGQgdXAgYXMgd2VsbDogICBwICArIG4tcC0xPSBuLTEuDQoNClRoZSAqRiogaXMgdGhlIHJhdGlvIG9mIHRoZSBNZWFuIFNxdWFyZWQgZXJyb3JzLiANCg0KIyMjIEFuYWx5c2lzIG9mIFZhcmlhbmNlIHRhYmxlIGZvciBDbGltYXRlIGRhdGENCg0KDQpOLkIuIGByIHhmdW46OmVtYmVkX2ZpbGUoIi4uLy4uL2RhdGEvQ2xpbWF0ZS5jc3YiKWAgdG8gYmUgYWJsZSB0byBydW4gdGhlIGV4YW1wbGVzIGJlbG93Lg0KDQoNCkZvciB0aGUgY2xpbWF0ZSBkYXRhIHdlIGhhdmUgDQoNCmBgYHtyIGNsaW1hdGV9DQpDbGltYXRlID0gcmVhZC5jc3YoZmlsZT0gJy4uLy4uL2RhdGEvQ2xpbWF0ZS5jc3YnLCBoZWFkZXI9VFJVRSwgcm93Lm5hbWVzID0gMSkNCkNsaW1hdGUubG0wPSBsbShNbkpseVRlbXAgfiAxLCBkYXRhPSBDbGltYXRlKQ0KQ2xpbWF0ZS5sbTEgPSBsbSggTW5KbHlUZW1wfiAuLCBkYXRhPUNsaW1hdGUpDQphbm92YShDbGltYXRlLmxtMCwgQ2xpbWF0ZS5sbTEpDQpgYGANCg0KTm90ZSB0aGF0IHdlIGhhdmUgZXhwbGljaXRseSBjcmVhdGVkIHRoZSBudWxsIG1vZGVsIGBDbGltYXRlLmxtMGAgd2l0aCBubyBwcmVkaWN0b3IgdmFyaWFibGVzLg0KDQpUaGUgdXNlIG9mIHRoZSBgYW5vdmEoKWAgY29tbWFuZCBoYXMgY29tcGFyZWQgdHdvIG1vZGVscyBoZXJlLiBXZSBzaG93IHRoYXQgdGhpcyB3YXkgb2YgdXNpbmcgYGFub3ZhKClgIGlzIHVubmVjZXNzYXJ5IGJlbG93LCBidXQgd2UgZG8gbWFrZSBmcmVxdWVudCB1c2Ugb2YgdGhlIGBhbm92YSgpYCBjb21tYW5kIHdpdGggcmVmZXJlbmNlIHRvIHR3byAob3IgbW9yZSkgbW9kZWxzIGEgbG90IHdoZW4gd29ya2luZyB3aXRoIHJlZ3Jlc3Npb24gbW9kZWxzLg0KDQoNCiMjIE9tbmlidXMgKkYqIFRlc3QgU3RhdGlzdGljcyBpbiBSDQoNClRoZSBhYm92ZSB0ZXN0IG9mIHdoZXRoZXIgdGhlIHJlc3BvbnNlIGlzIHJlbGF0ZWQgdG8gYW55IG9mIHRoZQ0KICAgIGV4cGxhbmF0b3J5IHZhcmlhYmxlcyBpcyBzb21ldGltZXMgY2FsbGVkIGFuICoqb21uaWJ1cyoqICpGKiAgICB0ZXN0LCB3aGlsZSBvdGhlcnMgcmVmZXIgdG8gaXQgYXMgYSAqKip0ZXN0IG9mIG1vZGVsIHV0aWxpdHkqKiouDQoNCldlIGRvIG5vdCBoYXZlIHRvIGRvIHRoZSB0ZXN0IGJ5IGhhbmQsIG9yIGJ5IGZpdHRpbmcgdGhlIG51bGwgbW9kZWwgYmVjYXVzZSBSIHByb3ZpZGVzIHRoZSAqRiogc3RhdGlzdGljDQogICAgYW5kIGNvcnJlc3BvbmRpbmcgKlAqLXZhbHVlIGZvciB0aGlzIHRlc3QgYXMgYSBzdGFuZGFyZCBwYXJ0IG9mIHRoZQ0KICAgIGBzdW1tYXJ5KClgIG91dHB1dCBmb3IgYSBsaW5lYXIgbW9kZWwuDQoNCg0KDQoNCiMjIyBCYWNrIHRvIENsaW1hdGUgZXhhbXBsZQ0KDQpgYGB7ciBzdW1tYXJ5IGluZm99DQpDbGltYXRlLmxtMS5zdW0gPSBzdW1tYXJ5KENsaW1hdGUubG0xKQ0KQ2xpbWF0ZS5sbTEuc3VtDQpuYW1lcyhDbGltYXRlLmxtMS5zdW0pDQpDbGltYXRlLmxtMS5zdW0kci5zcXVhcmVkDQpDbGltYXRlLmxtMS5zdW0kZnN0YXRpc3RpYw0KYGBgDQoNClRoZXNlIGZpZ3VyZXMgYXJlIHRoZSBzYW1lIGFzIHdlcmUgc2VlbiBlYXJsaWVyIHdoZW4gd2UgdXNlZCB0aGUgYGFub3ZhKClgIGNvbW1hbmQuIA0KDQoNCg==