Statische test:
Welke test kan men
uitvoeren om het gemiddelde gewicht simultaan te vergelijken tussen alle
soorten voeding? Wat is de link met het lineair model? Geef de nul- en
alternatieve hypothese van deze test.
In vorige oefening zagen we enkel de two-sample t-test om twee
gemiddelden met elkaar vergelijken. We hebben echter ook reeds gezien
dat de two-sample t-test een specifieke versie is van een lineair model,
namelijk van een lineair model waarbij de covariaat een categorische
variabele \(X\) is met \(2\) levels, i.e. \[ E[Y_i] = \beta_0 + \beta_1 X_i \]
Dit lineair model kan echter ook makkelijk veralgemeend worden naar
factoren met meerdere levels.
\[ E[Y_i] = \beta_0 + \beta_1 X_{1i} +
\beta_2 X_{2i} \]
Waarbij \(X_{1i}\) gelijk is aan 1
wanneer de voeding linseed is en anders 0. Anderzijds is \(X_{2i}\) gelijk aan 1 bij soybeans en
gelijk aan 0 bij de andere voedingen.
Er bestaat een manier waarbij we alle levels simultaan kunnen
testen, men zal namelijk testen of de gehele categorische
variabele een invloed heeft op de respons variabele. In de context van
ons voorbeeld, zal men kunnen testen of de voeding-soort überhaupt een
effect heeft op het gemiddelde gewicht van kuikentjes. Zo’n een test
heet een one-way ANOVA.
Stel dat \(\mu_1\) het gemiddelde
gewicht van kuikens voor caseïne voorstelt, en idem voor \(\mu_2\) en \(\mu_3\). De nul- en alternatieve hypothese
voor een ANOVA kan men dan voorstellen als
\(H_0\): \(\mu_1=\mu_2=\mu_3\)
\(H_A\): Voor minstens één \(i \ne j\) is \(\mu_i \neq \mu_j\): met andere woorden
\(\mu_1 \ne \mu_2\) of \(\mu_1 \ne \mu_3\) of \(\mu_2 \ne \mu_3\)
In woorden, zegt de nulhypothese dat het gemiddelde gewicht van
kuikens onafhankelijk is van de voeding: er is geen systematisch
verschil in gemiddeld gewicht van het kuiken. De alternatieve hypothese
zegt dat het gemiddelde gewicht verschilt tussen minstens twee
voeding-soorten. Merk op dat men bij het verwerpen van de
nulhypothese niet weet tussen welke soorten er een
verschil is!
Indien we de ANOVA testen op basis van het lineair model kunnen we
ook de volgende nul- en alternatieve hypothese opstellen:
\(H_0\): \(\beta_1 = \beta_2 = 0\)
\(H_A\): \(\beta_1 \ne 0\) of \(\beta_2 \ne 0\)
Geef de assumpties
voor dit model en ga deze na:
Zoals beschreven in de cursus, veronderstelt ANOVA een locatie-shift.
Dit wil zeggen dat elke groep een gelijke variantie heeft en er enkel
shifts in gemiddelde kunnen optreden. Een andere assumptie is dat de
data van elke groep normaal verdeeld is, en dat de observaties
onafhankelijk van elkaar zijn.
Er zijn dus drie assumpties die moeten voldaan zijn. Aangezien we in
de data niet kunnen waarnemen of de observaties onafhankelijk zijn van
elkaar, moeten we dit veronderstellen dat de onderzoeker dit correct
heeft uitgevoerd. Daarnaast moeten we controleren dat:
We gaan gelijkheid van varianties na met boxplots. Dit lijkt alvast
in orde te zijn.
We zullen nu de assumptie van normale verdeling binnen elke groep
nagaan.
#Maak een QQplot voor het gewicht per voedingssoort.
chickwts %>%
ggplot(aes(sample = weight)) +
geom_qq() +
geom_qq_line() +
facet_grid(.~feed) +
ylab("Relatieve abundantie")
De afwijkingen die we in onze qqplot zien lijken niet zeer
uitzonderlijk. Daarom kunnen we stellen dat elke groep een normale
verdeling lijkt te volgen.
Indien men veel groepen moet vergelijken, kan het makkelijker zijn om
slechts één plot te moeten beoordelen. In dat geval kan men ervoor
kiezen om niet voor elke groep apart een QQ-plot te maken, maar kan men
de residuen van het lineair model checken. Merk op dat men dan checkt
voor een normale distributie van alle residuen
van het gewicht ten opzichte van hun groepsgemiddelde, en dus niet voor
een normale distributie binnen elke groep apart.
model_lm <- lm(weight ~ feed, data = chickwts)
par(mfrow=c(2,2))
plot(model_lm) # Enkel figuur rechts boven is relevant
De QQ-plot vertoont geen systematische afwijkingen van een normale
distributie. Dit is geen garantie dat de data normaal verdeeld is binnen
elke groep, maar het is een benadering die we kunnen gebruiken in het
geval dat:
- er te veel groepen zijn om de assumpties te checken binnen elke
groep;
- er te weinig observaties zijn per groep om binnen elke groep de
assumpties na te gaan.
Merk op dat je in principe de assumptie van gelijke varianties ook op
basis van de plot linksboven zou kunnen checken: elke ‘kolom’ van punten
stelt een soort voor (1 soort heeft 1 geschat gemiddelde) en de punten
stellen de residuen voor ten opzichte van hun groepsgemiddelde. Men kan
deze plot dus ook gebruiken om te kijken of er groepen (soorten) zijn
die een verschillende variantie hebben ten opzichte van andere
groepen.
Modelleer de data met
het lineair model:
##
## Call:
## lm(formula = weight ~ feed, data = chickwts)
##
## Residuals:
## Min 1Q Median 3Q Max
## -107.583 -45.717 2.571 40.500 90.250
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 323.58 16.46 19.660 < 2e-16 ***
## feedlinseed -104.83 23.28 -4.504 7.11e-05 ***
## feedsoybean -77.15 22.43 -3.440 0.00152 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 57.01 on 35 degrees of freedom
## Multiple R-squared: 0.3854, Adjusted R-squared: 0.3503
## F-statistic: 10.97 on 2 and 35 DF, p-value: 0.0001996
De p-waarden die we hier krijgen voor de parameters komen niet
overeen met de ANOVA-test die we willen uitvoeren. De p-waarde bij de
F-statistic is wel de juiste p-waarde. We kunnen dit ook verkrijgen door
de volgende code:
#Voer de ANOVA uit op het lineare model.
anova(model_lm)
We voerden de ANOVA test uit aan de hand van het lineair
regressiemodel. In principe testen we dan volgende nulhypothese:
\[ H_0: \beta_1 = \beta_2 =
0 \]
Merk op dat deze nulhypothese evenwaardig is aan de nulhypothese die
we eerder formuleerden. Als alle gemiddelden \(\mu_1, \mu_2, \mu_3 = 0\), betekent dit dat
beide regressieparameters \(\beta_1\)
en \(\beta_1\) gelijk zijn aan 0.
De p-waarde van deze ANOVA test is bijzonder klein. We besluiten dat
we de nulhypothese kunnen verwerpen (\(p<<0.001\)) en dat het gemiddelde
gewicht van kuikens verschilt tussen minstens twee van de
voedingspatronen op het 5% significantieniveau.
Aan de hand van dit resultaat weten we echter niet tussen welke
voedingen er een verschil optreedt, en hiervoor zullen we een
post-hoc analyse moeten uitvoeren. Een post-hoc analyse
voert men enkel uit indien de ANOVA test significant was, en bestaat
erin om paarsgewijze vergelijkingen uit te voeren tussen de groepen. In
dit geval komt dit overeen met het vergelijken of er een verschil is
tussen groep 1 en 2, tussen groep 1 en 3 en tussen groep 2 en 3.
Post-hoc analyse
De post-hoc analyse bestaat eruit om paarsgewijze testen uit te
voeren. Indien men over \(k\) groepen
beschikt is het totaal aantal paarsgewijze vergelijkingen gelijk aan
\(k(k-1)/2\). Bij ons is \(k=3\) waardoor we \(3\) paarsgewijze vergelijkingen zullen
uitvoeren. We kunnen echter niet elke test op het 5% significantieniveau
uitvoeren vanwege het meervoudig toetsen probleem. Indien we 3
vergelijkingen zouden testen elk op het 5% significantieniveau, dan is
de kans dat we minstens één nulhypothese onterecht zouden verwerpen niet
langer gelijk aan ons significantieniveau (5%). In ons geval, zou deze
kans gelijk zijn aan:
alpha <- 0.05
nComparisons <- 3
1-(1-alpha)^nComparisons
## [1] 0.142625
Dus indien we elke test op het 5% significantieniveau zouden
uitvoeren hebben we, als alle nulhypotheses waar zouden zijn, een kans
van 14.3% dat we minstens één nulhypothese verkeerd zouden verwerpen. Om
deze kans globaal gezien (dit is, over alle paarsgewijze vergelijkingen)
op 5% te houden, kunnen we bijvoorbeeld de Bonferroni correctie
uitvoeren.
In R
kunnen we de post-hoc analyse uitvoeren met behulp
van het multcomp
package aan de hand van de
glht
functie. We specifiëren hier in het
linfct
argument dat we multiple comparisons
(mcp
) willen uitvoeren waarbij we alle paarsgewijze
vergelijkingen voor de feed
variabele willen testen aan de
hand van de "Tukey"
methode. De multcomp
package zorgt ervoor dat deze p-waarden automatisch gecorrigeerd worden
voor meervoudig toetsen.
suppressPackageStartupMessages(library(multcomp))
mcp <- glht(model_lm,linfct=mcp(feed="Tukey"))
summary <- summary(mcp)
summary
##
## Simultaneous Tests for General Linear Hypotheses
##
## Multiple Comparisons of Means: Tukey Contrasts
##
##
## Fit: lm(formula = weight ~ feed, data = chickwts)
##
## Linear Hypotheses:
## Estimate Std. Error t value Pr(>|t|)
## linseed - casein == 0 -104.83 23.28 -4.504 <0.001 ***
## soybean - casein == 0 -77.15 22.43 -3.440 0.0042 **
## soybean - linseed == 0 27.68 22.43 1.234 0.4414
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## (Adjusted p values reported -- single-step method)
In de output hiervan zien we de verschillende paarsgewijze
vergelijkingen die werden uitvoerd. Bijvoorbeeld
linseed - casein == 0
duidt erop dat voor dit contrast
wordt getest of het gemiddelde gewicht voor voeding linseed
min het gemiddelde gewicht voor soort casein
verschillend
is van nul. In de tweede kolom wordt het verschil in gemiddelden
weergegeven, met hun standaard error en teststatistiek in de
respectievelijk derde en vierde kolom. De laatste kolom geeft aangepaste
p-waarden weer op een globaal significantieniveau van 5%. Aan de hand
van de aangepaste p-waarden zien we dat het gemiddelde gewicht bij
casein
verschilt van zowel linseed
en
soybean
(p < 0.001 en p = 0.004) op het 5%
significantieniveau. We zien ook dat er geen significant verschil is in
gemiddeld gewicht bij voeding soybean
en
linseed
op het 5% significantieniveau. De effectgrootte is
voor bij zowel linseed
als soybean
negatief,
wat erop duidt dat het gemiddelde gewicht van kuikens hoger is bij
voedingspatroon casein
.
De betrouwbaarheidsintervallen van elke paarsgewijze test kunnen we
ook makkelijk grafisch voorstellen aan de hand van de plot
functie die zo op een glht
object kan toegepast worden.
##
## Simultaneous Confidence Intervals
##
## Multiple Comparisons of Means: Tukey Contrasts
##
##
## Fit: lm(formula = weight ~ feed, data = chickwts)
##
## Quantile = 2.4475
## 95% family-wise confidence level
##
##
## Linear Hypotheses:
## Estimate lwr upr
## linseed - casein == 0 -104.8333 -161.8019 -47.8648
## soybean - casein == 0 -77.1548 -132.0511 -22.2585
## soybean - linseed == 0 27.6786 -27.2177 82.5749
LS0tCnRpdGxlOiAiUHJhY3RpY3VtIDE6IE9lZmVuaW5nIGFub3ZhIgphdXRob3I6ICJBbGV4YW5kcmUgU2VnZXJzICYgTGlldmVuIENsZW1lbnQiCmRhdGU6ICJzdGF0T21pY3MsIEdoZW50IFVuaXZlcnNpdHkgKGh0dHBzOi8vc3RhdG9taWNzLmdpdGh1Yi5pbykiCm91dHB1dDoKICAgIGh0bWxfZG9jdW1lbnQ6CiAgICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgICAgdGhlbWU6IGNvc21vCiAgICAgIHRvYzogdHJ1ZQogICAgICB0b2NfZmxvYXQ6IHRydWUKICAgICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHBkZl9kb2N1bWVudDoKICAgICAgdG9jOiB0cnVlCiAgICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgICBsYXRleF9lbmdpbmU6IHhlbGF0ZXgKbGlua2NvbG9yOiBibHVlCnVybGNvbG9yOiBibHVlCmNpdGVjb2xvcjogYmx1ZQoKLS0tCgo8YSByZWw9ImxpY2Vuc2UiIGhyZWY9Imh0dHBzOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy1zYS80LjAiPjxpbWcgYWx0PSJDcmVhdGl2ZSBDb21tb25zIExpY2Vuc2UiIHN0eWxlPSJib3JkZXItd2lkdGg6MCIgc3JjPSJodHRwczovL2kuY3JlYXRpdmVjb21tb25zLm9yZy9sL2J5LW5jLXNhLzQuMC84OHgzMS5wbmciIC8+PC9hPgoKCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCiMgQU5PVkE6IEt1aWtlbnRqZXMKCkluIGRlemUgc3R1ZGllICgxOTQ4KSB3ZXJkIGRlIGludmxvZWQgdmFuIHZlcnNjaGlsbGVuZGUgc29vcnRlbiB2b2VkaW5nIG9wIGhldCBnZXdpY2h0IHZhbiBrdWlrZW50amVzIG9uZGVyem9jaHQuIERlIGt1aWtlbnRqZXMgd2VyZGVuIG5hIGdlYm9vcnRlIHdpbGxla2V1cmlnIGluIMOpw6luIHZhbiB6ZXMgZ3JvZXBlbiB0b2VnZWtlbmQsIHdhYXJuYSBkZXplIGdyb2VwZW4gZWxrIGVlbiBhbmRlcmUgdm9lZGluZyBrcmVnZW4uIEhldCBnZXdpY2h0IHZhbiBkZXplIGt1aWtlbnRqZXMgd2VyZCBnZW1ldGVuIG5hIHplcyB3ZWtlbi4gV2lqIHp1bGxlbiBvbnMgYmVwZXJrZW4gdG90IGRyaWUgZ3JvZXBlbiB2YW4gdm9lZGluZzogY2FzZcOvbmUgKGNhc2VpbiksIGxpam56YWFkIChsaW5zZWVkKSBlbiBzb2phYm9uZW4gKHNveWJlYW4pLgoKCgpgYGB7cn0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKHsKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ2dwbG90Mil9KQpgYGAKCiMgRGF0YSBleHBsb3JhdGllCmBgYHtyfQpkYXRhKCJjaGlja3d0cyIpCmBgYAoKIyMgRGF0YXN0cnVjdHV1ciBiZWtpamtlbgoKYGBge3J9CiNCZWtpamsgZGUgc3RydWN0dXVyIHZhbiBkYXRhc2V0IGNoaWNrd3RzCmhlYWQoY2hpY2t3dHMpCmBgYAoKIyMgRGF0YSBmaWx0ZXJlbgoKV2UgZ2FhbiBkZSBhbmFseXNlIGJlcGVya2VuIHRvdCBoZXQgdmVyZ2VsaWprZW4gdmFuIHZvZWRpbmcgY2FzZcOvbmUgKGNhc2VpbiksIGxpam56YWFkIChsaW5zZWVkKSBlbiBzb2phYm9uZW4gKHNveWJlYW4pLiAKCmBgYHtyfQojRmlsdGVyIGRlIGRhdGFzZXQgem9kYXQgZW5rZWwgZGF0YXB1bnRlbiB2YW4gZGUgcmVsZXZhbnRlIHZvZWRpbmcgKGZlZWQpIGFhbndlemlnIHppam4uCmNoaWNrd3RzIDwtIGNoaWNrd3RzICU+JSBmaWx0ZXIoZmVlZCAlaW4lIGMoImNhc2VpbiIsImxpbnNlZWQiLCJzb3liZWFuIikpCmBgYAoKIyMgRmlndXVyIHZhbiBkZSBkYXRhCgpXZSBnYWFuIGVlcnN0IGRlIGRhdGEgYmVraWprZW4gem9kYXQgd2UgZWVuIGlkZWUgaGViYmVuIHdhYXJtZWUgd2UgdGUgbWFrZW4gaGViYmVuLgoKYGBge3J9CiNNYWFrIGVlbiBib3hwbG90IHZhbiBoZXQgZ2V3aWNodCB2b29yIGVsa2UgZ3JvZXAgdmFuIHZvZWRpbmcuIFBsb3Qgb29rIGRlIGluZGl2aWR1ZWxlIG9ic2VydmF0aWVzLgpjaGlja3d0cyAlPiUgZ2dwbG90KGFlcyh4PWZlZWQseT13ZWlnaHQpKSArIAogIGdlb21fYm94cGxvdCgpICsKICBnZW9tX2ppdHRlcigpICsKICBnZ3RpdGxlKCJHZXdpY2h0IHZhbiBrdWlrZW50amVzIG5hIHplcyB3ZWtlbiBwZXIgc29vcnQgdm9lZGluZyIpCmBgYAoKCiMgU3RhdGlzY2hlIHRlc3Q6CgojIyBXZWxrZSB0ZXN0IGthbiBtZW4gdWl0dm9lcmVuIG9tIGhldCBnZW1pZGRlbGRlIGdld2ljaHQgc2ltdWx0YWFuIHRlIHZlcmdlbGlqa2VuIHR1c3NlbiBhbGxlIHNvb3J0ZW4gdm9lZGluZz8gV2F0IGlzIGRlIGxpbmsgbWV0IGhldCBsaW5lYWlyIG1vZGVsPyBHZWVmIGRlIG51bC0gZW4gYWx0ZXJuYXRpZXZlIGh5cG90aGVzZSB2YW4gZGV6ZSB0ZXN0LgoKSW4gdm9yaWdlIG9lZmVuaW5nIHphZ2VuIHdlIGVua2VsIGRlIHR3by1zYW1wbGUgdC10ZXN0IG9tIHR3ZWUgZ2VtaWRkZWxkZW4gbWV0IGVsa2FhciB2ZXJnZWxpamtlbi4KV2UgaGViYmVuIGVjaHRlciBvb2sgcmVlZHMgZ2V6aWVuIGRhdCBkZSB0d28tc2FtcGxlIHQtdGVzdCBlZW4gc3BlY2lmaWVrZSB2ZXJzaWUgaXMgdmFuIGVlbiBsaW5lYWlyIG1vZGVsLCBuYW1lbGlqayB2YW4gZWVuIGxpbmVhaXIgbW9kZWwgd2FhcmJpaiBkZSBjb3ZhcmlhYXQgZWVuIGNhdGVnb3Jpc2NoZSB2YXJpYWJlbGUgJFgkIGlzIG1ldCAkMiQgbGV2ZWxzLCBpLmUuClxbIEVbWV9pXSA9IFxiZXRhXzAgKyBcYmV0YV8xIFhfaSBcXQoKRGl0IGxpbmVhaXIgbW9kZWwga2FuIGVjaHRlciBvb2sgbWFra2VsaWprIHZlcmFsZ2VtZWVuZCB3b3JkZW4gbmFhciBmYWN0b3JlbiBtZXQgbWVlcmRlcmUgbGV2ZWxzLiAKClxbIEVbWV9pXSA9IFxiZXRhXzAgKyBcYmV0YV8xIFhfezFpfSArIFxiZXRhXzIgWF97Mml9IFxdCgpXYWFyYmlqICRYX3sxaX0kIGdlbGlqayBpcyBhYW4gMSB3YW5uZWVyIGRlIHZvZWRpbmcgbGluc2VlZCBpcyBlbiBhbmRlcnMgMC4gQW5kZXJ6aWpkcyBpcyAkWF97Mml9JCBnZWxpamsgYWFuIDEgYmlqIHNveWJlYW5zIGVuIGdlbGlqayBhYW4gMCBiaWogZGUgYW5kZXJlIHZvZWRpbmdlbi4gCgpFciBiZXN0YWF0IGVlbiBtYW5pZXIgd2FhcmJpaiB3ZSAqKmFsbGUgbGV2ZWxzIHNpbXVsdGFhbiBrdW5uZW4gdGVzdGVuKiosIG1lbiB6YWwgbmFtZWxpamsgdGVzdGVuIG9mIGRlIGdlaGVsZSBjYXRlZ29yaXNjaGUgdmFyaWFiZWxlIGVlbiBpbnZsb2VkIGhlZWZ0IG9wIGRlIHJlc3BvbnMgdmFyaWFiZWxlLgpJbiBkZSBjb250ZXh0IHZhbiBvbnMgdm9vcmJlZWxkLCB6YWwgbWVuIGt1bm5lbiB0ZXN0ZW4gb2YgZGUgdm9lZGluZy1zb29ydCDDvGJlcmhhdXB0IGVlbiBlZmZlY3QgaGVlZnQgb3AgaGV0IGdlbWlkZGVsZGUgZ2V3aWNodCB2YW4ga3Vpa2VudGplcy4KWm8nbiBlZW4gdGVzdCBoZWV0IGVlbiBvbmUtd2F5IEFOT1ZBLgoKU3RlbCBkYXQgJFxtdV8xJCBoZXQgZ2VtaWRkZWxkZSBnZXdpY2h0IHZhbiBrdWlrZW5zIHZvb3IgY2FzZcOvbmUgdm9vcnN0ZWx0LCBlbiBpZGVtIHZvb3IgJFxtdV8yJCBlbiAkXG11XzMkLgpEZSBudWwtIGVuIGFsdGVybmF0aWV2ZSBoeXBvdGhlc2Ugdm9vciBlZW4gQU5PVkEga2FuIG1lbiBkYW4gdm9vcnN0ZWxsZW4gYWxzCgokSF8wJDogJFxtdV8xPVxtdV8yPVxtdV8zJAoKJEhfQSQ6IFZvb3IgbWluc3RlbnMgw6nDqW4gJGkgXG5lIGokIGlzICRcbXVfaSBcbmVxIFxtdV9qJDogbWV0IGFuZGVyZSB3b29yZGVuICRcbXVfMSBcbmUgXG11XzIkIG9mICRcbXVfMSBcbmUgXG11XzMkIG9mICRcbXVfMiBcbmUgXG11XzMkCgpJbiB3b29yZGVuLCB6ZWd0IGRlIG51bGh5cG90aGVzZSBkYXQgaGV0IGdlbWlkZGVsZGUgZ2V3aWNodCB2YW4ga3Vpa2VucyBvbmFmaGFua2VsaWprIGlzIHZhbiBkZSB2b2VkaW5nOiBlciBpcyBnZWVuIHN5c3RlbWF0aXNjaCB2ZXJzY2hpbCBpbiBnZW1pZGRlbGQgZ2V3aWNodCB2YW4gaGV0IGt1aWtlbi4KRGUgYWx0ZXJuYXRpZXZlIGh5cG90aGVzZSB6ZWd0IGRhdCBoZXQgZ2VtaWRkZWxkZSBnZXdpY2h0IHZlcnNjaGlsdCB0dXNzZW4gKiptaW5zdGVucyB0d2VlIHZvZWRpbmctc29vcnRlbioqLiBNZXJrIG9wIGRhdCBtZW4gYmlqIGhldCB2ZXJ3ZXJwZW4gdmFuIGRlIG51bGh5cG90aGVzZSAqKm5pZXQgd2VldCB0dXNzZW4gd2Vsa2Ugc29vcnRlbioqIGVyIGVlbiB2ZXJzY2hpbCBpcyEKCkluZGllbiB3ZSBkZSBBTk9WQSB0ZXN0ZW4gb3AgYmFzaXMgdmFuIGhldCBsaW5lYWlyIG1vZGVsIGt1bm5lbiB3ZSBvb2sgZGUgdm9sZ2VuZGUgbnVsLSBlbiBhbHRlcm5hdGlldmUgaHlwb3RoZXNlIG9wc3RlbGxlbjoKCiRIXzAkOiAkXGJldGFfMSA9IFxiZXRhXzIgPSAwJAogCiRIX0EkOiAkXGJldGFfMSBcbmUgMCQgb2YgJFxiZXRhXzIgXG5lIDAkCgojIyBHZWVmIGRlIGFzc3VtcHRpZXMgdm9vciBkaXQgbW9kZWwgZW4gZ2EgZGV6ZSBuYToKClpvYWxzIGJlc2NocmV2ZW4gaW4gZGUgY3Vyc3VzLCB2ZXJvbmRlcnN0ZWx0IEFOT1ZBIGVlbiBsb2NhdGllLXNoaWZ0LgpEaXQgd2lsIHplZ2dlbiBkYXQgZWxrZSBncm9lcCBlZW4gZ2VsaWprZSB2YXJpYW50aWUgaGVlZnQgZW4gZXIgZW5rZWwgc2hpZnRzIGluIGdlbWlkZGVsZGUga3VubmVuIG9wdHJlZGVuLiBFZW4gYW5kZXJlIGFzc3VtcHRpZSBpcyBkYXQgZGUgZGF0YSB2YW4gZWxrZSBncm9lcCBub3JtYWFsIHZlcmRlZWxkIGlzLCBlbiBkYXQgZGUgb2JzZXJ2YXRpZXMgb25hZmhhbmtlbGlqayB2YW4gZWxrYWFyIHppam4uIAoKRXIgemlqbiBkdXMgZHJpZSBhc3N1bXB0aWVzIGRpZSBtb2V0ZW4gdm9sZGFhbiB6aWpuLiBBYW5nZXppZW4gd2UgaW4gZGUgZGF0YSBuaWV0IGt1bm5lbiB3YWFybmVtZW4gb2YgZGUgb2JzZXJ2YXRpZXMgb25hZmhhbmtlbGlqayB6aWpuIHZhbiBlbGthYXIsIG1vZXRlbiB3ZSBkaXQgdmVyb25kZXJzdGVsbGVuIGRhdCBkZSBvbmRlcnpvZWtlciBkaXQgY29ycmVjdCBoZWVmdCB1aXRnZXZvZXJkLiBEYWFybmFhc3QgbW9ldGVuIHdlIGNvbnRyb2xlcmVuIGRhdDoKCiAtIGVsa2UgZ3JvZXAgbm9ybWFhbCBpcy4KIAogLSBkZSBncm9lcGVuIGVlbiBnZWxpamtlIHZhcmlhbnRpZSBoZWJiZW4uIChob21vc2NlZGFzdGljaXRlaXQpCgpXZSBnYWFuIGdlbGlqa2hlaWQgdmFuIHZhcmlhbnRpZXMgbmEgbWV0IGJveHBsb3RzLiBEaXQgbGlqa3QgYWx2YXN0IGluIG9yZGUgdGUgemlqbi4KCldlIHp1bGxlbiBudSBkZSBhc3N1bXB0aWUgdmFuIG5vcm1hbGUgdmVyZGVsaW5nIGJpbm5lbiBlbGtlIGdyb2VwIG5hZ2Fhbi4gCgpgYGB7cn0KI01hYWsgZWVuIFFRcGxvdCB2b29yIGhldCBnZXdpY2h0IHBlciB2b2VkaW5nc3Nvb3J0LgpjaGlja3d0cyAlPiUKICBnZ3Bsb3QoYWVzKHNhbXBsZSA9IHdlaWdodCkpICsKICBnZW9tX3FxKCkgKwogIGdlb21fcXFfbGluZSgpICsKICBmYWNldF9ncmlkKC5+ZmVlZCkgKwogIHlsYWIoIlJlbGF0aWV2ZSBhYnVuZGFudGllIikKCmBgYAoKCkRlIGFmd2lqa2luZ2VuIGRpZSB3ZSBpbiBvbnplIHFxcGxvdCB6aWVuIGxpamtlbiBuaWV0IHplZXIgdWl0em9uZGVybGlqay4gRGFhcm9tIGt1bm5lbiB3ZSBzdGVsbGVuIGRhdCBlbGtlIGdyb2VwIGVlbiBub3JtYWxlIHZlcmRlbGluZyBsaWprdCB0ZSB2b2xnZW4uCgpJbmRpZW4gbWVuIHZlZWwgZ3JvZXBlbiBtb2V0IHZlcmdlbGlqa2VuLCBrYW4gaGV0IG1ha2tlbGlqa2VyIHppam4gb20gc2xlY2h0cyDDqcOpbiBwbG90IHRlIG1vZXRlbiBiZW9vcmRlbGVuLiBJbiBkYXQgZ2V2YWwga2FuIG1lbiBlcnZvb3Iga2llemVuIG9tIG5pZXQgdm9vciBlbGtlIGdyb2VwIGFwYXJ0IGVlbiBRUS1wbG90IHRlIG1ha2VuLCBtYWFyIGthbiBtZW4gZGUgcmVzaWR1ZW4gdmFuIGhldCBsaW5lYWlyIG1vZGVsIGNoZWNrZW4uIApNZXJrIG9wIGRhdCBtZW4gZGFuIGNoZWNrdCB2b29yIGVlbiBub3JtYWxlIGRpc3RyaWJ1dGllIHZhbiAqKiphbGxlKioqIHJlc2lkdWVuIHZhbiBoZXQgZ2V3aWNodCB0ZW4gb3B6aWNodGUgdmFuIGh1biBncm9lcHNnZW1pZGRlbGRlLCBlbiBkdXMgbmlldCB2b29yIGVlbiBub3JtYWxlIGRpc3RyaWJ1dGllIGJpbm5lbiBlbGtlIGdyb2VwIGFwYXJ0LgoKYGBge3J9Cm1vZGVsX2xtIDwtIGxtKHdlaWdodCB+IGZlZWQsIGRhdGEgPSBjaGlja3d0cykKcGFyKG1mcm93PWMoMiwyKSkKcGxvdChtb2RlbF9sbSkgIyBFbmtlbCBmaWd1dXIgcmVjaHRzIGJvdmVuIGlzIHJlbGV2YW50CnBhcihtZnJvdz1jKDEsMSkpCmBgYAoKRGUgUVEtcGxvdCB2ZXJ0b29udCBnZWVuIHN5c3RlbWF0aXNjaGUgYWZ3aWpraW5nZW4gdmFuIGVlbiBub3JtYWxlIGRpc3RyaWJ1dGllLiBEaXQgaXMgZ2VlbiBnYXJhbnRpZSBkYXQgZGUgZGF0YSBub3JtYWFsIHZlcmRlZWxkIGlzIGJpbm5lbiBlbGtlIGdyb2VwLCBtYWFyIGhldCBpcyBlZW4gYmVuYWRlcmluZyBkaWUgd2Uga3VubmVuIGdlYnJ1aWtlbiBpbiBoZXQgZ2V2YWwgZGF0OgoKIC0gZXIgdGUgdmVlbCBncm9lcGVuIHppam4gb20gZGUgYXNzdW1wdGllcyB0ZSBjaGVja2VuIGJpbm5lbiBlbGtlIGdyb2VwOwogLSBlciB0ZSB3ZWluaWcgb2JzZXJ2YXRpZXMgemlqbiBwZXIgZ3JvZXAgb20gYmlubmVuIGVsa2UgZ3JvZXAgZGUgYXNzdW1wdGllcyBuYSB0ZSBnYWFuLgoKTWVyayBvcCBkYXQgamUgaW4gcHJpbmNpcGUgZGUgYXNzdW1wdGllIHZhbiBnZWxpamtlIHZhcmlhbnRpZXMgb29rIG9wIGJhc2lzIHZhbiBkZSBwbG90IGxpbmtzYm92ZW4gem91IGt1bm5lbiBjaGVja2VuOiBlbGtlICdrb2xvbScgdmFuIHB1bnRlbiBzdGVsdCBlZW4gc29vcnQgdm9vciAoMSBzb29ydCBoZWVmdCAxIGdlc2NoYXQgZ2VtaWRkZWxkZSkgZW4gZGUgcHVudGVuIHN0ZWxsZW4gZGUgcmVzaWR1ZW4gdm9vciB0ZW4gb3B6aWNodGUgdmFuIGh1biBncm9lcHNnZW1pZGRlbGRlLiBNZW4ga2FuIGRlemUgcGxvdCBkdXMgb29rIGdlYnJ1aWtlbiBvbSB0ZSBraWprZW4gb2YgZXIgZ3JvZXBlbiAoc29vcnRlbikgemlqbiBkaWUgZWVuIHZlcnNjaGlsbGVuZGUgdmFyaWFudGllIGhlYmJlbiB0ZW4gb3B6aWNodGUgdmFuIGFuZGVyZSBncm9lcGVuLgoKCgojIyBNb2RlbGxlZXIgZGUgZGF0YSBtZXQgaGV0IGxpbmVhaXIgbW9kZWw6CgpgYGB7cn0Kc3VtbWFyeShtb2RlbF9sbSkKYGBgCgpEZSBwLXdhYXJkZW4gZGllIHdlIGhpZXIga3JpamdlbiB2b29yIGRlIHBhcmFtZXRlcnMga29tZW4gbmlldCBvdmVyZWVuIG1ldCBkZSBBTk9WQS10ZXN0IGRpZSB3ZSB3aWxsZW4gdWl0dm9lcmVuLiBEZSBwLXdhYXJkZSBiaWogZGUgRi1zdGF0aXN0aWMgaXMgd2VsIGRlIGp1aXN0ZSBwLXdhYXJkZS4gV2Uga3VubmVuIGRpdCBvb2sgdmVya3JpamdlbiBkb29yIGRlIHZvbGdlbmRlIGNvZGU6CgpgYGB7cn0KI1ZvZXIgZGUgQU5PVkEgdWl0IG9wIGhldCBsaW5lYXJlIG1vZGVsLgphbm92YShtb2RlbF9sbSkKYGBgCgpXZSB2b2VyZGVuIGRlIEFOT1ZBIHRlc3QgdWl0IGFhbiBkZSBoYW5kIHZhbiBoZXQgbGluZWFpciByZWdyZXNzaWVtb2RlbC4gSW4gcHJpbmNpcGUgdGVzdGVuIHdlIGRhbiB2b2xnZW5kZSBudWxoeXBvdGhlc2U6CgpcWyBIXzA6IFxiZXRhXzEgPSBcYmV0YV8yID0gMCAgXF0KCgpNZXJrIG9wIGRhdCBkZXplIG51bGh5cG90aGVzZSBldmVud2FhcmRpZyBpcyBhYW4gZGUgbnVsaHlwb3RoZXNlIGRpZSB3ZSBlZXJkZXIgZm9ybXVsZWVyZGVuLiBBbHMgYWxsZSBnZW1pZGRlbGRlbiAkXG11XzEsIFxtdV8yLCBcbXVfMyA9IDAkLCBiZXRla2VudCBkaXQgZGF0IGJlaWRlIHJlZ3Jlc3NpZXBhcmFtZXRlcnMgJFxiZXRhXzEkIGVuICRcYmV0YV8xJCBnZWxpamsgemlqbiBhYW4gMC4KCgpEZSBwLXdhYXJkZSB2YW4gZGV6ZSBBTk9WQSB0ZXN0IGlzIGJpanpvbmRlciBrbGVpbi4gV2UgYmVzbHVpdGVuIGRhdCB3ZSBkZSBudWxoeXBvdGhlc2Uga3VubmVuIHZlcndlcnBlbiAoJHA8PDAuMDAxJCkgZW4gZGF0IGhldCBnZW1pZGRlbGRlIGdld2ljaHQgdmFuIGt1aWtlbnMgdmVyc2NoaWx0IHR1c3NlbiBtaW5zdGVucyB0d2VlIHZhbiBkZSB2b2VkaW5nc3BhdHJvbmVuIG9wIGhldCA1JSBzaWduaWZpY2FudGllbml2ZWF1LgoKQWFuIGRlIGhhbmQgdmFuIGRpdCByZXN1bHRhYXQgd2V0ZW4gd2UgZWNodGVyIG5pZXQgdHVzc2VuIHdlbGtlIHZvZWRpbmdlbiBlciBlZW4gdmVyc2NoaWwgb3B0cmVlZHQsIGVuIGhpZXJ2b29yIHp1bGxlbiB3ZSBlZW4gKipwb3N0LWhvYyBhbmFseXNlKiogbW9ldGVuIHVpdHZvZXJlbi4gRWVuIHBvc3QtaG9jIGFuYWx5c2Ugdm9lcnQgbWVuIGVua2VsIHVpdCBpbmRpZW4gZGUgQU5PVkEgdGVzdCBzaWduaWZpY2FudCB3YXMsIGVuIGJlc3RhYXQgZXJpbiBvbSBwYWFyc2dld2lqemUgdmVyZ2VsaWpraW5nZW4gdWl0IHRlIHZvZXJlbiB0dXNzZW4gZGUgZ3JvZXBlbi4gSW4gZGl0IGdldmFsIGtvbXQgZGl0IG92ZXJlZW4gbWV0IGhldCB2ZXJnZWxpamtlbiBvZiBlciBlZW4gdmVyc2NoaWwgaXMgdHVzc2VuIGdyb2VwIDEgZW4gMiwgdHVzc2VuIGdyb2VwIDEgZW4gMyBlbiB0dXNzZW4gZ3JvZXAgMiBlbiAzLiAKCgojIyBQb3N0LWhvYyBhbmFseXNlCgpEZSBwb3N0LWhvYyBhbmFseXNlIGJlc3RhYXQgZXJ1aXQgb20gcGFhcnNnZXdpanplIHRlc3RlbiB1aXQgdGUgdm9lcmVuLiBJbmRpZW4gbWVuIG92ZXIgJGskIGdyb2VwZW4gYmVzY2hpa3QgaXMgaGV0IHRvdGFhbCBhYW50YWwgcGFhcnNnZXdpanplIHZlcmdlbGlqa2luZ2VuIGdlbGlqayBhYW4gJGsoay0xKS8yJC4gQmlqIG9ucyBpcyAkaz0zJCB3YWFyZG9vciB3ZSAkMyQgcGFhcnNnZXdpanplIHZlcmdlbGlqa2luZ2VuIHp1bGxlbiB1aXR2b2VyZW4uCldlIGt1bm5lbiBlY2h0ZXIgbmlldCBlbGtlIHRlc3Qgb3AgaGV0IDUlIHNpZ25pZmljYW50aWVuaXZlYXUgdWl0dm9lcmVuIHZhbndlZ2UgaGV0IG1lZXJ2b3VkaWcgdG9ldHNlbiBwcm9ibGVlbS4gCkluZGllbiB3ZSAzIHZlcmdlbGlqa2luZ2VuIHpvdWRlbiB0ZXN0ZW4gZWxrIG9wIGhldCA1JSBzaWduaWZpY2FudGllbml2ZWF1LCBkYW4gaXMgZGUga2FucyBkYXQgd2UgbWluc3RlbnMgw6nDqW4gbnVsaHlwb3RoZXNlIG9udGVyZWNodCB6b3VkZW4gdmVyd2VycGVuIG5pZXQgbGFuZ2VyIGdlbGlqayBhYW4gb25zIHNpZ25pZmljYW50aWVuaXZlYXUgKDUlKS4KSW4gb25zIGdldmFsLCB6b3UgZGV6ZSBrYW5zIGdlbGlqayB6aWpuIGFhbjoKCmBgYHtSfQphbHBoYSA8LSAwLjA1Cm5Db21wYXJpc29ucyA8LSAzCjEtKDEtYWxwaGEpXm5Db21wYXJpc29ucwpgYGAKCkR1cyBpbmRpZW4gd2UgZWxrZSB0ZXN0IG9wIGhldCA1JSBzaWduaWZpY2FudGllbml2ZWF1IHpvdWRlbiB1aXR2b2VyZW4gaGViYmVuIHdlLCBhbHMgYWxsZSBudWxoeXBvdGhlc2VzIHdhYXIgem91ZGVuIHppam4sIGVlbiBrYW5zIHZhbiBgciByb3VuZCgxLSgxLWFscGhhKV5uQ29tcGFyaXNvbnMsMykqMTAwYCUgZGF0IHdlIG1pbnN0ZW5zIMOpw6luIG51bGh5cG90aGVzZSB2ZXJrZWVyZCB6b3VkZW4gdmVyd2VycGVuLgpPbSBkZXplIGthbnMgZ2xvYmFhbCBnZXppZW4gKGRpdCBpcywgb3ZlciBhbGxlIHBhYXJzZ2V3aWp6ZSB2ZXJnZWxpamtpbmdlbikgb3AgNSUgdGUgaG91ZGVuLCBrdW5uZW4gd2UgYmlqdm9vcmJlZWxkIGRlIEJvbmZlcnJvbmkgY29ycmVjdGllIHVpdHZvZXJlbi4KCkluIGBSYCBrdW5uZW4gd2UgZGUgcG9zdC1ob2MgYW5hbHlzZSB1aXR2b2VyZW4gbWV0IGJlaHVscCB2YW4gaGV0IGBtdWx0Y29tcGAgcGFja2FnZSBhYW4gZGUgaGFuZCB2YW4gZGUgYGdsaHRgIGZ1bmN0aWUuIFdlIHNwZWNpZmnDq3JlbiBoaWVyIGluIGhldCBgbGluZmN0YCBhcmd1bWVudCBkYXQgd2UgKm11bHRpcGxlIGNvbXBhcmlzb25zKiAoYG1jcGApIHdpbGxlbiB1aXR2b2VyZW4gd2FhcmJpaiB3ZSBhbGxlIHBhYXJzZ2V3aWp6ZSB2ZXJnZWxpamtpbmdlbiB2b29yIGRlIGBmZWVkYCB2YXJpYWJlbGUgd2lsbGVuIHRlc3RlbiBhYW4gZGUgaGFuZCB2YW4gZGUgYCJUdWtleSJgIG1ldGhvZGUuIERlIGBtdWx0Y29tcGAgcGFja2FnZSB6b3JndCBlcnZvb3IgZGF0IGRlemUgcC13YWFyZGVuIGF1dG9tYXRpc2NoIGdlY29ycmlnZWVyZCB3b3JkZW4gdm9vciBtZWVydm91ZGlnIHRvZXRzZW4uCgpgYGB7cn0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKGxpYnJhcnkobXVsdGNvbXApKQptY3AgPC0gZ2xodChtb2RlbF9sbSxsaW5mY3Q9bWNwKGZlZWQ9IlR1a2V5IikpCnN1bW1hcnkgPC0gc3VtbWFyeShtY3ApCnN1bW1hcnkKYGBgCgpJbiBkZSBvdXRwdXQgaGllcnZhbiB6aWVuIHdlIGRlIHZlcnNjaGlsbGVuZGUgcGFhcnNnZXdpanplIHZlcmdlbGlqa2luZ2VuIGRpZSB3ZXJkZW4gdWl0dm9lcmQuIEJpanZvb3JiZWVsZCBgbGluc2VlZCAtIGNhc2VpbiA9PSAwYCBkdWlkdCBlcm9wIGRhdCB2b29yIGRpdCBjb250cmFzdCB3b3JkdCBnZXRlc3Qgb2YgaGV0IGdlbWlkZGVsZGUgZ2V3aWNodCB2b29yIHZvZWRpbmcgYGxpbnNlZWRgIG1pbiBoZXQgZ2VtaWRkZWxkZSBnZXdpY2h0IHZvb3Igc29vcnQgYGNhc2VpbmAgdmVyc2NoaWxsZW5kIGlzIHZhbiBudWwuCkluIGRlIHR3ZWVkZSBrb2xvbSB3b3JkdCBoZXQgdmVyc2NoaWwgaW4gZ2VtaWRkZWxkZW4gd2VlcmdlZ2V2ZW4sIG1ldCBodW4gc3RhbmRhYXJkIGVycm9yIGVuIHRlc3RzdGF0aXN0aWVrIGluIGRlIHJlc3BlY3RpZXZlbGlqayBkZXJkZSBlbiB2aWVyZGUga29sb20uCkRlIGxhYXRzdGUga29sb20gZ2VlZnQgYWFuZ2VwYXN0ZSBwLXdhYXJkZW4gd2VlciBvcCBlZW4gZ2xvYmFhbCBzaWduaWZpY2FudGllbml2ZWF1IHZhbiA1JS4KQWFuIGRlIGhhbmQgdmFuIGRlIGFhbmdlcGFzdGUgcC13YWFyZGVuIHppZW4gd2UgZGF0IGhldCBnZW1pZGRlbGRlIGdld2ljaHQgYmlqIGBjYXNlaW5gIHZlcnNjaGlsdCB2YW4gem93ZWwgYGxpbnNlZWRgIGVuIGBzb3liZWFuYCAocCA8IDAuMDAxIGVuIHAgPSAwLjAwNCkgb3AgaGV0IDUlIHNpZ25pZmljYW50aWVuaXZlYXUuIFdlIHppZW4gb29rIGRhdCBlciBnZWVuIHNpZ25pZmljYW50IHZlcnNjaGlsIGlzIGluIGdlbWlkZGVsZCBnZXdpY2h0IGJpaiB2b2VkaW5nIGBzb3liZWFuYCBlbiBgbGluc2VlZGAgb3AgaGV0IDUlIHNpZ25pZmljYW50aWVuaXZlYXUuCkRlIGVmZmVjdGdyb290dGUgaXMgdm9vciBiaWogem93ZWwgYGxpbnNlZWRgIGFscyBgc295YmVhbmAgbmVnYXRpZWYsIHdhdCBlcm9wIGR1aWR0IGRhdCBoZXQgZ2VtaWRkZWxkZSBnZXdpY2h0IHZhbiBrdWlrZW5zIGhvZ2VyIGlzIGJpaiB2b2VkaW5nc3BhdHJvb24gYGNhc2VpbmAuCgpEZSBiZXRyb3V3YmFhcmhlaWRzaW50ZXJ2YWxsZW4gdmFuIGVsa2UgcGFhcnNnZXdpanplIHRlc3Qga3VubmVuIHdlIG9vayBtYWtrZWxpamsgZ3JhZmlzY2ggdm9vcnN0ZWxsZW4gYWFuIGRlIGhhbmQgdmFuIGRlIGBwbG90YCBmdW5jdGllIGRpZSB6byBvcCBlZW4gYGdsaHRgIG9iamVjdCBrYW4gdG9lZ2VwYXN0IHdvcmRlbi4KCmBgYHtyfQpjb25maW50KG1jcCkKYGBgCgpgYGB7cn0KcGxvdChtY3ApCmBgYAoKCiMgQ29uY2x1c2llCgpXZSBrdW5uZW4gY29uY2x1ZGVyZW4gZGF0IGVyIGVlbiBzaWduaWZpY2FudCB2ZXJzY2hpbCBpbiBnZXdpY2h0IGlzIHR1c3NlbiBoZXQgZ2V3aWNodCB2YW4ga3Vpa2VudGplcyBtZXQgdm9lZGluZyBjYXNlaW5lIHRlZ2Vub3ZlciBkZSBhbmRlcmUgdm9lZGluZ2VuIG9wIGhldCA1JSBzaWduaWZpY2FudGllbml2ZWF1LiBUdXNzZW4gbGluc2VlZCBlbiBzb3liZWFuIGlzIGVyIGdlZW4gc2lnbmlmaWNhbnQgdmVyc2NoaWwgaW4gZ2V3aWNodCB2YW4gZGUga3Vpa2VudGplcy4KCg==