Parsed with column specification:
cols(
  X1 = col_integer(),
  TV = col_double(),
  Radio = col_double(),
  Newspaper = col_double(),
  Sales = col_double()
)

Objetivos

  1. Regresion lineal
  2. Regresion lineal multiple
  3. Otras consideraciones en modelos de regression lineal

Introduccion

Usaremos el dataset Advertising

library(readr)
Advertising <- read_csv("~/Dropbox/Cursos/ISL Chapters/Advertising.csv")
Advertising <- Advertising[,-1]
names(Advertising)
[1] "TV"        "Radio"     "Newspaper" "Sales"    
summary(Advertising)
       TV             Radio          Newspaper          Sales      
 Min.   :  0.70   Min.   : 0.000   Min.   :  0.30   Min.   : 1.60  
 1st Qu.: 74.38   1st Qu.: 9.975   1st Qu.: 12.75   1st Qu.:10.38  
 Median :149.75   Median :22.900   Median : 25.75   Median :12.90  
 Mean   :147.04   Mean   :23.264   Mean   : 30.55   Mean   :14.02  
 3rd Qu.:218.82   3rd Qu.:36.525   3rd Qu.: 45.10   3rd Qu.:17.40  
 Max.   :296.40   Max.   :49.600   Max.   :114.00   Max.   :27.00  

Regresion lineal simple

Es de la forma \[Y = \beta_0+\beta_1X +\epsilon_i.\] \(Y\) es la respuesta y \(X\) es el predictor. En el caso de nuestra base de datos de publicidad seria de la forma \[\text{sales} \approx \beta_o + \beta_1 \text{TV}\] \(\beta_0\) y \(\beta_1\) son los coefficientonces de la regresion.

Advertising %>% select(Sales,TV) %>% 
  ggplot(aes(x=TV,y=Sales)) +
  geom_point()

Advertising %>% select(Sales,TV) %>% 
  ggplot(aes(x=TV,y=Sales)) +
  geom_point()+
  stat_quantile(quantiles = seq(0.05,0.95,by=0.05))

Para encontrar la recta de mejor ajuste basta con resolver \[\text{min } RSS=\sum e^2_i = \sum \left ( Y_i-\hat Y_i \right )^2=\sum \left ( Y_i-\hat \beta_0-\hat \beta_1X_i \right )^2 \]

La solucion de este problema de optimizacion la pueden encontra en el siguiente video.

Ahora hagamolo usando la funcion lm() de R.

fit1<-lm(Sales~TV,data = Advertising)
fit1

Call:
lm(formula = Sales ~ TV, data = Advertising)

Coefficients:
(Intercept)           TV  
    7.03259      0.04754  
str(fit1)
List of 12
 $ coefficients : Named num [1:2] 7.0326 0.0475
  ..- attr(*, "names")= chr [1:2] "(Intercept)" "TV"
 $ residuals    : Named num [1:200] 4.13 1.25 1.45 4.27 -2.73 ...
  ..- attr(*, "names")= chr [1:200] "1" "2" "3" "4" ...
 $ effects      : Named num [1:200] -198.31 57.57 1.08 3.99 -2.98 ...
  ..- attr(*, "names")= chr [1:200] "(Intercept)" "TV" "" "" ...
 $ rank         : int 2
 $ fitted.values: Named num [1:200] 17.97 9.15 7.85 14.23 15.63 ...
  ..- attr(*, "names")= chr [1:200] "1" "2" "3" "4" ...
 $ assign       : int [1:2] 0 1
 $ qr           :List of 5
  ..$ qr   : num [1:200, 1:2] -14.1421 0.0707 0.0707 0.0707 0.0707 ...
  .. ..- attr(*, "dimnames")=List of 2
  .. .. ..$ : chr [1:200] "1" "2" "3" "4" ...
  .. .. ..$ : chr [1:2] "(Intercept)" "TV"
  .. ..- attr(*, "assign")= int [1:2] 0 1
  ..$ qraux: num [1:2] 1.07 1.09
  ..$ pivot: int [1:2] 1 2
  ..$ tol  : num 1e-07
  ..$ rank : int 2
  ..- attr(*, "class")= chr "qr"
 $ df.residual  : int 198
 $ xlevels      : Named list()
 $ call         : language lm(formula = Sales ~ TV, data = Advertising)
 $ terms        :Classes 'terms', 'formula'  language Sales ~ TV
  .. ..- attr(*, "variables")= language list(Sales, TV)
  .. ..- attr(*, "factors")= int [1:2, 1] 0 1
  .. .. ..- attr(*, "dimnames")=List of 2
  .. .. .. ..$ : chr [1:2] "Sales" "TV"
  .. .. .. ..$ : chr "TV"
  .. ..- attr(*, "term.labels")= chr "TV"
  .. ..- attr(*, "order")= int 1
  .. ..- attr(*, "intercept")= int 1
  .. ..- attr(*, "response")= int 1
  .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv> 
  .. ..- attr(*, "predvars")= language list(Sales, TV)
  .. ..- attr(*, "dataClasses")= Named chr [1:2] "numeric" "numeric"
  .. .. ..- attr(*, "names")= chr [1:2] "Sales" "TV"
 $ model        :'data.frame':  200 obs. of  2 variables:
  ..$ Sales: num [1:200] 22.1 10.4 9.3 18.5 12.9 7.2 11.8 13.2 4.8 10.6 ...
  ..$ TV   : num [1:200] 230.1 44.5 17.2 151.5 180.8 ...
  ..- attr(*, "terms")=Classes 'terms', 'formula'  language Sales ~ TV
  .. .. ..- attr(*, "variables")= language list(Sales, TV)
  .. .. ..- attr(*, "factors")= int [1:2, 1] 0 1
  .. .. .. ..- attr(*, "dimnames")=List of 2
  .. .. .. .. ..$ : chr [1:2] "Sales" "TV"
  .. .. .. .. ..$ : chr "TV"
  .. .. ..- attr(*, "term.labels")= chr "TV"
  .. .. ..- attr(*, "order")= int 1
  .. .. ..- attr(*, "intercept")= int 1
  .. .. ..- attr(*, "response")= int 1
  .. .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv> 
  .. .. ..- attr(*, "predvars")= language list(Sales, TV)
  .. .. ..- attr(*, "dataClasses")= Named chr [1:2] "numeric" "numeric"
  .. .. .. ..- attr(*, "names")= chr [1:2] "Sales" "TV"
 - attr(*, "class")= chr "lm"
fit1$coefficients
(Intercept)          TV 
 7.03259355  0.04753664 
fit1$residuals[1:10]
         1          2          3          4          5          6          7 
 4.1292255  1.2520260  1.4497762  4.2656054 -2.7272181 -0.2461623  2.0340496 
         8          9         10 
 0.4535023 -2.6414087 -5.9304143 
fit1$fitted.values[1:10]
        1         2         3         4         5         6         7 
17.970775  9.147974  7.850224 14.234395 15.627218  7.446162  9.765950 
        8         9        10 
12.746498  7.441409 16.530414 
summary(fit1)

Call:
lm(formula = Sales ~ TV, data = Advertising)

Residuals:
    Min      1Q  Median      3Q     Max 
-8.3860 -1.9545 -0.1913  2.0671  7.2124 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 7.032594   0.457843   15.36   <2e-16 ***
TV          0.047537   0.002691   17.67   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.259 on 198 degrees of freedom
Multiple R-squared:  0.6119,    Adjusted R-squared:  0.6099 
F-statistic: 312.1 on 1 and 198 DF,  p-value: < 2.2e-16
sim_data<-function(){
  x<-runif(30,min = -3, max = 3)
  epsilon<-rnorm(n=length(x),mean = 0,sd = 1)
  y<-2+3*x+epsilon
  return(data.frame(x,y))
}
dataset1<-sim_data()
dataset2<-sim_data()
dataset3<-sim_data()
dataset4<-sim_data()

sim_fit_1<-lm(y~x,dataset1)
sim_fit_2<-lm(y~x,dataset2)
sim_fit_3<-lm(y~x,dataset3)
sim_fit_4<-lm(y~x,dataset4)
Dataset \(\beta_0\) \(\beta_1\)
Dataset1 2.0404619 3.0366712
Dataset2 2.0478985 2.9865992
Dataset3 2.2121774 2.9710174
Dataset4 1.6032715 3.0603625
fit_summary <- summary(fit1)
fit_summary$coefficients
              Estimate  Std. Error  t value    Pr(>|t|)
(Intercept) 7.03259355 0.457842940 15.36028 1.40630e-35
TV          0.04753664 0.002690607 17.66763 1.46739e-42

Intervalos de confianza de los parametros

\[\left [ \hat \beta_i - 2 \cdot \text{SE}(\hat \beta_i) , \hat \beta_i + 2 \cdot \text{SE}(\hat \beta_i) \right]\]

Parametro Intervalo
\(\hat \beta_0\) [6.1169077,7.9482794]
\(\hat \beta_1\) [0.0421554,0.0529179]

Relacion entre X y Y

Se hace una prueba de hipotesis asociada al parametro que relaciona las dos variables. En nuestro caso seria Sales y TV \(H_0\) es la hipotesis nula y \(H_a\) es la hipotesis alternativa

  • \(H_0:\) No hay relacion entre Sales y TV
  • \(H_a:\) Hay relacion entre Sales y TV

Esto se traduce a,

  • \(H_0:\) \(\beta_1=0\)
  • \(H_a:\) \(\beta_1 \neq 0\)
Parametro valor t
\(\hat \beta_0\) 15.3602752
\(\hat \beta_1\) 17.6676256
fit_summary$coefficients[,3]
(Intercept)          TV 
   15.36028    17.66763 
Parametro valor t codigo
RSE 3.2586564 fit_summary$sigma
\(R^2\) 0.6118751 fit_summary$r.squared
Estadistivo F 312.1449944 fit_summary$fstatistic[1]
fit_summary$sigma/mean(Advertising$Sales)*100 %>% round()
[1] 23.23877

Regresión Lineal Multiple

plot(Advertising)

fit2<-lm(Sales ~ Radio + TV + Newspaper, data = Advertising)
summary(fit2)

Call:
lm(formula = Sales ~ Radio + TV + Newspaper, data = Advertising)

Residuals:
    Min      1Q  Median      3Q     Max 
-8.8277 -0.8908  0.2418  1.1893  2.8292 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)  2.938889   0.311908   9.422   <2e-16 ***
Radio        0.188530   0.008611  21.893   <2e-16 ***
TV           0.045765   0.001395  32.809   <2e-16 ***
Newspaper   -0.001037   0.005871  -0.177     0.86    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.686 on 196 degrees of freedom
Multiple R-squared:  0.8972,    Adjusted R-squared:  0.8956 
F-statistic: 570.3 on 3 and 196 DF,  p-value: < 2.2e-16
cor(Advertising)
                  TV      Radio  Newspaper     Sales
TV        1.00000000 0.05480866 0.05664787 0.7822244
Radio     0.05480866 1.00000000 0.35410375 0.5762226
Newspaper 0.05664787 0.35410375 1.00000000 0.2282990
Sales     0.78222442 0.57622257 0.22829903 1.0000000

Interacción entre varibles

\[\text{sales}=\beta_0+\beta_1\cdot\text{TV}+\beta_2\cdot\text{Radio}\]

En este caso se quiere verificar si un incremento en la adquisicion de anuncios en radio aumenta o disminuye el \(\beta_1\) se propone el siguiente modelo

\[\text{sales}=\beta_0+\beta_1\cdot\text{TV}+\beta_2\cdot\text{Radio}+\beta_3\cdot\text{Radio}\times\text{TV}\]

lo cual se puede simplificar como

\[\begin{align*} \text{sales} &= \beta_0+\beta_1\cdot\text{TV}+\beta_2\cdot\text{Radio}+\beta_3\cdot\text{Radio}\times\text{TV} \\ &= \beta_0 + \left(\beta_1 + \beta_3 \cdot \text{Radio}\right)\cdot\text{TV}+\beta_2 \cdot \text{Radio} \\ &= \beta_0 + \tilde \beta_1 \cdot \text{TV} + \beta_3 \cdot \text{Radio} \end{align*}\]

fit3 <- lm(Sales ~ TV + Radio + TV * Radio,data = Advertising)
summary(fit3)$coefficients
               Estimate   Std. Error   t value     Pr(>|t|)
(Intercept) 6.750220203 0.2478713699 27.232755 1.541461e-68
TV          0.019101074 0.0015041455 12.698953 2.363605e-27
Radio       0.028860340 0.0089052729  3.240815 1.400461e-03
TV:Radio    0.001086495 0.0000524204 20.726564 2.757681e-51

Preguntas

  1. Hay relaciones entre las ventas y la inversion de publicidad en los diferentes medios?
  2. Que tan fuerte es la relación?
  3. Que tipos de medio son los que contribuyen a las ventas?
  4. Que tan grande es la contribucion de cada medio a las ventas?
  5. Como podemos predcir futuras ventas?
  6. Es la relacion lineal?
  7. Hay sinergia entre los diferentes medios?

Regresiones lineales con variables cualitativas

Variables Binarias

credit <- read_csv("~/OneDrive/Dropbox/Cursos/ISL Chapters/Credit.csv")
Parsed with column specification:
cols(
  X1 = col_integer(),
  Income = col_double(),
  Limit = col_integer(),
  Rating = col_integer(),
  Cards = col_integer(),
  Age = col_integer(),
  Education = col_integer(),
  Gender = col_character(),
  Student = col_character(),
  Married = col_character(),
  Ethnicity = col_character(),
  Balance = col_integer()
)
names(credit)<-tolower(names(credit))
credit<-credit[,-1]
head(credit)
fit4 <- lm(balance ~ gender , data = credit)
summary(fit4)$coefficients
             Estimate Std. Error    t value     Pr(>|t|)
(Intercept) 529.53623   31.98819 16.5541153 3.312981e-47
genderMale  -19.73312   46.05121 -0.4285039 6.685161e-01

\[gender_i = \left\{\begin{matrix} 0 & Female\\ 1 & Male \end{matrix}\right.\]

\[ balance = \beta_0 + \beta_1 \cdot gender=\left\{\begin{matrix} \beta_0 + \beta_1 & male\\ \beta_0 & female \end{matrix}\right. \]

\[gender_i = \left\{\begin{matrix} -1 & Female\\ 1 & Male \end{matrix}\right.\]

\[ balance = \beta_0 + \beta_1 \cdot gender=\left\{\begin{matrix} \beta_0 + \beta_1 & male\\ \beta_0 - \beta_1 & female \end{matrix}\right. \]

credit$coded_gender <- ifelse(credit$gender=="Female",-1,1)
fit5 <- lm(balance ~ coded_gender , data = credit)
summary(fit5)$coefficients
               Estimate Std. Error    t value     Pr(>|t|)
(Intercept)  519.669670   23.02561 22.5692080 3.191322e-73
coded_gender  -9.866562   23.02561 -0.4285039 6.685161e-01

Variables Multinomiales

unique(credit$ethnicity)
[1] "Caucasian"        "Asian"            "African American"

\[asian_i = \left\{\begin{matrix} 0 & no\\ 1 & yes \end{matrix}\right.\]

\[ caucasian_i = \left\{\begin{matrix} 0 & no\\ 1 & yes \end{matrix}\right. \]

credit$caucasian <- ifelse( credit$ethnicity == "Caucasian", 1, 0)
credit$asian <- ifelse( credit$ethnicity == "Asian", 1, 0)

\[balance = \beta_0 + \beta_1 \cdot asian + \beta_2 \cdot caucasian =\left\{\begin{matrix} \beta_0 + \beta_1 & asian\\ \beta_0 + \beta_2 & caucasian \\ \beta_0 & \text{african american} \end{matrix}\right.\]

fit6 <- lm(balance ~ asian + caucasian, data=credit)
summary(fit6)$coefficients
             Estimate Std. Error    t value     Pr(>|t|)
(Intercept) 531.00000   46.31868 11.4640565 1.774117e-26
asian       -18.68627   65.02107 -0.2873880 7.739652e-01
caucasian   -12.50251   56.68104 -0.2205766 8.255355e-01
LS0tCnRpdGxlOiAiUmVncmVzaW9uIExpbmVhbCIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3IsZWNobz1GQUxTRSxldmFsPVRSVUUsd2FybmluZz1GQUxTRX0KbGlicmFyeShJU0xSKQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCkFkdmVydGlzaW5nIDwtIHJlYWRfY3N2KCJBZHZlcnRpc2luZy5jc3YiKQpBZHZlcnRpc2luZyA8LSBBZHZlcnRpc2luZ1ssLTFdCmBgYAoKCiMjIE9iamV0aXZvcwoKMS4gUmVncmVzaW9uIGxpbmVhbAoyLiBSZWdyZXNpb24gbGluZWFsIG11bHRpcGxlCjMuIE90cmFzIGNvbnNpZGVyYWNpb25lcyBlbiBtb2RlbG9zIGRlIHJlZ3Jlc3Npb24gbGluZWFsCgojIyBJbnRyb2R1Y2Npb24KClVzYXJlbW9zIGVsIGRhdGFzZXQgYEFkdmVydGlzaW5nYAoKYGBge3IsZXZhbD1GQUxTRX0KbGlicmFyeShyZWFkcikKQWR2ZXJ0aXNpbmcgPC0gcmVhZF9jc3YoIn4vRHJvcGJveC9DdXJzb3MvSVNMIENoYXB0ZXJzL0FkdmVydGlzaW5nLmNzdiIpCkFkdmVydGlzaW5nIDwtIEFkdmVydGlzaW5nWywtMV0KYGBgCgpgYGB7cn0KbmFtZXMoQWR2ZXJ0aXNpbmcpCmBgYAoKYGBge3J9CnN1bW1hcnkoQWR2ZXJ0aXNpbmcpCmBgYAoKIyMgUmVncmVzaW9uIGxpbmVhbCBzaW1wbGUKCkVzIGRlIGxhIGZvcm1hICQkWSA9IFxiZXRhXzArXGJldGFfMVggK1xlcHNpbG9uX2kuJCQgJFkkIGVzIGxhIHJlc3B1ZXN0YSB5ICRYJCBlcyBlbCBwcmVkaWN0b3IuIEVuIGVsIGNhc28gZGUgbnVlc3RyYSBiYXNlIGRlIGRhdG9zIGRlIHB1YmxpY2lkYWQgc2VyaWEgZGUgbGEgZm9ybWEgJCRcdGV4dHtzYWxlc30gXGFwcHJveCBcYmV0YV9vICsgXGJldGFfMSBcdGV4dHtUVn0kJCAkXGJldGFfMCQgeSAkXGJldGFfMSQgc29uIGxvcyBjb2VmZmljaWVudG9uY2VzIGRlIGxhIHJlZ3Jlc2lvbi4KCmBgYHtyfQpBZHZlcnRpc2luZyAlPiUgc2VsZWN0KFNhbGVzLFRWKSAlPiUgCiAgZ2dwbG90KGFlcyh4PVRWLHk9U2FsZXMpKSArCiAgZ2VvbV9wb2ludCgpCmBgYApgYGB7cn0KQWR2ZXJ0aXNpbmcgJT4lIHNlbGVjdChTYWxlcyxUVikgJT4lIAogIGdncGxvdChhZXMoeD1UVix5PVNhbGVzKSkgKwogIGdlb21fcG9pbnQoKSsKICBzdGF0X3F1YW50aWxlKHF1YW50aWxlcyA9IHNlcSgwLjA1LDAuOTUsYnk9MC4wNSkpCmBgYAoKUGFyYSBlbmNvbnRyYXIgbGEgcmVjdGEgZGUgbWVqb3IgYWp1c3RlIGJhc3RhIGNvbiByZXNvbHZlciAKJCRcdGV4dHttaW4gfSBSU1M9XHN1bSBlXjJfaSA9IFxzdW0gXGxlZnQgKCBZX2ktXGhhdCBZX2kgXHJpZ2h0ICleMj1cc3VtIFxsZWZ0ICggWV9pLVxoYXQgXGJldGFfMC1caGF0IFxiZXRhXzFYX2kgXHJpZ2h0ICleMiAkJAoKTGEgc29sdWNpb24gZGUgZXN0ZSBwcm9ibGVtYSBkZSBvcHRpbWl6YWNpb24gbGEgcHVlZGVuIGVuY29udHJhIGVuIGVsIHNpZ3VpZW50ZSB2aWRlby4KCjxpZnJhbWUgd2lkdGg9IjU2MCIgaGVpZ2h0PSIzMTUiIHNyYz0iaHR0cHM6Ly93d3cueW91dHViZS5jb20vZW1iZWQvQ0s4QXVWT2xPTDAiIGZyYW1lYm9yZGVyPSIwIiBhbGxvd2Z1bGxzY3JlZW4+PC9pZnJhbWU+CgoKQWhvcmEgaGFnYW1vbG8gdXNhbmRvIGxhIGZ1bmNpb24gYGxtKClgIGRlIFIuCgoKYGBge3J9CmZpdDE8LWxtKFNhbGVzflRWLGRhdGEgPSBBZHZlcnRpc2luZykKZml0MQpgYGAKCmBgYHtyfQpzdHIoZml0MSkKYGBgCgoKYGBge3J9CmZpdDEkY29lZmZpY2llbnRzCmBgYAoKYGBge3J9CmZpdDEkcmVzaWR1YWxzWzE6MTBdCmBgYAoKKiBUb3RhbCBkZSBSZXNpZHVvcyBgciBsZW5ndGgoZml0MSRyZXNpZHVhbHMpYAoqIFRvdGFsIGRlIE9ic2VydmFjaW9uZXMgYHIgbnJvdyhBZHZlcnRpc2luZylgCgpgYGB7cn0KZml0MSRmaXR0ZWQudmFsdWVzWzE6MTBdCmBgYAoKYGBge3J9CnN1bW1hcnkoZml0MSkKYGBgCgoKCmBgYHtyfQpzaW1fZGF0YTwtZnVuY3Rpb24oKXsKICB4PC1ydW5pZigzMCxtaW4gPSAtMywgbWF4ID0gMykKICBlcHNpbG9uPC1ybm9ybShuPWxlbmd0aCh4KSxtZWFuID0gMCxzZCA9IDEpCiAgeTwtMiszKngrZXBzaWxvbgogIHJldHVybihkYXRhLmZyYW1lKHgseSkpCn0KCmRhdGFzZXQxPC1zaW1fZGF0YSgpCmRhdGFzZXQyPC1zaW1fZGF0YSgpCmRhdGFzZXQzPC1zaW1fZGF0YSgpCmRhdGFzZXQ0PC1zaW1fZGF0YSgpCmBgYAoKCmBgYHtyLGVjaG89RkFMU0V9CmRhdGFzZXQxJGRhdGFfc291cmNlPC0nRGF0YXNldDEnCmRhdGFzZXQyJGRhdGFfc291cmNlPC0nRGF0YXNldDInCmRhdGFzZXQzJGRhdGFfc291cmNlPC0nRGF0YXNldDMnCmRhdGFzZXQ0JGRhdGFfc291cmNlPC0nRGF0YXNldDQnCnNpbV9kYXRhc2V0czwtcmJpbmQoZGF0YXNldDEsZGF0YXNldDIsZGF0YXNldDMsZGF0YXNldDQpCnNpbV9kYXRhc2V0cyAlPiUgZ2dwbG90KGFlcyh4LHkpKSsKICBnZW9tX3BvaW50KCkrCiAgZmFjZXRfd3JhcCh+ZGF0YV9zb3VyY2UpCmBgYAoKCgpgYGB7cn0Kc2ltX2ZpdF8xPC1sbSh5fngsZGF0YXNldDEpCnNpbV9maXRfMjwtbG0oeX54LGRhdGFzZXQyKQpzaW1fZml0XzM8LWxtKHl+eCxkYXRhc2V0MykKc2ltX2ZpdF80PC1sbSh5fngsZGF0YXNldDQpCmBgYAoKRGF0YXNldCB8ICRcYmV0YV8wJCB8ICRcYmV0YV8xJAotLS0tLS0tIHwgLS0tLS0tLS0tIHwgLS0tLS0tLS0KRGF0YXNldDEgfCBgciBzaW1fZml0XzEkY29lZmZpY2llbnRzWzFdYCB8IGByIHNpbV9maXRfMSRjb2VmZmljaWVudHNbMl1gCkRhdGFzZXQyIHwgYHIgc2ltX2ZpdF8yJGNvZWZmaWNpZW50c1sxXWAgfCBgciBzaW1fZml0XzIkY29lZmZpY2llbnRzWzJdYApEYXRhc2V0MyB8IGByIHNpbV9maXRfMyRjb2VmZmljaWVudHNbMV1gIHwgYHIgc2ltX2ZpdF8zJGNvZWZmaWNpZW50c1syXWAKRGF0YXNldDQgfCBgciBzaW1fZml0XzQkY29lZmZpY2llbnRzWzFdYCB8IGByIHNpbV9maXRfNCRjb2VmZmljaWVudHNbMl1gCgpgYGB7cn0KZml0X3N1bW1hcnkgPC0gc3VtbWFyeShmaXQxKQpmaXRfc3VtbWFyeSRjb2VmZmljaWVudHMKYGBgCgoqIEVycm9yIGVzdGFuZGFyIGRlICRcYmV0YV8wPSQgYHIgZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzEsMl1gCiogRXJyb3IgZXN0YW5kYXIgZGUgJFxiZXRhXzE9JCBgciBmaXRfc3VtbWFyeSRjb2VmZmljaWVudHNbMiwyXWAKCiMjIyBJbnRlcnZhbG9zIGRlIGNvbmZpYW56YSBkZSBsb3MgcGFyYW1ldHJvcwoKJCRcbGVmdCBbIFxoYXQgXGJldGFfaSAtIDIgXGNkb3QgXHRleHR7U0V9KFxoYXQgXGJldGFfaSkgLCBcaGF0IFxiZXRhX2kgKyAyIFxjZG90IFx0ZXh0e1NFfShcaGF0IFxiZXRhX2kpIFxyaWdodF0kJAoKUGFyYW1ldHJvIHwgSW50ZXJ2YWxvCi0tLS0tLS0tLSB8IC0tLS0tLS0tLQokXGhhdCBcYmV0YV8wJCB8IFtgciBmaXQxJGNvZWZmaWNpZW50c1sxXS0yKmZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1sxLDJdYCxgciBmaXQxJGNvZWZmaWNpZW50c1sxXSsyKmZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1sxLDJdYF0KJFxoYXQgXGJldGFfMSQgfCBbYHIgZml0MSRjb2VmZmljaWVudHNbMl0tMipmaXRfc3VtbWFyeSRjb2VmZmljaWVudHNbMiwyXWAsYHIgZml0MSRjb2VmZmljaWVudHNbMl0rMipmaXRfc3VtbWFyeSRjb2VmZmljaWVudHNbMiwyXWBdCgoKIyMjIFJlbGFjaW9uIGVudHJlIFggeSBZCgpTZSBoYWNlIHVuYSBwcnVlYmEgZGUgaGlwb3Rlc2lzIGFzb2NpYWRhIGFsIHBhcmFtZXRybyBxdWUgcmVsYWNpb25hIGxhcyBkb3MgdmFyaWFibGVzLiBFbiBudWVzdHJvIGNhc28gc2VyaWEgYFNhbGVzYCB5IGBUVmAKJEhfMCQgZXMgbGEgaGlwb3Rlc2lzIG51bGEgeSAkSF9hJCBlcyBsYSBoaXBvdGVzaXMgYWx0ZXJuYXRpdmEgCgoqICRIXzA6JCBObyBoYXkgcmVsYWNpb24gZW50cmUgYFNhbGVzYCB5IGBUVmAKKiAkSF9hOiQgSGF5IHJlbGFjaW9uIGVudHJlIGBTYWxlc2AgeSBgVFZgCgpFc3RvIHNlIHRyYWR1Y2UgYSwKCiogJEhfMDokICRcYmV0YV8xPTAkCiogJEhfYTokICRcYmV0YV8xIFxuZXEgMCQKClBhcmFtZXRybyB8IHZhbG9yIHQKLS0tLS0tLS0tIHwgLS0tLS0tLS0tCiRcaGF0IFxiZXRhXzAkIHwgYHIgZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzEsM11gCiRcaGF0IFxiZXRhXzEkIHwgYHIgZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzIsM11gCgpgYGB7cn0KZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWywzXQpgYGAKCgpQYXJhbWV0cm8gfCB2YWxvciB0ICAgfCBjb2RpZ28KLS0tLS0tLS0tIHwgLS0tLS0tLS0tIHwgLS0tLS0KUlNFIHwgYHIgZml0X3N1bW1hcnkkc2lnbWFgIHwgIGBmaXRfc3VtbWFyeSRzaWdtYWAKJFJeMiR8IGByIGZpdF9zdW1tYXJ5JHIuc3F1YXJlZGAgfCBgZml0X3N1bW1hcnkkci5zcXVhcmVkYApFc3RhZGlzdGl2byBGIHwgYHIgZml0X3N1bW1hcnkkZnN0YXRpc3RpY1sxXWAgfCBgZml0X3N1bW1hcnkkZnN0YXRpc3RpY1sxXWAKCgpgYGB7cn0KZml0X3N1bW1hcnkkc2lnbWEvbWVhbihBZHZlcnRpc2luZyRTYWxlcykqMTAwICU+JSByb3VuZCgpCmBgYAoKIyMgUmVncmVzacOzbiBMaW5lYWwgTXVsdGlwbGUKYGBge3J9CnBsb3QoQWR2ZXJ0aXNpbmcpCmBgYAoKCmBgYHtyfQpmaXQyPC1sbShTYWxlcyB+IFJhZGlvICsgVFYgKyBOZXdzcGFwZXIsIGRhdGEgPSBBZHZlcnRpc2luZykKc3VtbWFyeShmaXQyKQpgYGAKCmBgYHtyfQpjb3IoQWR2ZXJ0aXNpbmcpCmBgYAoKIyMgSW50ZXJhY2Npw7NuIGVudHJlIHZhcmlibGVzCgokJFx0ZXh0e3NhbGVzfT1cYmV0YV8wK1xiZXRhXzFcY2RvdFx0ZXh0e1RWfStcYmV0YV8yXGNkb3RcdGV4dHtSYWRpb30kJAoKRW4gZXN0ZSBjYXNvIHNlIHF1aWVyZSB2ZXJpZmljYXIgc2kgdW4gaW5jcmVtZW50byBlbiBsYSBhZHF1aXNpY2lvbiBkZSBhbnVuY2lvcyBlbiByYWRpbyBhdW1lbnRhIG8gZGlzbWludXllIGVsICRcYmV0YV8xJCBzZSBwcm9wb25lIGVsIHNpZ3VpZW50ZSBtb2RlbG8KCiQkXHRleHR7c2FsZXN9PVxiZXRhXzArXGJldGFfMVxjZG90XHRleHR7VFZ9K1xiZXRhXzJcY2RvdFx0ZXh0e1JhZGlvfStcYmV0YV8zXGNkb3RcdGV4dHtSYWRpb31cdGltZXNcdGV4dHtUVn0kJAoKbG8gY3VhbCBzZSBwdWVkZSBzaW1wbGlmaWNhciBjb21vIAoKJCRcYmVnaW57YWxpZ24qfQpcdGV4dHtzYWxlc30gJj0gXGJldGFfMCtcYmV0YV8xXGNkb3RcdGV4dHtUVn0rXGJldGFfMlxjZG90XHRleHR7UmFkaW99K1xiZXRhXzNcY2RvdFx0ZXh0e1JhZGlvfVx0aW1lc1x0ZXh0e1RWfSBcXCAKICY9IFxiZXRhXzAgKyBcbGVmdChcYmV0YV8xICsgXGJldGFfMyBcY2RvdCBcdGV4dHtSYWRpb31ccmlnaHQpXGNkb3RcdGV4dHtUVn0rXGJldGFfMiBcY2RvdCBcdGV4dHtSYWRpb30gXFwgCiAmPSBcYmV0YV8wICsgXHRpbGRlIFxiZXRhXzEgXGNkb3QgXHRleHR7VFZ9ICsgXGJldGFfMyBcY2RvdCBcdGV4dHtSYWRpb30gIApcZW5ke2FsaWduKn0kJAoKYGBge3J9CmZpdDMgPC0gbG0oU2FsZXMgfiBUViArIFJhZGlvICsgVFYgKiBSYWRpbyxkYXRhID0gQWR2ZXJ0aXNpbmcpCnN1bW1hcnkoZml0MykkY29lZmZpY2llbnRzCmBgYAoKIyMgUHJlZ3VudGFzCgoxLiBIYXkgcmVsYWNpb25lcyBlbnRyZSBsYXMgdmVudGFzIHkgbGEgaW52ZXJzaW9uIGRlIHB1YmxpY2lkYWQgZW4gbG9zIGRpZmVyZW50ZXMgbWVkaW9zPwoyLiBRdWUgdGFuIGZ1ZXJ0ZSBlcyBsYSByZWxhY2nDs24/CjMuIFF1ZSB0aXBvcyBkZSBtZWRpbyBzb24gbG9zIHF1ZSBjb250cmlidXllbiBhIGxhcyB2ZW50YXM/CjQuIFF1ZSB0YW4gZ3JhbmRlIGVzIGxhIGNvbnRyaWJ1Y2lvbiBkZSBjYWRhIG1lZGlvIGEgbGFzIHZlbnRhcz8KNS4gQ29tbyBwb2RlbW9zIHByZWRjaXIgZnV0dXJhcyB2ZW50YXM/CjYuIEVzIGxhIHJlbGFjaW9uIGxpbmVhbD8KNy4gSGF5IHNpbmVyZ2lhIGVudHJlIGxvcyBkaWZlcmVudGVzIG1lZGlvcz8KCgoKIyMgUmVncmVzaW9uZXMgbGluZWFsZXMgY29uIHZhcmlhYmxlcyBjdWFsaXRhdGl2YXMKCiMjIyBWYXJpYWJsZXMgQmluYXJpYXMKCmBgYHtyLHdhcm5pbmc9RkFMU0V9CmNyZWRpdCA8LSByZWFkX2Nzdigifi9PbmVEcml2ZS9Ecm9wYm94L0N1cnNvcy9JU0wgQ2hhcHRlcnMvQ3JlZGl0LmNzdiIpCm5hbWVzKGNyZWRpdCk8LXRvbG93ZXIobmFtZXMoY3JlZGl0KSkKY3JlZGl0PC1jcmVkaXRbLC0xXQpoZWFkKGNyZWRpdCkKYGBgCgpgYGB7cn0KZml0NCA8LSBsbShiYWxhbmNlIH4gZ2VuZGVyICwgZGF0YSA9IGNyZWRpdCkKc3VtbWFyeShmaXQ0KSRjb2VmZmljaWVudHMKYGBgCgoKJCRnZW5kZXJfaSA9IFxsZWZ0XHtcYmVnaW57bWF0cml4fQowICYgRmVtYWxlXFwgCjEgJiBNYWxlClxlbmR7bWF0cml4fVxyaWdodC4kJAoKJCQgYmFsYW5jZSA9IFxiZXRhXzAgKyBcYmV0YV8xIFxjZG90IGdlbmRlcj1cbGVmdFx7XGJlZ2lue21hdHJpeH0KXGJldGFfMCArIFxiZXRhXzEgJiBtYWxlXFwgClxiZXRhXzAgJiBmZW1hbGUKXGVuZHttYXRyaXh9XHJpZ2h0LgokJAoKJCRnZW5kZXJfaSA9IFxsZWZ0XHtcYmVnaW57bWF0cml4fQotMSAmIEZlbWFsZVxcIAoxICYgTWFsZQpcZW5ke21hdHJpeH1ccmlnaHQuJCQKCiQkIGJhbGFuY2UgPSBcYmV0YV8wICsgXGJldGFfMSBcY2RvdCBnZW5kZXI9XGxlZnRce1xiZWdpbnttYXRyaXh9ClxiZXRhXzAgKyBcYmV0YV8xICYgbWFsZVxcIApcYmV0YV8wIC0gXGJldGFfMSAmIGZlbWFsZQpcZW5ke21hdHJpeH1ccmlnaHQuCiQkCgoKCmBgYHtyfQpjcmVkaXQkY29kZWRfZ2VuZGVyIDwtIGlmZWxzZShjcmVkaXQkZ2VuZGVyPT0iRmVtYWxlIiwtMSwxKQpmaXQ1IDwtIGxtKGJhbGFuY2UgfiBjb2RlZF9nZW5kZXIgLCBkYXRhID0gY3JlZGl0KQpzdW1tYXJ5KGZpdDUpJGNvZWZmaWNpZW50cwpgYGAKCgoKCiMjIyBWYXJpYWJsZXMgTXVsdGlub21pYWxlcwpgYGB7cn0KdW5pcXVlKGNyZWRpdCRldGhuaWNpdHkpCmBgYAoKCiQkYXNpYW5faSA9IFxsZWZ0XHtcYmVnaW57bWF0cml4fQowICYgbm9cXCAKMSAmIHllcwpcZW5ke21hdHJpeH1ccmlnaHQuJCQKCiQkCmNhdWNhc2lhbl9pID0gXGxlZnRce1xiZWdpbnttYXRyaXh9CjAgJiBub1xcIAoxICYgeWVzClxlbmR7bWF0cml4fVxyaWdodC4KJCQKCmBgYHtyfQpjcmVkaXQkY2F1Y2FzaWFuIDwtIGlmZWxzZSggY3JlZGl0JGV0aG5pY2l0eSA9PSAiQ2F1Y2FzaWFuIiwgMSwgMCkKY3JlZGl0JGFzaWFuIDwtIGlmZWxzZSggY3JlZGl0JGV0aG5pY2l0eSA9PSAiQXNpYW4iLCAxLCAwKQpgYGAKCiQkYmFsYW5jZSA9IFxiZXRhXzAgKyBcYmV0YV8xIFxjZG90IGFzaWFuICsgXGJldGFfMiBcY2RvdCBjYXVjYXNpYW4gPVxsZWZ0XHtcYmVnaW57bWF0cml4fQpcYmV0YV8wICsgXGJldGFfMSAmIGFzaWFuXFwgClxiZXRhXzAgKyBcYmV0YV8yICYgY2F1Y2FzaWFuIFxcClxiZXRhXzAgICYgXHRleHR7YWZyaWNhbiBhbWVyaWNhbn0KXGVuZHttYXRyaXh9XHJpZ2h0LiQkCgpgYGB7cn0KZml0NiA8LSBsbShiYWxhbmNlIH4gYXNpYW4gKyBjYXVjYXNpYW4sIGRhdGE9Y3JlZGl0KQpzdW1tYXJ5KGZpdDYpJGNvZWZmaWNpZW50cwoKYGBgCgoKCgoKCgoKCg==