Question #3: Consider the Gini index, classification
error, and entropy in a simple classification setting with two classes.
Create a single plot that displays each of these quantities as a
function of ˆpm1. The x-axis should display ˆpm1, ranging from 0 to 1,
and the y-axis should display the value of the Gini index,
classification error, and entropy.
p = seq(0, 1, 0.01)
gini = p * (1 - p) * 2
entropy = -(p * log(p) + (1 - p) * log(1 - p))
class.err = 1 - pmax(p, 1 - p)
matplot(p, cbind(gini, entropy, class.err), col = c("blue", "red", "green"))

Question #8: In the lab, a classification tree was
applied to the Carseats data set after converting Sales into a
qualitative response variable. Now we will seek to predict Sales using
regression trees and related approaches, treating the response as a
quantitative variable.
library(ISLR2)
attach(Carseats)
(a) Split the data set into a training set and a
test set.
set.seed(1)
train = sample(dim(Carseats)[1], dim(Carseats)[1]/2)
train.carseats = Carseats[train, ]
test.carseats = Carseats[-train, ]
y.test <- test.carseats$Sales
(b) Fit a regression tree to the training set. Plot
the tree, and interpret the results. What test MSE do you obtain?
library(tree)
tree.carseats = tree(Sales ~ ., data = train.carseats)
summary(tree.carseats)
Regression tree:
tree(formula = Sales ~ ., data = train.carseats)
Variables actually used in tree construction:
[1] "ShelveLoc" "Price" "Age" "Advertising" "CompPrice"
[6] "US"
Number of terminal nodes: 18
Residual mean deviance: 2.167 = 394.3 / 182
Distribution of residuals:
Min. 1st Qu. Median Mean 3rd Qu. Max.
-3.88200 -0.88200 -0.08712 0.00000 0.89590 4.09900
plot(tree.carseats)
text(tree.carseats, pretty = 0)

pred.carseats = predict(tree.carseats, test.carseats)
mean((test.carseats$Sales - pred.carseats)^2)
[1] 4.922039
- Based on the results, the MSE is 4.92.
(c) Use cross-validation in order to determine the
optimal level of tree complexity. Does pruning the tree improve the test
MSE?
cv.carseats <- cv.tree(tree.carseats)
plot(cv.carseats$size, cv.carseats$dev, type='b')

prune.carseats <- prune.tree(tree.carseats, best=11)
plot(prune.carseats)
text(prune.carseats, pretty=0)

yhat <- predict(prune.carseats, test.carseats)
mean((yhat-y.test)^2)
[1] 4.757881
- Based on the results, pruning resulted in a lower MSE.
(d) Use the bagging approach in order to analyze
this data. What test MSE do you obtain? Use the importance() function to
determine which variables are most important.
#library(randomForest)
#bag.carseats <- randomForest(Sales ~., data=train.carseats, mtry=10, importance=TRUE)
#yhat.bag <- predict(bag.carseats, newdata=test.carseats)
#mean((yhat.bag-y.test)^2)
-Bagging decreases the test MSE to 3.7.
#importance(bag.carseats)
- Based on the results the two most important variables are ShelveLoc
and Price.
(e) Use random forests to analyze this data. What
test MSE do you obtain? Use the importance() function to determine which
variables are most important. Describe the effect of m, the number of
variables considered at each split, on the error rate obtained.
#rf.carseats <- randomForest(Sales~., data=train.carseats, #mtry=floor((ncol(Carseats)-1)/3),importance=TRUE)
#yhat.rf <- predict(rf.carseats, newdata = test.carseats)
#mean((yhat.rf-y.test)^2)
- When using p/3 variables at each node in random forest, we obtain a
higher test MSE (4.43) than by bagging.
#importance(rf.carseats)
- The two most important variables are still ShelveLoc and Price.
(f) Now analyze the data using BART, and report your
results.
Question #9: This problem involves the OJ data set
which is part of the ISLR2 package.
data(OJ)
attach(OJ)
(a) Create a training set containing a random sample
of 800 observations, and a test set containing the remaining
observations.
set.seed(100)
train2 <- sample(1:nrow(OJ), 800)
train.OJ <- OJ[train_n, ]
test.OJ <- OJ[-train_n, ]
(b) Fit a tree to the training data, with Purchase
as the response and the other variables as predictors. Use the summary()
function to produce summary statistics about the tree, and describe the
results obtained. What is the training error rate? How many terminal
nodes does the tree have?
tree.OJ <- tree(Purchase ~., data=train.OJ)
summary(tree.OJ)
- There are 9 terminal nodes in this tree. The training error is
0.15.
(c) Type in the name of the tree object in order to
get a detailed text output. Pick one of the terminal nodes, and
interpret the information displayed.
tree.OJ
- Node 24 in the decision tree comprises 31 observations and has a
deviance of 82.11. The figures in parentheses indicate that
approximately 57% of the observations are incorrectly classified as CH,
while about 43% are accurately classified as MM.
(d) Create a plot of the tree, and interpret the
results.
plot(tree.OJ)
text(tree.OJ, pretty=0)
- The initial split took place at the variable LoyalCH < 0.48,
indicating its significance as a predictor with three additional splits
at this variable. Another vital predictor is PriceDiff, which also
appears at three distinct splits.
(e) Predict the response on the test data, and
produce a confusion matrix comparing the test labels to the predicted
test labels. What is the test error rate?
ytest.OJ <- test.OJ$Purchase
tree.pred <- predict(tree.OJ, test.OJ, type="class")
table(tree.pred, ytest.OJ)
(21+37)/(150+37+21+62)
(f) Apply the cv.tree() function to the training set
in order to determine the optimal tree size.
cv.tree <- cv.tree(tree.OJ, FUN=prune.misclass)
cv.tree
- The cross-validation error is at its lowest point with either 9 or 8
terminal nodes, making these two tree sizes the optimal choices for this
case.
(g) Produce a plot with tree size on the x-axis and
cross-validated classification error rate on the y-axis.
plot(cv.tree$size, cv.tree$dev, type='b')
(h) Which tree size corresponds to the lowest
cross-validated classification error rate?
- The cross-validation method indicates that the tree size of 8 or 9
yields the minimum classification error rate, which is identical for
both sizes.
(i) Produce a pruned tree corresponding to the
optimal tree size obtained using cross-validation. If cross-validation
does not lead to selection of a pruned tree, then create a pruned tree
with five terminal nodes.
prune.OJ <- prune.misclass(tree.OJ, best=5)
summary(prune.OJ)
- Based on the new results, there is a slightly higher training error,
and there are 5 terminal nodes.
plot(prune.OJ)
text(prune.OJ, pretty=0)
(j) Compare the training error rates between the
pruned and unpruned trees. Which is higher?
- The pruned tree training error rate is higher by .0088
(k) Compare the test error rates between the pruned
and unpruned trees. Which is higher?
prune.pred <- predict(prune.OJ, test.OJ, type = "class")
table(prune.pred, ytest.OJ)
(29+33)/(138+29+33+70)
The test error rate results are higher at 22.96% for the pruned tree,
while it was 21.5% for the unpruned tree.
LS0tCnRpdGxlOiAnQXNzaWdubWVudCAjNzogVHJlZS1CYXNlZCBNZXRob2RzJwpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKZGF0ZTogJzIwMjMtMDQtMjcnCi0tLQoKKipRdWVzdGlvbiAjMzoqKiBDb25zaWRlciB0aGUgR2luaSBpbmRleCwgY2xhc3NpZmljYXRpb24gZXJyb3IsIGFuZCBlbnRyb3B5IGluIGEgc2ltcGxlIGNsYXNzaWZpY2F0aW9uIHNldHRpbmcgd2l0aCB0d28gY2xhc3Nlcy4gQ3JlYXRlIGEgc2luZ2xlIHBsb3QgdGhhdCBkaXNwbGF5cyBlYWNoIG9mIHRoZXNlIHF1YW50aXRpZXMgYXMgYSBmdW5jdGlvbiBvZiDLhnBtMS4gVGhlIHgtYXhpcyBzaG91bGQgZGlzcGxheSDLhnBtMSwgcmFuZ2luZyBmcm9tIDAgdG8gMSwgYW5kIHRoZSB5LWF4aXMgc2hvdWxkIGRpc3BsYXkgdGhlIHZhbHVlIG9mIHRoZSBHaW5pIGluZGV4LCBjbGFzc2lmaWNhdGlvbiBlcnJvciwgYW5kIGVudHJvcHkuCgpgYGB7cn0KcCA9IHNlcSgwLCAxLCAwLjAxKQpnaW5pID0gcCAqICgxIC0gcCkgKiAyCmVudHJvcHkgPSAtKHAgKiBsb2cocCkgKyAoMSAtIHApICogbG9nKDEgLSBwKSkKY2xhc3MuZXJyID0gMSAtIHBtYXgocCwgMSAtIHApCm1hdHBsb3QocCwgY2JpbmQoZ2luaSwgZW50cm9weSwgY2xhc3MuZXJyKSwgY29sID0gYygiYmx1ZSIsICJyZWQiLCAiZ3JlZW4iKSkKYGBgCgotLS0KCioqUXVlc3Rpb24gIzg6KiogSW4gdGhlIGxhYiwgYSBjbGFzc2lmaWNhdGlvbiB0cmVlIHdhcyBhcHBsaWVkIHRvIHRoZSBDYXJzZWF0cyBkYXRhIHNldCBhZnRlciBjb252ZXJ0aW5nIFNhbGVzIGludG8gYSBxdWFsaXRhdGl2ZSByZXNwb25zZSB2YXJpYWJsZS4gTm93IHdlIHdpbGwKc2VlayB0byBwcmVkaWN0IFNhbGVzIHVzaW5nIHJlZ3Jlc3Npb24gdHJlZXMgYW5kIHJlbGF0ZWQgYXBwcm9hY2hlcywKdHJlYXRpbmcgdGhlIHJlc3BvbnNlIGFzIGEgcXVhbnRpdGF0aXZlIHZhcmlhYmxlLgpgYGB7cn0KbGlicmFyeShJU0xSMikKYXR0YWNoKENhcnNlYXRzKQpgYGAKCgoqKihhKSoqIFNwbGl0IHRoZSBkYXRhIHNldCBpbnRvIGEgdHJhaW5pbmcgc2V0IGFuZCBhIHRlc3Qgc2V0LgpgYGB7cn0Kc2V0LnNlZWQoMSkKCnRyYWluID0gc2FtcGxlKGRpbShDYXJzZWF0cylbMV0sIGRpbShDYXJzZWF0cylbMV0vMikKdHJhaW4uY2Fyc2VhdHMgPSBDYXJzZWF0c1t0cmFpbiwgXQp0ZXN0LmNhcnNlYXRzID0gQ2Fyc2VhdHNbLXRyYWluLCBdCgp5LnRlc3QgPC0gdGVzdC5jYXJzZWF0cyRTYWxlcwoKYGBgCgoKKiooYikqKiBGaXQgYSByZWdyZXNzaW9uIHRyZWUgdG8gdGhlIHRyYWluaW5nIHNldC4gUGxvdCB0aGUgdHJlZSwgYW5kIGludGVycHJldCB0aGUgcmVzdWx0cy4gV2hhdCB0ZXN0IE1TRSBkbyB5b3Ugb2J0YWluPwpgYGB7cn0KbGlicmFyeSh0cmVlKQp0cmVlLmNhcnNlYXRzID0gdHJlZShTYWxlcyB+IC4sIGRhdGEgPSB0cmFpbi5jYXJzZWF0cykKc3VtbWFyeSh0cmVlLmNhcnNlYXRzKQpgYGAKCmBgYHtyfQpwbG90KHRyZWUuY2Fyc2VhdHMpCnRleHQodHJlZS5jYXJzZWF0cywgcHJldHR5ID0gMCkKYGBgCgpgYGB7cn0KcHJlZC5jYXJzZWF0cyA9IHByZWRpY3QodHJlZS5jYXJzZWF0cywgdGVzdC5jYXJzZWF0cykKbWVhbigodGVzdC5jYXJzZWF0cyRTYWxlcyAtIHByZWQuY2Fyc2VhdHMpXjIpCmBgYAoKLSBCYXNlZCBvbiB0aGUgcmVzdWx0cywgdGhlIE1TRSBpcyA0LjkyLgoKCioqKGMpKiogVXNlIGNyb3NzLXZhbGlkYXRpb24gaW4gb3JkZXIgdG8gZGV0ZXJtaW5lIHRoZSBvcHRpbWFsIGxldmVsIG9mCnRyZWUgY29tcGxleGl0eS4gRG9lcyBwcnVuaW5nIHRoZSB0cmVlIGltcHJvdmUgdGhlIHRlc3QgTVNFPwoKYGBge3J9CmN2LmNhcnNlYXRzIDwtIGN2LnRyZWUodHJlZS5jYXJzZWF0cykKcGxvdChjdi5jYXJzZWF0cyRzaXplLCBjdi5jYXJzZWF0cyRkZXYsIHR5cGU9J2InKQpgYGAKYGBge3J9CnBydW5lLmNhcnNlYXRzIDwtIHBydW5lLnRyZWUodHJlZS5jYXJzZWF0cywgYmVzdD0xMSkKcGxvdChwcnVuZS5jYXJzZWF0cykKdGV4dChwcnVuZS5jYXJzZWF0cywgcHJldHR5PTApCmBgYApgYGB7cn0KeWhhdCA8LSBwcmVkaWN0KHBydW5lLmNhcnNlYXRzLCB0ZXN0LmNhcnNlYXRzKQptZWFuKCh5aGF0LXkudGVzdCleMikKYGBgCgotIEJhc2VkIG9uIHRoZSByZXN1bHRzLCBwcnVuaW5nIHJlc3VsdGVkIGluIGEgbG93ZXIgTVNFLgoKKiooZCkqKiBVc2UgdGhlIGJhZ2dpbmcgYXBwcm9hY2ggaW4gb3JkZXIgdG8gYW5hbHl6ZSB0aGlzIGRhdGEuIFdoYXQKdGVzdCBNU0UgZG8geW91IG9idGFpbj8gVXNlIHRoZSBpbXBvcnRhbmNlKCkgZnVuY3Rpb24gdG8gZGV0ZXJtaW5lIHdoaWNoIHZhcmlhYmxlcyBhcmUgbW9zdCBpbXBvcnRhbnQuCgpgYGB7cn0gCiNsaWJyYXJ5KHJhbmRvbUZvcmVzdCkKCiNiYWcuY2Fyc2VhdHMgPC0gcmFuZG9tRm9yZXN0KFNhbGVzIH4uLCBkYXRhPXRyYWluLmNhcnNlYXRzLCBtdHJ5PTEwLCBpbXBvcnRhbmNlPVRSVUUpCmBgYAoKYGBge3J9CiN5aGF0LmJhZyA8LSBwcmVkaWN0KGJhZy5jYXJzZWF0cywgbmV3ZGF0YT10ZXN0LmNhcnNlYXRzKQojbWVhbigoeWhhdC5iYWcteS50ZXN0KV4yKQpgYGAKCi1CYWdnaW5nIGRlY3JlYXNlcyB0aGUgdGVzdCBNU0UgdG8gMy43LgoKCmBgYHtyfQojaW1wb3J0YW5jZShiYWcuY2Fyc2VhdHMpCmBgYAoKLSBCYXNlZCBvbiB0aGUgcmVzdWx0cyB0aGUgdHdvIG1vc3QgaW1wb3J0YW50IHZhcmlhYmxlcyBhcmUgU2hlbHZlTG9jIGFuZCBQcmljZS4KCgoqKihlKSoqIFVzZSByYW5kb20gZm9yZXN0cyB0byBhbmFseXplIHRoaXMgZGF0YS4gV2hhdCB0ZXN0IE1TRSBkbyB5b3UKb2J0YWluPyBVc2UgdGhlIGltcG9ydGFuY2UoKSBmdW5jdGlvbiB0byBkZXRlcm1pbmUgd2hpY2ggdmFyaWFibGVzIGFyZSBtb3N0IGltcG9ydGFudC4gRGVzY3JpYmUgdGhlIGVmZmVjdCBvZiBtLCB0aGUgbnVtYmVyIG9mCnZhcmlhYmxlcyBjb25zaWRlcmVkIGF0IGVhY2ggc3BsaXQsIG9uIHRoZSBlcnJvciByYXRlCm9idGFpbmVkLgpgYGB7cn0KI3JmLmNhcnNlYXRzIDwtIHJhbmRvbUZvcmVzdChTYWxlc34uLCBkYXRhPXRyYWluLmNhcnNlYXRzLCAjbXRyeT1mbG9vcigobmNvbChDYXJzZWF0cyktMSkvMyksaW1wb3J0YW5jZT1UUlVFKQpgYGAKCmBgYHtyfQojeWhhdC5yZiA8LSBwcmVkaWN0KHJmLmNhcnNlYXRzLCBuZXdkYXRhID0gdGVzdC5jYXJzZWF0cykKI21lYW4oKHloYXQucmYteS50ZXN0KV4yKQpgYGAKCi0gV2hlbiB1c2luZyBwLzMgdmFyaWFibGVzIGF0IGVhY2ggbm9kZSBpbiByYW5kb20gZm9yZXN0LCB3ZSBvYnRhaW4gYSBoaWdoZXIgdGVzdCBNU0UgKDQuNDMpIHRoYW4gYnkgYmFnZ2luZy4KCmBgYHtyfQojaW1wb3J0YW5jZShyZi5jYXJzZWF0cykKYGBgCgotIFRoZSB0d28gbW9zdCBpbXBvcnRhbnQgdmFyaWFibGVzIGFyZSBzdGlsbCBTaGVsdmVMb2MgYW5kIFByaWNlLgoKKiooZikqKiBOb3cgYW5hbHl6ZSB0aGUgZGF0YSB1c2luZyBCQVJULCBhbmQgcmVwb3J0IHlvdXIgcmVzdWx0cy4KCi0tLQoKKipRdWVzdGlvbiAjOToqKiBUaGlzIHByb2JsZW0gaW52b2x2ZXMgdGhlIE9KIGRhdGEgc2V0IHdoaWNoIGlzIHBhcnQgb2YgdGhlIElTTFIyCnBhY2thZ2UuCmBgYHtyfQpkYXRhKE9KKQphdHRhY2goT0opCmBgYAoKKiooYSkqKiBDcmVhdGUgYSB0cmFpbmluZyBzZXQgY29udGFpbmluZyBhIHJhbmRvbSBzYW1wbGUgb2YgODAwIG9ic2VydmF0aW9ucywgYW5kIGEgdGVzdCBzZXQgY29udGFpbmluZyB0aGUgcmVtYWluaW5nIG9ic2VydmF0aW9ucy4KYGBge3J9CnNldC5zZWVkKDEwMCkKdHJhaW4yIDwtIHNhbXBsZSgxOm5yb3coT0opLCA4MDApCnRyYWluLk9KIDwtIE9KW3RyYWluX24sIF0KdGVzdC5PSiA8LSBPSlstdHJhaW5fbiwgXQpgYGAKCgoqKihiKSoqIEZpdCBhIHRyZWUgdG8gdGhlIHRyYWluaW5nIGRhdGEsIHdpdGggUHVyY2hhc2UgYXMgdGhlIHJlc3BvbnNlCmFuZCB0aGUgb3RoZXIgdmFyaWFibGVzIGFzIHByZWRpY3RvcnMuIFVzZSB0aGUgc3VtbWFyeSgpIGZ1bmN0aW9uCnRvIHByb2R1Y2Ugc3VtbWFyeSBzdGF0aXN0aWNzIGFib3V0IHRoZSB0cmVlLCBhbmQgZGVzY3JpYmUgdGhlCnJlc3VsdHMgb2J0YWluZWQuIFdoYXQgaXMgdGhlIHRyYWluaW5nIGVycm9yIHJhdGU/IEhvdyBtYW55CnRlcm1pbmFsIG5vZGVzIGRvZXMgdGhlIHRyZWUgaGF2ZT8KYGBge3J9CnRyZWUuT0ogPC0gdHJlZShQdXJjaGFzZSB+LiwgZGF0YT10cmFpbi5PSikgCnN1bW1hcnkodHJlZS5PSikKYGBgCi0gVGhlcmUgYXJlIDkgdGVybWluYWwgbm9kZXMgaW4gdGhpcyB0cmVlLiBUaGUgdHJhaW5pbmcgZXJyb3IgaXMgMC4xNS4KCgoqKihjKSoqIFR5cGUgaW4gdGhlIG5hbWUgb2YgdGhlIHRyZWUgb2JqZWN0IGluIG9yZGVyIHRvIGdldCBhIGRldGFpbGVkCnRleHQgb3V0cHV0LiBQaWNrIG9uZSBvZiB0aGUgdGVybWluYWwgbm9kZXMsIGFuZCBpbnRlcnByZXQgdGhlCmluZm9ybWF0aW9uIGRpc3BsYXllZC4KYGBge3J9CnRyZWUuT0oKYGBgCgotIE5vZGUgMjQgaW4gdGhlIGRlY2lzaW9uIHRyZWUgY29tcHJpc2VzIDMxIG9ic2VydmF0aW9ucyBhbmQgaGFzIGEgZGV2aWFuY2Ugb2YgODIuMTEuIFRoZSBmaWd1cmVzIGluIHBhcmVudGhlc2VzIGluZGljYXRlIHRoYXQgYXBwcm94aW1hdGVseSA1NyUgb2YgdGhlIG9ic2VydmF0aW9ucyBhcmUgaW5jb3JyZWN0bHkgY2xhc3NpZmllZCBhcyBDSCwgd2hpbGUgYWJvdXQgNDMlIGFyZSBhY2N1cmF0ZWx5IGNsYXNzaWZpZWQgYXMgTU0uCgoqKihkKSoqIENyZWF0ZSBhIHBsb3Qgb2YgdGhlIHRyZWUsIGFuZCBpbnRlcnByZXQgdGhlIHJlc3VsdHMuCmBgYHtyfQpwbG90KHRyZWUuT0opCnRleHQodHJlZS5PSiwgcHJldHR5PTApCmBgYAoKLSBUaGUgaW5pdGlhbCBzcGxpdCB0b29rIHBsYWNlIGF0IHRoZSB2YXJpYWJsZSBMb3lhbENIIDwgMC40OCwgaW5kaWNhdGluZyBpdHMgc2lnbmlmaWNhbmNlIGFzIGEgcHJlZGljdG9yIHdpdGggdGhyZWUgYWRkaXRpb25hbCBzcGxpdHMgYXQgdGhpcyB2YXJpYWJsZS4gQW5vdGhlciB2aXRhbCBwcmVkaWN0b3IgaXMgUHJpY2VEaWZmLCB3aGljaCBhbHNvIGFwcGVhcnMgYXQgdGhyZWUgZGlzdGluY3Qgc3BsaXRzLgoKKiooZSkqKiBQcmVkaWN0IHRoZSByZXNwb25zZSBvbiB0aGUgdGVzdCBkYXRhLCBhbmQgcHJvZHVjZSBhIGNvbmZ1c2lvbgptYXRyaXggY29tcGFyaW5nIHRoZSB0ZXN0IGxhYmVscyB0byB0aGUgcHJlZGljdGVkIHRlc3QgbGFiZWxzLgpXaGF0IGlzIHRoZSB0ZXN0IGVycm9yIHJhdGU/CmBgYHtyfQp5dGVzdC5PSiA8LSB0ZXN0Lk9KJFB1cmNoYXNlCgp0cmVlLnByZWQgPC0gcHJlZGljdCh0cmVlLk9KLCB0ZXN0Lk9KLCB0eXBlPSJjbGFzcyIpCnRhYmxlKHRyZWUucHJlZCwgeXRlc3QuT0opCmBgYApgYGB7cn0KKDIxKzM3KS8oMTUwKzM3KzIxKzYyKQpgYGAKCi0gVGVzdCBlcnJvciBpcyAyMS41JQoKKiooZikqKiBBcHBseSB0aGUgY3YudHJlZSgpIGZ1bmN0aW9uIHRvIHRoZSB0cmFpbmluZyBzZXQgaW4gb3JkZXIgdG8KZGV0ZXJtaW5lIHRoZSBvcHRpbWFsIHRyZWUgc2l6ZS4KYGBge3J9CmN2LnRyZWUgPC0gY3YudHJlZSh0cmVlLk9KLCBGVU49cHJ1bmUubWlzY2xhc3MpCmN2LnRyZWUKYGBgCgotIFRoZSBjcm9zcy12YWxpZGF0aW9uIGVycm9yIGlzIGF0IGl0cyBsb3dlc3QgcG9pbnQgd2l0aCBlaXRoZXIgOSBvciA4IHRlcm1pbmFsIG5vZGVzLCBtYWtpbmcgdGhlc2UgdHdvIHRyZWUgc2l6ZXMgdGhlIG9wdGltYWwgY2hvaWNlcyBmb3IgdGhpcyBjYXNlLgoKKiooZykqKiBQcm9kdWNlIGEgcGxvdCB3aXRoIHRyZWUgc2l6ZSBvbiB0aGUgeC1heGlzIGFuZCBjcm9zcy12YWxpZGF0ZWQKY2xhc3NpZmljYXRpb24gZXJyb3IgcmF0ZSBvbiB0aGUgeS1heGlzLgpgYGB7cn0KcGxvdChjdi50cmVlJHNpemUsIGN2LnRyZWUkZGV2LCB0eXBlPSdiJykKYGBgCgoqKihoKSoqIFdoaWNoIHRyZWUgc2l6ZSBjb3JyZXNwb25kcyB0byB0aGUgbG93ZXN0IGNyb3NzLXZhbGlkYXRlZCBjbGFzc2lmaWNhdGlvbiBlcnJvciByYXRlPwoKLSBUaGUgY3Jvc3MtdmFsaWRhdGlvbiBtZXRob2QgaW5kaWNhdGVzIHRoYXQgdGhlIHRyZWUgc2l6ZSBvZiA4IG9yIDkgeWllbGRzIHRoZSBtaW5pbXVtIGNsYXNzaWZpY2F0aW9uIGVycm9yIHJhdGUsIHdoaWNoIGlzIGlkZW50aWNhbCBmb3IgYm90aCBzaXplcy4KCioqKGkpKiogUHJvZHVjZSBhIHBydW5lZCB0cmVlIGNvcnJlc3BvbmRpbmcgdG8gdGhlIG9wdGltYWwgdHJlZSBzaXplCm9idGFpbmVkIHVzaW5nIGNyb3NzLXZhbGlkYXRpb24uIElmIGNyb3NzLXZhbGlkYXRpb24gZG9lcyBub3QgbGVhZAp0byBzZWxlY3Rpb24gb2YgYSBwcnVuZWQgdHJlZSwgdGhlbiBjcmVhdGUgYSBwcnVuZWQgdHJlZSB3aXRoIGZpdmUKdGVybWluYWwgbm9kZXMuCmBgYHtyfQpwcnVuZS5PSiA8LSBwcnVuZS5taXNjbGFzcyh0cmVlLk9KLCBiZXN0PTUpCnN1bW1hcnkocHJ1bmUuT0opCmBgYAotIEJhc2VkIG9uIHRoZSBuZXcgIHJlc3VsdHMsIHRoZXJlIGlzIGEgc2xpZ2h0bHkgaGlnaGVyIHRyYWluaW5nIGVycm9yLCBhbmQgdGhlcmUgYXJlIDUgdGVybWluYWwgbm9kZXMuCgpgYGB7cn0KcGxvdChwcnVuZS5PSikKdGV4dChwcnVuZS5PSiwgcHJldHR5PTApCmBgYAoKKiooaikqKiBDb21wYXJlIHRoZSB0cmFpbmluZyBlcnJvciByYXRlcyBiZXR3ZWVuIHRoZSBwcnVuZWQgYW5kIHVucHJ1bmVkIHRyZWVzLiBXaGljaCBpcyBoaWdoZXI/CgotIFRoZSBwcnVuZWQgdHJlZSB0cmFpbmluZyBlcnJvciByYXRlIGlzIGhpZ2hlciBieSAuMDA4OAoKKiooaykqKiBDb21wYXJlIHRoZSB0ZXN0IGVycm9yIHJhdGVzIGJldHdlZW4gdGhlIHBydW5lZCBhbmQgdW5wcnVuZWQKdHJlZXMuIFdoaWNoIGlzIGhpZ2hlcj8KYGBge3J9CnBydW5lLnByZWQgPC0gcHJlZGljdChwcnVuZS5PSiwgdGVzdC5PSiwgdHlwZSA9ICJjbGFzcyIpCnRhYmxlKHBydW5lLnByZWQsIHl0ZXN0Lk9KKQpgYGAKYGBge3J9CigyOSszMykvKDEzOCsyOSszMys3MCkKYGBgCgpUaGUgdGVzdCBlcnJvciByYXRlIHJlc3VsdHMgYXJlIGhpZ2hlciBhdCAyMi45NiUgZm9yIHRoZSBwcnVuZWQgdHJlZSwgd2hpbGUgaXQgd2FzIDIxLjUlIGZvciB0aGUgdW5wcnVuZWQgdHJlZS4gCgo=