View the
latest recording of this lecture
The two factor models that we have considered so far have assumed
that the overall treatment effect is purely the sum of the main effects
of the factors.
To put it another way, we have assumed that the effect of receiving
level 3 of factor A is the same irrespective of the level of
factor B.
Sometimes this will not be the case because the factors
‘interact’.
We will explore this issue in this lecture.
An Intuitive Introduction to Interactions
Suppose we are looking at two drugs that may reduce hypertension
(high blood pressure).
Factor A has two levels: drug 1 absent, and drug 1
present.
Factor B has two levels: drug 2 absent, and drug 2
present.
Suppose that drug 1 on its own reduces blood pressure by 3 units.
Suppose that drug 2 on its own reduces blood pressure by 5 units.
It is not necessarily reasonable to assume that combined effect of
drugs will be to reduce blood pressure by 8 units. Drugs may interact to
give combined effect smaller than this.
The ‘main effects’ model for two factors is
\[Y_{ijk} = \mu + \alpha_i + \beta_j +
\varepsilon_{ijk}\]
For the two drug example we would have \(\alpha_2 = -3\) and \(\beta_2 = -5\).
According to the main effects model, the treatment effect with both
drugs (relative to the baseline level) is \(\alpha_2 + \beta_2 = -8\).
To represent an interactive effect between the drugs we need to
introduce an extra term in the model:
\[Y_{ijk} = \mu + \alpha_i + \beta_j +
(\alpha\beta)_{ij} + \varepsilon_{ijk}\]
Here \((\alpha\beta)_{ij}\) is the
so-called interaction term in the model.
The notation \((\alpha\beta)_{ij}\)
represents new parameters (not a ’multiplication’ of
the \(\alpha\) and \(\beta\) parameters).
It is necessary to impose constraints on the interaction parameters
to avoid overparameterization.
The treatment constraint sets all \((\alpha\beta)_{ij}=0\) when either
i or j is one.
Hence, in the two drug example, only \((\alpha\beta)_{22}\) is non zero.
For the model with interaction, the treatment effect in the presence
of both drugs is \(\alpha_2 + \beta_2 +
(\alpha\beta)_{22} = -8 + (\alpha\beta)_{22}\), so that \((\alpha\beta)_{22}\) here represents the
change from the main effects model that is caused by the interaction of
the drugs.
Two-Way Model with Interaction
For a general model with two factors, the model with interaction
is
\[Y_{ijk} = \mu + \alpha_i + \beta_j +
(\alpha\beta)_{ij} + \varepsilon_{ijk}\]
As we have seen, both the main effects parameters (\(\alpha_i\), \(\beta_j\)) and the interaction parameters
\((\alpha\beta)_{ij}\) must be
constrained. We assume use of the treatment constrained (all parameters
indexed by level 1 of either factor are zero).
If factor A has K levels and factor B has
L levels then there are (K-1)(L-1) unconstrained
interaction parameters.
Modelling with an interaction term allows any pattern of means
between the different factor levels (no particular structure).
Inference for the Two-Way Model with Interaction
Parameter estimation is done by the method of least squares. Fitted
values and residuals continue to be defined in the usual way.
The first test that is commonly done with the interaction model is to
assess whether the interaction term in the model is statistically
significant.
This test will involve multiple parameters (in general), and so will
be done using the F test.
If the interaction term is important, then no more testing is
necessary.
In particular, if a model contains an interaction term then
it must also contain the corresponding main effects (even if
these appear to be non-significant).
Testing for an Interaction Between Factors
Testing for the importance of the interaction is equivalent to
comparing models
\(M0:~~~Y_{ijk} = \mu + \alpha_i + \beta_j
+ \varepsilon_{ijk}\) and \(M1:~~~Y_{ijk} = \mu + \alpha_i + \beta_j +
(\alpha\beta)_{ij} + \varepsilon_{ijk}\)
In terms of hypothesis tests for parameters, we wish to test
H0: \((\alpha\beta)_{ij} = 0~\mbox{for all}~i,
j\)
H1: \((\alpha\beta)_{ij}~\mbox{not zero for all}~i,
j\)
The F test statistic is
\[F = \frac{[RSS_{M0} -
RSS_{M1}]/[(K-1)(L-1)]}{RSS_{M1}/(n-KL)}\]
with the corresponding P-value computed in the usual
manner.
ANOVA Table for the Interaction Model
The information for conducting an F test for an interaction
is usually displayed in an (extended) ANOVA table.
Factor A |
\(K-1\) |
\(SSA\) |
\(MSA\) |
\(f_a\) |
\(P_A\) |
Factor B (adj.A) |
\(L-1\) |
\(SSB|A\) |
\(MSB|A\) |
\(f_{B|A}\) |
\(P_{B|A}\) |
Interaction |
\((K-1)(L-1)\) |
\(SSI\) |
\(MSI\) |
\(f_I\) |
\(P_I\) |
Residual |
\(n-KL\) |
\(RSS\) |
\(RMS\) |
|
|
Total |
\(n-1\) |
\(TSS\) |
|
|
|
The sum of squares for the interaction (\(SSI\) in the table) can be computed by
subtraction (difference in RSS for models M0 and
M1).
The F test statistic for the interaction is \(f_I = MSI/RMS\)
Rat Weight Gain and Diet
This Example concerns the data introduced in an earlier Task. The
response is rat weight gain. There are two explanatory factors:
- Protein: either beef or cereal;
- Amount: either low or high.
The data contains ten replicates at each treatment.
Those rats
In this example we will fit a model with interaction.
Design Matrix for the Rat Diet Data
Write down the model for the rat diet data in matrix format.
Take care to specify clearly the design matrix.
Assume the treatment constraint on parameters (with reference levels
chosen as Beef
for Protein
and
High
for Amount
, following R’s default
alphabetical allocation).
Analysis of Rat Diet Data
Download ratdiet.csv
## RatDiet <- read.csv(file = "ratdiet.csv", header = TRUE)
RatDiet.lm <- lm(Gain ~ Amount * Protein, data = RatDiet)
By default (alphabetical ordering), levels Beef
for
Protein
and High
for Amount
are
set as reference (level 1).
On the RHS of the R formula, the syntax A*B
for factors
A
and B
indicates the main effects of the
factors themselves and their interaction, which is written
A:B
.
Hence, for example,
Gain ~ Amount*Protein
and
Gain ~ Amount + Protein + Amount:Protein
are the same formula.
Anova table:
Analysis of Variance Table
Response: Gain
Df Sum Sq Mean Sq F value Pr(>F)
Amount 1 1299.6 1299.60 5.8123 0.02114 *
Protein 1 220.9 220.90 0.9879 0.32688
Amount:Protein 1 883.6 883.60 3.9518 0.05447 .
Residuals 36 8049.4 223.59
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
The P-value for testing for an interaction between
Protein
and Amount
is P=0.055, from
an F-statistic of 3.95 on 1, 36 degrees of
freedom.
There is some weak evidence of the existence of an interaction,
although it does not quite reach formal statistical significance at the
5% level.
Summary Table:
Call:
lm(formula = Gain ~ Amount * Protein, data = RatDiet)
Residuals:
Min 1Q Median 3Q Max
-29.90 -9.90 2.05 10.85 25.10
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 100.000 4.729 21.148 < 2e-16 ***
AmountLow -20.800 6.687 -3.110 0.00364 **
ProteinCereal -14.100 6.687 -2.109 0.04201 *
AmountLow:ProteinCereal 18.800 9.457 1.988 0.05447 .
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 14.95 on 36 degrees of freedom
Multiple R-squared: 0.23, Adjusted R-squared: 0.1658
F-statistic: 3.584 on 3 and 36 DF, p-value: 0.02297
Fitted Values
In the previous example, write down the fitted values for each of the
four possible treatments.
Obtain these using R code.
cbind(RatDiet, RatDiet.lm$fitted.values)
Gain Protein Amount RatDiet.lm$fitted.values
1 90 Beef Low 79.2
2 76 Beef Low 79.2
3 90 Beef Low 79.2
4 64 Beef Low 79.2
5 86 Beef Low 79.2
6 51 Beef Low 79.2
7 72 Beef Low 79.2
8 90 Beef Low 79.2
9 95 Beef Low 79.2
10 78 Beef Low 79.2
11 73 Beef High 100.0
12 102 Beef High 100.0
13 118 Beef High 100.0
14 104 Beef High 100.0
15 81 Beef High 100.0
16 107 Beef High 100.0
17 100 Beef High 100.0
18 87 Beef High 100.0
19 117 Beef High 100.0
20 111 Beef High 100.0
21 107 Cereal Low 83.9
22 95 Cereal Low 83.9
23 97 Cereal Low 83.9
24 80 Cereal Low 83.9
25 98 Cereal Low 83.9
26 74 Cereal Low 83.9
27 74 Cereal Low 83.9
28 67 Cereal Low 83.9
29 89 Cereal Low 83.9
30 58 Cereal Low 83.9
31 98 Cereal High 85.9
32 74 Cereal High 85.9
33 56 Cereal High 85.9
34 111 Cereal High 85.9
35 95 Cereal High 85.9
36 88 Cereal High 85.9
37 82 Cereal High 85.9
38 77 Cereal High 85.9
39 86 Cereal High 85.9
40 92 Cereal High 85.9
LS0tDQp0aXRsZTogIkxlY3R1cmUgMjQ6IEZhY3RvcnMgd2l0aCBJbnRlcmFjdGlvbnMiDQpzdWJ0aXRsZTogMTYxLjI1MSBSZWdyZXNzaW9uIE1vZGVsbGluZw0KYXV0aG9yOiAiUHJlc2VudGVkIGJ5IEpvbmF0aGFuIEdvZGZyZXkgPGEuai5nb2RmcmV5QG1hc3NleS5hYy5uej4iICANCmRhdGU6ICJXZWVrIDggb2YgU2VtZXN0ZXIgMiwgYHIgbHVicmlkYXRlOjp5ZWFyKGx1YnJpZGF0ZTo6bm93KCkpYCINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgdGhlbWU6IHlldGkNCiAgICBoaWdobGlnaHQ6IHRhbmdvDQogIGh0bWxfbm90ZWJvb2s6DQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHRoZW1lOiB5ZXRpDQogICAgaGlnaGxpZ2h0OiB0YW5nbw0KICBpb3NsaWRlc19wcmVzZW50YXRpb246DQogICAgd2lkZXNjcmVlbjogdHJ1ZQ0KICAgIHNtYWxsZXI6IHRydWUNCiAgd29yZF9kb2N1bWVudDogZGVmYXVsdA0KICBzbGlkeV9wcmVzZW50YXRpb246IA0KICAgIHRoZW1lOiB5ZXRpDQogICAgaGlnaGxpZ2h0OiB0YW5nbw0KICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQNCi0tLQ0KDQoNCg0KDQoNCltWaWV3IHRoZSBsYXRlc3QgcmVjb3JkaW5nIG9mIHRoaXMgbGVjdHVyZV0oaHR0cHM6Ly9SLVJlc291cmNlcy5tYXNzZXkuYWMubnovdmlkZW9zLzI1MUwyNC5tcDQpDQo8IS0tLSBEYXRhIGlzIG9uDQpodHRwczovL3ItcmVzb3VyY2VzLm1hc3NleS5hYy5uei9kYXRhLzE2MTI1MS8NCi0tLT4NCg0KYGBge3Igc2V0dXAsIHB1cmw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9DQpsaWJyYXJ5KGtuaXRyKQ0Kb3B0c19jaHVuayRzZXQoZGV2PWMoInBuZyIsICJwZGYiKSkNCm9wdHNfY2h1bmskc2V0KGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTcsIGZpZy5wYXRoPSJGaWd1cmVzLyIsIGZpZy5hbHQ9InVubGFiZWxsZWQiKQ0Kb3B0c19jaHVuayRzZXQoY29tbWVudD0iIiwgZmlnLmFsaWduPSJjZW50ZXIiLCB0aWR5PVRSVUUpDQpvcHRpb25zKGtuaXRyLmthYmxlLk5BID0gJycpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoYnJvb20pDQpgYGANCg0KDQo8IS0tLSBEbyBub3QgZWRpdCBhbnl0aGluZyBhYm92ZSB0aGlzIGxpbmUuIC0tLT4NCg0KVGhlIHR3byBmYWN0b3IgbW9kZWxzIHRoYXQgd2UgaGF2ZSBjb25zaWRlcmVkIHNvIGZhciBoYXZlIGFzc3VtZWQgICAgdGhhdCB0aGUgb3ZlcmFsbCB0cmVhdG1lbnQgZWZmZWN0IGlzIHB1cmVseSB0aGUgc3VtIG9mIHRoZSBtYWluDQogICAgZWZmZWN0cyBvZiB0aGUgZmFjdG9ycy4NCg0KVG8gcHV0IGl0IGFub3RoZXIgd2F5LCB3ZSBoYXZlIGFzc3VtZWQgdGhhdCB0aGUgZWZmZWN0IG9mIHJlY2VpdmluZyBsZXZlbCAzIG9mIGZhY3RvciAqQSogaXMgdGhlIHNhbWUgaXJyZXNwZWN0aXZlIG9mIHRoZSBsZXZlbCBvZiBmYWN0b3IgKkIqLg0KDQpTb21ldGltZXMgdGhpcyB3aWxsIG5vdCBiZSB0aGUgY2FzZSBiZWNhdXNlIHRoZSBmYWN0b3JzIOKAmGludGVyYWN04oCZLg0KDQpXZSB3aWxsIGV4cGxvcmUgdGhpcyBpc3N1ZSBpbiB0aGlzIGxlY3R1cmUuDQoNCiMjIEFuIEludHVpdGl2ZSBJbnRyb2R1Y3Rpb24gdG8gSW50ZXJhY3Rpb25zDQoNClN1cHBvc2Ugd2UgYXJlIGxvb2tpbmcgYXQgdHdvIGRydWdzIHRoYXQgbWF5IHJlZHVjZSBoeXBlcnRlbnNpb24NCiAgICAoaGlnaCBibG9vZCBwcmVzc3VyZSkuDQoNCkZhY3RvciAqQSogaGFzIHR3byBsZXZlbHM6IGRydWcgMSBhYnNlbnQsIGFuZCBkcnVnIDEgcHJlc2VudC4NCg0KRmFjdG9yICpCKiBoYXMgdHdvIGxldmVsczogZHJ1ZyAyIGFic2VudCwgYW5kIGRydWcgMiBwcmVzZW50Lg0KDQpTdXBwb3NlIHRoYXQgZHJ1ZyAxIG9uIGl0cyBvd24gcmVkdWNlcyBibG9vZCBwcmVzc3VyZSBieSAzIHVuaXRzLg0KDQpTdXBwb3NlIHRoYXQgZHJ1ZyAyIG9uIGl0cyBvd24gcmVkdWNlcyBibG9vZCBwcmVzc3VyZSBieSA1IHVuaXRzLg0KDQpJdCBpcyBub3QgbmVjZXNzYXJpbHkgcmVhc29uYWJsZSB0byBhc3N1bWUgdGhhdCBjb21iaW5lZCBlZmZlY3Qgb2YgZHJ1Z3Mgd2lsbCBiZSB0byByZWR1Y2UgYmxvb2QgcHJlc3N1cmUgYnkgOCB1bml0cy4gRHJ1Z3MgbWF5IGludGVyYWN0IHRvIGdpdmUgY29tYmluZWQgZWZmZWN0IHNtYWxsZXIgdGhhbiB0aGlzLg0KDQoNClRoZSDigJhtYWluIGVmZmVjdHPigJkgbW9kZWwgZm9yIHR3byBmYWN0b3JzIGlzDQoNCiQkWV97aWprfSA9IFxtdSArIFxhbHBoYV9pICsgXGJldGFfaiArIFx2YXJlcHNpbG9uX3tpamt9JCQNCg0KRm9yIHRoZSB0d28gZHJ1ZyBleGFtcGxlIHdlIHdvdWxkIGhhdmUgJFxhbHBoYV8yID0gLTMkIGFuZCAkXGJldGFfMiA9IC01JC4NCg0KQWNjb3JkaW5nIHRvIHRoZSBtYWluIGVmZmVjdHMgbW9kZWwsIHRoZSB0cmVhdG1lbnQgZWZmZWN0IHdpdGggYm90aA0KICAgIGRydWdzIChyZWxhdGl2ZSB0byB0aGUgYmFzZWxpbmUgbGV2ZWwpIGlzICRcYWxwaGFfMiArIFxiZXRhXzIgPSAtOCQuDQoNClRvIHJlcHJlc2VudCBhbiBpbnRlcmFjdGl2ZSBlZmZlY3QgYmV0d2VlbiB0aGUgZHJ1Z3Mgd2UgbmVlZCB0bw0KICAgIGludHJvZHVjZSBhbiBleHRyYSB0ZXJtIGluIHRoZSBtb2RlbDoNCg0KJCRZX3tpamt9ID0gXG11ICsgXGFscGhhX2kgKyBcYmV0YV9qICsgKFxhbHBoYVxiZXRhKV97aWp9ICsgXHZhcmVwc2lsb25fe2lqa30kJA0KDQpIZXJlICQoXGFscGhhXGJldGEpX3tpan0kIGlzIHRoZSBzby1jYWxsZWQgKippbnRlcmFjdGlvbg0KICAgIHRlcm0qKiBpbiB0aGUgbW9kZWwuDQoNClRoZSBub3RhdGlvbiAkKFxhbHBoYVxiZXRhKV97aWp9JCByZXByZXNlbnRzIG5ldyBwYXJhbWV0ZXJzDQogICAgKCoqbm90KiogYSDigJltdWx0aXBsaWNhdGlvbuKAmSBvZiB0aGUgJFxhbHBoYSQgYW5kICRcYmV0YSQNCiAgICBwYXJhbWV0ZXJzKS4NCg0KDQpJdCBpcyBuZWNlc3NhcnkgdG8gaW1wb3NlIGNvbnN0cmFpbnRzIG9uIHRoZSBpbnRlcmFjdGlvbiBwYXJhbWV0ZXJzDQogICAgdG8gYXZvaWQgb3ZlcnBhcmFtZXRlcml6YXRpb24uDQoNClRoZSB0cmVhdG1lbnQgY29uc3RyYWludCBzZXRzIGFsbCAkKFxhbHBoYVxiZXRhKV97aWp9PTAkIHdoZW4NCiAgICBlaXRoZXIgKmkqIG9yICpqKiBpcyBvbmUuDQoNCkhlbmNlLCBpbiB0aGUgdHdvIGRydWcgZXhhbXBsZSwgb25seSAkKFxhbHBoYVxiZXRhKV97MjJ9JCBpcyBub24NCiAgICB6ZXJvLg0KDQpGb3IgdGhlIG1vZGVsIHdpdGggaW50ZXJhY3Rpb24sIHRoZSB0cmVhdG1lbnQgZWZmZWN0IGluIHRoZSBwcmVzZW5jZQ0KICAgIG9mIGJvdGggZHJ1Z3MgaXMgJFxhbHBoYV8yICsgXGJldGFfMiArIChcYWxwaGFcYmV0YSlfezIyfSA9IC04ICsgKFxhbHBoYVxiZXRhKV97MjJ9JCwNCiAgICBzbyB0aGF0ICQoXGFscGhhXGJldGEpX3syMn0kIGhlcmUgcmVwcmVzZW50cyB0aGUgY2hhbmdlIGZyb20gdGhlDQogICAgbWFpbiBlZmZlY3RzIG1vZGVsIHRoYXQgaXMgY2F1c2VkIGJ5IHRoZSBpbnRlcmFjdGlvbiBvZiB0aGUgZHJ1Z3MuDQoNCiMjIFR3by1XYXkgTW9kZWwgd2l0aCBJbnRlcmFjdGlvbg0KDQpGb3IgYSBnZW5lcmFsIG1vZGVsIHdpdGggdHdvIGZhY3RvcnMsIHRoZSBtb2RlbCB3aXRoIGludGVyYWN0aW9uIGlzDQoNCiQkWV97aWprfSA9IFxtdSArIFxhbHBoYV9pICsgXGJldGFfaiArIChcYWxwaGFcYmV0YSlfe2lqfSArIFx2YXJlcHNpbG9uX3tpamt9JCQNCg0KQXMgd2UgaGF2ZSBzZWVuLCBib3RoIHRoZSBtYWluIGVmZmVjdHMgcGFyYW1ldGVycyAoJFxhbHBoYV9pJCwgJFxiZXRhX2okKSBhbmQgdGhlIGludGVyYWN0aW9uIHBhcmFtZXRlcnMgJChcYWxwaGFcYmV0YSlfe2lqfSQNCiAgICBtdXN0IGJlIGNvbnN0cmFpbmVkLiBXZSBhc3N1bWUgdXNlIG9mIHRoZSB0cmVhdG1lbnQgY29uc3RyYWluZWQgKGFsbA0KICAgIHBhcmFtZXRlcnMgaW5kZXhlZCBieSBsZXZlbCAxIG9mIGVpdGhlciBmYWN0b3IgYXJlIHplcm8pLg0KDQpJZiBmYWN0b3IgKkEqIGhhcyAqSyogbGV2ZWxzIGFuZCBmYWN0b3IgKkIqIGhhcyAqTCogbGV2ZWxzDQogICAgdGhlbiB0aGVyZSBhcmUgKihLLTEpKEwtMSkqIHVuY29uc3RyYWluZWQgaW50ZXJhY3Rpb24gcGFyYW1ldGVycy4NCg0KTW9kZWxsaW5nIHdpdGggYW4gaW50ZXJhY3Rpb24gdGVybSBhbGxvd3MgYW55ICAgIHBhdHRlcm4gb2YgbWVhbnMgYmV0d2VlbiB0aGUgZGlmZmVyZW50IGZhY3RvciBsZXZlbHMgKG5vIHBhcnRpY3VsYXIgICAgc3RydWN0dXJlKS4NCg0KIyMgSW5mZXJlbmNlIGZvciB0aGUgVHdvLVdheSBNb2RlbCB3aXRoIEludGVyYWN0aW9uDQoNClBhcmFtZXRlciBlc3RpbWF0aW9uIGlzIGRvbmUgYnkgdGhlIG1ldGhvZCBvZiBsZWFzdCBzcXVhcmVzLiBGaXR0ZWQgdmFsdWVzIGFuZCByZXNpZHVhbHMgY29udGludWUgdG8gYmUgZGVmaW5lZCBpbiB0aGUgdXN1YWwgd2F5Lg0KDQpUaGUgZmlyc3QgdGVzdCB0aGF0IGlzIGNvbW1vbmx5IGRvbmUgd2l0aCB0aGUgaW50ZXJhY3Rpb24gbW9kZWwgaXMgICAgdG8gYXNzZXNzIHdoZXRoZXIgdGhlIGludGVyYWN0aW9uIHRlcm0gaW4gdGhlIG1vZGVsIGlzIHN0YXRpc3RpY2FsbHkNCiAgICBzaWduaWZpY2FudC4NCg0KVGhpcyB0ZXN0IHdpbGwgaW52b2x2ZSBtdWx0aXBsZSBwYXJhbWV0ZXJzIChpbiBnZW5lcmFsKSwgYW5kIHNvIHdpbGwNCiAgICBiZSBkb25lIHVzaW5nIHRoZSAqRiogdGVzdC4NCg0KSWYgdGhlIGludGVyYWN0aW9uIHRlcm0gaXMgaW1wb3J0YW50LCB0aGVuIG5vIG1vcmUgdGVzdGluZyBpcw0KICAgIG5lY2Vzc2FyeS4NCg0KSW4gcGFydGljdWxhciwgKippZiBhIG1vZGVsIGNvbnRhaW5zIGFuIGludGVyYWN0aW9uIHRlcm0gdGhlbiBpdA0KICAgIG11c3QgYWxzbyBjb250YWluIHRoZSBjb3JyZXNwb25kaW5nIG1haW4gZWZmZWN0cyoqIChldmVuIGlmIHRoZXNlDQogICAgYXBwZWFyIHRvIGJlIG5vbi1zaWduaWZpY2FudCkuDQoNCiMjIFRlc3RpbmcgZm9yIGFuIEludGVyYWN0aW9uIEJldHdlZW4gRmFjdG9ycw0KDQpUZXN0aW5nIGZvciB0aGUgaW1wb3J0YW5jZSBvZiB0aGUgaW50ZXJhY3Rpb24gaXMgZXF1aXZhbGVudCB0bw0KICAgIGNvbXBhcmluZyBtb2RlbHMNCg0KJE0wOn5+fllfe2lqa30gPSBcbXUgKyBcYWxwaGFfaSArIFxiZXRhX2ogKyBcdmFyZXBzaWxvbl97aWprfSQgYW5kDQokTTE6fn5+WV97aWprfSA9IFxtdSArIFxhbHBoYV9pICsgXGJldGFfaiArIChcYWxwaGFcYmV0YSlfe2lqfSArIFx2YXJlcHNpbG9uX3tpamt9JA0KDQpJbiB0ZXJtcyBvZiBoeXBvdGhlc2lzIHRlc3RzIGZvciBwYXJhbWV0ZXJzLCB3ZSB3aXNoIHRvIHRlc3QgICAgDQoNCipIfjB+KjogJChcYWxwaGFcYmV0YSlfe2lqfSA9IDB+XG1ib3h7Zm9yIGFsbH1+aSwgaiQNCg0KKkh+MX4qOiAkKFxhbHBoYVxiZXRhKV97aWp9flxtYm94e25vdCB6ZXJvIGZvciBhbGx9fmksIGokDQoNClRoZSAqRiogdGVzdCBzdGF0aXN0aWMgaXMNCg0KJCRGID0gXGZyYWN7W1JTU197TTB9IC0gUlNTX3tNMX1dL1soSy0xKShMLTEpXX17UlNTX3tNMX0vKG4tS0wpfSQkDQoNCndpdGggdGhlIGNvcnJlc3BvbmRpbmcgKlAqLXZhbHVlIGNvbXB1dGVkIGluIHRoZSB1c3VhbCBtYW5uZXIuDQoNCiMjIEFOT1ZBIFRhYmxlIGZvciB0aGUgSW50ZXJhY3Rpb24gTW9kZWwNCg0KVGhlIGluZm9ybWF0aW9uIGZvciBjb25kdWN0aW5nIGFuICpGKiB0ZXN0IGZvciBhbiBpbnRlcmFjdGlvbiBpcyB1c3VhbGx5DQpkaXNwbGF5ZWQgaW4gYW4gKGV4dGVuZGVkKSBBTk9WQQ0KdGFibGUuDQoNCnwgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgIERmICAgICAgIHwgICAgU3VtIFNxIHwgICBNZWFuIFNxIHwgICAgIEYgdmFsdWUgfCAgICAgUCB2YWx1ZSB8DQp8IDotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gfCA6LS0tLS0tLS0tLS0tOiB8IC0tLS0tLS0tOiB8IC0tLS0tLS0tOiB8IC0tLS0tLS0tLS06IHwgLS0tLS0tLS0tLTogfA0KfCBGYWN0b3IgKkEqICAgICAgICAgICAgICB8ICRLLTEkICAgICB8ICRTU0EkIHwgJE1TQSQgfCAkZl9hJCB8ICRQX0EkIHwNCnwgRmFjdG9yICpCKiAoYWRqLipBKikgfCAkTC0xJCAgICAgfCAkU1NCfEEkIHwgJE1TQnxBJCB8ICRmX3tCfEF9JCB8ICRQX3tCfEF9JCB8DQp8IEludGVyYWN0aW9uICAgICAgICAgICAgICAgfCAkKEstMSkoTC0xKSQgfCAkU1NJJCB8ICRNU0kkIHwgJGZfSSQgfCAkUF9JJCB8DQp8IFJlc2lkdWFsICAgICAgICAgICAgICAgICAgfCAkbi1LTCQgICAgfCAkUlNTJCB8ICRSTVMkIHwgICAgICAgICAgICAgfCAgICAgICAgICAgICB8DQp8IFRvdGFsICAgICAgICAgICAgICAgICAgICAgfCAkbi0xJCAgICAgfCAgICRUU1MkIHwgICAgICAgICAgIHwgICAgICAgICAgICAgfCAgICAgICAgICAgICB8DQoNClRoZSBzdW0gb2Ygc3F1YXJlcyBmb3IgdGhlIGludGVyYWN0aW9uICgkU1NJJCBpbiB0aGUgdGFibGUpIGNhbiBiZSBjb21wdXRlZCBieQ0KICAgIHN1YnRyYWN0aW9uIChkaWZmZXJlbmNlIGluIFJTUyBmb3IgbW9kZWxzICpNMCogYW5kICpNMSopLg0KDQpUaGUgKkYqIHRlc3Qgc3RhdGlzdGljIGZvciB0aGUgaW50ZXJhY3Rpb24gaXMgJGZfSSA9IE1TSS9STVMkDQoNCiMjIFJhdCBXZWlnaHQgR2FpbiBhbmQgRGlldA0KDQoNCg0KVGhpcyBFeGFtcGxlIGNvbmNlcm5zIHRoZSBkYXRhIGludHJvZHVjZWQgaW4gYW4gZWFybGllciBUYXNrLiBUaGUgcmVzcG9uc2UgaXMgcmF0IHdlaWdodCBnYWluLiBUaGVyZSBhcmUgdHdvIGV4cGxhbmF0b3J5IGZhY3RvcnM6DQoNCjEuIFByb3RlaW46IGVpdGhlciBiZWVmIG9yIGNlcmVhbDsNCjIuIEFtb3VudDogZWl0aGVyIGxvdyBvciBoaWdoLg0KDQpUaGUgZGF0YSBjb250YWlucyB0ZW4gcmVwbGljYXRlcyBhdCBlYWNoIHRyZWF0bWVudC4NCg0KIVtUaG9zZSByYXRzXSguLi9ncmFwaGljcy9yYXRzLmpwZykNCg0KDQoNCg0KSW4gdGhpcyBleGFtcGxlIHdlIHdpbGwgZml0IGEgbW9kZWwgd2l0aCBpbnRlcmFjdGlvbi4NCg0KIyMjIERlc2lnbiBNYXRyaXggZm9yIHRoZSBSYXQgRGlldCBEYXRhDQoNCldyaXRlIGRvd24gdGhlIG1vZGVsIGZvciB0aGUgcmF0IGRpZXQgZGF0YSBpbiBtYXRyaXggZm9ybWF0Lg0KDQpUYWtlIGNhcmUgdG8gc3BlY2lmeSBjbGVhcmx5IHRoZSBkZXNpZ24gbWF0cml4Lg0KDQpBc3N1bWUgdGhlIHRyZWF0bWVudCBjb25zdHJhaW50IG9uIHBhcmFtZXRlcnMgKHdpdGggcmVmZXJlbmNlIGxldmVscw0KICAgIGNob3NlbiBhcyBgQmVlZmAgZm9yIGBQcm90ZWluYCBhbmQgYEhpZ2hgIGZvciBgQW1vdW50YCwgZm9sbG93aW5nIFLigJlzIGRlZmF1bHQgYWxwaGFiZXRpY2FsDQogICAgYWxsb2NhdGlvbikuDQoNCiMjIyBBbmFseXNpcyBvZiBSYXQgRGlldCBEYXRhDQoNCmByIHhmdW46OmVtYmVkX2ZpbGUoIi4uLy4uL2RhdGEvcmF0ZGlldC5jc3YiKWANCg0KYGBge3IgUmF0RGlldC5sbSwgZWNobz0tMSwgZXZhbD0tMn0NClJhdERpZXQgPC0gcmVhZC5jc3YoZmlsZT0iLi4vLi4vZGF0YS9yYXRkaWV0LmNzdiIsIGhlYWRlcj1UUlVFKQ0KUmF0RGlldCA8LSByZWFkLmNzdihmaWxlPSJyYXRkaWV0LmNzdiIsIGhlYWRlcj1UUlVFKQ0KUmF0RGlldC5sbSA8LSBsbShHYWluIH4gQW1vdW50KlByb3RlaW4sIGRhdGE9UmF0RGlldCkNCmBgYA0KDQpCeSBkZWZhdWx0IChhbHBoYWJldGljYWwgb3JkZXJpbmcpLCBsZXZlbHMgYEJlZWZgIGZvciBgUHJvdGVpbmAgYW5kIGBIaWdoYCBmb3IgYEFtb3VudGAgYXJlIHNldCBhcw0KICAgIHJlZmVyZW5jZSAobGV2ZWwgMSkuDQoNCk9uIHRoZSBSSFMgb2YgdGhlIFIgZm9ybXVsYSwgdGhlIHN5bnRheCBgQSpCYCBmb3IgZmFjdG9ycyBgQWAgYW5kDQogICAgYEJgIGluZGljYXRlcyB0aGUgbWFpbiBlZmZlY3RzIG9mIHRoZSBmYWN0b3JzIHRoZW1zZWx2ZXMgYW5kIHRoZWlyDQogICAgaW50ZXJhY3Rpb24sIHdoaWNoIGlzIHdyaXR0ZW4gYEE6QmAuDQoNCkhlbmNlLCBmb3IgZXhhbXBsZSwgIA0KICAgIGBHYWluIH4gQW1vdW50KlByb3RlaW5gICANCiAgICBhbmQgIA0KICAgIGBHYWluIH4gQW1vdW50ICsgUHJvdGVpbiArIEFtb3VudDpQcm90ZWluYCAgDQogICAgYXJlIHRoZSBzYW1lIGZvcm11bGEuDQoNCkFub3ZhIHRhYmxlOg0KDQpgYGB7ciBhbm92YVJhdERpZXQubG19DQphbm92YShSYXREaWV0LmxtKQ0KYGBgDQoNCg0KVGhlICpQKi12YWx1ZSBmb3IgdGVzdGluZyBmb3IgYW4gaW50ZXJhY3Rpb24gYmV0d2VlbiBgUHJvdGVpbmAgYW5kIGBBbW91bnRgIGlzDQogICAgKlA9MC4wNTUqLCBmcm9tIGFuICpGKi1zdGF0aXN0aWMgb2YgKjMuOTUqIG9uICoxLCAzNiogICAgZGVncmVlcyBvZiBmcmVlZG9tLg0KDQpUaGVyZSBpcyBzb21lIHdlYWsgZXZpZGVuY2Ugb2YgdGhlIGV4aXN0ZW5jZSBvZiBhbiBpbnRlcmFjdGlvbiwNCiAgICBhbHRob3VnaCBpdCBkb2VzIG5vdCBxdWl0ZSByZWFjaCBmb3JtYWwgc3RhdGlzdGljYWwgc2lnbmlmaWNhbmNlIGF0DQogICAgdGhlIDUlIGxldmVsLg0KDQpTdW1tYXJ5IFRhYmxlOg0KDQpgYGB7ciBzdW1tYXJ5UmF0RGlldC5sbX0NCnN1bW1hcnkoUmF0RGlldC5sbSkNCmBgYA0KDQoNCiMjIyBGaXR0ZWQgVmFsdWVzIA0KDQpJbiB0aGUgcHJldmlvdXMgZXhhbXBsZSwgd3JpdGUgZG93biB0aGUgZml0dGVkIHZhbHVlcyBmb3IgZWFjaCBvZg0KICAgIHRoZSBmb3VyIHBvc3NpYmxlIHRyZWF0bWVudHMuDQoNCk9idGFpbiB0aGVzZSB1c2luZyBSIGNvZGUuDQoNCmBgYHtyfQ0KY2JpbmQoUmF0RGlldCwgUmF0RGlldC5sbSRmaXR0ZWQudmFsdWVzKQ0KYGBgDQo=