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.

Df Sum Sq Mean Sq F value P value
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:

  1. Protein: either beef or cereal;
  2. Amount: either low or high.

The data contains ten replicates at each treatment.

Those rats
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:

anova(RatDiet.lm)
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:

summary(RatDiet.lm)

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=