library("ggplot2")
Example 16.1
The annual bonuses ($1,000s) of six employees with different years of experience were recorded as follows. We wish to determine the straight-line relationship between annual bonus and years of experience.
Récupérer les données
years=1:6
bonus=c(6,1,9,5,17,12)
bonusdata=data.frame(years,bonus)
Représenter les données par un nuage de points

Représenter la droite des moindres carrés avec ggplot

Calcul manuel des coefficients de la régression
round(b0,3)
[1] 0.933
Les résidus
sum(e)
[1] -3.108624e-15
Représentation graphique des résidus (ou erreurs)

Illustration des moindres carrés
To be done

Faire une régression avec la fonction lm()
lm signifie linear models ## Effectuer la régression
LM$coefficients[2]
years
2.114286
Les sorties de la régression
LM$fitted.values ## Les valeurs ajustés (ychap_i=b0+b1x_i) i.e. les ordonnées sur la droite
1 2 3 4 5 6
3.047619 5.161905 7.276190 9.390476 11.504762 13.619048
Un bilan de la régression avec summary()
summary(LM)
Call:
lm(formula = bonus ~ years, data = bonusdata)
Residuals:
1 2 3 4 5 6
2.952 -4.162 1.724 -4.390 5.495 -1.619
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.9333 4.1920 0.223 0.835
years 2.1143 1.0764 1.964 0.121
Residual standard error: 4.503 on 4 degrees of freedom
Multiple R-squared: 0.491, Adjusted R-squared: 0.3637
F-statistic: 3.858 on 1 and 4 DF, p-value: 0.121
Une présentation des résultats plus professionnelle avec Stargazer()
##stargazer(LM,type = "latex")
summary(LM)
Call:
lm(formula = bonus ~ years, data = bonusdata)
Residuals:
1 2 3 4 5 6
2.952 -4.162 1.724 -4.390 5.495 -1.619
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.9333 4.1920 0.223 0.835
years 2.1143 1.0764 1.964 0.121
Residual standard error: 4.503 on 4 degrees of freedom
Multiple R-squared: 0.491, Adjusted R-squared: 0.3637
F-statistic: 3.858 on 1 and 4 DF, p-value: 0.121
5*(var(bonusdata$bonus)-
(cov(bonusdata$years,bonusdata$bonus))^2/var(bonusdata$years))
[1] 81.10476
summary(LM)
Call:
lm(formula = bonus ~ years, data = bonusdata)
Residuals:
1 2 3 4 5 6
2.952 -4.162 1.724 -4.390 5.495 -1.619
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.9333 4.1920 0.223 0.835
years 2.1143 1.0764 1.964 0.121
Residual standard error: 4.503 on 4 degrees of freedom
Multiple R-squared: 0.491, Adjusted R-squared: 0.3637
F-statistic: 3.858 on 1 and 4 DF, p-value: 0.121
sqrt(sum((LM$residuals)^2)/98) ## Calculer l'estimation de l'écart-type des erreurs formule p. 650 SSE/(n-2)
[1] 0.3264886
Odometer Reading and Prices of Used Toyota Camrys—Part 2
Find the standard error of estimate for Example 16.2 and describe what it tells you about the model’s fit.
SLM=summary(LM)
SLM$sigma
SSE=sum((LM$residuals)^2)
sqrt(SSE/98)
## Estimation de l’écart de b1
SLM$sigma/sqrt(99*var(data$Odometer))
[1] 0.004974639
SLM
Call:
lm(formula = Price ~ Odometer, data = data)
Residuals:
Min 1Q Median 3Q Max
-0.68679 -0.27263 0.00521 0.23210 0.70071
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 17.248727 0.182093 94.72 <2e-16 ***
Odometer -0.066861 0.004975 -13.44 <2e-16 ***
---
Signif. codes:
0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.3265 on 98 degrees of freedom
Multiple R-squared: 0.6483, Adjusted R-squared: 0.6447
F-statistic: 180.6 on 1 and 98 DF, p-value: < 2.2e-16
Calcul de p-value du test de nullité de la pente
qt(0.025,98,lower.tail=F)*
SLM$sigma/(sqrt(99*var(data$Odometer))
)
[1] 0.009872009
EXAMPLE 16. 5 Measuring the Strength of the Linear Relationship between Odometer Reading and Price of Used Toyota Camrys
Find the coefficient of determination for Example 16.2 and describe what this statistic tells you about the regression model.
SLM$r.squared
(cor(data$Price,data$Odometer))^2
This statistic tells us that 64.83% of the variation in the auction selling prices is explained by the variation in the odometer readings.
ANOVA=anova(LM)
sum(ANOVA[,2])
99*var(data$Price)
ANOVA[1,2]/(99*var(data$Price))
EXAMPLE 16.7 Predicting the Price and Estimating the Mean Price of Used Toyota Camrys
- A used-car dealer is about to bid on a 3-year-old Toyota Camry equipped with all the standard features and with 40,000 (\(x_g\) ⫽ 40) miles on the odometer. To help him decide how much to bid, he needs to predict the selling price.
xg=data.frame(Odometer = c(40))
PREDICT=predict.lm(LM,xg,interval = "prediction")
SLM$coefficients[,1]%*%c(1,40)
?predict.lm
PREDICT[1]-PREDICT[2]
- The used-car dealer mentioned in part (a) has an opportunity to bid on a lot of cars offered by a rental company. The rental company has 250 Toyota Camrys all equipped with standard features. All the cars in this lot have about 40,000 (xg ⫽ 40) miles on their odometers. The dealer would like an estimate of the selling price of all the cars in the lot.
PREDICTEXP=predict.lm(LM,xg,interval = "confidence")
PREDICTEXP[1]-PREDICTEXP[2]
PREDICTEXP[3]-PREDICTEXP[1]
Avec les matrices
Si on note \[
Y=\begin{bmatrix}
y_1\\
\vdots\\
y_n \\
\end{bmatrix} \text{ et }
X=\begin{bmatrix}
1 & x_1\\
\vdots & \vdots \\
1 & x_n \\
\end{bmatrix},
\] on obtient les estimateurs grâce à un clcul matriciel \[
\begin{bmatrix}
b_0 \\
b_1
\end{bmatrix}=
(X^tX)^{-1}X^tY,
\] où \[
X^t=\begin{bmatrix}
1 &\cdots& 1 \\
1 & \cdots &x_n \\
\end{bmatrix},
\] est la matrice transposée de \(X\).
X=matrix(c(rep(1,100),data$Odometer),nrow = 100,ncol=2)
dim(X)
Y=matrix(data$Price,nrow = 100,ncol=1)
solve(t(X)%*%X)%*%t(X)%*%Y
SLM$coefficients
La matice de variance-covariance de \((b_0,b_1)\) est donnée par
\[
\sigma^2(X^tX)^{-1}.
\] Comme \(\sigma^2\) est incommu, on l’estime ce qui donne
SLM$sigma
sqrt(sum((SLM$residuals)^2)/98)
(SLM$sigma)^2*solve(t(X)%*%X)
(SLM$coefficients[2,2])^2
vcov(LM)
Un peu d’algèbre
On rappelle que la méthode de moindres carrés va résoudre le programme suivant
\[
\min_{b_0,b_1} \sum (y_i-\hat{y_i})^2,\text{ avec } \hat{y_i}=b_0+b_1 x_i.
\]
Par dérivation par rapport à \(b_0\) et \(b_1\) on obtient les deux condition du premier ordre suivantes (on notera que \(\partial \hat{y}_i/\partial b_1= x_i\))
\[
\begin{equation}
\begin{cases}
\sum x_i(y_i-\hat{y_i})=0;\\
\sum (y_i-\hat{y_i})=0.
\end{cases}
\end{equation}
\]
La première condition vous dit que les erreurs sont de moyenne zero et la seconde que la variable des erreurs et la variables explicative ne sont pas corrélés.
On peut réécrire ces deux conditions ainsi \[
\begin{equation}
\begin{cases}
\sum (x_i-\bar{x})(y_i-\hat{y_i})=0;\\
\sum (y_i-\hat{y_i})=0.
\end{cases}
\end{equation}
\]
On remarquera que \(\bar{y}=\bar{\hat{y}}\).
Pour fini, en replaçant \(b_0\) et \(b_1\) par leurs valeurs optimales, on trouve
\[
SSE=\sum (y_i-\hat{y_i})^2=\sum (y_i-\bar{y}+ \bar{y}-\hat{y_i})^2,
\] ce qui donne
\[
SSE=\sum [y_i-\bar{y}-b_1(x_i-\bar{x})] ^2.
\] En développant, on trouve
\[
SSE=\sum (y_i-\bar{y})^2-2b_1\sum(x_i-\bar{x})(y_i-\bar{y})+b^2_1\sum (x_i-\bar{x})^2.
\]
En remarquant que
\[
b^2_1\sum (x_i-\bar{x})^2=b_1\sum(x_i-\bar{x})(y_i-\bar{y}),
\] On obtient
\[
SSE=\sum (y_i-\bar{y})^2-b_1\sum(x_i-\bar{x})(y_i-\bar{y}).
\]
En utilisant la valeur de \(b_1\), on trouve
\[
SSE=\sum (y_i-\bar{y})^2-\frac{[ \sum(x_i-\bar{x})(y_i-\bar{y}) ]^2}{\sum (x_i-\bar{x})^2}
\]
On a aussi
\[
SSE=(1-R^2)\sum (y_i-\bar{y})^2.
\] où \[
R^2=\frac{[ \sum(x_i-\bar{x})(y_i-\bar{y}) ]^2}{\sum (x_i-\bar{x})^2\sum (y_i-\bar{y})^2}=\frac{s^2_{xy}}{s_{x}s_{y}}.
\] On a aussi
\[
R^2=1-\frac{SSE }{\sum (y_i-\bar{y})^2},
\]
En remarquant qye \[
\sum(y_i-\bar{y })^2=\sum(y_i-\hat{y }_i)^2+\sum(\hat{y }_i-\bar{y })^2=SSE+\sum(\hat{y }_i-\bar{y })^2,
\] On a aussi \[
R^2=\frac{\sum (y_i-\bar{y})^2-SSE }{\sum (y_i-\bar{y})^2}=\frac{\sum(\hat{y }_i-\bar{y })^2 }{\sum (y_i-\bar{y})^2}.
\]
\(R^2\) devientb la part de variance expliquée par le modèle.
LS0tCnRpdGxlOiAiQ2hhcGl0cmUgNiIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CmxpYnJhcnkoImdncGxvdDIiKQpgYGAKCiMjIEV4YW1wbGUgMTYuMQoKVGhlIGFubnVhbCBib251c2VzICgkMSwwMDBzKSBvZiBzaXggZW1wbG95ZWVzIHdpdGggZGlmZmVyZW50IHllYXJzIG9mIGV4cGVyaWVuY2Ugd2VyZSByZWNvcmRlZCBhcyBmb2xsb3dzLiBXZSB3aXNoIHRvIGRldGVybWluZSB0aGUgc3RyYWlnaHQtbGluZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBhbm51YWwgYm9udXMgYW5kIHllYXJzIG9mIGV4cGVyaWVuY2UuCgojIFLDqWN1cMOpcmVyIGxlcyBkb25uw6llcwoKCmBgYHtyfQp5ZWFycz0xOjYKYm9udXM9Yyg2LDEsOSw1LDE3LDEyKQpib251c2RhdGE9ZGF0YS5mcmFtZSh5ZWFycyxib251cykKYGBgCgojIFJlcHLDqXNlbnRlciBsZXMgZG9ubsOpZXMgcGFyIHVuIG51YWdlIGRlIHBvaW50cwoKYGBge3J9ClBQPC1nZ3Bsb3QoYm9udXNkYXRhLCBhZXMoeD15ZWFycywgeT1ib251cykpKyBnZW9tX3BvaW50KCkrZ2d0aXRsZSgiQm9udXMgRGF0YSIpClBQCmBgYAoKIyBSZXByw6lzZW50ZXIgbGEgZHJvaXRlIGRlcyBtb2luZHJlcyBjYXJyw6lzIGF2ZWMgZ2dwbG90CgpgYGB7cn0KUFA8LVBQK2dlb21fc21vb3RoKG1ldGhvZD0nbG0nLHNlPUZBTFNFKQoKYGBgCiMjIENhbGN1bCBtYW51ZWwgZGVzIGNvZWZmaWNpZW50cyBkZSBsYSByw6lncmVzc2lvbgoKYGBge3J9CmIxPC1jb3YoeCx5KS92YXIoeCkKcm91bmQoYjEsMykKYjA8LW1lYW4oeSktYjEqbWVhbih4KQpyb3VuZChiMCwzKQpgYGAKIyMgTGVzIHLDqXNpZHVzCgpgYGB7cn0KZTwteS1iMC1iMSp4CnN1bShlKQpzdW0oZV4yKQpgYGAKCiMjIFJlcHLDqXNlbnRhdGlvbiBncmFwaGlxdWUgZGVzIHLDqXNpZHVzIChvdSBlcnJldXJzKQoKYGBge3J9ClBQK2dlb21fc2VnbWVudChhZXMoeCA9IHllYXJzLCB5ID0gYm9udXMsIHhlbmQgPSB5ZWFycywgeWVuZCA9IGIwK2IxKnllYXJzKSkKICAKYGBgCgoKCgojIElsbHVzdHJhdGlvbiBkZXMgbW9pbmRyZXMgY2FycsOpcwpUbyBiZSBkb25lCgpgYGB7cn0KYjA9MwpiMT0xCnk9Ym9udXMKeD15ZWFycwoKClNTIDwtIGZ1bmN0aW9uKGIwLGIxKSB7CnN1bSgoeS0oYjArYjEqeCkpXjIpCn0KU1MoMCwyKQoKY3VydmUoZXhwLHhsaW0gPSBjKDAsMTApKQpgYGAKIyBGYWlyZSB1bmUgcsOpZ3Jlc3Npb24gYXZlYyBsYSBmb25jdGlvbiBsbSgpIAoKIGxtIHNpZ25pZmllIGxpbmVhciBtb2RlbHMKIyMgRWZmZWN0dWVyIGxhIHLDqWdyZXNzaW9uIApgYGB7cn0KTE08LWxtKGJvbnVzfnllYXJzLGRhdGE9Ym9udXNkYXRhKQoKCmBgYAojIyBMZXMgc29ydGllcyBkZSBsYSByw6lncmVzc2lvbgpgYGB7cn0KTE0kY29lZmZpY2llbnRzICMjIExlcyBjb2VmZmljaWVudHMgZGUgbGEgcsOpZ3Jlc3Npb24KTE0kY29lZmZpY2llbnRzWzFdICMjIEludGVyY2VwdCBiMApMTSRjb2VmZmljaWVudHNbMl0gIyMgc2xvcGUgYjEKTE0kcmVzaWR1YWxzICMjIExlcyByw6lzaWR1cyAoIGVfaSkKTE0kZml0dGVkLnZhbHVlcyAjIyBMZXMgdmFsZXVycyBhanVzdMOpcyAoeWNoYXBfaT1iMCtiMXhfaSkgaS5lLiBsZXMgb3Jkb25uw6llcyBzdXIgbGEgZHJvaXRlIApgYGAKIyBVbiBiaWxhbiBkZSBsYSByw6lncmVzc2lvbiBhdmVjIHN1bW1hcnkoKQoKYGBge3J9CnN1bW1hcnkoTE0pCmBgYAoKIyBVbmUgcHLDqXNlbnRhdGlvbiBkZXMgcsOpc3VsdGF0cyBwbHVzIHByb2Zlc3Npb25uZWxsZSBhdmVjIFN0YXJnYXplcigpCgoKYGBge3Isd2FybmluZz1GQUxTRX0KaW5zdGFsbC5wYWNrYWdlcygic3RhcmdhemVyIikKc3RhcmdhemVyKExNLHR5cGUgPSAidGV4dCIpCiMjc3RhcmdhemVyKExNLHR5cGUgPSAibGF0ZXgiKQpzdW1tYXJ5KExNKQpgYGAKYGBge3J9ClNTRQpzdW0oKExNJHJlc2lkdWFscyleMikKNSoodmFyKGJvbnVzZGF0YSRib251cyktCiAgICAoY292KGJvbnVzZGF0YSR5ZWFycyxib251c2RhdGEkYm9udXMpKV4yL3Zhcihib251c2RhdGEkeWVhcnMpKQoKYGBgCgoKYGBge3J9ClBQPWdncGxvdChib251c2RhdGEsIGFlcyh4PXllYXJzLCB5PWJvbnVzKSkrIGdlb21fcG9pbnQoKQpQUD1QUCsKUFA9UFArCmIxPWNvdih5ZWFycyxib251cykvdmFyKHllYXJzKQpiMD1tZWFuKGJvbnVzKS1iMSptZWFuKHllYXJzKSAgICAgICAgICAgICAgICAKUFA9UFArZ2VvbV9zZWdtZW50KGFlcyh4ID0geWVhcnMsIHkgPSBib251cywgeGVuZCA9IHllYXJzLCB5ZW5kID0gYjArYjEqeWVhcnMpKQpQUCAgICAgICAgICAgICAgICAKTE09bG0oYm9udXN+eWVhcnMsZGF0YT1ib251c2RhdGEpCnN1bW1hcnkoTE0pCnllbmQ9TE0kZml0dGVkLnZhbHVlcwp4ZW5kPWJvbnVzZGF0YSR5ZWFycwpQUD1QUCtnZW9tX3NlZ21lbnQoYWVzKHggPSB5ZWFycywgeSA9IGJvbnVzLCB4ZW5kID0geWVhcnMsIHllbmQgPSB5ZW5kKSkKUFArZ2VvbV9wb2ludChhZXMoeD14ZW5kLHk9eWVuZCksY29sb3I9InJlZCIpClBQClNTRT1zdW0oKExNJHJlc2lkdWFscyleMikKc3FydChTU0UvKDYtMikpCnN1bW1hcnkoTE0pCgpgYGAKYGBge3Isd2FybmluZz1GQUxTRX0KbGlicmFyeShyZWFkeGwpCmRhdGEgPC0gcmVhZF9leGNlbCgiWG0xNi0wMi54bHN4IikKTE09bG0oUHJpY2V+T2RvbWV0ZXIsZGF0YT1kYXRhKSAjIyBGYWlyZSB1bmUgcsOpZ3Jlc3Npb24Kc3RhcmdhemVyKExNLHR5cGU9InRleHQiKSAjIyBQcsOpc2VudGVyIGxhIHLDqWdyZXNzaW9uIGRhbnMgdW4gdGFibGVhdQpzcXJ0KHN1bSgoTE0kcmVzaWR1YWxzKV4yKS85OCkgIyMgQ2FsY3VsZXIgbCdlc3RpbWF0aW9uIGRlIGwnw6ljYXJ0LXR5cGUgZGVzIGVycmV1cnMgZm9ybXVsZSBwLiA2NTAgU1NFLyhuLTIpClNMTT1zdW1tYXJ5KExNKSAKU0xNJHNpZ21hICMgRXh0YWlyZSBsJ2VzdGltYXRpb24gZGUgbCfDqWNhcnQtdHlwZSBkZXMgZXJyZXVycyBkZSBzdW1tYXJ5CmBgYAoKCiMjIE9kb21ldGVyIFJlYWRpbmcgYW5kIFByaWNlcyBvZiBVc2VkIFRveW90YSBDYW1yeXPigJRQYXJ0IDIKRmluZCB0aGUgc3RhbmRhcmQgZXJyb3Igb2YgZXN0aW1hdGUgZm9yIEV4YW1wbGUgMTYuMiBhbmQgZGVzY3JpYmUgd2hhdCBpdCB0ZWxscyB5b3UgYWJvdXQgdGhlIG1vZGVs4oCZcyBmaXQuCgoKYGBge3J9ClNMTT1zdW1tYXJ5KExNKQpTTE0kc2lnbWEKClNTRT1zdW0oKExNJHJlc2lkdWFscyleMikKc3FydChTU0UvOTgpCgoKYGBgCiAKICMjIEVzdGltYXRpb24gZGUgbCfDqWNhcnQgZGUgYjEKIApgYGB7cn0KU0xNJHNpZ21hL3NxcnQoOTkqdmFyKGRhdGEkT2RvbWV0ZXIpKQpTTE0KYGBgCgojIyBDYWxjdWwgZGUgcC12YWx1ZSBkdSB0ZXN0IGRlIG51bGxpdMOpIGRlIGxhIHBlbnRlCgpgYGB7cn0KMipwdCgxMy40NCw5OCxsb3dlci50YWlsID0gRikKMipwdCgtMTMuNDQsOTgpCkxNJGNvZWZmaWNpZW50c1syXQpxdCgwLjAyNSw5OCxsb3dlci50YWlsPUYpKgpTTE0kc2lnbWEvKHNxcnQoOTkqdmFyKGRhdGEkT2RvbWV0ZXIpKQopCiAgICAgCgpgYGAKCgoKCiMjIEV4YW1wbGUgMTYuNCBBcmUgT2RvbWV0ZXIgUmVhZGluZyBhbmQgUHJpY2Ugb2YgVXNlZCBUb3lvdGEgQ2FtcnlzIFJlbGF0ZWQ/CgpUZXN0IHRvIGRldGVybWluZSB3aGV0aGVyIHRoZXJlIGlzIGVub3VnaCBldmlkZW5jZSBpbiBFeGFtcGxlIDE2LjIgdG8gaW5mZXIgdGhhdCB0aGVyZSBpcyBhIGxpbmVhciByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgYXVjdGlvbiBwcmljZSBhbmQgdGhlIG9kb21ldGVyIHJlYWRpbmcgZm9yIGFsbCAzLXllYXItb2xkIFRveW90YSBDYW1yeXMuIFVzZSBhIDUlIHNpZ25pZmljYW5jZSBsZXZlbC4KCk9uIHZhIHRlc3RlciBsJ2h5cHRow6hzZSAKCiQkCkhfMDpcOlxiZXRhXzE9MCBcdGV4dHsgY29udHJlIH0gSF8xOlw6XGJldGFfMVxuZXEgMC4gCiQkCk9uIHRyb3V2ZSAKYGBge3J9ClNMTSRjb2VmZmljaWVudHNbMiwxXSAjIyBiMQpTTE0kY29lZmZpY2llbnRzWzIsMl0gIyMgc19iMQp0PVNMTSRjb2VmZmljaWVudHNbMiwzXSAjIyB0ClNMTSRjb2VmZmljaWVudHNbMiw0XQoyKnB0KGFicyh0KSw5OCxsb3dlci50YWlsID0gRkFMU0UpCmBgYAoKIyMgRVhBTVBMRSAxNi4gNSBNZWFzdXJpbmcgdGhlIFN0cmVuZ3RoIG9mIHRoZSBMaW5lYXIgUmVsYXRpb25zaGlwIGJldHdlZW4gT2RvbWV0ZXIgUmVhZGluZyBhbmQgUHJpY2Ugb2YgVXNlZCBUb3lvdGEgQ2FtcnlzCkZpbmQgdGhlIGNvZWZmaWNpZW50IG9mIGRldGVybWluYXRpb24gZm9yIEV4YW1wbGUgMTYuMiBhbmQgZGVzY3JpYmUgd2hhdCB0aGlzIHN0YXRpc3RpYyB0ZWxscyB5b3UgYWJvdXQgdGhlIHJlZ3Jlc3Npb24gbW9kZWwuCmBgYHtyfQpTTE0kci5zcXVhcmVkCihjb3IoZGF0YSRQcmljZSxkYXRhJE9kb21ldGVyKSleMgpgYGAKVGhpcyBzdGF0aXN0aWMgdGVsbHMgdXMgdGhhdCA2NC44MyUgb2YgdGhlIHZhcmlhdGlvbiBpbiB0aGUgYXVjdGlvbiBzZWxsaW5nIHByaWNlcyBpcyBleHBsYWluZWQgYnkgdGhlIHZhcmlhdGlvbiBpbiB0aGUgb2RvbWV0ZXIgcmVhZGluZ3MuCgoKYGBge3J9CkFOT1ZBPWFub3ZhKExNKQpzdW0oQU5PVkFbLDJdKQo5OSp2YXIoZGF0YSRQcmljZSkKQU5PVkFbMSwyXS8oOTkqdmFyKGRhdGEkUHJpY2UpKQoKYGBgCgojIyBFWEFNUExFIDE2LjcgUHJlZGljdGluZyB0aGUgUHJpY2UgYW5kIEVzdGltYXRpbmcgdGhlIE1lYW4gUHJpY2Ugb2YgVXNlZCBUb3lvdGEgQ2FtcnlzIAphLiBBIHVzZWQtY2FyIGRlYWxlciBpcyBhYm91dCB0byBiaWQgb24gYSAzLXllYXItb2xkIFRveW90YSBDYW1yeSBlcXVpcHBlZCB3aXRoIGFsbCB0aGUKc3RhbmRhcmQgZmVhdHVyZXMgYW5kIHdpdGggNDAsMDAwICgkeF9nJCDiq70gNDApIG1pbGVzIG9uIHRoZSBvZG9tZXRlci4gVG8gaGVscCBoaW0gZGVjaWRlIGhvdyBtdWNoIHRvIGJpZCwgaGUgbmVlZHMgdG8gcHJlZGljdCB0aGUgc2VsbGluZyBwcmljZS4KCmBgYHtyfQp4Zz1kYXRhLmZyYW1lKE9kb21ldGVyID0gYyg0MCkpCgpQUkVESUNUPXByZWRpY3QubG0oTE0seGcsaW50ZXJ2YWwgPSAicHJlZGljdGlvbiIpClNMTSRjb2VmZmljaWVudHNbLDFdJSolYygxLDQwKQo/cHJlZGljdC5sbQpQUkVESUNUWzFdLVBSRURJQ1RbMl0KCmBgYAoKCgpiLiBUaGUgdXNlZC1jYXIgZGVhbGVyIG1lbnRpb25lZCBpbiBwYXJ0IChhKSBoYXMgYW4gb3Bwb3J0dW5pdHkgdG8gYmlkIG9uIGEgbG90IG9mIGNhcnMgb2ZmZXJlZCBieSBhIHJlbnRhbCBjb21wYW55LiBUaGUgcmVudGFsIGNvbXBhbnkgaGFzIDI1MCBUb3lvdGEgQ2FtcnlzIGFsbCBlcXVpcHBlZCB3aXRoIHN0YW5kYXJkIGZlYXR1cmVzLiBBbGwgdGhlIGNhcnMgaW4gdGhpcyBsb3QgaGF2ZSBhYm91dCA0MCwwMDAgKHhnIOKrvSA0MCkgbWlsZXMgb24gdGhlaXIgb2RvbWV0ZXJzLiBUaGUgZGVhbGVyIHdvdWxkIGxpa2UgYW4gZXN0aW1hdGUgb2YgdGhlIHNlbGxpbmcgcHJpY2Ugb2YgYWxsIHRoZSBjYXJzIGluIHRoZSBsb3QuCmBgYHtyfQpQUkVESUNURVhQPXByZWRpY3QubG0oTE0seGcsaW50ZXJ2YWwgPSAiY29uZmlkZW5jZSIpClBSRURJQ1RFWFBbMV0tUFJFRElDVEVYUFsyXQpQUkVESUNURVhQWzNdLVBSRURJQ1RFWFBbMV0KCmBgYAoKCiMgQXZlYyBsZXMgbWF0cmljZXMKClNpIG9uIG5vdGUgCiQkClk9XGJlZ2lue2JtYXRyaXh9CnlfMVxcClx2ZG90c1xcCnlfbiBcXApcZW5ke2JtYXRyaXh9IFx0ZXh0eyBldCB9Clg9XGJlZ2lue2JtYXRyaXh9CjEgJiB4XzFcXApcdmRvdHMgJiBcdmRvdHMgXFwKMSAmIHhfbiBcXApcZW5ke2JtYXRyaXh9LAokJApvbiBvYnRpZW50IGxlcyBlc3RpbWF0ZXVycyBncsOiY2Ugw6AgdW4gY2xjdWwgbWF0cmljaWVsCiQkClxiZWdpbntibWF0cml4fQpiXzAgXFwKYl8xClxlbmR7Ym1hdHJpeH09CihYXnRYKV57LTF9WF50WSwKJCQKb8O5CiQkClhedD1cYmVnaW57Ym1hdHJpeH0KMSAmXGNkb3RzJiAxIFxcCjEgJiBcY2RvdHMgJnhfbiBcXApcZW5ke2JtYXRyaXh9LAokJAplc3QgbGEgbWF0cmljZSB0cmFuc3Bvc8OpZSBkZSAkWCQuCgpgYGB7cn0KWD1tYXRyaXgoYyhyZXAoMSwxMDApLGRhdGEkT2RvbWV0ZXIpLG5yb3cgPSAxMDAsbmNvbD0yKQpkaW0oWCkKWT1tYXRyaXgoZGF0YSRQcmljZSxucm93ID0gMTAwLG5jb2w9MSkKc29sdmUodChYKSUqJVgpJSoldChYKSUqJVkKClNMTSRjb2VmZmljaWVudHMKCgpgYGAKCkxhIG1hdGljZSBkZSB2YXJpYW5jZS1jb3ZhcmlhbmNlIGRlICQoYl8wLGJfMSkkIGVzdCBkb25uw6llIHBhcgoKJCQKXHNpZ21hXjIoWF50WCleey0xfS4KJCQKQ29tbWUgJFxzaWdtYV4yJCBlc3QgaW5jb21tdSwgb24gbCdlc3RpbWUgY2UgcXVpIGRvbm5lIAoKYGBge3J9CgoKU0xNJHNpZ21hCgpzcXJ0KHN1bSgoU0xNJHJlc2lkdWFscyleMikvOTgpCmBgYAoKYGBge3J9CihTTE0kc2lnbWEpXjIqc29sdmUodChYKSUqJVgpCgooU0xNJGNvZWZmaWNpZW50c1syLDJdKV4yCgp2Y292KExNKQoKYGBgCgoKIyBVbiBwZXUgZCdhbGfDqGJyZQoKT24gcmFwcGVsbGUgcXVlIGxhIG3DqXRob2RlIGRlIG1vaW5kcmVzIGNhcnLDqXMgdmEgcsOpc291ZHJlIGxlIHByb2dyYW1tZSBzdWl2YW50IAoKJCQKXG1pbl97Yl8wLGJfMX0gXHN1bSAoeV9pLVxoYXR7eV9pfSleMixcdGV4dHsgYXZlYyB9IFxoYXR7eV9pfT1iXzArYl8xIHhfaS4KJCQKClBhciBkw6lyaXZhdGlvbiBwYXIgcmFwcG9ydCDDoCAkYl8wJCBldCAkYl8xJCBvbiBvYnRpZW50IGxlcyBkZXV4IGNvbmRpdGlvbiBkdSBwcmVtaWVyIG9yZHJlIHN1aXZhbnRlcyAob24gbm90ZXJhIHF1ZSAkXHBhcnRpYWwgXGhhdHt5fV9pL1xwYXJ0aWFsIGJfMT0geF9pJCkKCgokJApcYmVnaW57ZXF1YXRpb259ClxiZWdpbntjYXNlc30KXHN1bSB4X2koeV9pLVxoYXR7eV9pfSk9MDtcXApcc3VtICh5X2ktXGhhdHt5X2l9KT0wLgpcZW5ke2Nhc2VzfQpcZW5ke2VxdWF0aW9ufQokJAoKTGEgcHJlbWnDqHJlIGNvbmRpdGlvbiB2b3VzIGRpdCBxdWUgbGVzIGVycmV1cnMgc29udCBkZSBtb3llbm5lIHplcm8gZXQgbGEgc2Vjb25kZSBxdWUgbGEgdmFyaWFibGUgZGVzIGVycmV1cnMgZXQgbGEgdmFyaWFibGVzIGV4cGxpY2F0aXZlIG5lIHNvbnQgcGFzIGNvcnLDqWzDqXMuCgpPbiBwZXV0IHLDqcOpY3JpcmUgY2VzIGRldXggY29uZGl0aW9ucyBhaW5zaQokJApcYmVnaW57ZXF1YXRpb259ClxiZWdpbntjYXNlc30KXHN1bSAoeF9pLVxiYXJ7eH0pKHlfaS1caGF0e3lfaX0pPTA7XFwKXHN1bSAoeV9pLVxoYXR7eV9pfSk9MC4KXGVuZHtjYXNlc30KXGVuZHtlcXVhdGlvbn0KJCQKCgpPbiByZW1hcnF1ZXJhIHF1ZSAkXGJhcnt5fT1cYmFye1xoYXR7eX19JC4gCgoKUG91ciBmaW5pLCBlbiByZXBsYcOnYW50ICRiXzAkIGV0ICRiXzEkIHBhciBsZXVycyB2YWxldXJzIG9wdGltYWxlcywgb24gdHJvdXZlIAoKJCQKU1NFPVxzdW0gKHlfaS1caGF0e3lfaX0pXjI9XHN1bSAoeV9pLVxiYXJ7eX0rIFxiYXJ7eX0tXGhhdHt5X2l9KV4yLAokJApjZSBxdWkgZG9ubmUKCiQkClNTRT1cc3VtIFt5X2ktXGJhcnt5fS1iXzEoeF9pLVxiYXJ7eH0pXSBeMi4KJCQKRW4gZMOpdmVsb3BwYW50LCBvbiB0cm91dmUKCiQkClNTRT1cc3VtICh5X2ktXGJhcnt5fSleMi0yYl8xXHN1bSh4X2ktXGJhcnt4fSkoeV9pLVxiYXJ7eX0pK2JeMl8xXHN1bSAoeF9pLVxiYXJ7eH0pXjIuCiQkCgpFbiByZW1hcnF1YW50IHF1ZSAKCiQkCmJeMl8xXHN1bSAoeF9pLVxiYXJ7eH0pXjI9Yl8xXHN1bSh4X2ktXGJhcnt4fSkoeV9pLVxiYXJ7eX0pLAokJApPbiBvYnRpZW50IAoKJCQKU1NFPVxzdW0gKHlfaS1cYmFye3l9KV4yLWJfMVxzdW0oeF9pLVxiYXJ7eH0pKHlfaS1cYmFye3l9KS4KJCQKCkVuIHV0aWxpc2FudCBsYSB2YWxldXIgZGUgJGJfMSQsIG9uIHRyb3V2ZSAKCiQkClNTRT1cc3VtICh5X2ktXGJhcnt5fSleMi1cZnJhY3tbIFxzdW0oeF9pLVxiYXJ7eH0pKHlfaS1cYmFye3l9KSBdXjJ9e1xzdW0gKHhfaS1cYmFye3h9KV4yfQokJAoKT24gYSBhdXNzaQoKJCQKU1NFPSgxLVJeMilcc3VtICh5X2ktXGJhcnt5fSleMi4KJCQKb8O5CiQkClJeMj1cZnJhY3tbIFxzdW0oeF9pLVxiYXJ7eH0pKHlfaS1cYmFye3l9KSBdXjJ9e1xzdW0gKHhfaS1cYmFye3h9KV4yXHN1bSAoeV9pLVxiYXJ7eX0pXjJ9PVxmcmFje3NeMl97eHl9fXtzX3t4fXNfe3l9fS4KJCQKT24gYSBhdXNzaSAKCiQkClJeMj0xLVxmcmFje1NTRSB9e1xzdW0gKHlfaS1cYmFye3l9KV4yfSwKJCQKCkVuIHJlbWFycXVhbnQgcXllIAokJApcc3VtKHlfaS1cYmFye3kgfSleMj1cc3VtKHlfaS1caGF0e3kgfV9pKV4yK1xzdW0oXGhhdHt5IH1faS1cYmFye3kgfSleMj1TU0UrXHN1bShcaGF0e3kgfV9pLVxiYXJ7eSB9KV4yLAokJApPbiBhIGF1c3NpCiQkClJeMj1cZnJhY3tcc3VtICh5X2ktXGJhcnt5fSleMi1TU0UgfXtcc3VtICh5X2ktXGJhcnt5fSleMn09XGZyYWN7XHN1bShcaGF0e3kgfV9pLVxiYXJ7eSB9KV4yIH17XHN1bSAoeV9pLVxiYXJ7eX0pXjJ9LgokJAoKJFJeMiQgZGV2aWVudGIgbGEgcGFydCBkZSB2YXJpYW5jZSBleHBsaXF1w6llIHBhciBsZSBtb2TDqGxlLg==