library(zoo)
library(tseries)
library(lmtest)
library(sandwich)
library(car)
rm(list=ls())

1. Načítanie dát a predspracovanie

eco <- read.csv("economics.csv", stringsAsFactors = FALSE)
eco$date <- as.Date(eco$date)
str(eco)
'data.frame':   574 obs. of  7 variables:
 $ X       : int  1 2 3 4 5 6 7 8 9 10 ...
 $ date    : Date, format: "1967-07-01" "1967-08-01" "1967-09-01" ...
 $ pce     : num  507 510 516 512 517 ...
 $ pop     : num  198712 198911 199113 199311 199498 ...
 $ psavert : num  12.6 12.6 11.9 12.9 12.8 11.8 11.7 12.3 11.7 12.3 ...
 $ uempmed : num  4.5 4.7 4.6 4.9 4.7 4.8 5.1 4.5 4.1 4.6 ...
 $ unemploy: int  2944 2945 2958 3143 3066 3018 2878 3001 2877 2709 ...
summary(eco)
       X              date                 pce               pop            psavert      
 Min.   :  1.0   Min.   :1967-07-01   Min.   :  506.7   Min.   :198712   Min.   : 2.200  
 1st Qu.:144.2   1st Qu.:1979-06-08   1st Qu.: 1578.3   1st Qu.:224896   1st Qu.: 6.400  
 Median :287.5   Median :1991-05-16   Median : 3936.8   Median :253060   Median : 8.400  
 Mean   :287.5   Mean   :1991-05-17   Mean   : 4820.1   Mean   :257160   Mean   : 8.567  
 3rd Qu.:430.8   3rd Qu.:2003-04-23   3rd Qu.: 7626.3   3rd Qu.:290291   3rd Qu.:11.100  
 Max.   :574.0   Max.   :2015-04-01   Max.   :12193.8   Max.   :320402   Max.   :17.300  
    uempmed          unemploy    
 Min.   : 4.000   Min.   : 2685  
 1st Qu.: 6.000   1st Qu.: 6284  
 Median : 7.500   Median : 7494  
 Mean   : 8.609   Mean   : 7771  
 3rd Qu.: 9.100   3rd Qu.: 8686  
 Max.   :25.200   Max.   :15352  
pce_ts <- ts(eco$pce, start = c(as.numeric(format(min(eco$date), "%Y")), as.numeric(format(min(eco$date), "%m"))), frequency = 12)


plot(pce_ts, main = "PCE (Personal Consumption Expenditures) - časová rada", ylab = "pce")

2. Jednoduchá lineárna regresia

Ako príklad odhadnem model, kde závislá premenná je pce a vysvetľujúce premenné sú unemploy (počet nezamestnaných) a psavert (osobná miera úspor):

model <- lm(pce ~ unemploy + psavert, data = eco)
summary(model)

Call:
lm(formula = pce ~ unemploy + psavert, data = eco)

Residuals:
    Min      1Q  Median      3Q     Max 
-4908.2 -1051.0  -307.4   951.0  6577.6 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept) 7400.27144  353.89141   20.91   <2e-16 ***
unemploy       0.54969    0.02783   19.75   <2e-16 ***
psavert     -799.79277   24.80336  -32.24   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1674 on 571 degrees of freedom
Multiple R-squared:  0.7794,    Adjusted R-squared:  0.7786 
F-statistic:  1009 on 2 and 571 DF,  p-value: < 2.2e-16
# uložím rezidua
res <- residuals(model)


# graf rezíduí
ts.plot(res, main = "Rezíduá z lineárneho modelu", ylab = "rezíduá")

3. Diagnostika rezíduí — autokorelácia

par(mfrow = c(1,2))
acf(res, main = "ACF rezíduí")
pacf(res, main = "PACF rezíduí")
par(mfrow = c(1,1))

Ljung–Box test

# test na náhodnosť rezíduí (Ljung-Box)
Box.test(res, lag = 12, type = "Ljung-Box")

    Box-Ljung test

data:  res
X-squared = 4038.3, df = 12, p-value < 2.2e-16

Durbin–Watson test (prvá kontrola autokorelácie)

library(lmtest)
dwtest(model)

    Durbin-Watson test

data:  model
DW = 0.12773, p-value < 2.2e-16
alternative hypothesis: true autocorrelation is greater than 0

Breusch–Godfrey test (viacnásobná autokorelácia)

# bgtest z balíka lmtest - test na autokorelaciu rádov 1..p
bgtest(model, order = 12) # testujeme autokoreláciu až do 12 periód

    Breusch-Godfrey test for serial correlation of order up to 12

data:  model
LM test = 509.81, df = 12, p-value < 2.2e-16

4. Robustné štandardné chyby — Newey–West

library(sandwich)
library(lmtest)
coeftest(model, vcov = NeweyWest(model, lag = 12, prewhite = FALSE))

t test of coefficients:

               Estimate  Std. Error  t value  Pr(>|t|)    
(Intercept) 7400.271439  906.339604   8.1650 2.068e-15 ***
unemploy       0.549694    0.093081   5.9056 6.038e-09 ***
psavert     -799.792766   57.529831 -13.9022 < 2.2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

5. Alternatíva: dynamický model (lagy závislej premennej)

# pridám lag 1 z pce
eco$pce_lag1 <- dplyr::lag(eco$pce, 1)
# odstránime prvé NA pozorovanie
eco_dyn <- na.omit(eco[, c("date", "pce", "pce_lag1", "unemploy", "psavert")])


model_dyn <- lm(pce ~ pce_lag1 + unemploy + psavert, data = eco_dyn)
summary(model_dyn)

Call:
lm(formula = pce ~ pce_lag1 + unemploy + psavert, data = eco_dyn)

Residuals:
     Min       1Q   Median       3Q      Max 
-169.204   -7.954    0.067    9.415  159.690 

Coefficients:
              Estimate Std. Error  t value Pr(>|t|)    
(Intercept) 39.8107519  6.8857547    5.782 1.22e-08 ***
pce_lag1     1.0004423  0.0006150 1626.833  < 2e-16 ***
unemploy     0.0003373  0.0005312    0.635    0.526    
psavert     -2.8229677  0.6108563   -4.621 4.72e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 24.56 on 569 degrees of freedom
Multiple R-squared:      1, Adjusted R-squared:      1 
F-statistic: 3.995e+06 on 3 and 569 DF,  p-value: < 2.2e-16
# test autokorelácie rezíduí modelu_dyn
res_dyn <- residuals(model_dyn)
acf(res_dyn, main = "ACF rezíduí - dynamický model")

Box.test(res_dyn, lag = 12, type = "Ljung-Box")

    Box-Ljung test

data:  res_dyn
X-squared = 32.551, df = 12, p-value = 0.001137
dwtest(model_dyn)

    Durbin-Watson test

data:  model_dyn
DW = 2.0407, p-value = 0.6428
alternative hypothesis: true autocorrelation is greater than 0

6. Záver a komentár

V modeli, kde bola závislou premennou spotreba pce a vysvetľujúcimi premennými unemploy a psavert, sme síce dostali relatívne vysoké R² (≈ 0.78), ale diagnostika rezíduí ukázala, že model je výrazne ovplyvnený autokoreláciou. To znamená, že aj keď sú OLS odhady neskreslené, štandardné chyby sú podhodnotené a t-testy nespoľahlivé.

Diagnostika rezíduí – ACF, PACF, Ljung–Box, DW a BG test

Prečo práve tieto testy a grafy?

  • ACF (Autocorrelation Function) ukazuje, ako sú reziduá korelované s vlastnými oneskoreniami.
    Používa sa na detekciu systematických vzorcov, ktoré by v správne špecifikovanom modeli nemali byť.

  • PACF (Partial ACF) odhaľuje priamy vplyv konkrétneho oneskorenia rezíduí po odfiltrovaní ostatných lagov.
    Pomáha rozpoznať AR štruktúru, ktorá môže v reziduách zostať, ak model nie je dynamický.

  • Ljung–Box test je globálny test, ktorý kontroluje, či sú autokorelácie rezíduí súčasne významné.
    Je vhodný na overenie, či sa reziduá správajú ako biely šum.

  • Durbin–Watson test je klasický test prvej autokorelácie rezíduí.

  • Breusch–Godfrey test testuje autokoreláciu vyšších rádov (lag 1 až lag p).
    Je vhodnejší než DW pri modeloch s viac premennými.

Tieto nástroje spolu poskytujú komplexný obraz o tom, či model zachytil dynamiku časovej rady.

Výsledky diagnostiky

  • ACF rezíduí: pomalé a plynulé klesanie → silná pozitívna autokorelácia.
  • PACF rezíduí: vysoký prvý lag → nezachytený AR komponent.
  • Ljung–Box test (p < 2.2e-16): reziduá nie sú náhodné.
  • Durbin–Watson (0.1277): extrémne silná pozitívna autokorelácia.
  • Breusch–Godfrey (p < 2.2e-16): autokorelované až do 12 lagov.

Pôvodný statický model teda porušuje základné predpoklady OLS.

Robustné štandardné chyby – Newey–West

Aplikácia Newey–West korekcie spôsobila zvýšenie štandardných chýb:

  • unemploy zostal síce významný, ale menej výrazne,
  • psavert zostal vysoko významný.

To naznačuje, že pôvodné t-testy boli príliš optimistické práve kvôli autokorelácii a heteroskedasticite.

Dynamický model

Po zaradení oneskorenia závislej premennej (pce_lag1) do modelu:

  • koeficient pri pce_lag1 ≈ 1.0004, čo ukazuje silnú perzistenciu spotreby, nie však autokoreláciu = 1
    (regresný koeficient v dynamickom modeli ≠ autokorelačný koeficient),
  • unemploy prestal byť štatisticky významný (p = 0.526),
  • psavert zostala významná,
  • rezíduá modelu výrazne klesli (štandardná chyba 24.56 namiesto 1674).

Diagnostika rezíduí dynamického modelu

  • ACF: len veľmi slabé korelácie,
  • Durbin–Watson ≈ 2.04: takmer žiadna autokorelácia,
  • Ljung–Box (p = 0.0011): mierna zvyšková autokorelácia (rádovo nižšia než v pôvodnom modeli).

Dynamický model tak zachytáva dynamiku spotreby omnoho lepšie.

Interpretácia výsledkov

  • Pôvodný model bol síce formálne „silný“, ale neplatili jeho predpoklady, najmä nezávislosť rezíduí.
  • Newey–West korigoval štandardné chyby, ale príčinu neodstránil.
  • Pridanie oneskorenia pce_lag1:
    • odstránilo väčšinu autokorelácie,
    • výrazne zlepšilo presnosť modelu,
    • zmenilo významnosť vysvetľujúcich premenných,
    • potvrdilo, že minulá spotreba je dominantným prediktorom súčasnej spotreby.

Tento výsledok je veľmi typický pre makroekonomické časové rady, ktoré väčšinou vykazujú vysokú perzistenciu.

Zhrnutie

Pôvodný statický model trpel extrémnou autokoreláciou rezíduí. Diagnostické metódy (ACF, PACF, Ljung–Box, DW, BG) jasne ukázali, že reziduá nie sú náhodné.
Po dynamizácii modelu väčšina autokorelácie zmizla a model poskytuje oveľa spoľahlivejšie výsledky.

Najvhodnejším modelom pre tieto dáta je preto dynamický model s oneskorením pce_lag1.

LS0tCnRpdGxlOiAiQXV0b2tvcmVsw6FjaWEgcmV6w61kdcOtIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKYXV0aG9yOiBCYy4gQWxpY2EgVHZyZMOhCi0tLQoKPHN0eWxlPgovKiBSdcW+b3bDqSBwb3phZGllIHByZSBjZWzDvSBkb2t1bWVudCAqLwpib2R5IHsKICAgIGJhY2tncm91bmQtY29sb3I6ICNmZmU2ZjA7CiAgICBmb250LWZhbWlseTogQXJpYWwsIHNhbnMtc2VyaWY7CiAgICBsaW5lLWhlaWdodDogMS42Owp9CgovKiBSdcW+b3bDqSBuYWRwaXN5ICovCmgxLCBoMiwgaDMsIGg0IHsKICAgIGNvbG9yOiAjZmY2OWI0Owp9CgovKiBDaXTDoXR5ICovCmJsb2NrcXVvdGUgewogICAgYm9yZGVyLWxlZnQ6IDRweCBzb2xpZCAjZmY2OWI0OwogICAgYmFja2dyb3VuZC1jb2xvcjogI2ZmZjBmNTsKICAgIHBhZGRpbmc6IDEwcHggMTVweDsKICAgIG1hcmdpbjogMTBweCAwOwogICAgZm9udC1zdHlsZTogaXRhbGljOwp9CgovKiBadsO9cmF6bmVuaWUga8S+w7rEjW92w71jaCBzbG92ICovCnNwYW4uaGlnaGxpZ2h0IHsKICAgIGJhY2tncm91bmQtY29sb3I6ICNmZmI2YzE7CiAgICBmb250LXdlaWdodDogYm9sZDsKICAgIHBhZGRpbmc6IDJweCA0cHg7CiAgICBib3JkZXItcmFkaXVzOiAzcHg7Cn0KPC9zdHlsZT4KCmBgYHtyfQpsaWJyYXJ5KHpvbykKbGlicmFyeSh0c2VyaWVzKQpsaWJyYXJ5KGxtdGVzdCkKbGlicmFyeShzYW5kd2ljaCkKbGlicmFyeShjYXIpCnJtKGxpc3Q9bHMoKSkKYGBgCgojIDEuIE5hxI3DrXRhbmllIGTDoXQgYSBwcmVkc3ByYWNvdmFuaWUKCmBgYHtyfQplY28gPC0gcmVhZC5jc3YoImVjb25vbWljcy5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCmVjbyRkYXRlIDwtIGFzLkRhdGUoZWNvJGRhdGUpCnN0cihlY28pCnN1bW1hcnkoZWNvKQoKcGNlX3RzIDwtIHRzKGVjbyRwY2UsIHN0YXJ0ID0gYyhhcy5udW1lcmljKGZvcm1hdChtaW4oZWNvJGRhdGUpLCAiJVkiKSksIGFzLm51bWVyaWMoZm9ybWF0KG1pbihlY28kZGF0ZSksICIlbSIpKSksIGZyZXF1ZW5jeSA9IDEyKQoKCnBsb3QocGNlX3RzLCBtYWluID0gIlBDRSAoUGVyc29uYWwgQ29uc3VtcHRpb24gRXhwZW5kaXR1cmVzKSAtIMSNYXNvdsOhIHJhZGEiLCB5bGFiID0gInBjZSIpCmBgYAojIDIuIEplZG5vZHVjaMOhIGxpbmXDoXJuYSByZWdyZXNpYQoKQWtvIHByw61rbGFkIG9kaGFkbmVtIG1vZGVsLCBrZGUgesOhdmlzbMOhIHByZW1lbm7DoSBqZSBwY2UgYSB2eXN2ZXTEvnVqw7pjZSBwcmVtZW5uw6kgc8O6IHVuZW1wbG95IChwb8SNZXQgbmV6YW1lc3RuYW7DvWNoKSBhIHBzYXZlcnQgKG9zb2Juw6EgbWllcmEgw7pzcG9yKToKCmBgYHtyfQptb2RlbCA8LSBsbShwY2UgfiB1bmVtcGxveSArIHBzYXZlcnQsIGRhdGEgPSBlY28pCnN1bW1hcnkobW9kZWwpCgpyZXMgPC0gcmVzaWR1YWxzKG1vZGVsKQoKdHMucGxvdChyZXMsIG1haW4gPSAiUmV6w61kdcOhIHogbGluZcOhcm5laG8gbW9kZWx1IiwgeWxhYiA9ICJyZXrDrWR1w6EiKQpgYGAKCiMgMy4gRGlhZ25vc3Rpa2EgcmV6w61kdcOtIOKAlCBhdXRva29yZWzDoWNpYQoKYGBge3J9CnBhcihtZnJvdyA9IGMoMSwyKSkKYWNmKHJlcywgbWFpbiA9ICJBQ0YgcmV6w61kdcOtIikKcGFjZihyZXMsIG1haW4gPSAiUEFDRiByZXrDrWR1w60iKQpwYXIobWZyb3cgPSBjKDEsMSkpCmBgYAojIyMgTGp1bmfigJNCb3ggdGVzdAoKYGBge3J9CkJveC50ZXN0KHJlcywgbGFnID0gMTIsIHR5cGUgPSAiTGp1bmctQm94IikKYGBgCgojIyMgRHVyYmlu4oCTV2F0c29uIHRlc3QgKHBydsOhIGtvbnRyb2xhIGF1dG9rb3JlbMOhY2llKQoKYGBge3J9CmxpYnJhcnkobG10ZXN0KQpkd3Rlc3QobW9kZWwpCmBgYAojIyMgQnJldXNjaOKAk0dvZGZyZXkgdGVzdCAodmlhY27DoXNvYm7DoSBhdXRva29yZWzDoWNpYSkKCmBgYHtyfQpiZ3Rlc3QobW9kZWwsIG9yZGVyID0gMTIpICMgdGVzdHVqZW1lIGF1dG9rb3JlbMOhY2l1IGHFviBkbyAxMiBwZXJpw7NkCmBgYAojIDQuIFJvYnVzdG7DqSDFoXRhbmRhcmRuw6kgY2h5Ynkg4oCUIE5ld2V54oCTV2VzdAoKYGBge3J9CmxpYnJhcnkoc2FuZHdpY2gpCmxpYnJhcnkobG10ZXN0KQpjb2VmdGVzdChtb2RlbCwgdmNvdiA9IE5ld2V5V2VzdChtb2RlbCwgbGFnID0gMTIsIHByZXdoaXRlID0gRkFMU0UpKQpgYGAKCiMgNS4gQWx0ZXJuYXTDrXZhOiBkeW5hbWlja8O9IG1vZGVsIChsYWd5IHrDoXZpc2xlaiBwcmVtZW5uZWopCgpgYGB7cn0KZWNvJHBjZV9sYWcxIDwtIGRwbHlyOjpsYWcoZWNvJHBjZSwgMSkKZWNvX2R5biA8LSBuYS5vbWl0KGVjb1ssIGMoImRhdGUiLCAicGNlIiwgInBjZV9sYWcxIiwgInVuZW1wbG95IiwgInBzYXZlcnQiKV0pCgoKbW9kZWxfZHluIDwtIGxtKHBjZSB+IHBjZV9sYWcxICsgdW5lbXBsb3kgKyBwc2F2ZXJ0LCBkYXRhID0gZWNvX2R5bikKc3VtbWFyeShtb2RlbF9keW4pCgoKcmVzX2R5biA8LSByZXNpZHVhbHMobW9kZWxfZHluKQphY2YocmVzX2R5biwgbWFpbiA9ICJBQ0YgcmV6w61kdcOtIC0gZHluYW1pY2vDvSBtb2RlbCIpCkJveC50ZXN0KHJlc19keW4sIGxhZyA9IDEyLCB0eXBlID0gIkxqdW5nLUJveCIpCmR3dGVzdChtb2RlbF9keW4pCmBgYAojIDYuIFrDoXZlciBhIGtvbWVudMOhcgoKViBtb2RlbGksIGtkZSBib2xhIHrDoXZpc2xvdSBwcmVtZW5ub3Ugc3BvdHJlYmEgKipwY2UqKiBhIHZ5c3ZldMS+dWrDumNpbWkgcHJlbWVubsO9bWkgKip1bmVtcGxveSoqIGEgKipwc2F2ZXJ0KiosIHNtZSBzw61jZSBkb3N0YWxpIHJlbGF0w612bmUgdnlzb2vDqSBSwrIgKOKJiCAwLjc4KSwgYWxlIGRpYWdub3N0aWthIHJlesOtZHXDrSB1a8OhemFsYSwgxb5lIG1vZGVsIGplIHbDvXJhem5lIG92cGx5dm5lbsO9IGF1dG9rb3JlbMOhY2lvdS4gVG8gem5hbWVuw6EsIMW+ZSBhaiBrZcSPIHPDuiBPTFMgb2RoYWR5IG5lc2tyZXNsZW7DqSwgxaF0YW5kYXJkbsOpIGNoeWJ5IHPDuiBwb2Rob2Rub3RlbsOpIGEgdC10ZXN0eSBuZXNwb8S+YWhsaXbDqS4KCiMjIERpYWdub3N0aWthIHJlesOtZHXDrSDigJMgQUNGLCBQQUNGLCBManVuZ+KAk0JveCwgRFcgYSBCRyB0ZXN0CgojIyMgUHJlxI1vIHByw6F2ZSB0aWV0byB0ZXN0eSBhIGdyYWZ5PwoKLSAqKkFDRiAoQXV0b2NvcnJlbGF0aW9uIEZ1bmN0aW9uKSoqIHVrYXp1amUsIGFrbyBzw7ogcmV6aWR1w6Ega29yZWxvdmFuw6kgcyB2bGFzdG7DvW1pIG9uZXNrb3JlbmlhbWkuICAKICBQb3XFvsOtdmEgc2EgbmEgZGV0ZWtjaXUgc3lzdGVtYXRpY2vDvWNoIHZ6b3Jjb3YsIGt0b3LDqSBieSB2IHNwcsOhdm5lIMWhcGVjaWZpa292YW5vbSBtb2RlbGkgbmVtYWxpIGJ5xaUuCgotICoqUEFDRiAoUGFydGlhbCBBQ0YpKiogb2RoYcS+dWplIHByaWFteSB2cGx5diBrb25rcsOpdG5laG8gb25lc2tvcmVuaWEgcmV6w61kdcOtIHBvIG9kZmlsdHJvdmFuw60gb3N0YXRuw71jaCBsYWdvdi4gIAogIFBvbcOhaGEgcm96cG96bmHFpSBBUiDFoXRydWt0w7pydSwga3RvcsOhIG3DtMW+ZSB2IHJlemlkdcOhY2ggem9zdGHFpSwgYWsgbW9kZWwgbmllIGplIGR5bmFtaWNrw70uCgotICoqTGp1bmfigJNCb3ggdGVzdCoqIGplIGdsb2LDoWxueSB0ZXN0LCBrdG9yw70ga29udHJvbHVqZSwgxI1pIHPDuiBhdXRva29yZWzDoWNpZSByZXrDrWR1w60gc8O6xI1hc25lIHbDvXpuYW1uw6kuICAKICBKZSB2aG9kbsO9IG5hIG92ZXJlbmllLCDEjWkgc2EgcmV6aWR1w6Egc3Byw6F2YWrDuiBha28gYmllbHkgxaF1bS4KCi0gKipEdXJiaW7igJNXYXRzb24gdGVzdCoqIGplIGtsYXNpY2vDvSB0ZXN0IHBydmVqIGF1dG9rb3JlbMOhY2llIHJlesOtZHXDrS4KCi0gKipCcmV1c2No4oCTR29kZnJleSB0ZXN0KiogdGVzdHVqZSBhdXRva29yZWzDoWNpdSB2ecWhxaHDrWNoIHLDoWRvdiAobGFnIDEgYcW+IGxhZyBwKS4gIAogIEplIHZob2RuZWrFocOtIG5lxb4gRFcgcHJpIG1vZGVsb2NoIHMgdmlhYyBwcmVtZW5uw71taS4KClRpZXRvIG7DoXN0cm9qZSBzcG9sdSBwb3NreXR1asO6IGtvbXBsZXhuw70gb2JyYXogbyB0b20sIMSNaSBtb2RlbCB6YWNoeXRpbCBkeW5hbWlrdSDEjWFzb3ZlaiByYWR5LgoKIyMjIFbDvXNsZWRreSBkaWFnbm9zdGlreQoKLSAqKkFDRiByZXrDrWR1w60qKjogcG9tYWzDqSBhIHBseW51bMOpIGtsZXNhbmllIOKGkiBzaWxuw6EgcG96aXTDrXZuYSBhdXRva29yZWzDoWNpYS4KLSAqKlBBQ0YgcmV6w61kdcOtKio6IHZ5c29rw70gcHJ2w70gbGFnIOKGkiBuZXphY2h5dGVuw70gQVIga29tcG9uZW50LgotICoqTGp1bmfigJNCb3ggdGVzdCAocCA8IDIuMmUtMTYpKio6IHJlemlkdcOhIG5pZSBzw7ogbsOhaG9kbsOpLgotICoqRHVyYmlu4oCTV2F0c29uICgwLjEyNzcpKio6IGV4dHLDqW1uZSBzaWxuw6EgcG96aXTDrXZuYSBhdXRva29yZWzDoWNpYS4KLSAqKkJyZXVzY2jigJNHb2RmcmV5IChwIDwgMi4yZS0xNikqKjogYXV0b2tvcmVsb3ZhbsOpIGHFviBkbyAxMiBsYWdvdi4KClDDtHZvZG7DvSBzdGF0aWNrw70gbW9kZWwgdGVkYSBwb3J1xaF1amUgesOha2xhZG7DqSBwcmVkcG9rbGFkeSBPTFMuCgojIyBSb2J1c3Ruw6kgxaF0YW5kYXJkbsOpIGNoeWJ5IOKAkyBOZXdleeKAk1dlc3QKCkFwbGlrw6FjaWEgTmV3ZXnigJNXZXN0IGtvcmVrY2llIHNww7Rzb2JpbGEgenbDvcWhZW5pZSDFoXRhbmRhcmRuw71jaCBjaMO9YjoKCi0gKip1bmVtcGxveSoqIHpvc3RhbCBzw61jZSB2w716bmFtbsO9LCBhbGUgbWVuZWogdsO9cmF6bmUsCi0gKipwc2F2ZXJ0Kiogem9zdGFsIHZ5c29rbyB2w716bmFtbsO9LgoKVG8gbmF6bmHEjXVqZSwgxb5lIHDDtHZvZG7DqSB0LXRlc3R5IGJvbGkgcHLDrWxpxaEgb3B0aW1pc3RpY2vDqSBwcsOhdmUga3bDtGxpIGF1dG9rb3JlbMOhY2lpIGEgaGV0ZXJvc2tlZGFzdGljaXRlLgoKIyMgRHluYW1pY2vDvSBtb2RlbAoKUG8gemFyYWRlbsOtIG9uZXNrb3JlbmlhIHrDoXZpc2xlaiBwcmVtZW5uZWogKCoqcGNlX2xhZzEqKikgZG8gbW9kZWx1OgoKLSBrb2VmaWNpZW50IHByaSBwY2VfbGFnMSDiiYggKioxLjAwMDQqKiwgxI1vIHVrYXp1amUgKipzaWxuw7ogcGVyemlzdGVuY2l1IHNwb3RyZWJ5KiosIG5pZSB2xaFhayBhdXRva29yZWzDoWNpdSA9IDEgIAogIChyZWdyZXNuw70ga29lZmljaWVudCB2IGR5bmFtaWNrb20gbW9kZWxpIOKJoCBhdXRva29yZWxhxI1uw70ga29lZmljaWVudCksCi0gKip1bmVtcGxveSoqIHByZXN0YWwgYnnFpSDFoXRhdGlzdGlja3kgdsO9em5hbW7DvSAocCA9IDAuNTI2KSwKLSAqKnBzYXZlcnQqKiB6b3N0YWxhIHbDvXpuYW1uw6EsCi0gcmV6w61kdcOhIG1vZGVsdSB2w71yYXpuZSBrbGVzbGkgKMWhdGFuZGFyZG7DoSBjaHliYSAyNC41NiBuYW1pZXN0byAxNjc0KS4KCiMjIyBEaWFnbm9zdGlrYSByZXrDrWR1w60gZHluYW1pY2vDqWhvIG1vZGVsdQoKLSAqKkFDRioqOiBsZW4gdmXEvm1pIHNsYWLDqSBrb3JlbMOhY2llLAotICoqRHVyYmlu4oCTV2F0c29uIOKJiCAyLjA0Kio6IHRha21lciDFvmlhZG5hIGF1dG9rb3JlbMOhY2lhLAotICoqTGp1bmfigJNCb3ggKHAgPSAwLjAwMTEpKio6IG1pZXJuYSB6dnnFoWtvdsOhIGF1dG9rb3JlbMOhY2lhIChyw6Fkb3ZvIG5pxb7FoWlhIG5lxb4gdiBww7R2b2Rub20gbW9kZWxpKS4KCkR5bmFtaWNrw70gbW9kZWwgdGFrIHphY2h5dMOhdmEgZHluYW1pa3Ugc3BvdHJlYnkgb21ub2hvIGxlcMWhaWUuCgojIyBJbnRlcnByZXTDoWNpYSB2w71zbGVka292CgotIFDDtHZvZG7DvSBtb2RlbCBib2wgc8OtY2UgZm9ybcOhbG5lIOKAnnNpbG7DveKAnCwgYWxlIG5lcGxhdGlsaSBqZWhvIHByZWRwb2tsYWR5LCBuYWptw6QgbmV6w6F2aXNsb3PFpSByZXrDrWR1w60uCi0gTmV3ZXnigJNXZXN0IGtvcmlnb3ZhbCDFoXRhbmRhcmRuw6kgY2h5YnksIGFsZSBwcsOtxI1pbnUgbmVvZHN0csOhbmlsLgotIFByaWRhbmllIG9uZXNrb3JlbmlhIHBjZV9sYWcxOgogIC0gb2RzdHLDoW5pbG8gdsOkxI3FoWludSBhdXRva29yZWzDoWNpZSwKICAtIHbDvXJhem5lIHpsZXDFoWlsbyBwcmVzbm9zxaUgbW9kZWx1LAogIC0gem1lbmlsbyB2w716bmFtbm9zxaUgdnlzdmV0xL51asO6Y2ljaCBwcmVtZW5uw71jaCwKICAtIHBvdHZyZGlsbywgxb5lICoqbWludWzDoSBzcG90cmViYSBqZSBkb21pbmFudG7DvW0gcHJlZGlrdG9yb20gc8O6xI1hc25laiBzcG90cmVieSoqLgoKVGVudG8gdsO9c2xlZG9rIGplIHZlxL5taSB0eXBpY2vDvSBwcmUgbWFrcm9la29ub21pY2vDqSDEjWFzb3bDqSByYWR5LCBrdG9yw6kgdsOkxI3FoWlub3UgdnlrYXp1asO6IHZ5c29rw7ogcGVyemlzdGVuY2l1LgoKIyMgWmhybnV0aWUKClDDtHZvZG7DvSBzdGF0aWNrw70gbW9kZWwgdHJwZWwgZXh0csOpbW5vdSBhdXRva29yZWzDoWNpb3UgcmV6w61kdcOtLiBEaWFnbm9zdGlja8OpIG1ldMOzZHkgKEFDRiwgUEFDRiwgTGp1bmfigJNCb3gsIERXLCBCRykgamFzbmUgdWvDoXphbGksIMW+ZSByZXppZHXDoSBuaWUgc8O6IG7DoWhvZG7DqS4gIApQbyBkeW5hbWl6w6FjaWkgbW9kZWx1IHbDpMSNxaFpbmEgYXV0b2tvcmVsw6FjaWUgem1pemxhIGEgbW9kZWwgcG9za3l0dWplIG92ZcS+YSBzcG/EvmFobGl2ZWrFoWllIHbDvXNsZWRreS4KCk5hanZob2RuZWrFocOtbSBtb2RlbG9tIHByZSB0aWV0byBkw6F0YSBqZSBwcmV0byAqKmR5bmFtaWNrw70gbW9kZWwgcyBvbmVza29yZW7DrW0gcGNlX2xhZzEqKi4K