correlation and regression analysis

set working directory

setwd("~/R TRAINING/session 5")
G2;H2;Warningh: The working directory was changed to C:/Users/USER/Documents/R TRAINING/session 5 inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.g

supress

options(scipen=999)

##load the data

#Example:pearson correlation
data<-data.frame(x=c(1,2,3,4,5),
                 y=c(2,4,5,7,6))
data

Calculate pearson correlation

pearson_corr<-cor(data$x, data$y,method="pearson")
print(paste("pearson correlation:",pearson_corr))
[1] "pearson correlation: 0.904194430179465"

Test-significance of pearson correlation

pearson_test<-cor.test(data$x, data$y, method="pearson")
print(pearson_test,3)

    Pearson's product-moment correlation

data:  data$x and data$y
t = 4, df = 3, p-value = 0.04
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.108 0.994
sample estimates:
  cor 
0.904 

reject null hypothesis

calculate spearman correlation

spearman_corr<-cor(data$x,data$y,method="spearman")
print(paste("spearman correlation:",spearman_corr))
[1] "spearman correlation: 0.9"

test significance of spearman correlation

spearman_test<-cor.test(data$x, data$y, method = "spearman")
print(spearman_test,3)

    Spearman's rank correlation rho

data:  data$x and data$y
S = 2, p-value = 0.08
alternative hypothesis: true rho is not equal to 0
sample estimates:
rho 
0.9 

##pratical

library(ggplot2)
head(economics)

correlation matrix

corr_matrix <- economics%>%
  dplyr::select(pce,pop,psavert,unemploy)%>%
  cor(use="pairwise.complete.obs")
corr_matrix
                pce        pop    psavert   unemploy
pce       1.0000000  0.9872421 -0.7928546  0.6145176
pop       0.9872421  1.0000000 -0.8363147  0.6337165
psavert  -0.7928546 -0.8363147  1.0000000 -0.3093769
unemploy  0.6145176  0.6337165 -0.3093769  1.0000000
  
head(economics)

simple linear regression

create a simple data set of x and y

use im()to fit a simple linear regression model

data<-data.frame(x=c(1,2,3,4,5),
                 y=c(2,4,5,4,6))
print(data)
model<-lm(y~x,data=data)
summary(model)

Call:
lm(formula = y ~ x, data = data)

Residuals:
   1    2    3    4    5 
-0.6  0.6  0.8 -1.0  0.2 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)  
(Intercept)   1.8000     0.9381   1.919   0.1508  
x             0.8000     0.2828   2.828   0.0663 .
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.8944 on 3 degrees of freedom
Multiple R-squared:  0.7273,    Adjusted R-squared:  0.6364 
F-statistic:     8 on 1 and 3 DF,  p-value: 0.06628

##simple linear regression example using gapminder s=data set

library(gapminder)
data("gapminder")
head(gapminder)

fit simple linear regression models

model<-lm(lifeExp~ gdpPercap,data=gapminder)
summary(model)

Call:
lm(formula = lifeExp ~ gdpPercap, data = gapminder)

Residuals:
    Min      1Q  Median      3Q     Max 
-82.754  -7.758   2.176   8.225  18.426 

Coefficients:
               Estimate  Std. Error t value            Pr(>|t|)    
(Intercept) 53.95556088  0.31499494  171.29 <0.0000000000000002 ***
gdpPercap    0.00076488  0.00002579   29.66 <0.0000000000000002 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 10.49 on 1702 degrees of freedom
Multiple R-squared:  0.3407,    Adjusted R-squared:  0.3403 
F-statistic: 879.6 on 1 and 1702 DF,  p-value: < 0.00000000000000022

multiple linear regression model

data<-data.frame(y=c(2,4,5,4,6),
                 x1=c(1,2,3,4,5),
                 x2=c(3,5,7,6,8))
data

fit a multiple linear regression model

model<-lm(y~x1+x2,data=data)
summary(model)

Call:
lm(formula = y ~ x1 + x2, data = data)

Residuals:
       1        2        3        4        5 
-0.06667  0.33333 -0.26667 -0.20000  0.20000 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)  
(Intercept)  -0.4222     0.6748  -0.626   0.5954  
x1           -0.1778     0.2703  -0.658   0.5784  
x2            0.8889     0.2222   4.000   0.0572 .
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.3651 on 2 degrees of freedom
Multiple R-squared:  0.9697,    Adjusted R-squared:  0.9394 
F-statistic:    32 on 2 and 2 DF,  p-value: 0.0303

use economic data from gggplot2

library(ggplot2)
data("economics")
head(economics)

pce model 1

pce_model<-lm(psavert~pce,data=economics)
summary(pce_model)

Call:
lm(formula = psavert ~ pce, data = economics)

Residuals:
    Min      1Q  Median      3Q     Max 
-5.2442 -1.3751 -0.3442  1.3484  7.6090 

Coefficients:
               Estimate  Std. Error t value            Pr(>|t|)    
(Intercept) 11.75213073  0.12716708   92.42 <0.0000000000000002 ***
pce         -0.00066075  0.00002124  -31.12 <0.0000000000000002 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.808 on 572 degrees of freedom
Multiple R-squared:  0.6286,    Adjusted R-squared:  0.628 
F-statistic: 968.2 on 1 and 572 DF,  p-value: < 0.00000000000000022

pop model

pop_model<-lm(psavert~pce,data=economics)
summary(pop_model)

Call:
lm(formula = psavert ~ pce, data = economics)

Residuals:
    Min      1Q  Median      3Q     Max 
-5.2442 -1.3751 -0.3442  1.3484  7.6090 

Coefficients:
               Estimate  Std. Error t value            Pr(>|t|)    
(Intercept) 11.75213073  0.12716708   92.42 <0.0000000000000002 ***
pce         -0.00066075  0.00002124  -31.12 <0.0000000000000002 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.808 on 572 degrees of freedom
Multiple R-squared:  0.6286,    Adjusted R-squared:  0.628 
F-statistic: 968.2 on 1 and 572 DF,  p-value: < 0.00000000000000022

##unemploy model

unemploy_model<-lm(psavert~pce,data=economics)
summary(unemploy_model)

Call:
lm(formula = psavert ~ pce, data = economics)

Residuals:
    Min      1Q  Median      3Q     Max 
-5.2442 -1.3751 -0.3442  1.3484  7.6090 

Coefficients:
               Estimate  Std. Error t value            Pr(>|t|)    
(Intercept) 11.75213073  0.12716708   92.42 <0.0000000000000002 ***
pce         -0.00066075  0.00002124  -31.12 <0.0000000000000002 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.808 on 572 degrees of freedom
Multiple R-squared:  0.6286,    Adjusted R-squared:  0.628 
F-statistic: 968.2 on 1 and 572 DF,  p-value: < 0.00000000000000022

uempmed model

uempmed_model<-lm(psavert~pce,data=economics)
summary(uempmed_model)

Call:
lm(formula = psavert ~ pce, data = economics)

Residuals:
    Min      1Q  Median      3Q     Max 
-5.2442 -1.3751 -0.3442  1.3484  7.6090 

Coefficients:
               Estimate  Std. Error t value            Pr(>|t|)    
(Intercept) 11.75213073  0.12716708   92.42 <0.0000000000000002 ***
pce         -0.00066075  0.00002124  -31.12 <0.0000000000000002 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.808 on 572 degrees of freedom
Multiple R-squared:  0.6286,    Adjusted R-squared:  0.628 
F-statistic: 968.2 on 1 and 572 DF,  p-value: < 0.00000000000000022

estimate the multiple linear regression model

overal_model<-lm(psavert~pce+pop+unemploy+uempmed,data=economics)
summary(overal_model)

Call:
lm(formula = psavert ~ pce + pop + unemploy + uempmed, data = economics)

Residuals:
    Min      1Q  Median      3Q     Max 
-4.8282 -0.6982 -0.0981  0.6336  5.4816 

Coefficients:
               Estimate  Std. Error t value             Pr(>|t|)    
(Intercept) 45.67014927  2.23116237  20.469 < 0.0000000000000002 ***
pce          0.00085067  0.00011865   7.170     0.00000000000235 ***
pop         -0.00017334  0.00001101 -15.742 < 0.0000000000000002 ***
unemploy     0.00024997  0.00004824   5.182     0.00000030589469 ***
uempmed      0.16599616  0.03559460   4.664     0.00000387763733 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.186 on 569 degrees of freedom
Multiple R-squared:  0.8409,    Adjusted R-squared:  0.8398 
F-statistic: 752.1 on 4 and 569 DF,  p-value: < 0.00000000000000022

put all four models in one table using stargazer

library(stargazer)
G3;
Please cite as: 

gG3; Hlavac, Marek (2022). stargazer: Well-Formatted Regression and Summary Statistics Tables.
gG3; R package version 5.2.3. https://CRAN.R-project.org/package=stargazer 

g
stargazer(pce_model,pop_model,unemploy_model,uempmed_model,overal_model,
          type="text",
          title="regression results",
          dep.var.labels=c("savings rate"))
Warning :length of NULL cannot be changed
Warning :length of NULL cannot be changed
Warning :length of NULL cannot be changed
Warning :length of NULL cannot be changed
Warning :length of NULL cannot be changed
Warning :number of rows of result is not a multiple of vector length (arg 2)

regression results
================================================================================================================================================
                                                                        Dependent variable:                                                     
                    ----------------------------------------------------------------------------------------------------------------------------
                                                                            savings rate                                                        
                              (1)                      (2)                      (3)                      (4)                      (5)           
------------------------------------------------------------------------------------------------------------------------------------------------
pce                        -0.001***                -0.001***                -0.001***                -0.001***                 0.001***        
                           (0.00002)                (0.00002)                (0.00002)                (0.00002)                 (0.0001)        
                                                                                                                                                
pop                                                                                                                            -0.0002***       
                                                                                                                               (0.00001)        
                                                                                                                                                
unemploy                                                                                                                       0.0002***        
                                                                                                                               (0.00005)        
                                                                                                                                                
uempmed                                                                                                                         0.166***        
                                                                                                                                (0.036)         
                                                                                                                                                
Constant                   11.752***                11.752***                11.752***                11.752***                45.670***        
                            (0.127)                  (0.127)                  (0.127)                  (0.127)                  (2.231)         
                                                                                                                                                
------------------------------------------------------------------------------------------------------------------------------------------------
Observations                  574                      574                      574                      574                      574           
R2                           0.629                    0.629                    0.629                    0.629                    0.841          
Adjusted R2                  0.628                    0.628                    0.628                    0.628                    0.840          
Residual Std. Error     1.808 (df = 572)         1.808 (df = 572)         1.808 (df = 572)         1.808 (df = 572)         1.186 (df = 569)    
F Statistic         968.195*** (df = 1; 572) 968.195*** (df = 1; 572) 968.195*** (df = 1; 572) 968.195*** (df = 1; 572) 752.085*** (df = 4; 569)
================================================================================================================================================
Note:                                                                                                                *p<0.1; **p<0.05; ***p<0.01

model diagnostics

helps evaluate whether a linear regression model meets the key assumptions required for reliable inference.

checking multicollineality

library(car)
G3;Loading required package: carData
g
vif_values<-vif(overal_model)
print(vif_values)
      pce       pop  unemploy   uempmed 
72.508990 66.420421  6.613911  8.699492 

checking normality of residuals

library(tidyverse)
── Attaching core tidyverse packages ─────────────────────────────────────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ lubridate 1.9.4     ✔ tibble    3.2.1
✔ purrr     1.0.4     ✔ tidyr     1.3.1
── Conflicts ───────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks plotly::filter(), stats::filter()
✖ dplyr::lag()    masks stats::lag()
✖ dplyr::recode() masks car::recode()
✖ purrr::some()   masks car::some()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
library(corrplot)
G3;corrplot 0.95 loaded
g
cor_matrix<-cor(select(economics, where(is.numeric)),use="complete.obs")
corrplot(cor_matrix,
         method="color",
         type="upper",
         tl.col="black",
         tl.srt=45,
         addCoef.col="white",
         number.cex=0.7,
         diag=TRUE)

residual diagnostics

should have constant variance

library(forecast)
G3;Registered S3 method overwritten by 'quantmod':
  method            from
  as.zoo.data.frame zoo 
g
checkresiduals(overal_model)

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

data:  Residuals
LM test = 379.92, df = 10, p-value < 0.00000000000000022

testing for autocorrelation

library(lmtest)
G3;Loading required package: zoo
gG3;
Attaching package: ‘zoo’

gG3;The following objects are masked from ‘package:base’:

    as.Date, as.Date.numeric

g
library(car)
dwtest(overal_model)

    Durbin-Watson test

data:  overal_model
DW = 0.4103, p-value < 0.00000000000000022
alternative hypothesis: true autocorrelation is greater than 0

autocorrelation exists

heteroscedasticity

library(lmtest)
bptest(overal_model)

    studentized Breusch-Pagan test

data:  overal_model
BP = 50.022, df = 4, p-value = 0.0000000003573

non-constant variance(hetero…..)

Assignment

interpretation of correlation coefficient

#positive correlation

library(ggplot2)

ggplot(economics, aes(x = pop, y = psavert)) +
  geom_point(color = "steelblue") +
  geom_smooth(method = "lm", se = FALSE, color = "red") +
  labs(
    title = "Positive Correlation: Population vs. psaverting",
    x = "U.S. Population",
    y = "Unemployment"
  ) +
  theme_gray()

#negative correlation

ggplot(economics, aes(x = pop, y = unemploy)) +
  geom_point(color = "steelblue") +
  geom_smooth(method = "lm", se = FALSE, color = "red") +
  labs(title = "Negative Correlation: Population vs. Unemployment",
       x = "U.S. Population",
       y = "Unemployment") +
  theme_minimal()

#no correlation

ggplot(economics, aes(x = pop, y = pce)) +
  geom_point(color = "steelblue") +
  geom_smooth(method = "lm", se = FALSE, color = "red") +
  labs(title = "No Correlation: Population vs. Personal Consumption Expenditures",
       x = "U.S. Population",
       y = "Personal Consumption Expenditures") +
  theme_minimal()

#perfect correlation

ggplot(economics, aes(x = pop, y = pop)) +
  geom_point(color = "steelblue") +
  geom_smooth(method = "lm", se = FALSE, color = "red") +
  labs(title = "Perfect Correlation: Population vs. Population",
       x = "U.S. Population",
       y = "Population") +
  theme_minimal()

#weak correlation

ggplot(economics, aes(x = pop, y = psavert)) +
  geom_point(color = "steelblue") +
  geom_smooth(method = "lm", se = FALSE, color = "red") +
  labs(title = "Weak Correlation: Population vs. psaverting",
       x = "U.S. Population",
       y = "Unemployment") +
  theme_minimal()

#moderate correlation

ggplot(economics, aes(x = pop, y = unemploy)) +
  geom_point(color = "steelblue") +
  geom_smooth(method = "lm", se = FALSE, color = "red") +
  labs(
    title = "Moderate Correlation: Population vs. Unemployment",
    x = "U.S. Population",
    y = "Unemployment"
  ) +
  theme_minimal()

#strong correlation

ggplot(economics, aes(x = pop, y = pce)) +
  geom_point(color = "steelblue") +
  geom_smooth(method = "lm", se = FALSE, color = "red") +
  labs(
    title = "Strong Correlation: Population vs. Personal Consumption Expenditures",
    x = "U.S. Population",
    y = "Personal Consumption Expenditures"
  ) +
  theme_minimal()

#very strong correlation

ggplot(economics, aes(x = pop, y = pop)) +
  geom_point(color = "steelblue") +
  geom_smooth(method = "lm", se = FALSE, color = "red") +
  labs(
    title = "Very Strong Correlation: Population vs. Population",
    x = "U.S. Population",
    y = "Population"
  ) +
  theme_minimal()

#causation vs correlation

#Basic Correlation Analysis # Calculate correlation matrix

corr_matrix <- cor(economics[, c("pce", "pop", "psavert", "unemploy")], use = "pairwise.complete.obs")
corr_matrix
                pce        pop    psavert   unemploy
pce       1.0000000  0.9872421 -0.7928546  0.6145176
pop       0.9872421  1.0000000 -0.8363147  0.6337165
psavert  -0.7928546 -0.8363147  1.0000000 -0.3093769
unemploy  0.6145176  0.6337165 -0.3093769  1.0000000

Visualize correlation matrix

library(corrplot)
corrplot(corr_matrix, method = "circle", type = "upper", tl.col = "black", tl.srt = 45)

##simulating Correlation Without Causation

##sample data

x=c(10,20,30,40,50)
y=c(15,25,35,45,55)
z=c(50,40,30,20,10)
   
##Create a data frame
data <- data.frame(x, y, z)

##correlation matrix
cor_matrix <- cor(data)
print(cor_matrix)
   x  y  z
x  1  1 -1
y  1  1 -1
z -1 -1  1

interpretation of correlation coefficient

interprete_correlation <- function(corr) {
  if (corr > 0.8) {
    return("Very Strong Positive Correlation")
  } else if (corr > 0.6) {
    return("Strong Positive Correlation")
  } else if (corr > 0.4) {
    return("Moderate Positive Correlation")
  } else if (corr > 0.2) {
    return("Weak Positive Correlation")
  } else if (corr < -0.2) {
    return("Weak Negative Correlation")
  } else if (corr < -0.4) {
    return("Moderate Negative Correlation")
  } else if (corr < -0.6) {
    return("Strong Negative Correlation")
  } else if (corr < -0.8) {
    return("Very Strong Negative Correlation")
  } else {
    return("No Correlation")
  }
}

r_value <- cor(data$x, data$y)
cat("correlation between x and y is, r_value", ":",)
G1;H1;Errorh in cat("correlation between x and y is, r_value", ":", ) : 
  argument is missing, with no default
gG1;H1;Error during wrapuph: not that many frames on the stack
Error: no more error handlers available (recursive errors?); invoking 'abort' restart
g
    
interprete_correlation(r_value)
[1] "Very Strong Positive Correlation"
LS0tDQp0aXRsZTogImNvcnJlbGF0aW9uIGFuZCByZWdyZXNzaW9uIGFuYWx5c2lzIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KIyMgY29ycmVsYXRpb24gYW5kIHJlZ3Jlc3Npb24gYW5hbHlzaXMNCg0KIyMgc2V0IHdvcmtpbmcgZGlyZWN0b3J5DQpgYGB7cn0NCnNldHdkKCJ+L1IgVFJBSU5JTkcvc2Vzc2lvbiA1IikNCmBgYA0KDQojIyBzdXByZXNzDQpgYGB7cn0NCm9wdGlvbnMoc2NpcGVuPTk5OSkNCmBgYA0KDQojI2xvYWQgdGhlIGRhdGENCmBgYHtyfQ0KI0V4YW1wbGU6cGVhcnNvbiBjb3JyZWxhdGlvbg0KZGF0YTwtZGF0YS5mcmFtZSh4PWMoMSwyLDMsNCw1KSwNCiAgICAgICAgICAgICAgICAgeT1jKDIsNCw1LDcsNikpDQpkYXRhDQpgYGANCiMjIENhbGN1bGF0ZSBwZWFyc29uIGNvcnJlbGF0aW9uDQpgYGB7cn0NCnBlYXJzb25fY29ycjwtY29yKGRhdGEkeCwgZGF0YSR5LG1ldGhvZD0icGVhcnNvbiIpDQpwcmludChwYXN0ZSgicGVhcnNvbiBjb3JyZWxhdGlvbjoiLHBlYXJzb25fY29ycikpDQpgYGANCiMjIFRlc3Qtc2lnbmlmaWNhbmNlIG9mIHBlYXJzb24gY29ycmVsYXRpb24gDQpgYGB7cn0NCnBlYXJzb25fdGVzdDwtY29yLnRlc3QoZGF0YSR4LCBkYXRhJHksIG1ldGhvZD0icGVhcnNvbiIpDQpwcmludChwZWFyc29uX3Rlc3QsMykNCmBgYA0KcmVqZWN0IG51bGwgaHlwb3RoZXNpcw0KDQojIyBjYWxjdWxhdGUgc3BlYXJtYW4gY29ycmVsYXRpb24NCmBgYHtyfQ0Kc3BlYXJtYW5fY29ycjwtY29yKGRhdGEkeCxkYXRhJHksbWV0aG9kPSJzcGVhcm1hbiIpDQpwcmludChwYXN0ZSgic3BlYXJtYW4gY29ycmVsYXRpb246IixzcGVhcm1hbl9jb3JyKSkNCmBgYA0KDQojIyB0ZXN0IHNpZ25pZmljYW5jZSBvZiBzcGVhcm1hbiBjb3JyZWxhdGlvbg0KYGBge3J9DQpzcGVhcm1hbl90ZXN0PC1jb3IudGVzdChkYXRhJHgsIGRhdGEkeSwgbWV0aG9kID0gInNwZWFybWFuIikNCnByaW50KHNwZWFybWFuX3Rlc3QsMykNCmBgYA0KDQojI3ByYXRpY2FsDQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikNCmhlYWQoZWNvbm9taWNzKQ0KYGBgDQoNCiMjIGNvcnJlbGF0aW9uIG1hdHJpeA0KYGBge3J9DQpjb3JyX21hdHJpeCA8LSBlY29ub21pY3MlPiUNCiAgZHBseXI6OnNlbGVjdChwY2UscG9wLHBzYXZlcnQsdW5lbXBsb3kpJT4lDQogIGNvcih1c2U9InBhaXJ3aXNlLmNvbXBsZXRlLm9icyIpDQpjb3JyX21hdHJpeA0KICANCmBgYA0KDQoNCmBgYHtyfQ0KaGVhZChlY29ub21pY3MpDQpgYGANCg0KIyMgc2ltcGxlIGxpbmVhciByZWdyZXNzaW9uDQoNCiMjIGNyZWF0ZSBhIHNpbXBsZSBkYXRhIHNldCBvZiB4IGFuZCB5DQp1c2UgaW0oKXRvIGZpdCBhIHNpbXBsZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbA0KYGBge3J9DQpkYXRhPC1kYXRhLmZyYW1lKHg9YygxLDIsMyw0LDUpLA0KICAgICAgICAgICAgICAgICB5PWMoMiw0LDUsNCw2KSkNCnByaW50KGRhdGEpDQpgYGANCg0KYGBge3J9DQptb2RlbDwtbG0oeX54LGRhdGE9ZGF0YSkNCnN1bW1hcnkobW9kZWwpDQpgYGANCg0KIyNzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24gZXhhbXBsZSB1c2luZyBnYXBtaW5kZXIgcz1kYXRhIHNldA0KYGBge3J9DQpsaWJyYXJ5KGdhcG1pbmRlcikNCmRhdGEoImdhcG1pbmRlciIpDQpoZWFkKGdhcG1pbmRlcikNCmBgYA0KDQojIyBmaXQgc2ltcGxlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVscw0KDQpgYGB7cn0NCm1vZGVsPC1sbShsaWZlRXhwfiBnZHBQZXJjYXAsZGF0YT1nYXBtaW5kZXIpDQpzdW1tYXJ5KG1vZGVsKQ0KYGBgDQojIyBtdWx0aXBsZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbA0KYGBge3J9DQpkYXRhPC1kYXRhLmZyYW1lKHk9YygyLDQsNSw0LDYpLA0KICAgICAgICAgICAgICAgICB4MT1jKDEsMiwzLDQsNSksDQogICAgICAgICAgICAgICAgIHgyPWMoMyw1LDcsNiw4KSkNCmRhdGENCmBgYA0KDQoNCiMjIGZpdCBhIG11bHRpcGxlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsDQpgYGB7cn0NCm1vZGVsPC1sbSh5fngxK3gyLGRhdGE9ZGF0YSkNCnN1bW1hcnkobW9kZWwpDQpgYGANCg0KIyMgdXNlIGVjb25vbWljIGRhdGEgZnJvbSBnZ2dwbG90Mg0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQpkYXRhKCJlY29ub21pY3MiKQ0KaGVhZChlY29ub21pY3MpDQpgYGANCg0KIyMgcGNlIG1vZGVsIDENCmBgYHtyfQ0KcGNlX21vZGVsPC1sbShwc2F2ZXJ0fnBjZSxkYXRhPWVjb25vbWljcykNCnN1bW1hcnkocGNlX21vZGVsKQ0KYGBgDQoNCiMjIHBvcCBtb2RlbA0KYGBge3J9DQpwb3BfbW9kZWw8LWxtKHBzYXZlcnR+cGNlLGRhdGE9ZWNvbm9taWNzKQ0Kc3VtbWFyeShwb3BfbW9kZWwpDQpgYGANCg0KIyN1bmVtcGxveSBtb2RlbA0KYGBge3J9DQp1bmVtcGxveV9tb2RlbDwtbG0ocHNhdmVydH5wY2UsZGF0YT1lY29ub21pY3MpDQpzdW1tYXJ5KHVuZW1wbG95X21vZGVsKQ0KYGBgDQojIyB1ZW1wbWVkIG1vZGVsDQpgYGB7cn0NCnVlbXBtZWRfbW9kZWw8LWxtKHBzYXZlcnR+cGNlLGRhdGE9ZWNvbm9taWNzKQ0Kc3VtbWFyeSh1ZW1wbWVkX21vZGVsKQ0KYGBgDQoNCg0KIyMgZXN0aW1hdGUgdGhlIG11bHRpcGxlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsDQoNCmBgYHtyfQ0Kb3ZlcmFsX21vZGVsPC1sbShwc2F2ZXJ0fnBjZStwb3ArdW5lbXBsb3krdWVtcG1lZCxkYXRhPWVjb25vbWljcykNCnN1bW1hcnkob3ZlcmFsX21vZGVsKQ0KYGBgDQoNCiMjIHB1dCBhbGwgZm91ciBtb2RlbHMgaW4gb25lIHRhYmxlIHVzaW5nIHN0YXJnYXplcg0KYGBge3J9DQpsaWJyYXJ5KHN0YXJnYXplcikNCnN0YXJnYXplcihwY2VfbW9kZWwscG9wX21vZGVsLHVuZW1wbG95X21vZGVsLHVlbXBtZWRfbW9kZWwsb3ZlcmFsX21vZGVsLA0KICAgICAgICAgIHR5cGU9InRleHQiLA0KICAgICAgICAgIHRpdGxlPSJyZWdyZXNzaW9uIHJlc3VsdHMiLA0KICAgICAgICAgIGRlcC52YXIubGFiZWxzPWMoInNhdmluZ3MgcmF0ZSIpKQ0KDQpgYGANCg0KIyMgbW9kZWwgZGlhZ25vc3RpY3MNCmhlbHBzIGV2YWx1YXRlIHdoZXRoZXIgYSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCBtZWV0cyB0aGUga2V5IGFzc3VtcHRpb25zIHJlcXVpcmVkIGZvciByZWxpYWJsZSBpbmZlcmVuY2UuDQoNCiMjIGNoZWNraW5nIG11bHRpY29sbGluZWFsaXR5DQpgYGB7cn0NCmxpYnJhcnkoY2FyKQ0KdmlmX3ZhbHVlczwtdmlmKG92ZXJhbF9tb2RlbCkNCnByaW50KHZpZl92YWx1ZXMpDQoNCmBgYA0KIyMgY2hlY2tpbmcgbm9ybWFsaXR5IG9mIHJlc2lkdWFscw0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoY29ycnBsb3QpDQpjb3JfbWF0cml4PC1jb3Ioc2VsZWN0KGVjb25vbWljcywgd2hlcmUoaXMubnVtZXJpYykpLHVzZT0iY29tcGxldGUub2JzIikNCmNvcnJwbG90KGNvcl9tYXRyaXgsDQogICAgICAgICBtZXRob2Q9ImNvbG9yIiwNCiAgICAgICAgIHR5cGU9InVwcGVyIiwNCiAgICAgICAgIHRsLmNvbD0iYmxhY2siLA0KICAgICAgICAgdGwuc3J0PTQ1LA0KICAgICAgICAgYWRkQ29lZi5jb2w9IndoaXRlIiwNCiAgICAgICAgIG51bWJlci5jZXg9MC43LA0KICAgICAgICAgZGlhZz1UUlVFKQ0KYGBgDQoNCg0KIyMgcmVzaWR1YWwgZGlhZ25vc3RpY3MNCnNob3VsZCBoYXZlIGNvbnN0YW50IHZhcmlhbmNlDQpgYGB7cn0NCmxpYnJhcnkoZm9yZWNhc3QpDQpjaGVja3Jlc2lkdWFscyhvdmVyYWxfbW9kZWwpDQpgYGANCg0KIyMgdGVzdGluZyBmb3IgYXV0b2NvcnJlbGF0aW9uDQpgYGB7cn0NCmxpYnJhcnkobG10ZXN0KQ0KbGlicmFyeShjYXIpDQpkd3Rlc3Qob3ZlcmFsX21vZGVsKQ0KYGBgDQphdXRvY29ycmVsYXRpb24gZXhpc3RzDQoNCiMjIGhldGVyb3NjZWRhc3RpY2l0eQ0KYGBge3J9DQpsaWJyYXJ5KGxtdGVzdCkNCmJwdGVzdChvdmVyYWxfbW9kZWwpDQpgYGANCm5vbi1jb25zdGFudCB2YXJpYW5jZShoZXRlcm8uLi4uLikNCg0KDQojIyMgQXNzaWdubWVudCANCg0KIyMgaW50ZXJwcmV0YXRpb24gb2YgY29ycmVsYXRpb24gY29lZmZpY2llbnQNCiNwb3NpdGl2ZSBjb3JyZWxhdGlvbg0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQoNCmdncGxvdChlY29ub21pY3MsIGFlcyh4ID0gcG9wLCB5ID0gcHNhdmVydCkpICsNCiAgZ2VvbV9wb2ludChjb2xvciA9ICJzdGVlbGJsdWUiKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGNvbG9yID0gInJlZCIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJQb3NpdGl2ZSBDb3JyZWxhdGlvbjogUG9wdWxhdGlvbiB2cy4gcHNhdmVydGluZyIsDQogICAgeCA9ICJVLlMuIFBvcHVsYXRpb24iLA0KICAgIHkgPSAiVW5lbXBsb3ltZW50Ig0KICApICsNCiAgdGhlbWVfZ3JheSgpDQpgYGANCg0KDQojbmVnYXRpdmUgY29ycmVsYXRpb24NCmBgYHtyfQ0KZ2dwbG90KGVjb25vbWljcywgYWVzKHggPSBwb3AsIHkgPSB1bmVtcGxveSkpICsNCiAgZ2VvbV9wb2ludChjb2xvciA9ICJzdGVlbGJsdWUiKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGNvbG9yID0gInJlZCIpICsNCiAgbGFicyh0aXRsZSA9ICJOZWdhdGl2ZSBDb3JyZWxhdGlvbjogUG9wdWxhdGlvbiB2cy4gVW5lbXBsb3ltZW50IiwNCiAgICAgICB4ID0gIlUuUy4gUG9wdWxhdGlvbiIsDQogICAgICAgeSA9ICJVbmVtcGxveW1lbnQiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCiNubyBjb3JyZWxhdGlvbg0KYGBge3J9DQpnZ3Bsb3QoZWNvbm9taWNzLCBhZXMoeCA9IHBvcCwgeSA9IHBjZSkpICsNCiAgZ2VvbV9wb2ludChjb2xvciA9ICJzdGVlbGJsdWUiKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGNvbG9yID0gInJlZCIpICsNCiAgbGFicyh0aXRsZSA9ICJObyBDb3JyZWxhdGlvbjogUG9wdWxhdGlvbiB2cy4gUGVyc29uYWwgQ29uc3VtcHRpb24gRXhwZW5kaXR1cmVzIiwNCiAgICAgICB4ID0gIlUuUy4gUG9wdWxhdGlvbiIsDQogICAgICAgeSA9ICJQZXJzb25hbCBDb25zdW1wdGlvbiBFeHBlbmRpdHVyZXMiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCiNwZXJmZWN0IGNvcnJlbGF0aW9uDQpgYGB7cn0NCmdncGxvdChlY29ub21pY3MsIGFlcyh4ID0gcG9wLCB5ID0gcG9wKSkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gInN0ZWVsYmx1ZSIpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAicmVkIikgKw0KICBsYWJzKHRpdGxlID0gIlBlcmZlY3QgQ29ycmVsYXRpb246IFBvcHVsYXRpb24gdnMuIFBvcHVsYXRpb24iLA0KICAgICAgIHggPSAiVS5TLiBQb3B1bGF0aW9uIiwNCiAgICAgICB5ID0gIlBvcHVsYXRpb24iKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCiN3ZWFrIGNvcnJlbGF0aW9uDQpgYGB7cn0NCmdncGxvdChlY29ub21pY3MsIGFlcyh4ID0gcG9wLCB5ID0gcHNhdmVydCkpICsNCiAgZ2VvbV9wb2ludChjb2xvciA9ICJzdGVlbGJsdWUiKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGNvbG9yID0gInJlZCIpICsNCiAgbGFicyh0aXRsZSA9ICJXZWFrIENvcnJlbGF0aW9uOiBQb3B1bGF0aW9uIHZzLiBwc2F2ZXJ0aW5nIiwNCiAgICAgICB4ID0gIlUuUy4gUG9wdWxhdGlvbiIsDQogICAgICAgeSA9ICJVbmVtcGxveW1lbnQiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQojbW9kZXJhdGUgY29ycmVsYXRpb24NCmBgYHtyfQ0KZ2dwbG90KGVjb25vbWljcywgYWVzKHggPSBwb3AsIHkgPSB1bmVtcGxveSkpICsNCiAgZ2VvbV9wb2ludChjb2xvciA9ICJzdGVlbGJsdWUiKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGNvbG9yID0gInJlZCIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJNb2RlcmF0ZSBDb3JyZWxhdGlvbjogUG9wdWxhdGlvbiB2cy4gVW5lbXBsb3ltZW50IiwNCiAgICB4ID0gIlUuUy4gUG9wdWxhdGlvbiIsDQogICAgeSA9ICJVbmVtcGxveW1lbnQiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQojc3Ryb25nIGNvcnJlbGF0aW9uDQpgYGB7cn0NCmdncGxvdChlY29ub21pY3MsIGFlcyh4ID0gcG9wLCB5ID0gcGNlKSkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gInN0ZWVsYmx1ZSIpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAicmVkIikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlN0cm9uZyBDb3JyZWxhdGlvbjogUG9wdWxhdGlvbiB2cy4gUGVyc29uYWwgQ29uc3VtcHRpb24gRXhwZW5kaXR1cmVzIiwNCiAgICB4ID0gIlUuUy4gUG9wdWxhdGlvbiIsDQogICAgeSA9ICJQZXJzb25hbCBDb25zdW1wdGlvbiBFeHBlbmRpdHVyZXMiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQojdmVyeSBzdHJvbmcgY29ycmVsYXRpb24NCmBgYHtyfQ0KZ2dwbG90KGVjb25vbWljcywgYWVzKHggPSBwb3AsIHkgPSBwb3ApKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSAic3RlZWxibHVlIikgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBjb2xvciA9ICJyZWQiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiVmVyeSBTdHJvbmcgQ29ycmVsYXRpb246IFBvcHVsYXRpb24gdnMuIFBvcHVsYXRpb24iLA0KICAgIHggPSAiVS5TLiBQb3B1bGF0aW9uIiwNCiAgICB5ID0gIlBvcHVsYXRpb24iDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQojY2F1c2F0aW9uIHZzIGNvcnJlbGF0aW9uDQoNCiNCYXNpYyBDb3JyZWxhdGlvbiBBbmFseXNpcw0KIyBDYWxjdWxhdGUgY29ycmVsYXRpb24gbWF0cml4DQpgYGB7cn0NCmNvcnJfbWF0cml4IDwtIGNvcihlY29ub21pY3NbLCBjKCJwY2UiLCAicG9wIiwgInBzYXZlcnQiLCAidW5lbXBsb3kiKV0sIHVzZSA9ICJwYWlyd2lzZS5jb21wbGV0ZS5vYnMiKQ0KY29ycl9tYXRyaXgNCmBgYA0KIyBWaXN1YWxpemUgY29ycmVsYXRpb24gbWF0cml4DQpgYGB7cn0NCmxpYnJhcnkoY29ycnBsb3QpDQpjb3JycGxvdChjb3JyX21hdHJpeCwgbWV0aG9kID0gImNpcmNsZSIsIHR5cGUgPSAidXBwZXIiLCB0bC5jb2wgPSAiYmxhY2siLCB0bC5zcnQgPSA0NSkNCg0KYGBgDQoNCiMjc2ltdWxhdGluZyBDb3JyZWxhdGlvbiBXaXRob3V0IENhdXNhdGlvbg0KDQoNCiMjc2FtcGxlIGRhdGENCmBgYHtyfQ0KeD1jKDEwLDIwLDMwLDQwLDUwKQ0KeT1jKDE1LDI1LDM1LDQ1LDU1KQ0Kej1jKDUwLDQwLDMwLDIwLDEwKQ0KICAgDQojI0NyZWF0ZSBhIGRhdGEgZnJhbWUNCmRhdGEgPC0gZGF0YS5mcmFtZSh4LCB5LCB6KQ0KDQojI2NvcnJlbGF0aW9uIG1hdHJpeA0KY29yX21hdHJpeCA8LSBjb3IoZGF0YSkNCnByaW50KGNvcl9tYXRyaXgpDQoNCmBgYA0KDQppbnRlcnByZXRhdGlvbiBvZiBjb3JyZWxhdGlvbiBjb2VmZmljaWVudA0KYGBge3J9DQppbnRlcnByZXRlX2NvcnJlbGF0aW9uIDwtIGZ1bmN0aW9uKGNvcnIpIHsNCiAgaWYgKGNvcnIgPiAwLjgpIHsNCiAgICByZXR1cm4oIlZlcnkgU3Ryb25nIFBvc2l0aXZlIENvcnJlbGF0aW9uIikNCiAgfSBlbHNlIGlmIChjb3JyID4gMC42KSB7DQogICAgcmV0dXJuKCJTdHJvbmcgUG9zaXRpdmUgQ29ycmVsYXRpb24iKQ0KICB9IGVsc2UgaWYgKGNvcnIgPiAwLjQpIHsNCiAgICByZXR1cm4oIk1vZGVyYXRlIFBvc2l0aXZlIENvcnJlbGF0aW9uIikNCiAgfSBlbHNlIGlmIChjb3JyID4gMC4yKSB7DQogICAgcmV0dXJuKCJXZWFrIFBvc2l0aXZlIENvcnJlbGF0aW9uIikNCiAgfSBlbHNlIGlmIChjb3JyIDwgLTAuMikgew0KICAgIHJldHVybigiV2VhayBOZWdhdGl2ZSBDb3JyZWxhdGlvbiIpDQogIH0gZWxzZSBpZiAoY29yciA8IC0wLjQpIHsNCiAgICByZXR1cm4oIk1vZGVyYXRlIE5lZ2F0aXZlIENvcnJlbGF0aW9uIikNCiAgfSBlbHNlIGlmIChjb3JyIDwgLTAuNikgew0KICAgIHJldHVybigiU3Ryb25nIE5lZ2F0aXZlIENvcnJlbGF0aW9uIikNCiAgfSBlbHNlIGlmIChjb3JyIDwgLTAuOCkgew0KICAgIHJldHVybigiVmVyeSBTdHJvbmcgTmVnYXRpdmUgQ29ycmVsYXRpb24iKQ0KICB9IGVsc2Ugew0KICAgIHJldHVybigiTm8gQ29ycmVsYXRpb24iKQ0KICB9DQp9DQoNCnJfdmFsdWUgPC0gY29yKGRhdGEkeCwgZGF0YSR5KQ0KY2F0KCJjb3JyZWxhdGlvbiBiZXR3ZWVuIHggYW5kIHkgaXMsIHJfdmFsdWUiLCAiOiIsKQ0KICAgIA0KaW50ZXJwcmV0ZV9jb3JyZWxhdGlvbihyX3ZhbHVlKQ0KYGBgDQoNCg0KDQoNCg0KDQoNCg0KDQo=