# Import BD
bd<- read.csv("C:\\Users\\Silva\\Downloads\\real_estate_data.csv")

Libraries

#Installing libraries
#library(pysch)
library(tidyverse)
library(ggplot2)
library(corrplot)
library(gmodels)
library(effects)
library(stargazer)
library(olsrr)        
library(kableExtra)
library(jtools)
library(fastmap)
library(dlookr)
library(Hmisc)
library(naniar)
library(glmnet)
library(caret)
library(car)
library(lmtest)

Regression Analysis

Estimate 3 different linear regression models

Models

## Model 1: Multiple linear regression
modelol <- lm(medv ~ indus + nox + rad + chas + tax + rm + crim + dis + lstat, data = bd)
summary(modelol)
## 
## Call:
## lm(formula = medv ~ indus + nox + rad + chas + tax + rm + crim + 
##     dis + lstat, data = bd)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -18.922  -3.164  -1.019   2.128  27.880 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 14.037486   3.996667   3.512 0.000485 ***
## indus       -0.102369   0.065751  -1.557 0.120127    
## nox         -9.128940   3.797284  -2.404 0.016579 *  
## rad          0.135520   0.069856   1.940 0.052947 .  
## chas         3.602529   0.934492   3.855 0.000131 ***
## tax         -0.010006   0.004004  -2.499 0.012790 *  
## rm           4.603069   0.431139  10.677  < 2e-16 ***
## crim        -0.095412   0.035470  -2.690 0.007388 ** 
## dis         -1.071326   0.184055  -5.821 1.05e-08 ***
## lstat       -0.575164   0.051430 -11.184  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 5.186 on 496 degrees of freedom
## Multiple R-squared:  0.6878, Adjusted R-squared:  0.6821 
## F-statistic: 121.4 on 9 and 496 DF,  p-value: < 2.2e-16
## Model 2: Linear model (logarithmic)
modelo2 <- lm(log(medv) ~ indus + nox + rad + chas + tax + rm + crim + dis + lstat, data = bd)
summary(modelo2)
## 
## Call:
## lm(formula = log(medv) ~ indus + nox + rad + chas + tax + rm + 
##     crim + dis + lstat, data = bd)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.75215 -0.11530 -0.02392  0.11428  0.85862 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  3.2723333  0.1583533  20.665  < 2e-16 ***
## indus       -0.0019455  0.0026051  -0.747 0.455539    
## nox         -0.4302928  0.1504535  -2.860 0.004415 ** 
## rad          0.0079011  0.0027678   2.855 0.004489 ** 
## chas         0.1369810  0.0370258   3.700 0.000240 ***
## tax         -0.0005753  0.0001587  -3.626 0.000318 ***
## rm           0.1187548  0.0170823   6.952 1.14e-11 ***
## crim        -0.0100107  0.0014054  -7.123 3.73e-12 ***
## dis         -0.0386950  0.0072925  -5.306 1.69e-07 ***
## lstat       -0.0308904  0.0020377 -15.159  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.2055 on 496 degrees of freedom
## Multiple R-squared:  0.7519, Adjusted R-squared:  0.7474 
## F-statistic:   167 on 9 and 496 DF,  p-value: < 2.2e-16
## Model 3: polynomial – multiple linear regression
polymodel = lm(log(medv) ~ indus + nox + rad + chas + rm + I(rm^2) + dis + tax + crim + lstat, data=bd) 
summary(polymodel)
## 
## Call:
## lm(formula = log(medv) ~ indus + nox + rad + chas + rm + I(rm^2) + 
##     dis + tax + crim + lstat, data = bd)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.96456 -0.10702 -0.00925  0.09530  0.88754 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  6.8502983  0.4015860  17.058  < 2e-16 ***
## indus        0.0006635  0.0024114   0.275 0.783318    
## nox         -0.4980196  0.1385524  -3.594 0.000358 ***
## rad          0.0076340  0.0025457   2.999 0.002847 ** 
## chas         0.1183804  0.0341080   3.471 0.000564 ***
## rm          -1.0108149  0.1191905  -8.481 2.60e-16 ***
## I(rm^2)      0.0876424  0.0091672   9.560  < 2e-16 ***
## dis         -0.0300090  0.0067681  -4.434 1.14e-05 ***
## tax         -0.0005642  0.0001459  -3.867 0.000125 ***
## crim        -0.0108652  0.0012956  -8.386 5.26e-16 ***
## lstat       -0.0313507  0.0018747 -16.723  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.189 on 495 degrees of freedom
## Multiple R-squared:  0.7905, Adjusted R-squared:  0.7863 
## F-statistic: 186.8 on 10 and 495 DF,  p-value: < 2.2e-16

Lasso regression model

# Lasso regression model
## Creation of data samples for train & test 
set.seed(123)                                
training.samples<-bd$medv %>%
  createDataPartition(p=0.75,list=FALSE)       

train.data<-bd[training.samples, ]   
test.data<-bd[-training.samples, ]

selected_model = lm(log(medv) ~ indus + nox + rad + chas + rm + I(rm^2) + dis + tax + crim + lstat, data=bd) 
summary(selected_model)
## 
## Call:
## lm(formula = log(medv) ~ indus + nox + rad + chas + rm + I(rm^2) + 
##     dis + tax + crim + lstat, data = bd)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.96456 -0.10702 -0.00925  0.09530  0.88754 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  6.8502983  0.4015860  17.058  < 2e-16 ***
## indus        0.0006635  0.0024114   0.275 0.783318    
## nox         -0.4980196  0.1385524  -3.594 0.000358 ***
## rad          0.0076340  0.0025457   2.999 0.002847 ** 
## chas         0.1183804  0.0341080   3.471 0.000564 ***
## rm          -1.0108149  0.1191905  -8.481 2.60e-16 ***
## I(rm^2)      0.0876424  0.0091672   9.560  < 2e-16 ***
## dis         -0.0300090  0.0067681  -4.434 1.14e-05 ***
## tax         -0.0005642  0.0001459  -3.867 0.000125 ***
## crim        -0.0108652  0.0012956  -8.386 5.26e-16 ***
## lstat       -0.0313507  0.0018747 -16.723  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.189 on 495 degrees of freedom
## Multiple R-squared:  0.7905, Adjusted R-squared:  0.7863 
## F-statistic: 186.8 on 10 and 495 DF,  p-value: < 2.2e-16
RMSE(selected_model$fitted.values,test.data$medv)
## Warning in pred - obs: longitud de objeto mayor no es múltiplo de la longitud
## de uno menor
## [1] 23.18747
# Creation of the lasso model
x = model.matrix(log(medv) ~ indus + nox + rad + chas + rm + I(rm^2) + dis + tax + crim + lstat, train.data)[,-1]
y = train.data$medv

set.seed(123) 
cv.lasso<-cv.glmnet(x,y,alpha=1)

cv.lasso$lambda.min 
## [1] 0.002175466
lassomodel<-glmnet(x,y,alpha=1,lambda=cv.lasso$lambda.min)

coef(lassomodel)
## 11 x 1 sparse Matrix of class "dgCMatrix"
##                       s0
## (Intercept) 113.02252202
## indus        -0.02689376
## nox         -11.19359043
## rad           0.07845893
## chas          1.55776739
## rm          -27.20726443
## I(rm^2)       2.47732516
## dis          -0.63931869
## tax          -0.01046509
## crim         -0.10082665
## lstat        -0.49493861
x.test<-model.matrix(log(medv) ~ indus + nox + rad + chas + rm + I(rm^2) + dis + tax + crim + lstat,test.data)[,-1]

lassopredictions <- lassomodel %>% predict(x.test) %>% as.vector()

data.frame(
  RMSE = RMSE(lassopredictions, test.data$medv),
  Rsquare = R2(lassopredictions, test.data$medv))
##       RMSE   Rsquare
## 1 6.190498 0.7101066
# Lasso model graph
lbs_fun <- function(fit, offset_x=1, ...) {
  L <- length(fit$lambda)
  x <- log(fit$lambda[L])+ offset_x
  y <- fit$beta[, L]
  labs <- names(y)
  text(x, y, labels=labs, ...)
}

lasso<-glmnet(scale(x),y,alpha=1)

plot(lasso,xvar="lambda",label=T)
lbs_fun(lasso)
abline(v=cv.lasso$lambda.min,col="red",lty=2)
abline(v=cv.lasso$lambda.1se,col="blue",lty=2)

Model accuracy

# Show the level of accuracy for each linear regression model
# Model 1 - level of accuracy
AIC(modelol)
## [1] 3113.49
# Model 2 - level of accuracy
AIC(modelo2)
## [1] -153.6378
# Model 3 - level of accuracy
AIC(polymodel)
## [1] -237.3781

Diagnostic tests

# Model 1:
## multicollinearity
vif(modelol)
##    indus      nox      rad     chas      tax       rm     crim      dis 
## 3.821185 3.636213 6.948218 1.058039 8.554215 1.723358 1.748175 2.820945 
##    lstat 
## 2.533120
## heteroscedasticity
bptest(modelol)
## 
##  studentized Breusch-Pagan test
## 
## data:  modelol
## BP = 51.207, df = 9, p-value = 6.382e-08
## normality of residuals
histogram(modelol$residuals)

# Model 2:
## multicollinearity
vif(modelo2)
##    indus      nox      rad     chas      tax       rm     crim      dis 
## 3.821185 3.636213 6.948218 1.058039 8.554215 1.723358 1.748175 2.820945 
##    lstat 
## 2.533120
## heteroscedasticity
bptest(modelo2)
## 
##  studentized Breusch-Pagan test
## 
## data:  modelo2
## BP = 58.896, df = 9, p-value = 2.187e-09
## normality of residuals
histogram(modelo2$residuals)

# Model 3:
## multicollinearity
vif(polymodel)
##     indus       nox       rad      chas        rm   I(rm^2)       dis       tax 
##  3.870759  3.645744  6.949055  1.061493 99.192665 97.984932  2.872709  8.554751 
##      crim     lstat 
##  1.756534  2.534792
## heteroscedasticity
bptest(polymodel)
## 
##  studentized Breusch-Pagan test
## 
## data:  polymodel
## BP = 60.406, df = 10, p-value = 3.036e-09
## normality of residuals
histogram(polymodel$residuals)

Solving diagnostic tests problems

# multicollinearity
## Eliminate variable that cause multicollinearity on the model 3 and estimate again
## Model 3: polynomial – multiple linear regression
polymodel = lm(log(medv) ~ indus + nox + rad + chas + I(rm^2) + dis + tax + crim + lstat, data=bd) 
summary(polymodel)
## 
## Call:
## lm(formula = log(medv) ~ indus + nox + rad + chas + I(rm^2) + 
##     dis + tax + crim + lstat, data = bd)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.73893 -0.11458 -0.01841  0.10837  0.84763 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  3.5732309  0.1168883  30.570  < 2e-16 ***
## indus       -0.0012317  0.0025670  -0.480 0.631561    
## nox         -0.4419377  0.1479584  -2.987 0.002958 ** 
## rad          0.0075824  0.0027216   2.786 0.005540 ** 
## chas         0.1324163  0.0364221   3.636 0.000306 ***
## I(rm^2)      0.0105767  0.0012918   8.187 2.27e-15 ***
## dis         -0.0365508  0.0071887  -5.084 5.23e-07 ***
## tax         -0.0005672  0.0001560  -3.636 0.000306 ***
## crim        -0.0101261  0.0013820  -7.327 9.60e-13 ***
## lstat       -0.0298361  0.0019951 -14.955  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.202 on 496 degrees of freedom
## Multiple R-squared:  0.7601, Adjusted R-squared:  0.7557 
## F-statistic: 174.6 on 9 and 496 DF,  p-value: < 2.2e-16
AIC(polymodel)
## [1] -170.7324

Models comparison

# Model comparison
stargazer(modelol,modelo2,polymodel,type="text",title="OLS Regression Results",single.row=TRUE,ci=FALSE,ci.level=0.9)
## 
## OLS Regression Results
## ======================================================================================
##                                                  Dependent variable:                  
##                                -------------------------------------------------------
##                                      medv                      log(medv)              
##                                       (1)               (2)                (3)        
## --------------------------------------------------------------------------------------
## indus                           -0.102 (0.066)     -0.002 (0.003)     -0.001 (0.003)  
## nox                            -9.129** (3.797)  -0.430*** (0.150)  -0.442*** (0.148) 
## rad                             0.136* (0.070)    0.008*** (0.003)   0.008*** (0.003) 
## chas                           3.603*** (0.934)   0.137*** (0.037)   0.132*** (0.036) 
## I(rm2)                                                               0.011*** (0.001) 
## tax                            -0.010** (0.004)  -0.001*** (0.0002) -0.001*** (0.0002)
## rm                             4.603*** (0.431)   0.119*** (0.017)                    
## crim                           -0.095*** (0.035) -0.010*** (0.001)  -0.010*** (0.001) 
## dis                            -1.071*** (0.184) -0.039*** (0.007)  -0.037*** (0.007) 
## lstat                          -0.575*** (0.051) -0.031*** (0.002)  -0.030*** (0.002) 
## Constant                       14.037*** (3.997)  3.272*** (0.158)   3.573*** (0.117) 
## --------------------------------------------------------------------------------------
## Observations                          506               506                506        
## R2                                   0.688             0.752              0.760       
## Adjusted R2                          0.682             0.747              0.756       
## Residual Std. Error (df = 496)       5.186             0.205              0.202       
## F Statistic (df = 9; 496)         121.396***         166.981***         174.612***    
## ======================================================================================
## Note:                                                      *p<0.1; **p<0.05; ***p<0.01

Selection of the model that better fits data

According to the previous analysis ,made on assignment 1, we can see that model 3 has the highest R^2 and also has the least AIC (the AIC is more important than the R^2). The purpose of assignment 2 is to prove through diagnostic tests the presence of multicollinearity. As we know multicollinearity is when two or more independent variables in the model are highly correlated. The presence of multicollinearity can cause difficulties in estimating the individual effects of the correlated variables on the dependent variable. Diagnostic tests in regression analysis can detect and correct if there is the presence of multicollinearity. With the Variance Inflation Factor is when we can see if there is multicollinearity, if VIF > 10 (or sometimes 5), then multicollinearity is high. The VIF

Model 3 continues being the most accurate model, with the diagnostic tests we can see that in this model, R decreased and the AIC is in the correct range to be considered good.

Results interpretation

  • In model 3 we previously transformed the dependent variable to a natural logarithm (log(medv)).

With the diagnostic tests we see that: (same results of A1)

  • all the variables used for the estimation of the model turned out to be significant with up to 99% confidence, except the variable “indus” (this continues to be true with the diagnostic test)

  • The rooms (rm) variable is the one that has a greater percentage impact on the model and on the value of the houses. This impact is negative, which would mean that the greater the number of rooms, the value of the same decreases.

  • The impact of the rooms (rm) variable is not linear, since its square is also significant in the model and in this case it points to a positive impact, contrary to that shown in the variable before being transformed. this phenomenon could be visualized from the exploration of the data in graph 4.

  • variables that had a significant negative impact:

    • nox, nitric oxides concentration (parts per 10 million)
    • rm, average number of rooms per dwelling
    • dis, weighted distances to five Boston employment centers
    • tax, ull-value property-tax rate per USD 10,000
    • crim, per capita crime rate by town
    • lstat, percentage of lower status of the population
  • variables that had a significant positive impact:

    • rad, index of accessibility to radial highways
    • chas, neighborhood bounds river
    • rm2, variable rm transformed

With the diagnostic tests we confirm that model 3 is the most appropriate for the given real estate database, considering the VIF between the variables.

The existence of heterosedasticity was found in the 3 models, this problem may be caused by the naturalness of the data, the database does not include areas or regions of the United States as a variable, which affected the data and it was not possible to perform a data segregation.

Results discussion

Diagnostics test plays an important role on modern tasks, by helping identify and improve the accuracy of the linear regression results and predictive analytics. By examining trends and correlation between the variables to determine the cause and get to know the story of what happened. According to consultancy firm Gartner, “predictive analytics is a form of advanced analytics that examines data or content to answer the question: what is likely to happen in the future?”, in other words it uses all the data collected to create a possible outcome or prediction about an assumption. In the same way, the diagnostic analysis helps us to extract value from the data according to the investigation and respond to the relationship of the variables, with this we are concerned with a deeper vision, which allows decision making to be with greater certainty.

Regression diagnostics. (s/f). Bumc.bu.edu. Recuperado el 22 de agosto de 2023, de https://sphweb.bumc.bu.edu/otlt/MPH-Modules/BS/R/R5_Correlation-Regression/R5_Correlation-Regression7.html

Corporativa, I. (2021, abril 22). Predictive analytics. Iberdrola. https://www.iberdrola.com/innovation/predictive-analytics

LS0tDQp0aXRsZTogIkFzc2lnbWVudDIiDQphdXRob3I6ICJKb3PDqSBBcnR1cm8gU2lsdmEgRmxvcmVzIEEwMTE5ODA0OSwgTWFyaWFuYSBMZWFsIExvcGV6IEEwMTU3MDk3NywgU2ViYXN0aWFuIEVzcGlub3phIEEwMDgzMzcwNCINCmRhdGU6ICIyMDIzLTA4LTIzIg0Kb3V0cHV0OiANCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IFRSVUUNCiAgICB0b2NfZmxvYXQ6IFRSVUUNCiAgICBjb2RlX2Rvd25sb2FkOiBUUlVFDQotLS0NCg0KYGBge3J9DQojIEltcG9ydCBCRA0KYmQ8LSByZWFkLmNzdigiQzpcXFVzZXJzXFxTaWx2YVxcRG93bmxvYWRzXFxyZWFsX2VzdGF0ZV9kYXRhLmNzdiIpDQpgYGANCg0KIyMgTGlicmFyaWVzDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KI0luc3RhbGxpbmcgbGlicmFyaWVzDQojbGlicmFyeShweXNjaCkNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShjb3JycGxvdCkNCmxpYnJhcnkoZ21vZGVscykNCmxpYnJhcnkoZWZmZWN0cykNCmxpYnJhcnkoc3RhcmdhemVyKQ0KbGlicmFyeShvbHNycikgICAgICAgIA0KbGlicmFyeShrYWJsZUV4dHJhKQ0KbGlicmFyeShqdG9vbHMpDQpsaWJyYXJ5KGZhc3RtYXApDQpsaWJyYXJ5KGRsb29rcikNCmxpYnJhcnkoSG1pc2MpDQpsaWJyYXJ5KG5hbmlhcikNCmxpYnJhcnkoZ2xtbmV0KQ0KbGlicmFyeShjYXJldCkNCmxpYnJhcnkoY2FyKQ0KbGlicmFyeShsbXRlc3QpDQpgYGANCg0KIyMgUmVncmVzc2lvbiBBbmFseXNpcw0KRXN0aW1hdGUgMyBkaWZmZXJlbnQgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWxzICANCg0KIyMjIE1vZGVscw0KYGBge3J9DQojIyBNb2RlbCAxOiBNdWx0aXBsZSBsaW5lYXIgcmVncmVzc2lvbg0KbW9kZWxvbCA8LSBsbShtZWR2IH4gaW5kdXMgKyBub3ggKyByYWQgKyBjaGFzICsgdGF4ICsgcm0gKyBjcmltICsgZGlzICsgbHN0YXQsIGRhdGEgPSBiZCkNCnN1bW1hcnkobW9kZWxvbCkNCiMjIE1vZGVsIDI6IExpbmVhciBtb2RlbCAobG9nYXJpdGhtaWMpDQptb2RlbG8yIDwtIGxtKGxvZyhtZWR2KSB+IGluZHVzICsgbm94ICsgcmFkICsgY2hhcyArIHRheCArIHJtICsgY3JpbSArIGRpcyArIGxzdGF0LCBkYXRhID0gYmQpDQpzdW1tYXJ5KG1vZGVsbzIpDQojIyBNb2RlbCAzOiBwb2x5bm9taWFsIOKAkyBtdWx0aXBsZSBsaW5lYXIgcmVncmVzc2lvbg0KcG9seW1vZGVsID0gbG0obG9nKG1lZHYpIH4gaW5kdXMgKyBub3ggKyByYWQgKyBjaGFzICsgcm0gKyBJKHJtXjIpICsgZGlzICsgdGF4ICsgY3JpbSArIGxzdGF0LCBkYXRhPWJkKSANCnN1bW1hcnkocG9seW1vZGVsKQ0KYGBgDQoNCiMjIyBMYXNzbyByZWdyZXNzaW9uIG1vZGVsDQpgYGB7cn0NCiMgTGFzc28gcmVncmVzc2lvbiBtb2RlbA0KIyMgQ3JlYXRpb24gb2YgZGF0YSBzYW1wbGVzIGZvciB0cmFpbiAmIHRlc3QgDQpzZXQuc2VlZCgxMjMpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCnRyYWluaW5nLnNhbXBsZXM8LWJkJG1lZHYgJT4lDQogIGNyZWF0ZURhdGFQYXJ0aXRpb24ocD0wLjc1LGxpc3Q9RkFMU0UpICAgICAgIA0KDQp0cmFpbi5kYXRhPC1iZFt0cmFpbmluZy5zYW1wbGVzLCBdICAgDQp0ZXN0LmRhdGE8LWJkWy10cmFpbmluZy5zYW1wbGVzLCBdDQoNCnNlbGVjdGVkX21vZGVsID0gbG0obG9nKG1lZHYpIH4gaW5kdXMgKyBub3ggKyByYWQgKyBjaGFzICsgcm0gKyBJKHJtXjIpICsgZGlzICsgdGF4ICsgY3JpbSArIGxzdGF0LCBkYXRhPWJkKSANCnN1bW1hcnkoc2VsZWN0ZWRfbW9kZWwpDQpSTVNFKHNlbGVjdGVkX21vZGVsJGZpdHRlZC52YWx1ZXMsdGVzdC5kYXRhJG1lZHYpDQpgYGANCg0KYGBge3J9DQojIENyZWF0aW9uIG9mIHRoZSBsYXNzbyBtb2RlbA0KeCA9IG1vZGVsLm1hdHJpeChsb2cobWVkdikgfiBpbmR1cyArIG5veCArIHJhZCArIGNoYXMgKyBybSArIEkocm1eMikgKyBkaXMgKyB0YXggKyBjcmltICsgbHN0YXQsIHRyYWluLmRhdGEpWywtMV0NCnkgPSB0cmFpbi5kYXRhJG1lZHYNCg0Kc2V0LnNlZWQoMTIzKSANCmN2Lmxhc3NvPC1jdi5nbG1uZXQoeCx5LGFscGhhPTEpDQoNCmN2Lmxhc3NvJGxhbWJkYS5taW4gDQoNCmxhc3NvbW9kZWw8LWdsbW5ldCh4LHksYWxwaGE9MSxsYW1iZGE9Y3YubGFzc28kbGFtYmRhLm1pbikNCg0KY29lZihsYXNzb21vZGVsKQ0KDQp4LnRlc3Q8LW1vZGVsLm1hdHJpeChsb2cobWVkdikgfiBpbmR1cyArIG5veCArIHJhZCArIGNoYXMgKyBybSArIEkocm1eMikgKyBkaXMgKyB0YXggKyBjcmltICsgbHN0YXQsdGVzdC5kYXRhKVssLTFdDQoNCmxhc3NvcHJlZGljdGlvbnMgPC0gbGFzc29tb2RlbCAlPiUgcHJlZGljdCh4LnRlc3QpICU+JSBhcy52ZWN0b3IoKQ0KDQpkYXRhLmZyYW1lKA0KICBSTVNFID0gUk1TRShsYXNzb3ByZWRpY3Rpb25zLCB0ZXN0LmRhdGEkbWVkdiksDQogIFJzcXVhcmUgPSBSMihsYXNzb3ByZWRpY3Rpb25zLCB0ZXN0LmRhdGEkbWVkdikpDQpgYGANCg0KYGBge3J9DQojIExhc3NvIG1vZGVsIGdyYXBoDQpsYnNfZnVuIDwtIGZ1bmN0aW9uKGZpdCwgb2Zmc2V0X3g9MSwgLi4uKSB7DQogIEwgPC0gbGVuZ3RoKGZpdCRsYW1iZGEpDQogIHggPC0gbG9nKGZpdCRsYW1iZGFbTF0pKyBvZmZzZXRfeA0KICB5IDwtIGZpdCRiZXRhWywgTF0NCiAgbGFicyA8LSBuYW1lcyh5KQ0KICB0ZXh0KHgsIHksIGxhYmVscz1sYWJzLCAuLi4pDQp9DQoNCmxhc3NvPC1nbG1uZXQoc2NhbGUoeCkseSxhbHBoYT0xKQ0KDQpwbG90KGxhc3NvLHh2YXI9ImxhbWJkYSIsbGFiZWw9VCkNCmxic19mdW4obGFzc28pDQphYmxpbmUodj1jdi5sYXNzbyRsYW1iZGEubWluLGNvbD0icmVkIixsdHk9MikNCmFibGluZSh2PWN2Lmxhc3NvJGxhbWJkYS4xc2UsY29sPSJibHVlIixsdHk9MikNCmBgYA0KDQojIyMgTW9kZWwgYWNjdXJhY3kNCmBgYHtyfQ0KIyBTaG93IHRoZSBsZXZlbCBvZiBhY2N1cmFjeSBmb3IgZWFjaCBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbA0KIyBNb2RlbCAxIC0gbGV2ZWwgb2YgYWNjdXJhY3kNCkFJQyhtb2RlbG9sKQ0KDQojIE1vZGVsIDIgLSBsZXZlbCBvZiBhY2N1cmFjeQ0KQUlDKG1vZGVsbzIpDQoNCiMgTW9kZWwgMyAtIGxldmVsIG9mIGFjY3VyYWN5DQpBSUMocG9seW1vZGVsKQ0KYGBgDQoNCiMjIyBEaWFnbm9zdGljIHRlc3RzDQpgYGB7cn0NCiMgTW9kZWwgMToNCiMjIG11bHRpY29sbGluZWFyaXR5DQp2aWYobW9kZWxvbCkNCiMjIGhldGVyb3NjZWRhc3RpY2l0eQ0KYnB0ZXN0KG1vZGVsb2wpDQojIyBub3JtYWxpdHkgb2YgcmVzaWR1YWxzDQpoaXN0b2dyYW0obW9kZWxvbCRyZXNpZHVhbHMpDQoNCiMgTW9kZWwgMjoNCiMjIG11bHRpY29sbGluZWFyaXR5DQp2aWYobW9kZWxvMikNCiMjIGhldGVyb3NjZWRhc3RpY2l0eQ0KYnB0ZXN0KG1vZGVsbzIpDQojIyBub3JtYWxpdHkgb2YgcmVzaWR1YWxzDQpoaXN0b2dyYW0obW9kZWxvMiRyZXNpZHVhbHMpDQoNCiMgTW9kZWwgMzoNCiMjIG11bHRpY29sbGluZWFyaXR5DQp2aWYocG9seW1vZGVsKQ0KIyMgaGV0ZXJvc2NlZGFzdGljaXR5DQpicHRlc3QocG9seW1vZGVsKQ0KIyMgbm9ybWFsaXR5IG9mIHJlc2lkdWFscw0KaGlzdG9ncmFtKHBvbHltb2RlbCRyZXNpZHVhbHMpDQpgYGANCg0KIyMjIFNvbHZpbmcgZGlhZ25vc3RpYyB0ZXN0cyBwcm9ibGVtcw0KYGBge3J9DQojIG11bHRpY29sbGluZWFyaXR5DQojIyBFbGltaW5hdGUgdmFyaWFibGUgdGhhdCBjYXVzZSBtdWx0aWNvbGxpbmVhcml0eSBvbiB0aGUgbW9kZWwgMyBhbmQgZXN0aW1hdGUgYWdhaW4NCiMjIE1vZGVsIDM6IHBvbHlub21pYWwg4oCTIG11bHRpcGxlIGxpbmVhciByZWdyZXNzaW9uDQpwb2x5bW9kZWwgPSBsbShsb2cobWVkdikgfiBpbmR1cyArIG5veCArIHJhZCArIGNoYXMgKyBJKHJtXjIpICsgZGlzICsgdGF4ICsgY3JpbSArIGxzdGF0LCBkYXRhPWJkKSANCnN1bW1hcnkocG9seW1vZGVsKQ0KQUlDKHBvbHltb2RlbCkNCmBgYA0KDQojIyMgTW9kZWxzIGNvbXBhcmlzb24gDQpgYGB7cn0NCiMgTW9kZWwgY29tcGFyaXNvbg0Kc3RhcmdhemVyKG1vZGVsb2wsbW9kZWxvMixwb2x5bW9kZWwsdHlwZT0idGV4dCIsdGl0bGU9Ik9MUyBSZWdyZXNzaW9uIFJlc3VsdHMiLHNpbmdsZS5yb3c9VFJVRSxjaT1GQUxTRSxjaS5sZXZlbD0wLjkpDQpgYGANCg0KIyMjIFNlbGVjdGlvbiBvZiB0aGUgbW9kZWwgdGhhdCBiZXR0ZXIgZml0cyBkYXRhDQoNCkFjY29yZGluZyB0byB0aGUgcHJldmlvdXMgYW5hbHlzaXMgLG1hZGUgb24gYXNzaWdubWVudCAxLCB3ZSBjYW4gc2VlIHRoYXQgbW9kZWwgMyBoYXMgdGhlIGhpZ2hlc3QgUl4yIGFuZCBhbHNvIGhhcyB0aGUgbGVhc3QgQUlDICh0aGUgQUlDIGlzIG1vcmUgaW1wb3J0YW50IHRoYW4gdGhlIFJeMikuIFRoZSBwdXJwb3NlIG9mIGFzc2lnbm1lbnQgMiBpcyB0byBwcm92ZSB0aHJvdWdoIGRpYWdub3N0aWMgdGVzdHMgdGhlIHByZXNlbmNlIG9mIG11bHRpY29sbGluZWFyaXR5LiBBcyB3ZSBrbm93IG11bHRpY29sbGluZWFyaXR5IGlzIHdoZW4gdHdvIG9yIG1vcmUgaW5kZXBlbmRlbnQgdmFyaWFibGVzIGluIHRoZSBtb2RlbCBhcmUgaGlnaGx5IGNvcnJlbGF0ZWQuIFRoZSBwcmVzZW5jZSBvZiBtdWx0aWNvbGxpbmVhcml0eSBjYW4gY2F1c2UgZGlmZmljdWx0aWVzIGluIGVzdGltYXRpbmcgdGhlIGluZGl2aWR1YWwgZWZmZWN0cyBvZiB0aGUgY29ycmVsYXRlZCB2YXJpYWJsZXMgb24gdGhlIGRlcGVuZGVudCB2YXJpYWJsZS4gRGlhZ25vc3RpYyB0ZXN0cyBpbiByZWdyZXNzaW9uIGFuYWx5c2lzIGNhbiBkZXRlY3QgYW5kIGNvcnJlY3QgaWYgdGhlcmUgaXMgdGhlIHByZXNlbmNlIG9mICBtdWx0aWNvbGxpbmVhcml0eS4gV2l0aCB0aGUgVmFyaWFuY2UgSW5mbGF0aW9uIEZhY3RvciBpcyB3aGVuIHdlIGNhbiBzZWUgaWYgdGhlcmUgaXMgbXVsdGljb2xsaW5lYXJpdHksIGlmIFZJRiA+IDEwIChvciBzb21ldGltZXMgNSksIHRoZW4gbXVsdGljb2xsaW5lYXJpdHkgaXMgaGlnaC4gVGhlIFZJRiANCg0KTW9kZWwgMyBjb250aW51ZXMgYmVpbmcgdGhlIG1vc3QgYWNjdXJhdGUgbW9kZWwsIHdpdGggdGhlIGRpYWdub3N0aWMgdGVzdHMgd2UgY2FuIHNlZSB0aGF0IGluIHRoaXMgbW9kZWwsIFIgZGVjcmVhc2VkIGFuZCB0aGUgQUlDIGlzIGluIHRoZSBjb3JyZWN0IHJhbmdlIHRvIGJlIGNvbnNpZGVyZWQgZ29vZC4gIA0KDQojIyBSZXN1bHRzIGludGVycHJldGF0aW9uDQoNCi0gSW4gbW9kZWwgMyB3ZSBwcmV2aW91c2x5IHRyYW5zZm9ybWVkIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgdG8gYSBuYXR1cmFsIGxvZ2FyaXRobSAobG9nKG1lZHYpKS4NCg0KV2l0aCB0aGUgZGlhZ25vc3RpYyB0ZXN0cyB3ZSBzZWUgdGhhdDogKHNhbWUgcmVzdWx0cyBvZiBBMSkgIA0KDQotIGFsbCB0aGUgdmFyaWFibGVzIHVzZWQgZm9yIHRoZSBlc3RpbWF0aW9uIG9mIHRoZSBtb2RlbCB0dXJuZWQgb3V0IHRvIGJlIHNpZ25pZmljYW50IHdpdGggdXAgdG8gOTklIGNvbmZpZGVuY2UsIGV4Y2VwdCB0aGUgdmFyaWFibGUg4oCcaW5kdXPigJ0gKHRoaXMgY29udGludWVzIHRvIGJlIHRydWUgd2l0aCB0aGUgZGlhZ25vc3RpYyB0ZXN0KSAgDQoNCi0gVGhlIHJvb21zIChybSkgdmFyaWFibGUgaXMgdGhlIG9uZSB0aGF0IGhhcyBhIGdyZWF0ZXIgcGVyY2VudGFnZSBpbXBhY3Qgb24gdGhlIG1vZGVsIGFuZCBvbiB0aGUgdmFsdWUgb2YgdGhlIGhvdXNlcy4gVGhpcyBpbXBhY3QgaXMgbmVnYXRpdmUsIHdoaWNoIHdvdWxkIG1lYW4gdGhhdCB0aGUgZ3JlYXRlciB0aGUgbnVtYmVyIG9mIHJvb21zLCB0aGUgdmFsdWUgb2YgdGhlIHNhbWUgZGVjcmVhc2VzLiAgICANCg0KLSBUaGUgaW1wYWN0IG9mIHRoZSByb29tcyAocm0pIHZhcmlhYmxlIGlzIG5vdCBsaW5lYXIsIHNpbmNlIGl0cyBzcXVhcmUgaXMgYWxzbyBzaWduaWZpY2FudCBpbiB0aGUgbW9kZWwgYW5kIGluIHRoaXMgY2FzZSBpdCBwb2ludHMgdG8gYSBwb3NpdGl2ZSBpbXBhY3QsIGNvbnRyYXJ5IHRvIHRoYXQgc2hvd24gaW4gdGhlIHZhcmlhYmxlIGJlZm9yZSBiZWluZyB0cmFuc2Zvcm1lZC4gdGhpcyBwaGVub21lbm9uIGNvdWxkIGJlIHZpc3VhbGl6ZWQgZnJvbSB0aGUgZXhwbG9yYXRpb24gb2YgdGhlIGRhdGEgaW4gZ3JhcGggNC4gIA0KDQotIHZhcmlhYmxlcyB0aGF0IGhhZCBhIHNpZ25pZmljYW50ICoqbmVnYXRpdmUqKiBpbXBhY3Q6DQogIC0gbm94LCBuaXRyaWMgb3hpZGVzIGNvbmNlbnRyYXRpb24gKHBhcnRzIHBlciAxMCBtaWxsaW9uKQ0KICAtIHJtLCBhdmVyYWdlIG51bWJlciBvZiByb29tcyBwZXIgZHdlbGxpbmcNCiAgLSBkaXMsIHdlaWdodGVkIGRpc3RhbmNlcyB0byBmaXZlIEJvc3RvbiBlbXBsb3ltZW50IGNlbnRlcnMNCiAgLSB0YXgsIHVsbC12YWx1ZSBwcm9wZXJ0eS10YXggcmF0ZSBwZXIgVVNEIDEwLDAwMA0KICAtIGNyaW0sIHBlciBjYXBpdGEgY3JpbWUgcmF0ZSBieSB0b3duDQogIC0gbHN0YXQsIHBlcmNlbnRhZ2Ugb2YgbG93ZXIgc3RhdHVzIG9mIHRoZSBwb3B1bGF0aW9uDQoNCi0gdmFyaWFibGVzIHRoYXQgaGFkIGEgc2lnbmlmaWNhbnQgKipwb3NpdGl2ZSoqIGltcGFjdDoNCiAgLSByYWQsIGluZGV4IG9mIGFjY2Vzc2liaWxpdHkgdG8gcmFkaWFsIGhpZ2h3YXlzDQogIC0gY2hhcywgbmVpZ2hib3Job29kIGJvdW5kcyByaXZlcg0KICAtIHJtXjJeLCB2YXJpYWJsZSBybSB0cmFuc2Zvcm1lZCAgDQoNCldpdGggdGhlIGRpYWdub3N0aWMgdGVzdHMgd2UgY29uZmlybSB0aGF0IG1vZGVsIDMgaXMgdGhlIG1vc3QgYXBwcm9wcmlhdGUgZm9yIHRoZSBnaXZlbiByZWFsIGVzdGF0ZSBkYXRhYmFzZSwgY29uc2lkZXJpbmcgdGhlIFZJRiBiZXR3ZWVuIHRoZSB2YXJpYWJsZXMuDQoNClRoZSBleGlzdGVuY2Ugb2YgaGV0ZXJvc2VkYXN0aWNpdHkgd2FzIGZvdW5kIGluIHRoZSAzIG1vZGVscywgdGhpcyBwcm9ibGVtIG1heSBiZSBjYXVzZWQgYnkgdGhlIG5hdHVyYWxuZXNzIG9mIHRoZSBkYXRhLCB0aGUgZGF0YWJhc2UgZG9lcyBub3QgaW5jbHVkZSBhcmVhcyBvciByZWdpb25zIG9mIHRoZSBVbml0ZWQgU3RhdGVzIGFzIGEgdmFyaWFibGUsIHdoaWNoIGFmZmVjdGVkIHRoZSBkYXRhIGFuZCBpdCB3YXMgbm90IHBvc3NpYmxlIHRvIHBlcmZvcm0gYSBkYXRhIHNlZ3JlZ2F0aW9uLg0KDQojIyBSZXN1bHRzIGRpc2N1c3Npb24gIA0KDQpEaWFnbm9zdGljcyB0ZXN0IHBsYXlzIGFuIGltcG9ydGFudCByb2xlIG9uIG1vZGVybiB0YXNrcywgYnkgaGVscGluZyBpZGVudGlmeSBhbmQgaW1wcm92ZSB0aGUgYWNjdXJhY3kgb2YgdGhlIGxpbmVhciByZWdyZXNzaW9uIHJlc3VsdHMgYW5kIHByZWRpY3RpdmUgYW5hbHl0aWNzLiBCeSBleGFtaW5pbmcgdHJlbmRzIGFuZCBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSB2YXJpYWJsZXMgdG8gZGV0ZXJtaW5lIHRoZSBjYXVzZSBhbmQgZ2V0IHRvIGtub3cgdGhlIHN0b3J5IG9mIHdoYXQgaGFwcGVuZWQuIEFjY29yZGluZyB0byBjb25zdWx0YW5jeSBmaXJtIEdhcnRuZXIsIOKAnHByZWRpY3RpdmUgYW5hbHl0aWNzIGlzIGEgZm9ybSBvZiBhZHZhbmNlZCBhbmFseXRpY3MgdGhhdCBleGFtaW5lcyBkYXRhIG9yIGNvbnRlbnQgdG8gYW5zd2VyIHRoZSBxdWVzdGlvbjogd2hhdCBpcyBsaWtlbHkgdG8gaGFwcGVuIGluIHRoZSBmdXR1cmU/4oCdLCBpbiBvdGhlciB3b3JkcyBpdCB1c2VzIGFsbCB0aGUgZGF0YSBjb2xsZWN0ZWQgdG8gY3JlYXRlIGEgcG9zc2libGUgb3V0Y29tZSBvciBwcmVkaWN0aW9uIGFib3V0IGFuIGFzc3VtcHRpb24uIEluIHRoZSBzYW1lIHdheSwgdGhlIGRpYWdub3N0aWMgYW5hbHlzaXMgaGVscHMgdXMgdG8gZXh0cmFjdCB2YWx1ZSBmcm9tIHRoZSBkYXRhIGFjY29yZGluZyB0byB0aGUgaW52ZXN0aWdhdGlvbiBhbmQgcmVzcG9uZCB0byB0aGUgcmVsYXRpb25zaGlwIG9mIHRoZSB2YXJpYWJsZXMsIHdpdGggdGhpcyB3ZSBhcmUgY29uY2VybmVkIHdpdGggYSBkZWVwZXIgdmlzaW9uLCB3aGljaCBhbGxvd3MgZGVjaXNpb24gbWFraW5nIHRvIGJlIHdpdGggZ3JlYXRlciBjZXJ0YWludHkuICANCg0KUmVncmVzc2lvbiBkaWFnbm9zdGljcy4gKHMvZikuIEJ1bWMuYnUuZWR1LiBSZWN1cGVyYWRvIGVsIDIyIGRlIGFnb3N0byBkZSAyMDIzLCBkZSBodHRwczovL3NwaHdlYi5idW1jLmJ1LmVkdS9vdGx0L01QSC1Nb2R1bGVzL0JTL1IvUjVfQ29ycmVsYXRpb24tUmVncmVzc2lvbi9SNV9Db3JyZWxhdGlvbi1SZWdyZXNzaW9uNy5odG1sICANCg0KQ29ycG9yYXRpdmEsIEkuICgyMDIxLCBhYnJpbCAyMikuIFByZWRpY3RpdmUgYW5hbHl0aWNzLiBJYmVyZHJvbGEuIGh0dHBzOi8vd3d3LmliZXJkcm9sYS5jb20vaW5ub3ZhdGlvbi9wcmVkaWN0aXZlLWFuYWx5dGljcyAgIA0K