1. 資料探索與邏輯式回歸
1.1 讀進資料
We will first get familiar with the data. Load the CSV file gerber.csv into R. What proportion of people in this dataset voted in this election?
gerber=read.csv('data/gerber.csv')
sum(gerber$voting==1)/sum(gerber$voting==0|gerber$voting==1)
[1] 0.3159
1.2 Examine Data
Which of the four “treatment groups” had the largest percentage of people who actually voted (voting = 1)?
tapply(gerber$voting, gerber$civicduty, mean)
0 1
0.3161 0.3145
tapply(gerber$voting, gerber$hawthorne, mean)
0 1
0.3151 0.3224
tapply(gerber$voting, gerber$self, mean)
0 1
0.3122 0.3452
tapply(gerber$voting, gerber$neighbors, mean)
0 1
0.3082 0.3779
#neighbors
1.3 Logistic Model
Build a logistic regression model for voting using the four treatment group variables as the independent variables (civicduty, hawthorne, self, and neighbors). Use all the data to build the model (DO NOT split the data into a training set and testing set). Which of the following coefficients are significant in the logistic regression model? Select all that apply.
lm_model=lm(voting~civicduty + hawthorne + self +neighbors,data=gerber)
summary(lm_model)
Call:
lm(formula = voting ~ civicduty + hawthorne + self + neighbors,
data = gerber)
Residuals:
Min 1Q Median 3Q Max
-0.378 -0.314 -0.297 0.655 0.703
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.29664 0.00106 279.53 < 2e-16 ***
civicduty 0.01790 0.00260 6.88 0.0000000000058 ***
hawthorne 0.02574 0.00260 9.90 < 2e-16 ***
self 0.04851 0.00260 18.66 < 2e-16 ***
neighbors 0.08131 0.00260 31.26 < 2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.464 on 344079 degrees of freedom
Multiple R-squared: 0.00339, Adjusted R-squared: 0.00338
F-statistic: 293 on 4 and 344079 DF, p-value: <2e-16
1.4 Model Accuracy (threshold = 0.3)
Using a threshold of 0.3, what is the accuracy of the logistic regression model?
pre_model=predict(lm_model)
table(gerber$voting,pre_model>0.3)
FALSE TRUE
0 134513 100875
1 56730 51966
(134513+51966)/(134513+100875+56730+51966)
[1] 0.542
1.5 Model Accuracy (threshold = 0.5)
Using a threshold of 0.5, what is the accuracy of the logistic regression model?
pre_model=predict(lm_model)
table(gerber$voting,pre_model>0.5)
FALSE
0 235388
1 108696
235388/(235388+108606)
[1] 0.6843
1.6 AUC
Compare your previous two answers to the percentage of people who did not vote (the baseline accuracy) and compute the AUC of the model. What is happening here?
library(ROCR)
Loading required package: gplots
Attaching package: 愼㸱愼㸵gplots愼㸱愼㸶
The following object is masked from 愼㸱愼㸵package:stats愼㸱愼㸶:
lowess
pre_roc = prediction(pre_model, gerber$voting)
as.numeric(performance(pre_roc, "auc")@y.values)
[1] 0.5308
2. 決策樹模型
2.1 Default Regression Tree
We will now try out trees. Build a CART tree for voting using all data and the same four treatment variables we used before. Don’t set the option method=“class” - we are actually going to create a regression tree here. We are interested in building a tree to explore the fraction of people who vote, or the probability of voting. We’d like CART to split our groups if they have different probabilities of voting. If we used method=‘class’, CART would only split if one of the groups had a probability of voting above 50% and the other had a probability of voting less than 50% (since the predicted outcomes would be different). However, with regression trees, CART will split even if both groups have probability less than 50%.
Leave all the parameters at their default values. You can use the following command in R to build the tree:
library(rpart)
#install.packages("rpart.plot")
library(rpart.plot)
CARTmodel = rpart(voting ~ civicduty + hawthorne + self + neighbors, data=gerber)
prp(CARTmodel)

#No variables are used (the tree is only a root node) - none of the variables make a big enough effect to be split on
2.2, 2.3 Tree with Zero Cost
Now build the tree using the command:
Using only the CART tree plot, determine what fraction (a number between 0 and 1) of “Civic Duty” people voted:
CARTmodel2 = rpart(voting ~ civicduty + hawthorne + self + neighbors, data=gerber, cp=0.0)
prp(CARTmodel2)

rr
#0.31
2.4 Tree with Zero Cost
Make a new tree that includes the “sex” variable, again with cp = 0.0. Notice that sex appears as a split that is of secondary importance to the treatment group.
In the control group, which gender is more likely to vote?
In the “Civic Duty” group, which gender is more likely to vote?
CARTmodel3 = rpart(voting ~ civicduty + hawthorne + self + neighbors + sex, data=gerber,cp=0.0)
prp(CARTmodel3)

#man
#civicdut=1,man
3. 加入交互作用項
3.1
We know trees can handle “nonlinear” relationships, e.g. “in the ‘Civic Duty’ group and female”, but as we will see in the next few questions, it is possible to do the same for logistic regression. First, let’s explore what trees can tell us some more.
Let’s just focus on the “Control” treatment group. Create a regression tree using just the “control” variable, then create another tree with the “control” and “sex” variables, both with cp=0.0.
In the “control” only tree, what is the absolute value of the difference in the predicted probability of voting between being in the control group versus being in a different group? You can use the absolute value function to get answer, i.e. abs(Control Prediction - Non-Control Prediction). Add the argument “digits = 6” to the prp command to get a more accurate estimate.
CARTmodel4=rpart(voting ~ control, data=gerber,cp=0.0)
prp(CARTmodel4,digits = 6)

CARTmodel5=rpart(voting ~ control+sex, data=gerber,cp=0.0)
abs(0.296638-0.34)
[1] 0.04336
#0.043362
3.2 Predictor’s Conditional Effect
Now, using the second tree (with control and sex), determine who is affected more by NOT being in the control group (being in any of the four treatment groups):
prp(CARTmodel5,digits = 6)

abs(0.290456-0.334176)#for woman 0.04372
[1] 0.04372
abs(0.302795-0.345818)#for man 0.043023
[1] 0.04302
3.3 Calculate Effect from Logistic Reg. Coef.
Going back to logistic regression now, create a model using “sex” and “control”. Interpret the coefficient for “sex”:
glmmodel<-glm(voting~sex+control,data=gerber,family="binomial")
summary(glmmodel)
Call:
glm(formula = voting ~ sex + control, family = "binomial", data = gerber)
Deviance Residuals:
Min 1Q Median 3Q Max
-0.922 -0.901 -0.829 1.456 1.572
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -0.63554 0.00651 -97.6 < 2e-16 ***
sex -0.05579 0.00734 -7.6 0.00000000000003 ***
control -0.20014 0.00736 -27.2 < 2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 429238 on 344083 degrees of freedom
Residual deviance: 428443 on 344081 degrees of freedom
AIC: 428449
Number of Fisher Scoring iterations: 4
#Coefficient is negative, reflecting that women are less likely to vote
3.4 Comparing Estimations of Effect
The regression tree calculated the percentage voting exactly for every one of the four possibilities (Man, Not Control), (Man, Control), (Woman, Not Control), (Woman, Control). Logistic regression has attempted to do the same, although it wasn’t able to do as well because it can’t consider exactly the joint possibility of being a women and in the control group.
We can quantify this precisely. Create the following dataframe (this contains all of the possible values of sex and control), and evaluate your logistic regression using the predict function (where “LogModelSex” is the name of your logistic regression model that uses both control and sex):
Possibilities = data.frame(sex=c(0,0,1,1),control=c(0,1,0,1))
predict(glmmodel, newdata=Possibilities, type="response")
1 2 3 4
0.3463 0.3024 0.3337 0.2908
abs(0.290456-0.2908065)
[1] 0.0003505
3.5 glm() with Interaction Term
So the difference is not too big for this dataset, but it is there. We’re going to add a new term to our logistic regression now, that is the combination of the “sex” and “control” variables - so if this new variable is 1, that means the person is a woman AND in the control group. We can do that with the following command:
glmmodel2 = glm(voting ~ sex + control + sex:control, data=gerber, family="binomial")
summary(glmmodel2)
Call:
glm(formula = voting ~ sex + control + sex:control, family = "binomial",
data = gerber)
Deviance Residuals:
Min 1Q Median 3Q Max
-0.921 -0.902 -0.828 1.457 1.573
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -0.63747 0.00760 -83.84 < 2e-16 ***
sex -0.05189 0.01080 -4.80 0.0000016 ***
control -0.19655 0.01036 -18.98 < 2e-16 ***
sex:control -0.00726 0.01473 -0.49 0.62
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 429238 on 344083 degrees of freedom
Residual deviance: 428442 on 344080 degrees of freedom
AIC: 428450
Number of Fisher Scoring iterations: 4
#If a person is a woman and in the control group, the chance that she voted goes down.
3.6 Compare the Effect Again
Run the same code as before to calculate the average for each group:
rr
predict(glmmodel2, newdata=Possibilities, type=\response\)
1 2 3 4
0.3458183 0.3027947 0.3341757 0.2904558
rr
abs(0.290456-0.2904558)
[1] 2e-07
3.7 Should we always include Interaction Terms?
This example has shown that trees can capture nonlinear relationships that logistic regression can not, but that we can get around this sometimes by using variables that are the combination of two variables. Should we always include all possible interaction terms of the independent variables when building a logistic regression model?
rr
#no
LS0tDQp0aXRsZTogIkFTNC0xIOaKleelqOihjOeCuueahOW9semfv+WboOe0oCAodGVtcC4pIg0KYXV0aG9yOiAi546L5rev5L2zIE0wNjQwMjAwMjAiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KPGJyPg0KKirkuLvopoHorbDpoYzvvJrnoJTnqbbkuI3lkIznmoTmj5DnpLroqIrmga/lsI3mipXnpajooYzngrrnmoTlvbHpn78qKg0KDQoqKuWtuOe/kumHjem7nu+8mioqDQoNCisg55So5a+m6amX6Kit6KiI56K66KqN5oeJ5p6c6Zec5L+CDQorIOeUqOWbnuatuOaoueaooeWei+mgkOa4rOWFqemhnuWIpeeahOapn+eOhw0KKyDomZvmk6zorormlbgoZHVtbXkgdmFyYWJsZSkNCisg5rG6562W5qi55qih5Z6L5ZKM6YKP6Lyv5byP5Zue5q245qih5Z6L55qE5q+U6LyDDQorIOS6pOS6kuS9nOeUqOmgheeahOS9v+eUqA0KDQoNCmBgYHtyIGVjaG89VCwgbWVzc2FnZT1GLCBjYWNoZT1GLCB3YXJuaW5nPUZ9DQpybShsaXN0PWxzKGFsbD1UKSkNCm9wdGlvbnMoZGlnaXRzPTQsIHNjaXBlbj0xMikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHJwYXJ0KQ0KbGlicmFyeShycGFydC5wbG90KQ0KbGlicmFyeShjYXJldCkNCmxpYnJhcnkocmFuZG9tRm9yZXN0KQ0KbGlicmFyeShjYVRvb2xzKQ0KDQpgYGANCi0gLSAtDQojIyMgMS4g6LOH5paZ5o6i57Si6IiH6YKP6Lyv5byP5Zue5q24IA0KDQojIyMjIyAxLjEg6K6A6YCy6LOH5paZDQpXZSB3aWxsIGZpcnN0IGdldCBmYW1pbGlhciB3aXRoIHRoZSBkYXRhLiBMb2FkIHRoZSBDU1YgZmlsZSBnZXJiZXIuY3N2IGludG8gUi4gV2hhdCBwcm9wb3J0aW9uIG9mIHBlb3BsZSBpbiB0aGlzIGRhdGFzZXQgdm90ZWQgaW4gdGhpcyBlbGVjdGlvbj8NCg0KYGBge3J9DQpnZXJiZXI9cmVhZC5jc3YoJ2RhdGEvZ2VyYmVyLmNzdicpDQpzdW0oZ2VyYmVyJHZvdGluZz09MSkvc3VtKGdlcmJlciR2b3Rpbmc9PTB8Z2VyYmVyJHZvdGluZz09MSkNCmBgYA0KDQojIyMjIyAxLjIgRXhhbWluZSBEYXRhDQpXaGljaCBvZiB0aGUgZm91ciAidHJlYXRtZW50IGdyb3VwcyIgaGFkIHRoZSBsYXJnZXN0IHBlcmNlbnRhZ2Ugb2YgcGVvcGxlIHdobyBhY3R1YWxseSB2b3RlZCAodm90aW5nID0gMSk/DQoNCmBgYHtyfQ0KdGFwcGx5KGdlcmJlciR2b3RpbmcsIGdlcmJlciRjaXZpY2R1dHksIG1lYW4pDQp0YXBwbHkoZ2VyYmVyJHZvdGluZywgZ2VyYmVyJGhhd3Rob3JuZSwgbWVhbikNCnRhcHBseShnZXJiZXIkdm90aW5nLCBnZXJiZXIkc2VsZiwgbWVhbikNCnRhcHBseShnZXJiZXIkdm90aW5nLCBnZXJiZXIkbmVpZ2hib3JzLCBtZWFuKQ0KI25laWdoYm9ycw0KYGBgDQoNCiMjIyMjIDEuMyBMb2dpc3RpYyBNb2RlbA0KQnVpbGQgYSBsb2dpc3RpYyByZWdyZXNzaW9uIG1vZGVsIGZvciB2b3RpbmcgdXNpbmcgdGhlIGZvdXIgdHJlYXRtZW50IGdyb3VwIHZhcmlhYmxlcyBhcyB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzIChjaXZpY2R1dHksIGhhd3Rob3JuZSwgc2VsZiwgYW5kIG5laWdoYm9ycykuIFVzZSBhbGwgdGhlIGRhdGEgdG8gYnVpbGQgdGhlIG1vZGVsIChETyBOT1Qgc3BsaXQgdGhlIGRhdGEgaW50byBhIHRyYWluaW5nIHNldCBhbmQgdGVzdGluZyBzZXQpLiBXaGljaCBvZiB0aGUgZm9sbG93aW5nIGNvZWZmaWNpZW50cyBhcmUgc2lnbmlmaWNhbnQgaW4gdGhlIGxvZ2lzdGljIHJlZ3Jlc3Npb24gbW9kZWw/IFNlbGVjdCBhbGwgdGhhdCBhcHBseS4NCg0KYGBge3J9DQpsbV9tb2RlbD1sbSh2b3Rpbmd+Y2l2aWNkdXR5ICsgaGF3dGhvcm5lICsgc2VsZiArbmVpZ2hib3JzLGRhdGE9Z2VyYmVyKQ0Kc3VtbWFyeShsbV9tb2RlbCkNCmBgYA0KDQojIyMjIyAxLjQgTW9kZWwgQWNjdXJhY3kgKHRocmVzaG9sZCA9IDAuMykNClVzaW5nIGEgdGhyZXNob2xkIG9mIDAuMywgd2hhdCBpcyB0aGUgYWNjdXJhY3kgb2YgdGhlIGxvZ2lzdGljIHJlZ3Jlc3Npb24gbW9kZWw/DQoNCmBgYHtyfQ0KcHJlX21vZGVsPXByZWRpY3QobG1fbW9kZWwpDQp0YWJsZShnZXJiZXIkdm90aW5nLHByZV9tb2RlbD4wLjMpDQooMTM0NTEzKzUxOTY2KS8oMTM0NTEzKzEwMDg3NSs1NjczMCs1MTk2NikNCmBgYA0KDQojIyMjIyAxLjUgTW9kZWwgQWNjdXJhY3kgKHRocmVzaG9sZCA9IDAuNSkNClVzaW5nIGEgdGhyZXNob2xkIG9mIDAuNSwgd2hhdCBpcyB0aGUgYWNjdXJhY3kgb2YgdGhlIGxvZ2lzdGljIHJlZ3Jlc3Npb24gbW9kZWw/DQoNCmBgYHtyfQ0KcHJlX21vZGVsPXByZWRpY3QobG1fbW9kZWwpDQp0YWJsZShnZXJiZXIkdm90aW5nLHByZV9tb2RlbD4wLjUpDQoyMzUzODgvKDIzNTM4OCsxMDg2MDYpDQpgYGANCg0KIyMjIyMgMS42IEFVQw0KQ29tcGFyZSB5b3VyIHByZXZpb3VzIHR3byBhbnN3ZXJzIHRvIHRoZSBwZXJjZW50YWdlIG9mIHBlb3BsZSB3aG8gZGlkIG5vdCB2b3RlICh0aGUgYmFzZWxpbmUgYWNjdXJhY3kpIGFuZCBjb21wdXRlIHRoZSBBVUMgb2YgdGhlIG1vZGVsLiBXaGF0IGlzIGhhcHBlbmluZyBoZXJlPw0KDQpgYGB7cn0NCmxpYnJhcnkoUk9DUikNCnByZV9yb2MgPSBwcmVkaWN0aW9uKHByZV9tb2RlbCwgZ2VyYmVyJHZvdGluZykNCmFzLm51bWVyaWMocGVyZm9ybWFuY2UocHJlX3JvYywgImF1YyIpQHkudmFsdWVzKQ0KYGBgDQo8YnI+DQoNCi0gLSAtDQoNCiMjIyAyLiDmsbrnrZbmqLnmqKHlnosgDQoNCiMjIyMjIDIuMSBEZWZhdWx0IFJlZ3Jlc3Npb24gVHJlZSANCldlIHdpbGwgbm93IHRyeSBvdXQgdHJlZXMuIEJ1aWxkIGEgQ0FSVCB0cmVlIGZvciB2b3RpbmcgdXNpbmcgYWxsIGRhdGEgYW5kIHRoZSBzYW1lIGZvdXIgdHJlYXRtZW50IHZhcmlhYmxlcyB3ZSB1c2VkIGJlZm9yZS4gRG9uJ3Qgc2V0IHRoZSBvcHRpb24gbWV0aG9kPSJjbGFzcyIgLSB3ZSBhcmUgYWN0dWFsbHkgZ29pbmcgdG8gY3JlYXRlIGEgcmVncmVzc2lvbiB0cmVlIGhlcmUuIFdlIGFyZSBpbnRlcmVzdGVkIGluIGJ1aWxkaW5nIGEgdHJlZSB0byBleHBsb3JlIHRoZSBmcmFjdGlvbiBvZiBwZW9wbGUgd2hvIHZvdGUsIG9yIHRoZSBwcm9iYWJpbGl0eSBvZiB2b3RpbmcuIFdl4oCZZCBsaWtlIENBUlQgdG8gc3BsaXQgb3VyIGdyb3VwcyBpZiB0aGV5IGhhdmUgZGlmZmVyZW50IHByb2JhYmlsaXRpZXMgb2Ygdm90aW5nLiBJZiB3ZSB1c2VkIG1ldGhvZD3igJhjbGFzc+KAmSwgQ0FSVCB3b3VsZCBvbmx5IHNwbGl0IGlmIG9uZSBvZiB0aGUgZ3JvdXBzIGhhZCBhIHByb2JhYmlsaXR5IG9mIHZvdGluZyBhYm92ZSA1MCUgYW5kIHRoZSBvdGhlciBoYWQgYSBwcm9iYWJpbGl0eSBvZiB2b3RpbmcgbGVzcyB0aGFuIDUwJSAoc2luY2UgdGhlIHByZWRpY3RlZCBvdXRjb21lcyB3b3VsZCBiZSBkaWZmZXJlbnQpLiBIb3dldmVyLCB3aXRoIHJlZ3Jlc3Npb24gdHJlZXMsIENBUlQgd2lsbCBzcGxpdCBldmVuIGlmIGJvdGggZ3JvdXBzIGhhdmUgcHJvYmFiaWxpdHkgbGVzcyB0aGFuIDUwJS4NCg0KTGVhdmUgYWxsIHRoZSBwYXJhbWV0ZXJzIGF0IHRoZWlyIGRlZmF1bHQgdmFsdWVzLiBZb3UgY2FuIHVzZSB0aGUgZm9sbG93aW5nIGNvbW1hbmQgaW4gUiB0byBidWlsZCB0aGUgdHJlZToNCg0KYGBge3J9DQpsaWJyYXJ5KHJwYXJ0KQ0KI2luc3RhbGwucGFja2FnZXMoInJwYXJ0LnBsb3QiKQ0KbGlicmFyeShycGFydC5wbG90KQ0KQ0FSVG1vZGVsID0gcnBhcnQodm90aW5nIH4gY2l2aWNkdXR5ICsgaGF3dGhvcm5lICsgc2VsZiArIG5laWdoYm9ycywgZGF0YT1nZXJiZXIpDQpwcnAoQ0FSVG1vZGVsKQ0KI05vIHZhcmlhYmxlcyBhcmUgdXNlZCAodGhlIHRyZWUgaXMgb25seSBhIHJvb3Qgbm9kZSkgLSBub25lIG9mIHRoZSB2YXJpYWJsZXMgbWFrZSBhIGJpZyBlbm91Z2ggZWZmZWN0IHRvIGJlIHNwbGl0IG9uDQpgYGANCg0KIyMjIyMgMi4yLCAyLjMgVHJlZSB3aXRoIFplcm8gQ29zdA0KTm93IGJ1aWxkIHRoZSB0cmVlIHVzaW5nIHRoZSBjb21tYW5kOg0KDQpVc2luZyBvbmx5IHRoZSBDQVJUIHRyZWUgcGxvdCwgZGV0ZXJtaW5lIHdoYXQgZnJhY3Rpb24gKGEgbnVtYmVyIGJldHdlZW4gMCBhbmQgMSkgb2YgIkNpdmljIER1dHkiIHBlb3BsZSB2b3RlZDoNCg0KYGBge3J9DQpDQVJUbW9kZWwyID0gcnBhcnQodm90aW5nIH4gY2l2aWNkdXR5ICsgaGF3dGhvcm5lICsgc2VsZiArIG5laWdoYm9ycywgZGF0YT1nZXJiZXIsIGNwPTAuMCkNCnBycChDQVJUbW9kZWwyKQ0KYGBgDQoNCg0KYGBge3J9DQojMC4zMQ0KYGBgDQoNCiMjIyMjIDIuNCBUcmVlIHdpdGggWmVybyBDb3N0DQpNYWtlIGEgbmV3IHRyZWUgdGhhdCBpbmNsdWRlcyB0aGUgInNleCIgdmFyaWFibGUsIGFnYWluIHdpdGggY3AgPSAwLjAuIE5vdGljZSB0aGF0IHNleCBhcHBlYXJzIGFzIGEgc3BsaXQgdGhhdCBpcyBvZiBzZWNvbmRhcnkgaW1wb3J0YW5jZSB0byB0aGUgdHJlYXRtZW50IGdyb3VwLg0KDQpJbiB0aGUgY29udHJvbCBncm91cCwgd2hpY2ggZ2VuZGVyIGlzIG1vcmUgbGlrZWx5IHRvIHZvdGU/DQoNCkluIHRoZSAiQ2l2aWMgRHV0eSIgZ3JvdXAsIHdoaWNoIGdlbmRlciBpcyBtb3JlIGxpa2VseSB0byB2b3RlPw0KDQpgYGB7cn0NCkNBUlRtb2RlbDMgPSBycGFydCh2b3RpbmcgfiBjaXZpY2R1dHkgKyBoYXd0aG9ybmUgKyBzZWxmICsgbmVpZ2hib3JzICsgc2V4LCBkYXRhPWdlcmJlcixjcD0wLjApDQpwcnAoQ0FSVG1vZGVsMykNCiNtYW4NCiNjaXZpY2R1dD0xLG1hbg0KYGBgDQoNCjxicj4NCg0KLSAtIC0NCg0KIyMjIDMuIOWKoOWFpeS6pOS6kuS9nOeUqOmghSANCg0KIyMjIyMgMy4xIA0KV2Uga25vdyB0cmVlcyBjYW4gaGFuZGxlICJub25saW5lYXIiIHJlbGF0aW9uc2hpcHMsIGUuZy4gImluIHRoZSAnQ2l2aWMgRHV0eScgZ3JvdXAgYW5kIGZlbWFsZSIsIGJ1dCBhcyB3ZSB3aWxsIHNlZSBpbiB0aGUgbmV4dCBmZXcgcXVlc3Rpb25zLCBpdCBpcyBwb3NzaWJsZSB0byBkbyB0aGUgc2FtZSBmb3IgbG9naXN0aWMgcmVncmVzc2lvbi4gRmlyc3QsIGxldCdzIGV4cGxvcmUgd2hhdCB0cmVlcyBjYW4gdGVsbCB1cyBzb21lIG1vcmUuDQoNCkxldCdzIGp1c3QgZm9jdXMgb24gdGhlICJDb250cm9sIiB0cmVhdG1lbnQgZ3JvdXAuIENyZWF0ZSBhIHJlZ3Jlc3Npb24gdHJlZSB1c2luZyBqdXN0IHRoZSAiY29udHJvbCIgdmFyaWFibGUsIHRoZW4gY3JlYXRlIGFub3RoZXIgdHJlZSB3aXRoIHRoZSAiY29udHJvbCIgYW5kICJzZXgiIHZhcmlhYmxlcywgYm90aCB3aXRoIGNwPTAuMC4NCg0KSW4gdGhlICJjb250cm9sIiBvbmx5IHRyZWUsIHdoYXQgaXMgdGhlIGFic29sdXRlIHZhbHVlIG9mIHRoZSBkaWZmZXJlbmNlIGluIHRoZSBwcmVkaWN0ZWQgcHJvYmFiaWxpdHkgb2Ygdm90aW5nIGJldHdlZW4gYmVpbmcgaW4gdGhlIGNvbnRyb2wgZ3JvdXAgdmVyc3VzIGJlaW5nIGluIGEgZGlmZmVyZW50IGdyb3VwPyBZb3UgY2FuIHVzZSB0aGUgYWJzb2x1dGUgdmFsdWUgZnVuY3Rpb24gdG8gZ2V0IGFuc3dlciwgaS5lLiBhYnMoQ29udHJvbCBQcmVkaWN0aW9uIC0gTm9uLUNvbnRyb2wgUHJlZGljdGlvbikuIEFkZCB0aGUgYXJndW1lbnQgImRpZ2l0cyA9IDYiIHRvIHRoZSBwcnAgY29tbWFuZCB0byBnZXQgYSBtb3JlIGFjY3VyYXRlIGVzdGltYXRlLg0KDQpgYGB7cn0NCkNBUlRtb2RlbDQ9cnBhcnQodm90aW5nIH4gY29udHJvbCwgZGF0YT1nZXJiZXIsY3A9MC4wKQ0KcHJwKENBUlRtb2RlbDQsZGlnaXRzID0gNikNCkNBUlRtb2RlbDU9cnBhcnQodm90aW5nIH4gY29udHJvbCtzZXgsIGRhdGE9Z2VyYmVyLGNwPTAuMCkNCmFicygwLjI5NjYzOC0wLjM0KQ0KIzAuMDQzMzYyDQpgYGANCg0KIyMjIyMgMy4yIFByZWRpY3RvcidzIENvbmRpdGlvbmFsIEVmZmVjdCANCk5vdywgdXNpbmcgdGhlIHNlY29uZCB0cmVlICh3aXRoIGNvbnRyb2wgYW5kIHNleCksIGRldGVybWluZSB3aG8gaXMgYWZmZWN0ZWQgbW9yZSBieSBOT1QgYmVpbmcgaW4gdGhlIGNvbnRyb2wgZ3JvdXAgKGJlaW5nIGluIGFueSBvZiB0aGUgZm91ciB0cmVhdG1lbnQgZ3JvdXBzKToNCg0KYGBge3J9DQpwcnAoQ0FSVG1vZGVsNSxkaWdpdHMgPSA2KQ0KDQphYnMoMC4yOTA0NTYtMC4zMzQxNzYpI2ZvciB3b21hbiAwLjA0MzcyDQphYnMoMC4zMDI3OTUtMC4zNDU4MTgpI2ZvciBtYW4gMC4wNDMwMjMNCg0KYGBgDQoNCiMjIyMjIDMuMyBDYWxjdWxhdGUgRWZmZWN0IGZyb20gTG9naXN0aWMgUmVnLiBDb2VmLg0KR29pbmcgYmFjayB0byBsb2dpc3RpYyByZWdyZXNzaW9uIG5vdywgY3JlYXRlIGEgbW9kZWwgdXNpbmcgInNleCIgYW5kICJjb250cm9sIi4gSW50ZXJwcmV0IHRoZSBjb2VmZmljaWVudCBmb3IgInNleCI6DQoNCmBgYHtyfQ0KZ2xtbW9kZWw8LWdsbSh2b3Rpbmd+c2V4K2NvbnRyb2wsZGF0YT1nZXJiZXIsZmFtaWx5PSJiaW5vbWlhbCIpDQpzdW1tYXJ5KGdsbW1vZGVsKQ0KI0NvZWZmaWNpZW50IGlzIG5lZ2F0aXZlLCByZWZsZWN0aW5nIHRoYXQgd29tZW4gYXJlIGxlc3MgbGlrZWx5IHRvIHZvdGUNCmBgYA0KDQojIyMjIyAzLjQgQ29tcGFyaW5nIEVzdGltYXRpb25zIG9mIEVmZmVjdCANClRoZSByZWdyZXNzaW9uIHRyZWUgY2FsY3VsYXRlZCB0aGUgcGVyY2VudGFnZSB2b3RpbmcgZXhhY3RseSBmb3IgZXZlcnkgb25lIG9mIHRoZSBmb3VyIHBvc3NpYmlsaXRpZXMgKE1hbiwgTm90IENvbnRyb2wpLCAoTWFuLCBDb250cm9sKSwgKFdvbWFuLCBOb3QgQ29udHJvbCksIChXb21hbiwgQ29udHJvbCkuIExvZ2lzdGljIHJlZ3Jlc3Npb24gaGFzIGF0dGVtcHRlZCB0byBkbyB0aGUgc2FtZSwgYWx0aG91Z2ggaXQgd2Fzbid0IGFibGUgdG8gZG8gYXMgd2VsbCBiZWNhdXNlIGl0IGNhbid0IGNvbnNpZGVyIGV4YWN0bHkgdGhlIGpvaW50IHBvc3NpYmlsaXR5IG9mIGJlaW5nIGEgd29tZW4gYW5kIGluIHRoZSBjb250cm9sIGdyb3VwLg0KDQpXZSBjYW4gcXVhbnRpZnkgdGhpcyBwcmVjaXNlbHkuIENyZWF0ZSB0aGUgZm9sbG93aW5nIGRhdGFmcmFtZSAodGhpcyBjb250YWlucyBhbGwgb2YgdGhlIHBvc3NpYmxlIHZhbHVlcyBvZiBzZXggYW5kIGNvbnRyb2wpLCBhbmQgZXZhbHVhdGUgeW91ciBsb2dpc3RpYyByZWdyZXNzaW9uIHVzaW5nIHRoZSBwcmVkaWN0IGZ1bmN0aW9uICh3aGVyZSAiTG9nTW9kZWxTZXgiIGlzIHRoZSBuYW1lIG9mIHlvdXIgbG9naXN0aWMgcmVncmVzc2lvbiBtb2RlbCB0aGF0IHVzZXMgYm90aCBjb250cm9sIGFuZCBzZXgpOg0KDQpgYGB7cn0NClBvc3NpYmlsaXRpZXMgPSBkYXRhLmZyYW1lKHNleD1jKDAsMCwxLDEpLGNvbnRyb2w9YygwLDEsMCwxKSkNCnByZWRpY3QoZ2xtbW9kZWwsIG5ld2RhdGE9UG9zc2liaWxpdGllcywgdHlwZT0icmVzcG9uc2UiKQ0KYWJzKDAuMjkwNDU2LTAuMjkwODA2NSkNCmBgYA0KDQojIyMjIyAzLjUgYGdsbSgpYCB3aXRoIEludGVyYWN0aW9uIFRlcm0NClNvIHRoZSBkaWZmZXJlbmNlIGlzIG5vdCB0b28gYmlnIGZvciB0aGlzIGRhdGFzZXQsIGJ1dCBpdCBpcyB0aGVyZS4gV2UncmUgZ29pbmcgdG8gYWRkIGEgbmV3IHRlcm0gdG8gb3VyIGxvZ2lzdGljIHJlZ3Jlc3Npb24gbm93LCB0aGF0IGlzIHRoZSBjb21iaW5hdGlvbiBvZiB0aGUgInNleCIgYW5kICJjb250cm9sIiB2YXJpYWJsZXMgLSBzbyBpZiB0aGlzIG5ldyB2YXJpYWJsZSBpcyAxLCB0aGF0IG1lYW5zIHRoZSBwZXJzb24gaXMgYSB3b21hbiBBTkQgaW4gdGhlIGNvbnRyb2wgZ3JvdXAuIFdlIGNhbiBkbyB0aGF0IHdpdGggdGhlIGZvbGxvd2luZyBjb21tYW5kOg0KDQpgYGB7cn0NCmdsbW1vZGVsMiA9IGdsbSh2b3RpbmcgfiBzZXggKyBjb250cm9sICsgc2V4OmNvbnRyb2wsIGRhdGE9Z2VyYmVyLCBmYW1pbHk9ImJpbm9taWFsIikNCnN1bW1hcnkoZ2xtbW9kZWwyKQ0KI0lmIGEgcGVyc29uIGlzIGEgd29tYW4gYW5kIGluIHRoZSBjb250cm9sIGdyb3VwLCB0aGUgY2hhbmNlIHRoYXQgc2hlIHZvdGVkIGdvZXMgZG93bi4NCmBgYA0KDQojIyMjIyAzLjYgQ29tcGFyZSB0aGUgRWZmZWN0IEFnYWluDQpSdW4gdGhlIHNhbWUgY29kZSBhcyBiZWZvcmUgdG8gY2FsY3VsYXRlIHRoZSBhdmVyYWdlIGZvciBlYWNoIGdyb3VwOg0KDQpgYGB7cn0NCnByZWRpY3QoZ2xtbW9kZWwyLCBuZXdkYXRhPVBvc3NpYmlsaXRpZXMsIHR5cGU9InJlc3BvbnNlIikNCmFicygwLjI5MDQ1Ni0wLjI5MDQ1NTgpDQojMA0KYGBgDQoNCiMjIyMjIDMuNyBTaG91bGQgd2UgYWx3YXlzIGluY2x1ZGUgSW50ZXJhY3Rpb24gVGVybXM/DQpUaGlzIGV4YW1wbGUgaGFzIHNob3duIHRoYXQgdHJlZXMgY2FuIGNhcHR1cmUgbm9ubGluZWFyIHJlbGF0aW9uc2hpcHMgdGhhdCBsb2dpc3RpYyByZWdyZXNzaW9uIGNhbiBub3QsIGJ1dCB0aGF0IHdlIGNhbiBnZXQgYXJvdW5kIHRoaXMgc29tZXRpbWVzIGJ5IHVzaW5nIHZhcmlhYmxlcyB0aGF0IGFyZSB0aGUgY29tYmluYXRpb24gb2YgdHdvIHZhcmlhYmxlcy4gU2hvdWxkIHdlIGFsd2F5cyBpbmNsdWRlIGFsbCBwb3NzaWJsZSBpbnRlcmFjdGlvbiB0ZXJtcyBvZiB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzIHdoZW4gYnVpbGRpbmcgYSBsb2dpc3RpYyByZWdyZXNzaW9uIG1vZGVsPw0KDQpgYGB7cn0NCiNubw0KYGBgDQoNCg0KDQotIC0gLQ0KDQoNCg0KPGJyPjxicj48YnI+PGJyPjxicj4NCg0KPHN0eWxlPg0KLmNhcHRpb24gew0KICBjb2xvcjogIzc3NzsNCiAgbWFyZ2luLXRvcDogMTBweDsNCn0NCnAgY29kZSB7DQogIHdoaXRlLXNwYWNlOiBpbmhlcml0Ow0KfQ0KcHJlIHsNCiAgd29yZC1icmVhazogbm9ybWFsOw0KICB3b3JkLXdyYXA6IG5vcm1hbDsNCiAgbGluZS1oZWlnaHQ6IDE7DQp9DQpwcmUgY29kZSB7DQogIHdoaXRlLXNwYWNlOiBpbmhlcml0Ow0KfQ0KcCxsaSB7DQogIGZvbnQtZmFtaWx5OiAiVHJlYnVjaGV0IE1TIiwgIuW+rui7n+ato+m7kemrlCIsICJNaWNyb3NvZnQgSmhlbmdIZWkiOw0KfQ0KDQoucnsNCiAgbGluZS1oZWlnaHQ6IDEuMjsNCn0NCg0KdGl0bGV7DQogIGNvbG9yOiAjY2MwMDAwOw0KICBmb250LWZhbWlseTogIlRyZWJ1Y2hldCBNUyIsICLlvq7ou5/mraPpu5Hpq5QiLCAiTWljcm9zb2Z0IEpoZW5nSGVpIjsNCn0NCg0KYm9keXsNCiAgZm9udC1mYW1pbHk6ICJUcmVidWNoZXQgTVMiLCAi5b6u6Luf5q2j6buR6auUIiwgIk1pY3Jvc29mdCBKaGVuZ0hlaSI7DQp9DQoNCmgxLGgyLGgzLGg0LGg1ew0KICBjb2xvcjogIzAwNjZmZjsNCiAgZm9udC1mYW1pbHk6ICJUcmVidWNoZXQgTVMiLCAi5b6u6Luf5q2j6buR6auUIiwgIk1pY3Jvc29mdCBKaGVuZ0hlaSI7DQp9DQoNCmg0LGg1ew0KICBiYWNrZ3JvdW5kOiAjY2NmZmZmOw0KfQ0KDQo8L3N0eWxlPg==