setwd(dir = "C:/Users/fkraus/Desktop/TD/2025-2026/ECONOMETRIE/séance4")
Les résidus d’une régression sont souvent notés \(\varepsilon_t\) par convention. Ils
représentent l’écart entre la variable dépendante de la régression et
ses valeurs prédites par le modèles : \[\begin{align}
&Y_t = a_0 + \beta X_t + \varepsilon_t \\
&\varepsilon_t = Y_t - \hat Y_t
\end{align}\]
Et les résidus représentent réellement à quel point notre modèle est
précis dans son estimation. Le modèle de régression est censé
représenter correctement la dynamique de la variable dépendante \(Y_t\) en fonction de la dynamique d’autres
variables (\(X_t\)), du temps (avec une
trend, un cycle, une saisonnalité, etc… si on observe leur présence) et
de la structure propre de la série (ARIMA). Cependant, on n’est pas
censé représenter la variable dépendante avec une précision parfaite :
le modèle peut sur-estimer ou sous-estimer de temps en temps la
dynamique.
Cependant, quand on fait le modèle de régression, on part du principe
que, si il est correct, on va correctement estimer la dynamique dans
l’ensemble. On peut sur-estimer ou sous-estimer, mais en moyenne il faut
que ces erreurs soient le plus proche possible de 0 : la moyenne
des résidus doit donc être proche de 0. Egalement, on veut se
tromper autant dans la sur-estimation que dans la sous-estimation (on ne
veut pas sous-estimer la variable en permanence) : la somme des
résidus doit être proche de 0. Egalement, on veut se tromper du
même ordre peu importe la période : la moyenne et la variance
des résidus doivent être constants. De cette condition découle
une autre : les résidus doivent être indépendants.
Autrement dit, le coefficient d’autocorrélation des résidus doit
être nul (si on se trompe à une période, ça ne veut pas dire
qu’on va se tromper à la période suivante) et ne doivent pas dépendre de
\(Y_t\) (le coefficient de régression
entre \(\varepsilon_t\) et \(Y_t\) doit être nul). Au final, les
résidus doivent donc suivre une loi normale, centrée autour de
zéro.
Si on résume ces cas : \[\begin{align}
& \mathbb{E}(\varepsilon) = 0 \\
& \sum_{i=1}^N\varepsilon_i = 0 \\
& \mathbb{E}(\varepsilon)=\mathbb{E}(\varepsilon_{t+h}) \\
& \operatorname{Var}(\varepsilon) = \sigma^2_\varepsilon \\
& \operatorname{Cov}(\varepsilon_t, \varepsilon_{t-h})=0 \\
& \operatorname{Cov}(\varepsilon_t, Y_{t})=0\\
& \rightarrow\varepsilon_t \overset{\text{i.i.d.}}{\sim} \mathcal
N(0,\sigma_\varepsilon^2)
\end{align}\]
Note : \(i.i.d\) signifie
identiquement et indépendamment distribués. Ces cas sont nombreux,
mais au final on retombe assez vite sur ce qu’on a vu dans la séance sur
la stationnarisation : on veut obtenir une suite de bruits blancs.
En effet, il faut imaginer que les séries temporelles ne sont qu’une
suite de bruits blancs, et que ces bruits blancs sont impactés par des
chocs exogènes (qui proviennent d’autres variables). Avec la régression,
on retire l’influence de ces variables exogènes, et on est censé
retomber sur la suite de bruits blancs originelle.
data_schularick <- read_excel("C:/users/fkraus/Desktop/data_schularick.xlsx")
donnees_france <- data_schularick %>%
filter(country=="France")%>%
dplyr::select(year, unemp, cpi) %>%
mutate(inflation = (log(cpi) - lag(log(cpi)))*100)%>%
mutate(dinflation = inflation - lag(inflation))%>%
mutate(dunemp = unemp - lag(unemp))%>%
na.omit()%>%
filter(year > 1950)
head(donnees_france)
require(fixest)
reg <- feols(inflation ~ dunemp, data=donnees_france)
etable(reg)
reg
Dependent Var.: inflation
Constant 4.060*** (0.4607)
dunemp 1.663* (0.7335)
_______________ _________________
S.E. type IID
Observations 70
R2 0.07031
Adj. R2 0.05664
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Analyse des résidus
On peut comparer la variable dépendante avec les valeurs prédites par
le modèles :
fitted_val <- reg$fitted.values
residuals <- reg$residuals
donnees_france_2 <- donnees_france %>%
cbind(fitted_val)%>%
cbind(residuals)
ggplot(donnees_france_2, aes(x=year, y=inflation))+
geom_line(lwd=1)+
geom_line(aes(y=fitted_val), color="red", lty=2, lwd=1)+
theme_bw()

On peut voir que notre modèle, bien qu’il utilise des variables
correctement stationnarisées, ne représente par correctement la
dynamique de la série : les fitted values ne suivent pas bien
la série d’origine, particulièrement avant les années 1990.
Homoscedasticité
Pour vérifier l’homoscédasticité (=variance constante dans le temps),
on peut déjà fait un graphique des résidus dans le temps.
ggplot(donnees_france_2, aes(x=year, y=residuals))+
geom_line(lwd=1)+
geom_hline(yintercept = 0, lty=2)+
theme_bw()

On peut voir que la variance des résidus change drastiquement à
partir de la fin des années 1980, ce qui pourrait indiquer que les
résidus sont hétéroscédastiques. Cependant, l’analyse visuelle n’est pas
un test formel. Pour vérifier l’homoscédasticité ou non des résidus, on
doit utiliser le test de Breusch-Pagan (BP). Le test BP a pour hypothèse
nulle l’hétéroscédasticité. Si la p-value est significative, on rejette
donc l’hypothèse nulle et on conclut de l’homoscédasticité.
require(lmtest)
bptest(inflation ~ dunemp, data=donnees_france)
studentized Breusch-Pagan test
data: inflation ~ dunemp
BP = 4.3177, df = 1, p-value = 0.03772
Ici, la p-value est significative, donc on conclut que les résidus de
la régression sont hétéroscédastiques.
Normalité des résidus
ggplot(donnees_france_2, aes(residuals))+geom_density(fill="grey60", bounds=c(-Inf, Inf))+theme_bw()

Les résidus sont bien distribués autour de zéro, et la moyenne est
relativement proche de zéro. En revanche, on peut voir que la queue de
distribution à droite est relativement large, donc on tend à
sous-estimer grandement le modèle à certains moments. La distribution
n’est qu’une vérification visuelle, pas un test statistique. Pour un
test formel, il faut se tourner vers le test de Shapiro qui teste la
normalité d’une série. Le test de Shapiro a pour hypothèse nulle la
normalité des résidus. Si la p-value est significative, on rejette donc
l’hypothèse nulle, et on conclut de la non-normalité de la série.
shapiro.test(donnees_france_2$residuals)
Shapiro-Wilk normality test
data: donnees_france_2$residuals
W = 0.92324, p-value = 0.0003666
Ici, la p-value est significative, donc les résidus ne suivent pas
une loi normale selon le test de Shapiro.
Indépendance
D’après l’hypothèse d’indépendance des résidus, les résidus d’une
période ne doivent pas être expliqués par les résidus précédents. On
peut tester cette hypothèse avec un simple autocorrélogramme :
acf(donnees_france_2$residuals)

Ici, on observe que les résidus ne semblent pas être indépendants,
car les résidus passés expliquent de manière systématique les résidus
actuels. Après l’analyse visuel, on peut faire le test formel. Le test
Ljung-Box effectue le test d’indépendance des résidus, et a pour
hypothèse nulle l’indépendance des résidus. Si la p-value est
significative, on rejette l’hypothèse nulle et on conclut de
l’autocorrélation (donc, l’absence d’indépendance) des résidus.
Box.test(donnees_france_2$residuals, lag = 10, type = "Ljung-Box")
Box-Ljung test
data: donnees_france_2$residuals
X-squared = 87.576, df = 10, p-value = 1.621e-14
Ici, il semble que nos résidus ne sont pas indépendants car la
p-value est significative.
Note : certains de ces tests sont résumés dans la fonction
checkresiduals() du package forecast:
require(forecast)
Le chargement a nécessité le package : forecast
Avis : le package ‘forecast’ a été compilé avec la version R 4.5.1Registered S3 method overwritten by 'quantmod':
method from
as.zoo.data.frame zoo
checkresiduals(reg)
Ljung-Box test
data: Residuals from feols
Q* = 87.576, df = 10, p-value = 1.621e-14
Model df: 0. Total lags used: 10

Ainsi, dans l’ensemble, notre modèle est peu performant dans
l’explication de la dynamique de l’inflation. En revanche, il explique
correctement ce qu’il explique ! C’est un bon début, car cela veut dire
qu’on peut maintenant ajouter d’autres variables explicatives dans le
modèles (en testant, à chaque ajout, les effets sur les résidus pour
vérifier qu’on ne crée par de problèmes qui seraient détectés dans les
résidus) pour améliorer le pouvoir explicatif, tout en respectant le
principe de parsimonie : on ne cherche pas à expliquer la totalité des
variations de \(Y_t\), simplement à
l’expliquer suffisamment pour que l’estimation de l’impact de \(\beta\) soit correct.
Overfitting
Parfois, on peut ajouter des variables qui vont créer un biais de
collinéarité : les variables explicatives peuvent s’influencer entre
elles, ou avoir un effet circulaire avec la variable dépendante, ce qui
va créer un problème dans la régression.
reg_colin <- feols(inflation ~dunemp + lag(inflation), data= donnees_france)
etable(reg_colin)
reg_colin
Dependent Var.: inflation
Constant 0e-16 (5.11e-17)
dunemp 4.44e-16*** (5.77e-17)
lag(inflation) 1*** (9.19e-18)
_______________ ______________________
S.E. type IID
Observations 70
R2 1
Adj. R2 1
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Et quand on regard l’écart entre les fitted valued et la
variable dépendante, on obtient :
fitted_val_colin <- reg_colin$fitted.values
residuals_colin <- reg_colin$residuals
donnees_france_3 <- donnees_france %>%
cbind(fitted_val_colin)%>%
cbind(residuals_colin)
ggplot(donnees_france_3, aes(x=year, y=inflation))+
geom_line(lwd=1)+
geom_line(aes(y=fitted_val_colin), color="red", lty=2, lwd=1)+
theme_bw()

Ici, on peut être tenté de dire que notre modèle est parfait parce
qu’il explique bien notre variable dépendante. Mais ici, on a un
problème de collinéarité : lag(dinflation) explique
quasi-parfaitement dinflation, et l’ajouter dans le modèle
créé de la collinéarité parfaite.
On peut tester la collinéarité avec un test VIF
require(car)
Le chargement a nécessité le package : car
Le chargement a nécessité le package : carData
Attachement du package : ‘car’
L'objet suivant est masqué depuis ‘package:dplyr’:
recode
L'objet suivant est masqué depuis ‘package:purrr’:
some
vif(reg_colin)
GVIF Df GVIF^(1/(2*Df))
dunemp 1.07563 0 Inf
lag(inflation) 1.07563 0 Inf
Ici, le GVIF corrigé (colonne à droite) tend vers l’infini. On essaie
en général de garder un VIF au maximum a 6 ou 7, au
delà il y a un problème.
Donc ici, ajouter le lag de l’inflation va créer plus de
problème qu’il n’en résout. Cependant, cette régression a pour
mérite de montrer que l’inflation, même si elle est considérée comme
étant stationnaire, continue d’avoir une structure auto-régressive
importante, au point où si on la néglige, on perd un pouvoir explicatif
très important. C’est la raison pour laquelle il faut s’intéresser à la
structure Auto-Régressive (AR) des séries temporelles, à leur degré
d’intégration (I) et à leur moyenne mobile (Moving Average - MA), dans
le cadre des modèles ARIMA que l’on verra dans la séance 4.
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2sgOiBBbmFseXNlIGRlcyByw6lzaWR1cyAiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCmh0bWxfbm90ZWJvb2s6IA0KICAgIHRvYzogdHJ1ZSAjIHBvdXIgYWZmaWNoZXIgdW5lIHRhYmxlIGRlcyBtYXRpw6hyZXMgYXUgZMOpYnV0IGR1IGRvY3VtZW50IChUYWJsZSBvZiBDb250ZW50KQ0KICAgIHRvY19kZXB0aDogNCAjIGxlIG5pdmVhdSBkJ2FmZmljaGFnZSBkZXMgdGl0cmVzLCBzb3VzLXRpdHJlcywgc2VjdGlvbi4uLiANCiAgICB0b2NfZmxvYXQ6IGZhbHNlDQotLS0NCg0KYGBge3J9DQpzZXR3ZChkaXIgPSAiQzovVXNlcnMvZmtyYXVzL0Rlc2t0b3AvVEQvMjAyNS0yMDI2L0VDT05PTUVUUklFL3PDqWFuY2U0IikNCmBgYA0KDQpMZXMgcsOpc2lkdXMgZCd1bmUgcsOpZ3Jlc3Npb24gc29udCBzb3V2ZW50IG5vdMOpcyAkXHZhcmVwc2lsb25fdCQgcGFyIGNvbnZlbnRpb24uIElscyByZXByw6lzZW50ZW50IGwnw6ljYXJ0IGVudHJlIGxhIHZhcmlhYmxlIGTDqXBlbmRhbnRlIGRlIGxhIHLDqWdyZXNzaW9uIGV0IHNlcyB2YWxldXJzIHByw6lkaXRlcyBwYXIgbGUgbW9kw6hsZXMgOg0KXGJlZ2lue2FsaWdufQ0KICZZX3QgPSBhXzAgKyBcYmV0YSBYX3QgKyBcdmFyZXBzaWxvbl90IFxcDQogJlx2YXJlcHNpbG9uX3QgPSBZX3QgLSBcaGF0IFlfdA0KXGVuZHthbGlnbn0NCg0KRXQgbGVzIHLDqXNpZHVzIHJlcHLDqXNlbnRlbnQgcsOpZWxsZW1lbnQgw6AgcXVlbCBwb2ludCBub3RyZSBtb2TDqGxlIGVzdCBwcsOpY2lzIGRhbnMgc29uIGVzdGltYXRpb24uIExlIG1vZMOobGUgZGUgcsOpZ3Jlc3Npb24gZXN0IGNlbnPDqSByZXByw6lzZW50ZXIgY29ycmVjdGVtZW50IGxhIGR5bmFtaXF1ZSBkZSBsYSB2YXJpYWJsZSBkw6lwZW5kYW50ZSAkWV90JCBlbiBmb25jdGlvbiBkZSBsYSBkeW5hbWlxdWUgZCdhdXRyZXMgdmFyaWFibGVzICgkWF90JCksIGR1IHRlbXBzIChhdmVjIHVuZSB0cmVuZCwgdW4gY3ljbGUsIHVuZSBzYWlzb25uYWxpdMOpLCBldGMuLi4gc2kgb24gb2JzZXJ2ZSBsZXVyIHByw6lzZW5jZSkgZXQgZGUgbGEgc3RydWN0dXJlIHByb3ByZSBkZSBsYSBzw6lyaWUgKEFSSU1BKS4gQ2VwZW5kYW50LCBvbiBuJ2VzdCBwYXMgY2Vuc8OpIHJlcHLDqXNlbnRlciBsYSB2YXJpYWJsZSBkw6lwZW5kYW50ZSBhdmVjIHVuZSBwcsOpY2lzaW9uIHBhcmZhaXRlIDogbGUgbW9kw6hsZSBwZXV0IHN1ci1lc3RpbWVyIG91IHNvdXMtZXN0aW1lciBkZSB0ZW1wcyBlbiB0ZW1wcyBsYSBkeW5hbWlxdWUuIA0KDQpDZXBlbmRhbnQsIHF1YW5kIG9uIGZhaXQgbGUgbW9kw6hsZSBkZSByw6lncmVzc2lvbiwgb24gcGFydCBkdSBwcmluY2lwZSBxdWUsIHNpIGlsIGVzdCBjb3JyZWN0LCBvbiB2YSBjb3JyZWN0ZW1lbnQgZXN0aW1lciBsYSBkeW5hbWlxdWUgZGFucyBsJ2Vuc2VtYmxlLiBPbiBwZXV0IHN1ci1lc3RpbWVyIG91IHNvdXMtZXN0aW1lciwgbWFpcyBlbiBtb3llbm5lIGlsIGZhdXQgcXVlIGNlcyBlcnJldXJzIHNvaWVudCBsZSBwbHVzIHByb2NoZSBwb3NzaWJsZSBkZSAwIDogKipsYSBtb3llbm5lIGRlcyByw6lzaWR1cyBkb2l0IGRvbmMgw6p0cmUgcHJvY2hlIGRlIDAqKi4gRWdhbGVtZW50LCBvbiB2ZXV0IHNlIHRyb21wZXIgYXV0YW50IGRhbnMgbGEgc3VyLWVzdGltYXRpb24gcXVlIGRhbnMgbGEgc291cy1lc3RpbWF0aW9uIChvbiBuZSB2ZXV0IHBhcyBzb3VzLWVzdGltZXIgbGEgdmFyaWFibGUgZW4gcGVybWFuZW5jZSkgOiAqKmxhIHNvbW1lIGRlcyByw6lzaWR1cyBkb2l0IMOqdHJlIHByb2NoZSBkZSAwKiouIEVnYWxlbWVudCwgb24gdmV1dCBzZSB0cm9tcGVyIGR1IG3Dqm1lIG9yZHJlIHBldSBpbXBvcnRlIGxhIHDDqXJpb2RlIDogKipsYSBtb3llbm5lIGV0IGxhIHZhcmlhbmNlIGRlcyByw6lzaWR1cyBkb2l2ZW50IMOqdHJlIGNvbnN0YW50cy4qKiBEZSBjZXR0ZSBjb25kaXRpb24gZMOpY291bGUgdW5lIGF1dHJlIDogKipsZXMgcsOpc2lkdXMgZG9pdmVudCDDqnRyZSBpbmTDqXBlbmRhbnRzLioqIEF1dHJlbWVudCBkaXQsICoqbGUgY29lZmZpY2llbnQgZCdhdXRvY29ycsOpbGF0aW9uIGRlcyByw6lzaWR1cyBkb2l0IMOqdHJlIG51bCoqIChzaSBvbiBzZSB0cm9tcGUgw6AgdW5lIHDDqXJpb2RlLCDDp2EgbmUgdmV1dCBwYXMgZGlyZSBxdSdvbiB2YSBzZSB0cm9tcGVyIMOgIGxhIHDDqXJpb2RlIHN1aXZhbnRlKSBldCBuZSBkb2l2ZW50IHBhcyBkw6lwZW5kcmUgZGUgJFlfdCQgKGxlIGNvZWZmaWNpZW50IGRlIHLDqWdyZXNzaW9uIGVudHJlICRcdmFyZXBzaWxvbl90JCBldCAkWV90JCBkb2l0IMOqdHJlIG51bCkuIEF1IGZpbmFsLCAqKmxlcyByw6lzaWR1cyBkb2l2ZW50IGRvbmMgc3VpdnJlIHVuZSBsb2kgbm9ybWFsZSwgY2VudHLDqWUgYXV0b3VyIGRlIHrDqXJvLioqDQoNClNpIG9uIHLDqXN1bWUgY2VzIGNhcyA6DQpcYmVnaW57YWxpZ259DQomIFxtYXRoYmJ7RX0oXHZhcmVwc2lsb24pID0gMCBcXA0KJiBcc3VtX3tpPTF9Xk5cdmFyZXBzaWxvbl9pID0gMCBcXA0KJiBcbWF0aGJie0V9KFx2YXJlcHNpbG9uKT1cbWF0aGJie0V9KFx2YXJlcHNpbG9uX3t0K2h9KSBcXA0KJiBcb3BlcmF0b3JuYW1le1Zhcn0oXHZhcmVwc2lsb24pID0gXHNpZ21hXjJfXHZhcmVwc2lsb24gXFwNCiYgXG9wZXJhdG9ybmFtZXtDb3Z9KFx2YXJlcHNpbG9uX3QsIFx2YXJlcHNpbG9uX3t0LWh9KT0wIFxcDQomIFxvcGVyYXRvcm5hbWV7Q292fShcdmFyZXBzaWxvbl90LCBZX3t0fSk9MFxcDQomIFxyaWdodGFycm93XHZhcmVwc2lsb25fdCBcb3ZlcnNldHtcdGV4dHtpLmkuZC59fXtcc2ltfSBcbWF0aGNhbCBOKDAsXHNpZ21hX1x2YXJlcHNpbG9uXjIpDQpcZW5ke2FsaWdufQ0KDQoqTm90ZSA6ICRpLmkuZCQgc2lnbmlmaWUgaWRlbnRpcXVlbWVudCBldCBpbmTDqXBlbmRhbW1lbnQgZGlzdHJpYnXDqXMqLiBDZXMgY2FzIHNvbnQgbm9tYnJldXgsIG1haXMgYXUgZmluYWwgb24gcmV0b21iZSBhc3NleiB2aXRlIHN1ciBjZSBxdSdvbiBhIHZ1IGRhbnMgbGEgc8OpYW5jZSBzdXIgbGEgc3RhdGlvbm5hcmlzYXRpb24gOiBvbiB2ZXV0IG9idGVuaXIgdW5lIHN1aXRlIGRlIGJydWl0cyBibGFuY3MuDQoNCkVuIGVmZmV0LCBpbCBmYXV0IGltYWdpbmVyIHF1ZSBsZXMgc8OpcmllcyB0ZW1wb3JlbGxlcyBuZSBzb250IHF1J3VuZSBzdWl0ZSBkZSBicnVpdHMgYmxhbmNzLCBldCBxdWUgY2VzIGJydWl0cyBibGFuY3Mgc29udCBpbXBhY3TDqXMgcGFyIGRlcyBjaG9jcyBleG9nw6huZXMgKHF1aSBwcm92aWVubmVudCBkJ2F1dHJlcyB2YXJpYWJsZXMpLiBBdmVjIGxhIHLDqWdyZXNzaW9uLCBvbiByZXRpcmUgbCdpbmZsdWVuY2UgZGUgY2VzIHZhcmlhYmxlcyBleG9nw6huZXMsIGV0IG9uIGVzdCBjZW5zw6kgcmV0b21iZXIgc3VyIGxhIHN1aXRlIGRlIGJydWl0cyBibGFuY3Mgb3JpZ2luZWxsZS4NCg0KYGBge3J9DQpkYXRhX3NjaHVsYXJpY2sgPC0gcmVhZF9leGNlbCgiQzovdXNlcnMvZmtyYXVzL0Rlc2t0b3AvZGF0YV9zY2h1bGFyaWNrLnhsc3giKSANCg0KZG9ubmVlc19mcmFuY2UgPC0gZGF0YV9zY2h1bGFyaWNrICU+JQ0KICBmaWx0ZXIoY291bnRyeT09IkZyYW5jZSIpJT4lDQogIGRwbHlyOjpzZWxlY3QoeWVhciwgdW5lbXAsIGNwaSkgJT4lDQogIG11dGF0ZShpbmZsYXRpb24gPSAobG9nKGNwaSkgLSBsYWcobG9nKGNwaSkpKSoxMDApJT4lDQogIG11dGF0ZShkaW5mbGF0aW9uID0gaW5mbGF0aW9uIC0gbGFnKGluZmxhdGlvbikpJT4lDQogIG11dGF0ZShkdW5lbXAgPSB1bmVtcCAtIGxhZyh1bmVtcCkpJT4lDQogIG5hLm9taXQoKSU+JQ0KICBmaWx0ZXIoeWVhciA+IDE5NTApDQoNCmhlYWQoZG9ubmVlc19mcmFuY2UpDQpgYGANCg0KDQpgYGB7cn0NCnJlcXVpcmUoZml4ZXN0KQ0KcmVnIDwtIGZlb2xzKGluZmxhdGlvbiB+IGR1bmVtcCwgZGF0YT1kb25uZWVzX2ZyYW5jZSkNCmV0YWJsZShyZWcpDQpgYGANCiMgQW5hbHlzZSBkZXMgcsOpc2lkdXMNCk9uIHBldXQgY29tcGFyZXIgbGEgdmFyaWFibGUgZMOpcGVuZGFudGUgYXZlYyBsZXMgdmFsZXVycyBwcsOpZGl0ZXMgcGFyIGxlIG1vZMOobGVzIDoNCmBgYHtyfQ0KZml0dGVkX3ZhbCA8LSByZWckZml0dGVkLnZhbHVlcw0KcmVzaWR1YWxzIDwtIHJlZyRyZXNpZHVhbHMNCg0KZG9ubmVlc19mcmFuY2VfMiA8LSBkb25uZWVzX2ZyYW5jZSAlPiUNCiAgY2JpbmQoZml0dGVkX3ZhbCklPiUNCiAgY2JpbmQocmVzaWR1YWxzKQ0KZ2dwbG90KGRvbm5lZXNfZnJhbmNlXzIsIGFlcyh4PXllYXIsIHk9aW5mbGF0aW9uKSkrDQogIGdlb21fbGluZShsd2Q9MSkrDQogIGdlb21fbGluZShhZXMoeT1maXR0ZWRfdmFsKSwgY29sb3I9InJlZCIsIGx0eT0yLCBsd2Q9MSkrIA0KICB0aGVtZV9idygpDQpgYGANCk9uIHBldXQgdm9pciBxdWUgbm90cmUgbW9kw6hsZSwgYmllbiBxdSdpbCB1dGlsaXNlIGRlcyB2YXJpYWJsZXMgY29ycmVjdGVtZW50IHN0YXRpb25uYXJpc8OpZXMsIG5lIHJlcHLDqXNlbnRlIHBhciBjb3JyZWN0ZW1lbnQgbGEgZHluYW1pcXVlIGRlIGxhIHPDqXJpZSA6IGxlcyAqZml0dGVkIHZhbHVlcyogbmUgc3VpdmVudCBwYXMgYmllbiBsYSBzw6lyaWUgZCdvcmlnaW5lLCBwYXJ0aWN1bGnDqHJlbWVudCBhdmFudCBsZXMgYW5uw6llcyAxOTkwLg0KDQojIyBIb21vc2NlZGFzdGljaXTDqQ0KDQpQb3VyIHbDqXJpZmllciBsJ2hvbW9zY8OpZGFzdGljaXTDqSAoPXZhcmlhbmNlIGNvbnN0YW50ZSBkYW5zIGxlIHRlbXBzKSwgb24gcGV1dCBkw6lqw6AgZmFpdCB1biBncmFwaGlxdWUgZGVzIHLDqXNpZHVzIGRhbnMgbGUgdGVtcHMuDQpgYGB7cn0NCmdncGxvdChkb25uZWVzX2ZyYW5jZV8yLCBhZXMoeD15ZWFyLCB5PXJlc2lkdWFscykpKw0KICBnZW9tX2xpbmUobHdkPTEpKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsdHk9MikrDQogIHRoZW1lX2J3KCkNCmBgYA0KT24gcGV1dCB2b2lyIHF1ZSBsYSB2YXJpYW5jZSBkZXMgcsOpc2lkdXMgY2hhbmdlIGRyYXN0aXF1ZW1lbnQgw6AgcGFydGlyIGRlIGxhIGZpbiBkZXMgYW5uw6llcyAxOTgwLCBjZSBxdWkgcG91cnJhaXQgaW5kaXF1ZXIgcXVlIGxlcyByw6lzaWR1cyBzb250IGjDqXTDqXJvc2PDqWRhc3RpcXVlcy4gQ2VwZW5kYW50LCBsJ2FuYWx5c2UgdmlzdWVsbGUgbidlc3QgcGFzIHVuIHRlc3QgZm9ybWVsLiBQb3VyIHbDqXJpZmllciBsJ2hvbW9zY8OpZGFzdGljaXTDqSBvdSBub24gZGVzIHLDqXNpZHVzLCBvbiBkb2l0IHV0aWxpc2VyIGxlIHRlc3QgZGUgQnJldXNjaC1QYWdhbiAoQlApLiBMZSB0ZXN0IEJQIGEgcG91ciBoeXBvdGjDqHNlIG51bGxlIGwnaMOpdMOpcm9zY8OpZGFzdGljaXTDqS4gU2kgbGEgcC12YWx1ZSBlc3Qgc2lnbmlmaWNhdGl2ZSwgb24gcmVqZXR0ZSBkb25jIGwnaHlwb3Row6hzZSBudWxsZSBldCBvbiBjb25jbHV0IGRlIGwnaG9tb3Njw6lkYXN0aWNpdMOpLg0KDQpgYGB7cn0NCnJlcXVpcmUobG10ZXN0KQ0KYnB0ZXN0KGluZmxhdGlvbiB+IGR1bmVtcCwgZGF0YT1kb25uZWVzX2ZyYW5jZSkgDQpgYGANCkljaSwgbGEgcC12YWx1ZSBlc3Qgc2lnbmlmaWNhdGl2ZSwgZG9uYyBvbiBjb25jbHV0IHF1ZSBsZXMgcsOpc2lkdXMgZGUgbGEgcsOpZ3Jlc3Npb24gc29udCBow6l0w6lyb3Njw6lkYXN0aXF1ZXMuDQoNCiMjIE5vcm1hbGl0w6kgZGVzIHLDqXNpZHVzDQpgYGB7cn0NCmdncGxvdChkb25uZWVzX2ZyYW5jZV8yLCBhZXMocmVzaWR1YWxzKSkrZ2VvbV9kZW5zaXR5KGZpbGw9ImdyZXk2MCIsIGJvdW5kcz1jKC1JbmYsIEluZikpK3RoZW1lX2J3KCkNCmBgYA0KTGVzIHLDqXNpZHVzIHNvbnQgYmllbiBkaXN0cmlidcOpcyBhdXRvdXIgZGUgesOpcm8sIGV0IGxhIG1veWVubmUgZXN0IHJlbGF0aXZlbWVudCBwcm9jaGUgZGUgesOpcm8uIEVuIHJldmFuY2hlLCBvbiBwZXV0IHZvaXIgcXVlIGxhIHF1ZXVlIGRlIGRpc3RyaWJ1dGlvbiDDoCBkcm9pdGUgZXN0IHJlbGF0aXZlbWVudCBsYXJnZSwgZG9uYyBvbiB0ZW5kIMOgIHNvdXMtZXN0aW1lciBncmFuZGVtZW50IGxlIG1vZMOobGUgw6AgY2VydGFpbnMgbW9tZW50cy4gTGEgZGlzdHJpYnV0aW9uIG4nZXN0IHF1J3VuZSB2w6lyaWZpY2F0aW9uIHZpc3VlbGxlLCBwYXMgdW4gdGVzdCBzdGF0aXN0aXF1ZS4gUG91ciB1biB0ZXN0IGZvcm1lbCwgaWwgZmF1dCBzZSB0b3VybmVyIHZlcnMgbGUgdGVzdCBkZSBTaGFwaXJvIHF1aSB0ZXN0ZSBsYSBub3JtYWxpdMOpIGQndW5lIHPDqXJpZS4gTGUgdGVzdCBkZSBTaGFwaXJvIGEgcG91ciBoeXBvdGjDqHNlIG51bGxlIGxhIG5vcm1hbGl0w6kgZGVzIHLDqXNpZHVzLiBTaSBsYSBwLXZhbHVlIGVzdCBzaWduaWZpY2F0aXZlLCBvbiByZWpldHRlIGRvbmMgbCdoeXBvdGjDqHNlIG51bGxlLCBldCBvbiBjb25jbHV0IGRlIGxhIG5vbi1ub3JtYWxpdMOpIGRlIGxhIHPDqXJpZS4NCg0KYGBge3J9DQpzaGFwaXJvLnRlc3QoZG9ubmVlc19mcmFuY2VfMiRyZXNpZHVhbHMpDQpgYGANCkljaSwgbGEgcC12YWx1ZSBlc3Qgc2lnbmlmaWNhdGl2ZSwgZG9uYyBsZXMgcsOpc2lkdXMgbmUgc3VpdmVudCBwYXMgdW5lIGxvaSBub3JtYWxlIHNlbG9uIGxlIHRlc3QgZGUgU2hhcGlyby4NCg0KDQoNCg0KIyMgSW5kw6lwZW5kYW5jZQ0KRCdhcHLDqHMgbCdoeXBvdGjDqHNlIGQnaW5kw6lwZW5kYW5jZSBkZXMgcsOpc2lkdXMsIGxlcyByw6lzaWR1cyBkJ3VuZSBww6lyaW9kZSBuZSBkb2l2ZW50IHBhcyDDqnRyZSBleHBsaXF1w6lzIHBhciBsZXMgcsOpc2lkdXMgcHLDqWPDqWRlbnRzLiBPbiBwZXV0IHRlc3RlciBjZXR0ZSBoeXBvdGjDqHNlIGF2ZWMgdW4gc2ltcGxlIGF1dG9jb3Jyw6lsb2dyYW1tZSA6DQpgYGB7cn0NCmFjZihkb25uZWVzX2ZyYW5jZV8yJHJlc2lkdWFscykNCmBgYA0KDQpJY2ksIG9uIG9ic2VydmUgcXVlIGxlcyByw6lzaWR1cyBuZSBzZW1ibGVudCBwYXMgw6p0cmUgaW5kw6lwZW5kYW50cywgY2FyIGxlcyByw6lzaWR1cyBwYXNzw6lzIGV4cGxpcXVlbnQgZGUgbWFuacOocmUgc3lzdMOpbWF0aXF1ZSBsZXMgcsOpc2lkdXMgYWN0dWVscy4gQXByw6hzIGwnYW5hbHlzZSB2aXN1ZWwsIG9uIHBldXQgZmFpcmUgbGUgdGVzdCBmb3JtZWwuIExlIHRlc3QgTGp1bmctQm94IGVmZmVjdHVlIGxlIHRlc3QgZCdpbmTDqXBlbmRhbmNlIGRlcyByw6lzaWR1cywgZXQgYSBwb3VyIGh5cG90aMOoc2UgbnVsbGUgbCdpbmTDqXBlbmRhbmNlIGRlcyByw6lzaWR1cy4gU2kgbGEgcC12YWx1ZSBlc3Qgc2lnbmlmaWNhdGl2ZSwgb24gcmVqZXR0ZSBsJ2h5cG90aMOoc2UgbnVsbGUgZXQgb24gY29uY2x1dCBkZSBsJ2F1dG9jb3Jyw6lsYXRpb24gKGRvbmMsIGwnYWJzZW5jZSBkJ2luZMOpcGVuZGFuY2UpIGRlcyByw6lzaWR1cy4NCmBgYHtyfQ0KQm94LnRlc3QoZG9ubmVlc19mcmFuY2VfMiRyZXNpZHVhbHMsIGxhZyA9IDEwLCB0eXBlID0gIkxqdW5nLUJveCIpDQpgYGANCkljaSwgaWwgc2VtYmxlIHF1ZSBub3MgcsOpc2lkdXMgbmUgc29udCBwYXMgaW5kw6lwZW5kYW50cyBjYXIgbGEgcC12YWx1ZSBlc3Qgc2lnbmlmaWNhdGl2ZS4NCg0KKk5vdGUgOiBjZXJ0YWlucyBkZSBjZXMgdGVzdHMgc29udCByw6lzdW3DqXMgZGFucyBsYSBmb25jdGlvbiBgY2hlY2tyZXNpZHVhbHMoKWAgZHUgcGFja2FnZSBgZm9yZWNhc3RgKjoNCmBgYHtyfQ0KcmVxdWlyZShmb3JlY2FzdCkNCmNoZWNrcmVzaWR1YWxzKHJlZykNCmBgYA0KDQoNCg0KQWluc2ksIGRhbnMgbCdlbnNlbWJsZSwgbm90cmUgbW9kw6hsZSBlc3QgcGV1IHBlcmZvcm1hbnQgZGFucyBsJ2V4cGxpY2F0aW9uIGRlIGxhIGR5bmFtaXF1ZSBkZSBsJ2luZmxhdGlvbi4gRW4gcmV2YW5jaGUsIGlsIGV4cGxpcXVlIGNvcnJlY3RlbWVudCBjZSBxdSdpbCBleHBsaXF1ZSAhIEMnZXN0IHVuIGJvbiBkw6lidXQsIGNhciBjZWxhIHZldXQgZGlyZSBxdSdvbiBwZXV0IG1haW50ZW5hbnQgYWpvdXRlciBkJ2F1dHJlcyB2YXJpYWJsZXMgZXhwbGljYXRpdmVzIGRhbnMgbGUgbW9kw6hsZXMgKGVuIHRlc3RhbnQsIMOgIGNoYXF1ZSBham91dCwgbGVzIGVmZmV0cyBzdXIgbGVzIHLDqXNpZHVzIHBvdXIgdsOpcmlmaWVyIHF1J29uIG5lIGNyw6llIHBhciBkZSBwcm9ibMOobWVzIHF1aSBzZXJhaWVudCBkw6l0ZWN0w6lzIGRhbnMgbGVzIHLDqXNpZHVzKSBwb3VyIGFtw6lsaW9yZXIgbGUgcG91dm9pciBleHBsaWNhdGlmLCB0b3V0IGVuIHJlc3BlY3RhbnQgbGUgcHJpbmNpcGUgZGUgcGFyc2ltb25pZSA6IG9uIG5lIGNoZXJjaGUgcGFzIMOgIGV4cGxpcXVlciBsYSB0b3RhbGl0w6kgZGVzIHZhcmlhdGlvbnMgZGUgJFlfdCQsIHNpbXBsZW1lbnQgw6AgbCdleHBsaXF1ZXIgc3VmZmlzYW1tZW50IHBvdXIgcXVlIGwnZXN0aW1hdGlvbiBkZSBsJ2ltcGFjdCBkZSAkXGJldGEkIHNvaXQgY29ycmVjdC4NCg0KDQoNCiMgT3ZlcmZpdHRpbmcNCg0KUGFyZm9pcywgb24gcGV1dCBham91dGVyIGRlcyB2YXJpYWJsZXMgcXVpIHZvbnQgY3LDqWVyIHVuIGJpYWlzIGRlIGNvbGxpbsOpYXJpdMOpIDogbGVzIHZhcmlhYmxlcyBleHBsaWNhdGl2ZXMgcGV1dmVudCBzJ2luZmx1ZW5jZXIgZW50cmUgZWxsZXMsIG91IGF2b2lyIHVuIGVmZmV0IGNpcmN1bGFpcmUgYXZlYyBsYSB2YXJpYWJsZSBkw6lwZW5kYW50ZSwgY2UgcXVpIHZhIGNyw6llciB1biBwcm9ibMOobWUgZGFucyBsYSByw6lncmVzc2lvbi4gDQoNCmBgYHtyfQ0KcmVnX2NvbGluIDwtIGZlb2xzKGluZmxhdGlvbiB+ZHVuZW1wICsgbGFnKGluZmxhdGlvbiksIGRhdGE9IGRvbm5lZXNfZnJhbmNlKQ0KZXRhYmxlKHJlZ19jb2xpbikNCmBgYA0KDQpFdCBxdWFuZCBvbiByZWdhcmQgbCfDqWNhcnQgZW50cmUgbGVzICpmaXR0ZWQgdmFsdWVkKiBldCBsYSB2YXJpYWJsZSBkw6lwZW5kYW50ZSwgb24gb2J0aWVudCA6DQpgYGB7cn0NCmZpdHRlZF92YWxfY29saW4gPC0gcmVnX2NvbGluJGZpdHRlZC52YWx1ZXMNCnJlc2lkdWFsc19jb2xpbiA8LSByZWdfY29saW4kcmVzaWR1YWxzDQoNCmRvbm5lZXNfZnJhbmNlXzMgPC0gZG9ubmVlc19mcmFuY2UgJT4lDQogIGNiaW5kKGZpdHRlZF92YWxfY29saW4pJT4lDQogIGNiaW5kKHJlc2lkdWFsc19jb2xpbikNCmdncGxvdChkb25uZWVzX2ZyYW5jZV8zLCBhZXMoeD15ZWFyLCB5PWluZmxhdGlvbikpKw0KICBnZW9tX2xpbmUobHdkPTEpKw0KICBnZW9tX2xpbmUoYWVzKHk9Zml0dGVkX3ZhbF9jb2xpbiksIGNvbG9yPSJyZWQiLCBsdHk9MiwgbHdkPTEpKyANCiAgdGhlbWVfYncoKQ0KYGBgDQpJY2ksIG9uIHBldXQgw6p0cmUgdGVudMOpIGRlIGRpcmUgcXVlIG5vdHJlIG1vZMOobGUgZXN0IHBhcmZhaXQgcGFyY2UgcXUnaWwgZXhwbGlxdWUgYmllbiBub3RyZSB2YXJpYWJsZSBkw6lwZW5kYW50ZS4gTWFpcyBpY2ksIG9uIGEgdW4gcHJvYmzDqG1lIGRlIGNvbGxpbsOpYXJpdMOpIDogYGxhZyhkaW5mbGF0aW9uKWAgZXhwbGlxdWUgcXVhc2ktcGFyZmFpdGVtZW50IGBkaW5mbGF0aW9uYCwgZXQgbCdham91dGVyIGRhbnMgbGUgbW9kw6hsZSBjcsOpw6kgZGUgbGEgY29sbGluw6lhcml0w6kgcGFyZmFpdGUuDQoNCg0KT24gcGV1dCB0ZXN0ZXIgbGEgY29sbGluw6lhcml0w6kgYXZlYyB1biB0ZXN0IFZJRg0KYGBge3J9DQpyZXF1aXJlKGNhcikNCnZpZihyZWdfY29saW4pDQpgYGANCkljaSwgbGUgR1ZJRiBjb3JyaWfDqSAoY29sb25uZSDDoCBkcm9pdGUpIHRlbmQgdmVycyBsJ2luZmluaS4gT24gZXNzYWllIGVuIGfDqW7DqXJhbCBkZSBnYXJkZXIgdW4gVklGICoqYXUgbWF4aW11bSoqIGEgNiBvdSA3LCBhdSBkZWzDoCBpbCB5IGEgdW4gcHJvYmzDqG1lLg0KDQoNCkRvbmMgaWNpLCAqKmFqb3V0ZXIgbGUgbGFnIGRlIGwnaW5mbGF0aW9uIHZhIGNyw6llciBwbHVzIGRlIHByb2Jsw6htZSBxdSdpbCBuJ2VuIHLDqXNvdXQqKi4gQ2VwZW5kYW50LCBjZXR0ZSByw6lncmVzc2lvbiBhIHBvdXIgbcOpcml0ZSBkZSBtb250cmVyIHF1ZSBsJ2luZmxhdGlvbiwgbcOqbWUgc2kgZWxsZSBlc3QgY29uc2lkw6lyw6llIGNvbW1lIMOpdGFudCBzdGF0aW9ubmFpcmUsIGNvbnRpbnVlIGQnYXZvaXIgdW5lIHN0cnVjdHVyZSBhdXRvLXLDqWdyZXNzaXZlIGltcG9ydGFudGUsIGF1IHBvaW50IG/DuSBzaSBvbiBsYSBuw6lnbGlnZSwgb24gcGVyZCB1biBwb3V2b2lyIGV4cGxpY2F0aWYgdHLDqHMgaW1wb3J0YW50LiBDJ2VzdCBsYSByYWlzb24gcG91ciBsYXF1ZWxsZSBpbCBmYXV0IHMnaW50w6lyZXNzZXIgw6AgbGEgc3RydWN0dXJlIEF1dG8tUsOpZ3Jlc3NpdmUgKEFSKSBkZXMgc8OpcmllcyB0ZW1wb3JlbGxlcywgw6AgbGV1ciBkZWdyw6kgZCdpbnTDqWdyYXRpb24gKEkpIGV0IMOgIGxldXIgbW95ZW5uZSBtb2JpbGUgKE1vdmluZyBBdmVyYWdlIC0gTUEpLCBkYW5zIGxlIGNhZHJlIGRlcyBtb2TDqGxlcyBBUklNQSBxdWUgbCdvbiB2ZXJyYSBkYW5zIGxhIHPDqWFuY2UgNC4NCg0KDQoNCg0K