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:

  1. Is the mean response related to any of the predictors?
  2. 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:

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)}\]

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…

unlabelled

Probability density functions for F distributions with numerator df of 3 (left) and 10 (right), and denominator df of (10 (upper) and 30 (lower)

… 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.)

Source Sum of squares df Mean Square F
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
names(Climate.lm1.sum)
 [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==