getwd() launch <- read.csv(“challenger.csv”)
estimate beta manually
b <- cov(launch\(temperature,
launch\)distress_ct) / var(launch$temperature) b
estimate alpha manually
a <- mean(launch\(distress_ct) - b *
mean(launch\)temperature) a
r <- cov(launch\(temperature,
launch\)distress_ct) / (sd(launch\(temperature) * sd(launch\)distress_ct))
r
cor(launch\(temperature,
launch\)distress_ct)
computing the slope using correlation
r * (sd(launch\(distress_ct) /
sd(launch\)temperature))
confirming the regression line using the lm function (not in
text)
model <- lm(distress_ct ~ temperature, data = launch) model
Call:
lm(formula = distress_ct ~ temperature, data = launch)
Coefficients:
(Intercept) temperature
2.81458 -0.03365
summary(model)
creating a simple multiple regression function
reg <- function(y, x) { x <- as.matrix(x) x <-
cbind(Intercept = 1, x) b <- solve(t(x) %% x) %% t(x) %*% y
colnames(b) <- “estimate” print(b) }
examine the launch data
str(launch)
test regression model with simple linear regression
reg(y = launch$distress_ct, x = launch[2])
use regression model with multiple regression
reg(y = launch$distress_ct, x = launch[2:4])
confirming the multiple regression result using the lm function (not
in text)
model <- lm(distress_ct ~ temperature + field_check_pressure +
flight_num, data = launch) model
Call:
lm(formula = distress_ct ~ temperature + field_check_pressure +
flight_num, data = launch)
Coefficients:
(Intercept) temperature field_check_pressure
2.240e+00 -3.124e-02 -2.587e-05
flight_num
Step 2: Exploring and preparing the data —-
insurance <- read.csv(“insurance.csv”, stringsAsFactors = TRUE)
str(insurance)
summarize the charges variable
summary(insurance$expenses)
histogram of insurance charges
hist(insurance$expenses)
table of region
table(insurance$region)
exploring relationships among features: correlation matrix
cor(insurance[c(“age”, “bmi”, “children”, “expenses”)])
visualing relationships among features: scatterplot matrix
pairs(insurance[c(“age”, “bmi”, “children”, “expenses”)])
Step 3: Training a model on the data —-
ins_model <- lm(expenses ~ age + children + bmi + sex + smoker +
region, data = insurance) ins_model <- lm(expenses ~ ., data =
insurance) # this is equivalent to above
see the estimated beta coefficients
ins_model
see more detail about the estimated beta coefficients
summary(ins_model)
Call:
lm(formula = expenses ~ ., data = insurance)
Residuals:
Min 1Q Median 3Q Max
-11302.7 -2850.9 -979.6 1383.9 29981.7
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -11941.6 987.8 -12.089 < 2e-16 ***
age 256.8 11.9 21.586 < 2e-16 ***
sexmale -131.3 332.9 -0.395 0.693255
bmi 339.3 28.6 11.864 < 2e-16 ***
children 475.7 137.8 3.452 0.000574 ***
smokeryes 23847.5 413.1 57.723 < 2e-16 ***
regionnorthwest -352.8 476.3 -0.741 0.458976
regionsoutheast -1035.6 478.7 -2.163 0.030685 *
regionsouthwest -959.3 477.9 -2.007 0.044921 *
—
Signif. codes: 0 ‘’ 0.001 ’’ 0.01 ’’ 0.05
‘.’ 0.1 ’ ’ 1
Residual standard error: 6062 on 1329 degrees of freedom
Multiple R-squared: 0.7509, Adjusted R-squared: 0.7494
F-statistic: 500.9 on 8 and 1329 DF, p-value: < 2.2e-16
add a higher-order “age” term
insurance\(age2 <-
insurance\)age^2
add an indicator for BMI >= 30
insurance\(bmi30 <-
ifelse(insurance\)bmi >= 30, 1, 0)
create final model
ins_model2 <- lm(expenses ~ age + age2 + children + bmi + sex +
bmi30*smoker + region, data = insurance)
summary(ins_model2)
Call:
lm(formula = expenses ~ age + age2 + children + bmi + sex + bmi30
*
smoker + region, data = insurance)
Residuals:
Min 1Q Median 3Q Max
-17297.1 -1656.0 -1262.7 -727.8 24161.6
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 139.0053 1363.1359 0.102 0.918792
age -32.6181 59.8250 -0.545 0.585690
age2 3.7307 0.7463 4.999 6.54e-07 ***
children 678.6017 105.8855 6.409 2.03e-10 ***
bmi 119.7715 34.2796 3.494 0.000492 ***
sexmale -496.7690 244.3713 -2.033 0.042267 *
bmi30 -997.9355 422.9607 -2.359 0.018449 *
smokeryes 13404.5952 439.9591 30.468 < 2e-16 ***
regionnorthwest -279.1661 349.2826 -0.799 0.424285
regionsoutheast -828.0345 351.6484 -2.355 0.018682 *
regionsouthwest -1222.1619 350.5314 -3.487 0.000505 ***
bmi30:smokeryes 19810.1534 604.6769 32.762 < 2e-16 ***
—
Signif. codes: 0 ‘’ 0.001 ’’ 0.01 ’’ 0.05
‘.’ 0.1 ’ ’ 1
Residual standard error: 4445 on 1326 degrees of freedom
Multiple R-squared: 0.8664, Adjusted R-squared: 0.8653
F-statistic: 781.7 on 11 and 1326 DF, p-value: < 2.2e-16
making predictions with the regression model
insurance\(pred <- predict(ins_model2,
insurance)
cor(insurance\)pred, insurance$expenses)
plot(insurance\(pred,
insurance\)expenses) abline(a = 0, b = 1, col = “red”, lwd = 3,
lty = 2)
predict(ins_model2, data.frame(age = 30, age2 = 30^2, children = 2,
bmi = 30, sex = “male”, bmi30 = 1, smoker = “no”, region = “northeast”))
predict(ins_model2, data.frame(age = 30, age2 = 30^2, children = 2, bmi
= 30, sex = “female”, bmi30 = 1, smoker = “no”, region =
“northeast”))
set up the data
tee <- c(1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 6, 7, 7, 7, 7) at1 <-
c(1, 1, 1, 2, 2, 3, 4, 5, 5) at2 <- c(6, 6, 7, 7, 7, 7) bt1 <-
c(1, 1, 1, 2, 2, 3, 4) bt2 <- c(5, 5, 6, 6, 7, 7, 7, 7)
compute the SDR
sdr_a <- sd(tee) - (length(at1) / length(tee) * sd(at1) +
length(at2) / length(tee) * sd(at2)) sdr_b <- sd(tee) - (length(bt1)
/ length(tee) * sd(bt1) + length(bt2) / length(tee) * sd(bt2))
compare the SDR for each split
sdr_a
sdr_b
wine <- read.csv(“whitewines.csv”)
examine the wine data
str(wine) # the distribution of quality ratings hist(wine$quality) #
summary statistics of the wine data summary(wine)
wine_train <- wine[1:3750, ] wine_test <- wine[3751:4898, ]
regression tree using rpart
library(rpart) m.rpart <- rpart(quality ~ ., data = wine_train) #
get basic information about the tree m.rpart # get more detailed
information about the tree summary(m.rpart)
install.packages(“rpart.plot”)
use the rpart.plot package to create a visualization
library(rpart.plot) # a basic decision tree diagram
rpart.plot(m.rpart, digits = 3) # a few adjustments to the diagram
rpart.plot(m.rpart, digits = 4, fallen.leaves = TRUE, type = 3, extra =
101)
generate predictions for the testing dataset
p.rpart <- predict(m.rpart, wine_test)
compare the distribution of predicted values vs. actual values
summary(p.rpart) summary(wine_test\(quality)
# compare the correlation
cor(p.rpart, wine_test\)quality)
function to calculate the mean absolute error
MAE <- function(actual, predicted) { mean(abs(actual -
predicted))
}
MAE(p.rpart, wine_test\(quality)
# mean absolute error between actual values and mean value
mean(wine_train\)quality) # result = 5.87
MAE(5.87, wine_test$quality)
install.packages(“plyr”) install.packages(“Cubist”) # train a Cubist
Model Tree library(Cubist) m.cubist <- cubist(x = wine_train[-12], y
= wine_train$quality) # display basic information about the model tree
m.cubist
display the tree itself
summary(m.cubist)
generate predictions for the model
p.cubist <- predict(m.cubist, wine_test)
summary statistics about the predictions
summary(p.cubist)
correlation between the predicted and true values
cor(p.cubist, wine_test$quality)
mean absolute error of predicted and true values
(uses a custom function defined above)
MAE(wine_test$quality, p.cubist)
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKZ2V0d2QoKQpsYXVuY2ggPC0gcmVhZC5jc3YoImNoYWxsZW5nZXIuY3N2IikKCiMgZXN0aW1hdGUgYmV0YSBtYW51YWxseQpiIDwtIGNvdihsYXVuY2gkdGVtcGVyYXR1cmUsIGxhdW5jaCRkaXN0cmVzc19jdCkgLyB2YXIobGF1bmNoJHRlbXBlcmF0dXJlKQpiCgojIGVzdGltYXRlIGFscGhhIG1hbnVhbGx5CmEgPC0gbWVhbihsYXVuY2gkZGlzdHJlc3NfY3QpIC0gYiAqIG1lYW4obGF1bmNoJHRlbXBlcmF0dXJlKQphCgpyIDwtIGNvdihsYXVuY2gkdGVtcGVyYXR1cmUsIGxhdW5jaCRkaXN0cmVzc19jdCkgLwogICAgICAgKHNkKGxhdW5jaCR0ZW1wZXJhdHVyZSkgKiBzZChsYXVuY2gkZGlzdHJlc3NfY3QpKQpyCgpjb3IobGF1bmNoJHRlbXBlcmF0dXJlLCBsYXVuY2gkZGlzdHJlc3NfY3QpCgojIGNvbXB1dGluZyB0aGUgc2xvcGUgdXNpbmcgY29ycmVsYXRpb24KciAqIChzZChsYXVuY2gkZGlzdHJlc3NfY3QpIC8gc2QobGF1bmNoJHRlbXBlcmF0dXJlKSkKCiMgY29uZmlybWluZyB0aGUgcmVncmVzc2lvbiBsaW5lIHVzaW5nIHRoZSBsbSBmdW5jdGlvbiAobm90IGluIHRleHQpCm1vZGVsIDwtIGxtKGRpc3RyZXNzX2N0IH4gdGVtcGVyYXR1cmUsIGRhdGEgPSBsYXVuY2gpCm1vZGVsCgojIyAKIyMgQ2FsbDoKIyMgbG0oZm9ybXVsYSA9IGRpc3RyZXNzX2N0IH4gdGVtcGVyYXR1cmUsIGRhdGEgPSBsYXVuY2gpCiMjIAojIyBDb2VmZmljaWVudHM6CiMjIChJbnRlcmNlcHQpICB0ZW1wZXJhdHVyZSAgCiMjICAgICAyLjgxNDU4ICAgICAtMC4wMzM2NQpzdW1tYXJ5KG1vZGVsKQoKCiMgY3JlYXRpbmcgYSBzaW1wbGUgbXVsdGlwbGUgcmVncmVzc2lvbiBmdW5jdGlvbgpyZWcgPC0gZnVuY3Rpb24oeSwgeCkgewogIHggPC0gYXMubWF0cml4KHgpCiAgeCA8LSBjYmluZChJbnRlcmNlcHQgPSAxLCB4KQogIGIgPC0gc29sdmUodCh4KSAlKiUgeCkgJSolIHQoeCkgJSolIHkKICBjb2xuYW1lcyhiKSA8LSAiZXN0aW1hdGUiCiAgcHJpbnQoYikKfQoKIyBleGFtaW5lIHRoZSBsYXVuY2ggZGF0YQpzdHIobGF1bmNoKQoKIyB0ZXN0IHJlZ3Jlc3Npb24gbW9kZWwgd2l0aCBzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24KcmVnKHkgPSBsYXVuY2gkZGlzdHJlc3NfY3QsIHggPSBsYXVuY2hbMl0pCgojIHVzZSByZWdyZXNzaW9uIG1vZGVsIHdpdGggbXVsdGlwbGUgcmVncmVzc2lvbgpyZWcoeSA9IGxhdW5jaCRkaXN0cmVzc19jdCwgeCA9IGxhdW5jaFsyOjRdKQoKIyBjb25maXJtaW5nIHRoZSBtdWx0aXBsZSByZWdyZXNzaW9uIHJlc3VsdCB1c2luZyB0aGUgbG0gZnVuY3Rpb24gKG5vdCBpbiB0ZXh0KQptb2RlbCA8LSBsbShkaXN0cmVzc19jdCB+IHRlbXBlcmF0dXJlICsgZmllbGRfY2hlY2tfcHJlc3N1cmUgKyBmbGlnaHRfbnVtLCBkYXRhID0gbGF1bmNoKQptb2RlbAoKIyMgCiMjIENhbGw6CiMjIGxtKGZvcm11bGEgPSBkaXN0cmVzc19jdCB+IHRlbXBlcmF0dXJlICsgZmllbGRfY2hlY2tfcHJlc3N1cmUgKyAKIyMgICAgIGZsaWdodF9udW0sIGRhdGEgPSBsYXVuY2gpCiMjIAojIyBDb2VmZmljaWVudHM6CiMjICAgICAgICAgIChJbnRlcmNlcHQpICAgICAgICAgICB0ZW1wZXJhdHVyZSAgZmllbGRfY2hlY2tfcHJlc3N1cmUgIAojIyAgICAgICAgICAgIDIuMjQwZSswMCAgICAgICAgICAgIC0zLjEyNGUtMDIgICAgICAgICAgICAtMi41ODdlLTA1ICAKIyMgICAgICAgICAgIGZsaWdodF9udW0gIAojIyAgICAgICAgICAgIDIuNzYyZS0wMgoKc3VtbWFyeShtb2RlbCkKCiMjIFN0ZXAgMjogRXhwbG9yaW5nIGFuZCBwcmVwYXJpbmcgdGhlIGRhdGEgLS0tLQppbnN1cmFuY2UgPC0gcmVhZC5jc3YoImluc3VyYW5jZS5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzID0gVFJVRSkKc3RyKGluc3VyYW5jZSkKCgojIHN1bW1hcml6ZSB0aGUgY2hhcmdlcyB2YXJpYWJsZQpzdW1tYXJ5KGluc3VyYW5jZSRleHBlbnNlcykKCiMgaGlzdG9ncmFtIG9mIGluc3VyYW5jZSBjaGFyZ2VzCmhpc3QoaW5zdXJhbmNlJGV4cGVuc2VzKQoKIyB0YWJsZSBvZiByZWdpb24KdGFibGUoaW5zdXJhbmNlJHJlZ2lvbikKCiMgZXhwbG9yaW5nIHJlbGF0aW9uc2hpcHMgYW1vbmcgZmVhdHVyZXM6IGNvcnJlbGF0aW9uIG1hdHJpeApjb3IoaW5zdXJhbmNlW2MoImFnZSIsICJibWkiLCAiY2hpbGRyZW4iLCAiZXhwZW5zZXMiKV0pCgojIHZpc3VhbGluZyByZWxhdGlvbnNoaXBzIGFtb25nIGZlYXR1cmVzOiBzY2F0dGVycGxvdCBtYXRyaXgKcGFpcnMoaW5zdXJhbmNlW2MoImFnZSIsICJibWkiLCAiY2hpbGRyZW4iLCAiZXhwZW5zZXMiKV0pCgojIyBTdGVwIDM6IFRyYWluaW5nIGEgbW9kZWwgb24gdGhlIGRhdGEgLS0tLQppbnNfbW9kZWwgPC0gbG0oZXhwZW5zZXMgfiBhZ2UgKyBjaGlsZHJlbiArIGJtaSArIHNleCArIHNtb2tlciArIHJlZ2lvbiwKICAgICAgICAgICAgICAgIGRhdGEgPSBpbnN1cmFuY2UpCmluc19tb2RlbCA8LSBsbShleHBlbnNlcyB+IC4sIGRhdGEgPSBpbnN1cmFuY2UpICMgdGhpcyBpcyBlcXVpdmFsZW50IHRvIGFib3ZlCgojIHNlZSB0aGUgZXN0aW1hdGVkIGJldGEgY29lZmZpY2llbnRzCmluc19tb2RlbAoKIyBzZWUgbW9yZSBkZXRhaWwgYWJvdXQgdGhlIGVzdGltYXRlZCBiZXRhIGNvZWZmaWNpZW50cwpzdW1tYXJ5KGluc19tb2RlbCkKCiMjIAojIyBDYWxsOgojIyBsbShmb3JtdWxhID0gZXhwZW5zZXMgfiAuLCBkYXRhID0gaW5zdXJhbmNlKQojIyAKIyMgUmVzaWR1YWxzOgojIyAgICAgIE1pbiAgICAgICAxUSAgIE1lZGlhbiAgICAgICAzUSAgICAgIE1heCAKIyMgLTExMzAyLjcgIC0yODUwLjkgICAtOTc5LjYgICAxMzgzLjkgIDI5OTgxLjcgCiMjIAojIyBDb2VmZmljaWVudHM6CiMjICAgICAgICAgICAgICAgICBFc3RpbWF0ZSBTdGQuIEVycm9yIHQgdmFsdWUgUHIoPnx0fCkgICAgCiMjIChJbnRlcmNlcHQpICAgICAtMTE5NDEuNiAgICAgIDk4Ny44IC0xMi4wODkgIDwgMmUtMTYgKioqCiMjIGFnZSAgICAgICAgICAgICAgICAyNTYuOCAgICAgICAxMS45ICAyMS41ODYgIDwgMmUtMTYgKioqCiMjIHNleG1hbGUgICAgICAgICAgIC0xMzEuMyAgICAgIDMzMi45ICAtMC4zOTUgMC42OTMyNTUgICAgCiMjIGJtaSAgICAgICAgICAgICAgICAzMzkuMyAgICAgICAyOC42ICAxMS44NjQgIDwgMmUtMTYgKioqCiMjIGNoaWxkcmVuICAgICAgICAgICA0NzUuNyAgICAgIDEzNy44ICAgMy40NTIgMC4wMDA1NzQgKioqCiMjIHNtb2tlcnllcyAgICAgICAgMjM4NDcuNSAgICAgIDQxMy4xICA1Ny43MjMgIDwgMmUtMTYgKioqCiMjIHJlZ2lvbm5vcnRod2VzdCAgIC0zNTIuOCAgICAgIDQ3Ni4zICAtMC43NDEgMC40NTg5NzYgICAgCiMjIHJlZ2lvbnNvdXRoZWFzdCAgLTEwMzUuNiAgICAgIDQ3OC43ICAtMi4xNjMgMC4wMzA2ODUgKiAgCiMjIHJlZ2lvbnNvdXRod2VzdCAgIC05NTkuMyAgICAgIDQ3Ny45ICAtMi4wMDcgMC4wNDQ5MjEgKiAgCiMjIC0tLQojIyBTaWduaWYuIGNvZGVzOiAgMCAnKioqJyAwLjAwMSAnKionIDAuMDEgJyonIDAuMDUgJy4nIDAuMSAnICcgMQojIyAKIyMgUmVzaWR1YWwgc3RhbmRhcmQgZXJyb3I6IDYwNjIgb24gMTMyOSBkZWdyZWVzIG9mIGZyZWVkb20KIyMgTXVsdGlwbGUgUi1zcXVhcmVkOiAgMC43NTA5LCBBZGp1c3RlZCBSLXNxdWFyZWQ6ICAwLjc0OTQgCiMjIEYtc3RhdGlzdGljOiA1MDAuOSBvbiA4IGFuZCAxMzI5IERGLCAgcC12YWx1ZTogPCAyLjJlLTE2CgojIGFkZCBhIGhpZ2hlci1vcmRlciAiYWdlIiB0ZXJtCmluc3VyYW5jZSRhZ2UyIDwtIGluc3VyYW5jZSRhZ2VeMgoKIyBhZGQgYW4gaW5kaWNhdG9yIGZvciBCTUkgPj0gMzAKaW5zdXJhbmNlJGJtaTMwIDwtIGlmZWxzZShpbnN1cmFuY2UkYm1pID49IDMwLCAxLCAwKQoKIyBjcmVhdGUgZmluYWwgbW9kZWwKaW5zX21vZGVsMiA8LSBsbShleHBlbnNlcyB+IGFnZSArIGFnZTIgKyBjaGlsZHJlbiArIGJtaSArIHNleCArCiAgICAgICAgICAgICAgICAgICBibWkzMCpzbW9rZXIgKyByZWdpb24sIGRhdGEgPSBpbnN1cmFuY2UpCiAgICAgICAgICAgICAgICAgICAKc3VtbWFyeShpbnNfbW9kZWwyKSAgICAgICAgICAgICAgICAgICAKCiMjIAojIyBDYWxsOgojIyBsbShmb3JtdWxhID0gZXhwZW5zZXMgfiBhZ2UgKyBhZ2UyICsgY2hpbGRyZW4gKyBibWkgKyBzZXggKyBibWkzMCAqIAojIyAgICAgc21va2VyICsgcmVnaW9uLCBkYXRhID0gaW5zdXJhbmNlKQojIyAKIyMgUmVzaWR1YWxzOgojIyAgICAgIE1pbiAgICAgICAxUSAgIE1lZGlhbiAgICAgICAzUSAgICAgIE1heCAKIyMgLTE3Mjk3LjEgIC0xNjU2LjAgIC0xMjYyLjcgICAtNzI3LjggIDI0MTYxLjYgCiMjIAojIyBDb2VmZmljaWVudHM6CiMjICAgICAgICAgICAgICAgICAgIEVzdGltYXRlIFN0ZC4gRXJyb3IgdCB2YWx1ZSBQcig+fHR8KSAgICAKIyMgKEludGVyY2VwdCkgICAgICAgMTM5LjAwNTMgIDEzNjMuMTM1OSAgIDAuMTAyIDAuOTE4NzkyICAgIAojIyBhZ2UgICAgICAgICAgICAgICAtMzIuNjE4MSAgICA1OS44MjUwICAtMC41NDUgMC41ODU2OTAgICAgCiMjIGFnZTIgICAgICAgICAgICAgICAgMy43MzA3ICAgICAwLjc0NjMgICA0Ljk5OSA2LjU0ZS0wNyAqKioKIyMgY2hpbGRyZW4gICAgICAgICAgNjc4LjYwMTcgICAxMDUuODg1NSAgIDYuNDA5IDIuMDNlLTEwICoqKgojIyBibWkgICAgICAgICAgICAgICAxMTkuNzcxNSAgICAzNC4yNzk2ICAgMy40OTQgMC4wMDA0OTIgKioqCiMjIHNleG1hbGUgICAgICAgICAgLTQ5Ni43NjkwICAgMjQ0LjM3MTMgIC0yLjAzMyAwLjA0MjI2NyAqICAKIyMgYm1pMzAgICAgICAgICAgICAtOTk3LjkzNTUgICA0MjIuOTYwNyAgLTIuMzU5IDAuMDE4NDQ5ICogIAojIyBzbW9rZXJ5ZXMgICAgICAgMTM0MDQuNTk1MiAgIDQzOS45NTkxICAzMC40NjggIDwgMmUtMTYgKioqCiMjIHJlZ2lvbm5vcnRod2VzdCAgLTI3OS4xNjYxICAgMzQ5LjI4MjYgIC0wLjc5OSAwLjQyNDI4NSAgICAKIyMgcmVnaW9uc291dGhlYXN0ICAtODI4LjAzNDUgICAzNTEuNjQ4NCAgLTIuMzU1IDAuMDE4NjgyICogIAojIyByZWdpb25zb3V0aHdlc3QgLTEyMjIuMTYxOSAgIDM1MC41MzE0ICAtMy40ODcgMC4wMDA1MDUgKioqCiMjIGJtaTMwOnNtb2tlcnllcyAxOTgxMC4xNTM0ICAgNjA0LjY3NjkgIDMyLjc2MiAgPCAyZS0xNiAqKioKIyMgLS0tCiMjIFNpZ25pZi4gY29kZXM6ICAwICcqKionIDAuMDAxICcqKicgMC4wMSAnKicgMC4wNSAnLicgMC4xICcgJyAxCiMjIAojIyBSZXNpZHVhbCBzdGFuZGFyZCBlcnJvcjogNDQ0NSBvbiAxMzI2IGRlZ3JlZXMgb2YgZnJlZWRvbQojIyBNdWx0aXBsZSBSLXNxdWFyZWQ6ICAwLjg2NjQsIEFkanVzdGVkIFItc3F1YXJlZDogIDAuODY1MyAKIyMgRi1zdGF0aXN0aWM6IDc4MS43IG9uIDExIGFuZCAxMzI2IERGLCAgcC12YWx1ZTogPCAyLjJlLTE2CgojIG1ha2luZyBwcmVkaWN0aW9ucyB3aXRoIHRoZSByZWdyZXNzaW9uIG1vZGVsCmluc3VyYW5jZSRwcmVkIDwtIHByZWRpY3QoaW5zX21vZGVsMiwgaW5zdXJhbmNlKQpjb3IoaW5zdXJhbmNlJHByZWQsIGluc3VyYW5jZSRleHBlbnNlcykKCnBsb3QoaW5zdXJhbmNlJHByZWQsIGluc3VyYW5jZSRleHBlbnNlcykKYWJsaW5lKGEgPSAwLCBiID0gMSwgY29sID0gInJlZCIsIGx3ZCA9IDMsIGx0eSA9IDIpCgpwcmVkaWN0KGluc19tb2RlbDIsCiAgICAgICAgZGF0YS5mcmFtZShhZ2UgPSAzMCwgYWdlMiA9IDMwXjIsIGNoaWxkcmVuID0gMiwKICAgICAgICAgICAgICAgICAgIGJtaSA9IDMwLCBzZXggPSAibWFsZSIsIGJtaTMwID0gMSwKICAgICAgICAgICAgICAgICAgIHNtb2tlciA9ICJubyIsIHJlZ2lvbiA9ICJub3J0aGVhc3QiKSkKcHJlZGljdChpbnNfbW9kZWwyLAogICAgICAgIGRhdGEuZnJhbWUoYWdlID0gMzAsIGFnZTIgPSAzMF4yLCBjaGlsZHJlbiA9IDIsCiAgICAgICAgICAgICAgICAgICBibWkgPSAzMCwgc2V4ID0gImZlbWFsZSIsIGJtaTMwID0gMSwKICAgICAgICAgICAgICAgICAgIHNtb2tlciA9ICJubyIsIHJlZ2lvbiA9ICJub3J0aGVhc3QiKSkKICAgICAgICAgICAgICAgICAgIAojIHNldCB1cCB0aGUgZGF0YQp0ZWUgPC0gYygxLCAxLCAxLCAyLCAyLCAzLCA0LCA1LCA1LCA2LCA2LCA3LCA3LCA3LCA3KQphdDEgPC0gYygxLCAxLCAxLCAyLCAyLCAzLCA0LCA1LCA1KQphdDIgPC0gYyg2LCA2LCA3LCA3LCA3LCA3KQpidDEgPC0gYygxLCAxLCAxLCAyLCAyLCAzLCA0KQpidDIgPC0gYyg1LCA1LCA2LCA2LCA3LCA3LCA3LCA3KQoKIyBjb21wdXRlIHRoZSBTRFIKc2RyX2EgPC0gc2QodGVlKSAtIChsZW5ndGgoYXQxKSAvIGxlbmd0aCh0ZWUpICogc2QoYXQxKSArIGxlbmd0aChhdDIpIC8gbGVuZ3RoKHRlZSkgKiBzZChhdDIpKQpzZHJfYiA8LSBzZCh0ZWUpIC0gKGxlbmd0aChidDEpIC8gbGVuZ3RoKHRlZSkgKiBzZChidDEpICsgbGVuZ3RoKGJ0MikgLyBsZW5ndGgodGVlKSAqIHNkKGJ0MikpCgojIGNvbXBhcmUgdGhlIFNEUiBmb3IgZWFjaCBzcGxpdApzZHJfYQoKc2RyX2IKCndpbmUgPC0gcmVhZC5jc3YoIndoaXRld2luZXMuY3N2IikKCiMgZXhhbWluZSB0aGUgd2luZSBkYXRhCnN0cih3aW5lKQojIHRoZSBkaXN0cmlidXRpb24gb2YgcXVhbGl0eSByYXRpbmdzCmhpc3Qod2luZSRxdWFsaXR5KQojIHN1bW1hcnkgc3RhdGlzdGljcyBvZiB0aGUgd2luZSBkYXRhCnN1bW1hcnkod2luZSkKCndpbmVfdHJhaW4gPC0gd2luZVsxOjM3NTAsIF0Kd2luZV90ZXN0IDwtIHdpbmVbMzc1MTo0ODk4LCBdCgojIHJlZ3Jlc3Npb24gdHJlZSB1c2luZyBycGFydApsaWJyYXJ5KHJwYXJ0KQptLnJwYXJ0IDwtIHJwYXJ0KHF1YWxpdHkgfiAuLCBkYXRhID0gd2luZV90cmFpbikKIyBnZXQgYmFzaWMgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHRyZWUKbS5ycGFydAojIGdldCBtb3JlIGRldGFpbGVkIGluZm9ybWF0aW9uIGFib3V0IHRoZSB0cmVlCnN1bW1hcnkobS5ycGFydCkKCmluc3RhbGwucGFja2FnZXMoInJwYXJ0LnBsb3QiKQoKIyB1c2UgdGhlIHJwYXJ0LnBsb3QgcGFja2FnZSB0byBjcmVhdGUgYSB2aXN1YWxpemF0aW9uCmxpYnJhcnkocnBhcnQucGxvdCkKIyBhIGJhc2ljIGRlY2lzaW9uIHRyZWUgZGlhZ3JhbQpycGFydC5wbG90KG0ucnBhcnQsIGRpZ2l0cyA9IDMpCiMgYSBmZXcgYWRqdXN0bWVudHMgdG8gdGhlIGRpYWdyYW0KcnBhcnQucGxvdChtLnJwYXJ0LCBkaWdpdHMgPSA0LCBmYWxsZW4ubGVhdmVzID0gVFJVRSwgdHlwZSA9IDMsIGV4dHJhID0gMTAxKQoKIyBnZW5lcmF0ZSBwcmVkaWN0aW9ucyBmb3IgdGhlIHRlc3RpbmcgZGF0YXNldApwLnJwYXJ0IDwtIHByZWRpY3QobS5ycGFydCwgd2luZV90ZXN0KQoKIyBjb21wYXJlIHRoZSBkaXN0cmlidXRpb24gb2YgcHJlZGljdGVkIHZhbHVlcyB2cy4gYWN0dWFsIHZhbHVlcwpzdW1tYXJ5KHAucnBhcnQpCnN1bW1hcnkod2luZV90ZXN0JHF1YWxpdHkpCiMgY29tcGFyZSB0aGUgY29ycmVsYXRpb24KY29yKHAucnBhcnQsIHdpbmVfdGVzdCRxdWFsaXR5KQoKIyBmdW5jdGlvbiB0byBjYWxjdWxhdGUgdGhlIG1lYW4gYWJzb2x1dGUgZXJyb3IKTUFFIDwtIGZ1bmN0aW9uKGFjdHVhbCwgcHJlZGljdGVkKSB7CiAgbWVhbihhYnMoYWN0dWFsIC0gcHJlZGljdGVkKSkgIAp9CgpNQUUocC5ycGFydCwgd2luZV90ZXN0JHF1YWxpdHkpCiMgbWVhbiBhYnNvbHV0ZSBlcnJvciBiZXR3ZWVuIGFjdHVhbCB2YWx1ZXMgYW5kIG1lYW4gdmFsdWUKbWVhbih3aW5lX3RyYWluJHF1YWxpdHkpICMgcmVzdWx0ID0gNS44NwoKTUFFKDUuODcsIHdpbmVfdGVzdCRxdWFsaXR5KQoKaW5zdGFsbC5wYWNrYWdlcygicGx5ciIpCmluc3RhbGwucGFja2FnZXMoIkN1YmlzdCIpCiMgdHJhaW4gYSBDdWJpc3QgTW9kZWwgVHJlZQpsaWJyYXJ5KEN1YmlzdCkKbS5jdWJpc3QgPC0gY3ViaXN0KHggPSB3aW5lX3RyYWluWy0xMl0sIHkgPSB3aW5lX3RyYWluJHF1YWxpdHkpCiMgZGlzcGxheSBiYXNpYyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgbW9kZWwgdHJlZQptLmN1YmlzdAoKIyBkaXNwbGF5IHRoZSB0cmVlIGl0c2VsZgpzdW1tYXJ5KG0uY3ViaXN0KQoKIyBnZW5lcmF0ZSBwcmVkaWN0aW9ucyBmb3IgdGhlIG1vZGVsCnAuY3ViaXN0IDwtIHByZWRpY3QobS5jdWJpc3QsIHdpbmVfdGVzdCkKCiMgc3VtbWFyeSBzdGF0aXN0aWNzIGFib3V0IHRoZSBwcmVkaWN0aW9ucwpzdW1tYXJ5KHAuY3ViaXN0KQoKIyBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSBwcmVkaWN0ZWQgYW5kIHRydWUgdmFsdWVzCmNvcihwLmN1YmlzdCwgd2luZV90ZXN0JHF1YWxpdHkpCgojIG1lYW4gYWJzb2x1dGUgZXJyb3Igb2YgcHJlZGljdGVkIGFuZCB0cnVlIHZhbHVlcwojICh1c2VzIGEgY3VzdG9tIGZ1bmN0aW9uIGRlZmluZWQgYWJvdmUpCk1BRSh3aW5lX3Rlc3QkcXVhbGl0eSwgcC5jdWJpc3QpIA==