Introduction

This article looks at how to interpret the output of the glm() R function using the Titanic train dataset.

A note on the p-value: the p-value is a test of significance for the null hypothesis \(H_0\) that

If p<0.5, we reject \(H_0\) as we have evidence to suggest that the difference between the two groups does not equal zero.

Log-odds are not the most intuitive to interpret. Instead of discussing the change in the log-odds, we can calculate the odds ratio for a given variable by exponentiating the coefficient. Odds ratio is read “have x times the odds of the outcome of interest compared to thos in the reference group”.

Reference group of the outcome variable: by default, R creates uses the lowest coded group as the reference. The reference category can ce changed by using the ‘relevel()’. Here, ‘not survived’ (coded 0) is the reference group!

Relatonship between Odds and Probabilities:


Categorical Explanatory Variable (2 Categories)

model1 <- glm(Survived ~ Sex, family=binomial(link='logit'), data=data)
summary(model1)

Call:
glm(formula = Survived ~ Sex, family = binomial(link = "logit"), 
    data = data)

Deviance Residuals: 
   Min      1Q  Median      3Q     Max  
-1.646  -0.647  -0.647   0.772   1.826  

Coefficients:
            Estimate Std. Error z value Pr(>|z|)    
(Intercept)    1.057      0.129    8.19  2.6e-16 ***
Sexmale       -2.514      0.167  -15.04  < 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: 1186.7  on 890  degrees of freedom
Residual deviance:  917.8  on 889  degrees of freedom
AIC: 921.8

Number of Fisher Scoring iterations: 4


Categorical Explanatory Variable (More than 2 Categories)

model2 <- glm(Survived ~ AgeGroup, family=binomial(link='logit'), 
              data=na.omit(data))
summary(model2)

Call:
glm(formula = Survived ~ AgeGroup, family = binomial(link = "logit"), 
    data = na.omit(data))

Deviance Residuals: 
   Min      1Q  Median      3Q     Max  
 -1.15   -0.99   -0.99    1.36    1.62  

Coefficients:
              Estimate Std. Error z value Pr(>|z|)  
(Intercept)    -0.0732     0.1563   -0.47    0.639  
AgeGroup20-39  -0.3842     0.1879   -2.04    0.041 *
AgeGroup40-59  -0.3567     0.2345   -1.52    0.128  
AgeGroup60+    -0.9253     0.4689   -1.97    0.048 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 964.52  on 713  degrees of freedom
Residual deviance: 957.93  on 710  degrees of freedom
AIC: 965.9

Number of Fisher Scoring iterations: 4


Now let’s change the reference group to 20-39:

  • this is still nased on data without missing age rows.
levels(AgeGroup)
[1] "0-19"  "20-39" "40-59" "60+"  
data$AgeGroupR <- relevel(AgeGroup, ref=2)
levels(data$AgeGroupR) # new col is not attached so must use data$
[1] "20-39" "0-19"  "40-59" "60+"  
model3 <- glm(Survived ~ AgeGroupR, family=binomial(link='logit'), 
              data=na.omit(data))
summary(model3)

Call:
glm(formula = Survived ~ AgeGroupR, family = binomial(link = "logit"), 
    data = na.omit(data))

Deviance Residuals: 
   Min      1Q  Median      3Q     Max  
 -1.15   -0.99   -0.99    1.36    1.62  

Coefficients:
               Estimate Std. Error z value Pr(>|z|)    
(Intercept)     -0.4574     0.1043   -4.38  1.2e-05 ***
AgeGroupR0-19    0.3842     0.1879    2.04    0.041 *  
AgeGroupR40-59   0.0276     0.2036    0.14    0.892    
AgeGroupR60+    -0.5411     0.4543   -1.19    0.234    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 964.52  on 713  degrees of freedom
Residual deviance: 957.93  on 710  degrees of freedom
AIC: 965.9

Number of Fisher Scoring iterations: 4
  • The findings are “worse”. Now there are two groups with \(p>0.5\).


Now let’s try with a different categorical age group variable AgeGroup2029:

levels(AgeGroup2029)
[1] "0" "1"
model2b <- glm(Survived ~ AgeGroup2029, family=binomial(link='logit'), 
              data=na.omit(data))
summary(model2b)

Call:
glm(formula = Survived ~ AgeGroup2029, family = binomial(link = "logit"), 
    data = na.omit(data))

Deviance Residuals: 
   Min      1Q  Median      3Q     Max  
-1.062  -1.062  -0.928   1.297   1.449  

Coefficients:
              Estimate Std. Error z value Pr(>|z|)   
(Intercept)    -0.2771     0.0908   -3.05   0.0023 **
AgeGroup20291  -0.3420     0.1680   -2.04   0.0418 * 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 964.52  on 713  degrees of freedom
Residual deviance: 960.32  on 712  degrees of freedom
AIC: 964.3

Number of Fisher Scoring iterations: 4
  • Intercept: The log-odds of Survival for passengers that are not in the 20-29 age group is -0.277.
  • AgeGroup20291:
    • The difference in the log-odds of survival between passengers in the 20-29 age group and those who are not is -0.342 i.e. the chance of survival is lower for passenger in the 20-29 age group.
    • Given \(p < 0.5\), we can reject the null hypothesis (\(b_1=0\)) that there is no difference in the log-odds between the two groups.
    • Passengers in the 20-29 age group have 0.081 times the odds (i.e. -29%) of survival than thos who are not in that age group.


Continuous Explanatory Variable

model4 <- glm(Survived ~ Age, family=binomial(link='logit'), data=data)
summary(model4)

Call:
glm(formula = Survived ~ Age, family = binomial(link = "logit"), 
    data = data)

Deviance Residuals: 
   Min      1Q  Median      3Q     Max  
-1.149  -1.036  -0.954   1.316   1.591  

Coefficients:
            Estimate Std. Error z value Pr(>|z|)  
(Intercept) -0.05672    0.17358   -0.33     0.74  
Age         -0.01096    0.00533   -2.06     0.04 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 964.52  on 713  degrees of freedom
Residual deviance: 960.23  on 712  degrees of freedom
  (177 observations deleted due to missingness)
AIC: 964.2

Number of Fisher Scoring iterations: 4


Now let’s try the same with imputed ages:

data.impute <- data %>% kNN() # Note: there will be imputed ages < 1 ...
model5 <- glm(Survived ~ Age, family=binomial(link='logit'), data=data.impute)
summary(model5)

Call:
glm(formula = Survived ~ Age, family = binomial(link = "logit"), 
    data = data.impute)

Deviance Residuals: 
   Min      1Q  Median      3Q     Max  
-1.003  -0.988  -0.977   1.381   1.424  

Coefficients:
            Estimate Std. Error z value Pr(>|z|)   
(Intercept) -0.42433    0.16229   -2.61   0.0089 **
Age         -0.00172    0.00518   -0.33   0.7393   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 1186.7  on 890  degrees of freedom
Residual deviance: 1186.5  on 889  degrees of freedom
AIC: 1191

Number of Fisher Scoring iterations: 4
  • The model has worsened considerably. Given \(p > 0.5\), we cannot reject the null hypothesis \(b_1=0\) that one unit increase in age does not chnage the chances of survival.


Estimating the Odds of an outcome

To estimate the odds of an outcome from pluig in the relevant values into the model equation \(ln(odds) = b_0 + b_1x_1 + ... + b_kx_k\)

For example let’s estimate the odds of survival for

model6 <- glm(Survived ~ AgeGroup2029, family=binomial(link='logit'), data=na.omit(data))
model6$coefficients
  (Intercept) AgeGroup20291 
       -0.277        -0.342 

Now, in terms of probabilities:


  1. By default R assigns the reference group based on alphabetical order

  2. log-odds to odds-ratio: exp(log-odds)

  3. odds-ratio to %: (OR-1) * 100

LS0tCnRpdGxlOiAiSW50ZXJwcmV0aW5nIHRoZSBPdXRwdXQgb2YgYSBMb2dpc3RpYyBSZWdyZXNzaW9uIE1vZGVsIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9VFJVRX0Kb3B0aW9ucyhkaWdpdHM9MykKbGlicmFyeSh0aWR5dmVyc2UpCmF0dGFjaChkYXRhKQpgYGAKPGJyPgoKIyMjIEludHJvZHVjdGlvbgoKVGhpcyBhcnRpY2xlIGxvb2tzIGF0IGhvdyB0byBpbnRlcnByZXQgdGhlIG91dHB1dCBvZiB0aGUgYGdsbSgpYCBSIGZ1bmN0aW9uIHVzaW5nIHRoZSAqVGl0YW5pYyogdHJhaW4gZGF0YXNldC4KCkEgbm90ZSBvbiB0aGUgKipwLXZhbHVlKio6IHRoZSBwLXZhbHVlIGlzIGEgdGVzdCBvZiBzaWduaWZpY2FuY2UgZm9yIHRoZSBudWxsIGh5cG90aGVzaXMgJEhfMCQgdGhhdAoKKiB0aGVyZSBpcyBubyBkaWZmZXJlbmNlIGluIHRoZSBsb2ctb2RkcyBvZiB0aGUgb3V0Y29tZSBiZXR3ZWVuIHRoZSByZWZlcmVuY2UgZ3JvdXAgKGNhcHR1cmVkIGJ5IHRoZSBpbnRlcmNlcHQpIGFuZCB0aGUgZXhwbGFuYXRvcnkgdmFyaWFibGUgKG9yIG9uZSBvZiBpdHMgY2F0ZWdvcmllcyksIG9yIHRoYXQgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgdHdvIGdyb3VwcyBlcXVhbHMgemVybzogJEhfMDogYl8xID0gMCQgYW5kICRIX2E6IGJfMSBcbmVxIDAkLgoKSWYgcDwwLjUsIHdlIHJlamVjdCAkSF8wJCBhcyB3ZSBoYXZlIGV2aWRlbmNlIHRvIHN1Z2dlc3QgdGhhdCB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSB0d28gZ3JvdXBzIGRvZXMgbm90IGVxdWFsIHplcm8uCgoqKkxvZy1vZGRzKiogYXJlIG5vdCB0aGUgbW9zdCBpbnR1aXRpdmUgdG8gaW50ZXJwcmV0LiBJbnN0ZWFkIG9mIGRpc2N1c3NpbmcgdGhlIGNoYW5nZSBpbiB0aGUgbG9nLW9kZHMsIHdlIGNhbiBjYWxjdWxhdGUgdGhlIG9kZHMgcmF0aW8gZm9yIGEgZ2l2ZW4gdmFyaWFibGUgYnkgZXhwb25lbnRpYXRpbmcgdGhlIGNvZWZmaWNpZW50LiBPZGRzIHJhdGlvIGlzIHJlYWQgIipoYXZlIHggdGltZXMgdGhlIG9kZHMgb2YgdGhlIG91dGNvbWUgb2YgaW50ZXJlc3QgY29tcGFyZWQgdG8gdGhvcyBpbiB0aGUgcmVmZXJlbmNlIGdyb3VwKiIuCgoqKlJlZmVyZW5jZSBncm91cCBvZiB0aGUgb3V0Y29tZSB2YXJpYWJsZSoqOiBieSBkZWZhdWx0LCBSIGNyZWF0ZXMgdXNlcyB0aGUgbG93ZXN0IGNvZGVkIGdyb3VwIGFzIHRoZSByZWZlcmVuY2UuIFRoZSByZWZlcmVuY2UgY2F0ZWdvcnkgY2FuIGNlIGNoYW5nZWQgYnkgdXNpbmcgdGhlICdyZWxldmVsKCknLiBIZXJlLCAqKidub3Qgc3Vydml2ZWQnIChjb2RlZCAwKSBpcyB0aGUgcmVmZXJlbmNlIGdyb3VwISoqCgoqKlJlbGF0b25zaGlwIGJldHdlZW4gT2RkcyBhbmQgUHJvYmFiaWxpdGllcyoqOgoKKiBgT2Rkcz1QLygxLVApYAoqIGBQPW9kZHMvKDErb2RkcylgCiogYE9kZHM9ZXhwKGxvZy1vZGRzKWAKKiBgUD1leHAobG9nLW9kZHMpLygxK2V4cChsb2ctb2RkcykpYAoKCjxicj4KCiMjIyBDYXRlZ29yaWNhbCBFeHBsYW5hdG9yeSBWYXJpYWJsZSAoMiBDYXRlZ29yaWVzKQoKKiAqU3Vydml2ZWQqIGlzIG1vZGVsbGVkIGFzIGEgZnVuY3Rpb24gb2YgKlNleCouCiogUmVmZXJlbmNlIGdyb3VwIGlzICpmZW1hbGUqXltCeSBkZWZhdWx0IFIgYXNzaWducyB0aGUgcmVmZXJlbmNlIGdyb3VwIGJhc2VkIG9uIGFscGhhYmV0aWNhbCBvcmRlcl0uCgoKYGBge3J9Cm1vZGVsMSA8LSBnbG0oU3Vydml2ZWQgfiBTZXgsIGZhbWlseT1iaW5vbWlhbChsaW5rPSdsb2dpdCcpLCBkYXRhPWRhdGEpCnN1bW1hcnkobW9kZWwxKQpgYGAKCiogKipJbnRlcmNlcHQqKjogVGhlIGxvZy1vZGRzIG9mIFN1cnZpdmFsIGZvciB3b21lbiBpcyBgciBtb2RlbDEkY29lZmZpY2llbnRzWzFdYC4KKiAqKlNleG1hbGUqKjogCiAgICogVGhlIGRpZmZlcmVuY2UgaW4gdGhlIGxvZy1vZGRzIG9mIHN1cnZpdmFsIGJldHdlZW4gbWVuIGFuZCB3b21lbiBpcyBgciBtb2RlbDEkY29lZmZpY2llbnRzWzJdYCBpLmUuIHRoZSBjaGFuY2Ugb2Ygc3Vydml2YWwgaXMgbG93ZXIgZm9yIG1lbiB0aGFuIGZvciB3b21lbi4KICAgKiBHaXZlbiAkcCA8IDAuNSQsIHdlIGNhbiAqKnJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzKiogKCRiXzE9MCQpIHRoYXQgdGhlcmUgaXMgbm8gZGlmZmVyZW5jZSBpbiB0aGUgbG9nLW9kZHMgYmV0d2VlbiBtZW4gYW5kIHdvbWVuLgogICAqIE1lbiBoYXZlIGByIGV4cChtb2RlbDEkY29lZmZpY2llbnRzWzJdKWBeW2xvZy1vZGRzIHRvIG9kZHMtcmF0aW86IGV4cChsb2ctb2RkcyldIHRpbWVzIHRoZSBvZGRzIChpLmUuIGByIHJvdW5kKChleHAobW9kZWwxJGNvZWZmaWNpZW50c1syXSkgLSAxKSAqMTAwLDApYCAlKV5bb2Rkcy1yYXRpbyB0byAlOiAoT1ItMSkgKiAxMDBdIG9mIHN1cnZpdmFsIHRoYW4gd29tZW4uCiogKk51bGwgZGV2aWFuY2UqID0gU1NUb3QKKiAqUmVzaWR1YWwgZGV2aWFuY2UqID0gU1NSZXNpZAoKPGJyPgoKIyMjIENhdGVnb3JpY2FsIEV4cGxhbmF0b3J5IFZhcmlhYmxlIChNb3JlIHRoYW4gMiBDYXRlZ29yaWVzKQoKKiAqU3Vydml2ZWQqIGlzIG1vZGVsZWQgYXMgYSBmdW5jdGlvbiBvZiAqQWdlR3JvdXAqLgoqIE5vdGUgdGhhdCB0aGlzIG1vZGVsIGlzIHByb2R1Y2VkIGZyb20gdGhlIGRhdGEgKip3aXRob3V0KiogbWlzc2luZyBBZ2Ugcm93cy4KKiBUaGUgZGVmYXVsdCByZWZlcmVuY2UgZ3JvdXAgaXMgKjAtMTkqLgoKYGBge3J9Cm1vZGVsMiA8LSBnbG0oU3Vydml2ZWQgfiBBZ2VHcm91cCwgZmFtaWx5PWJpbm9taWFsKGxpbms9J2xvZ2l0JyksIAogICAgICAgICAgICAgIGRhdGE9bmEub21pdChkYXRhKSkKc3VtbWFyeShtb2RlbDIpCmBgYAoKKiAqKkludGVyY2VwdCoqOiB0aGUgbG9nLW9kZHMgb2Ygc3Vydml2YWwgZm9yIHNvbWVvbmUgYWdlZCAwLTE5IChyZWZlcmVuY2UgZ3JvdXApIGlzIGByIG1vZGVsMiRjb2VmZmljaWVudHNbMV1gLgoqIEZvciBlYWNoIG9mIHRoZSBvdGhlciBhZ2UgZ3JvdXBzLCB0aGUgY29lZmZpY2llbnQgdGVsbHMgdXMgdGhhdCB0aGUgbG9nLW9kZHMgb2Ygc3Vydml2YWwgZm9yIGEgZ2l2ZW4gZ3JvdXAgaXMgc21hbGxlciB0aGFuIHRoYXQgb2YgdGhlIHJlZmVyZW5jZSBncm91cC4KKiBXaGVyZSAkcD4wLjUkLCB0aGUgKipudWxsIGh5cG90aGVzaXMgJGJfaz0wJCBjYW5ub3QgYmUgcmVqZWN0ZWQqKiBpLmUuIHRoZXJlIGlzIGluc3VmZmljaWVudCBzdGF0aXN0aWNhbCBldmlkZW5jZSB0aGF0IHRoZSBjaGFuY2Ugb2Ygc3Vydml2YWwgaXMgc2lnbmlmaWNhbnRseSBzbWFsbGVyIGNvbXBhcmVkIHRvIHRoZSByZWZlcmVuY2UgZ3JvdXAuCgo8YnI+CgojIyMjIE5vdyBsZXQncyBjaGFuZ2UgdGhlIHJlZmVyZW5jZSBncm91cCB0byAyMC0zOToKCiogdGhpcyBpcyBzdGlsbCBuYXNlZCBvbiBkYXRhICoqd2l0aG91dCoqIG1pc3NpbmcgYWdlIHJvd3MuCgpgYGB7cn0KbGV2ZWxzKEFnZUdyb3VwKQpkYXRhJEFnZUdyb3VwUiA8LSByZWxldmVsKEFnZUdyb3VwLCByZWY9MikKbGV2ZWxzKGRhdGEkQWdlR3JvdXBSKSAjIG5ldyBjb2wgaXMgbm90IGF0dGFjaGVkIHNvIG11c3QgdXNlIGRhdGEkCm1vZGVsMyA8LSBnbG0oU3Vydml2ZWQgfiBBZ2VHcm91cFIsIGZhbWlseT1iaW5vbWlhbChsaW5rPSdsb2dpdCcpLCAKICAgICAgICAgICAgICBkYXRhPW5hLm9taXQoZGF0YSkpCnN1bW1hcnkobW9kZWwzKQpgYGAKCiogVGhlIGZpbmRpbmdzIGFyZSAid29yc2UiLiBOb3cgdGhlcmUgYXJlIHR3byBncm91cHMgd2l0aCAkcD4wLjUkLgoKPGJyPgoKIyMjIyBOb3cgbGV0J3MgdHJ5IHdpdGggYSBkaWZmZXJlbnQgY2F0ZWdvcmljYWwgYWdlIGdyb3VwIHZhcmlhYmxlICpBZ2VHcm91cDIwMjkqOgoKYGBge3J9CmxldmVscyhBZ2VHcm91cDIwMjkpCm1vZGVsMmIgPC0gZ2xtKFN1cnZpdmVkIH4gQWdlR3JvdXAyMDI5LCBmYW1pbHk9Ymlub21pYWwobGluaz0nbG9naXQnKSwgCiAgICAgICAgICAgICAgZGF0YT1uYS5vbWl0KGRhdGEpKQpzdW1tYXJ5KG1vZGVsMmIpCmBgYAoKKiAqKkludGVyY2VwdCoqOiBUaGUgbG9nLW9kZHMgb2YgU3Vydml2YWwgZm9yIHBhc3NlbmdlcnMgdGhhdCBhcmUgbm90IGluIHRoZSAyMC0yOSBhZ2UgZ3JvdXAgaXMgYHIgbW9kZWwyYiRjb2VmZmljaWVudHNbMV1gLgoqICoqQWdlR3JvdXAyMDI5MSoqOiAKICAgKiBUaGUgZGlmZmVyZW5jZSBpbiB0aGUgbG9nLW9kZHMgb2Ygc3Vydml2YWwgYmV0d2VlbiBwYXNzZW5nZXJzIGluIHRoZSAyMC0yOSBhZ2UgZ3JvdXAgYW5kIHRob3NlIHdobyBhcmUgbm90IGlzIGByIG1vZGVsMmIkY29lZmZpY2llbnRzWzJdYCBpLmUuIHRoZSBjaGFuY2Ugb2Ygc3Vydml2YWwgaXMgbG93ZXIgZm9yIHBhc3NlbmdlciBpbiB0aGUgMjAtMjkgYWdlIGdyb3VwLgogICAqIEdpdmVuICRwIDwgMC41JCwgd2UgY2FuICoqcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMqKiAoJGJfMT0wJCkgdGhhdCB0aGVyZSBpcyBubyBkaWZmZXJlbmNlIGluIHRoZSBsb2ctb2RkcyBiZXR3ZWVuIHRoZSB0d28gZ3JvdXBzLgogICAqIFBhc3NlbmdlcnMgaW4gdGhlIDIwLTI5IGFnZSBncm91cCBoYXZlIGByIGV4cChtb2RlbDEkY29lZmZpY2llbnRzWzJdKWAgdGltZXMgdGhlIG9kZHMgKGkuZS4gYHIgcm91bmQoKGV4cChtb2RlbDJiJGNvZWZmaWNpZW50c1syXSkgLSAxKSAqMTAwLDApYCUpIG9mIHN1cnZpdmFsIHRoYW4gdGhvcyB3aG8gYXJlIG5vdCBpbiB0aGF0IGFnZSBncm91cC4KICAgCjxicj4KCgojIyMgQ29udGludW91cyBFeHBsYW5hdG9yeSBWYXJpYWJsZQoKKiAqU3Vydml2ZWQqIGlzIG1vZGVsbGVkIGFzIGEgZnVuY3Rpb24gb2YgKkFnZSouCiogVGhlcmUgaXMgbm8gcmVmZXJlbmNlIGdyb3VwIGFzIHN1Y2guCiogKipSICJjYW4gZGVhbCB3aXRoIiBtaXNzaW5nIGRhdGEgZm9yIGEgY29udGludW91cyB2YXJpYWJsZSoqIGkuZS50aHJvd3Mgbm8gZXJyb3IgZHUgdG8gbWlzc2luZyBkYXRhIGluIHRoZSBjb250aW51b3VzIHZhcmlhYmxlLgoKYGBge3J9Cm1vZGVsNCA8LSBnbG0oU3Vydml2ZWQgfiBBZ2UsIGZhbWlseT1iaW5vbWlhbChsaW5rPSdsb2dpdCcpLCBkYXRhPWRhdGEpCnN1bW1hcnkobW9kZWw0KQpgYGAKCiogKipJbnRlcmNlcHQqKjogVGhlIGxvZy1vZGRzIG9mIFN1cnZpdmFsIHdoZW4gJEFnZSA9IDAkIGlzIGByIG1vZGVsNCRjb2VmZmljaWVudHNbMV1gLgoqICoqQWdlKio6IAogICAqIEZvciBldmVyeSB1bml0IGluY3JlYXNlIGluICpBZ2UqIHRoZSBsb2ctb2RkcyBvZiBzdXJ2aXZhbCBkZWNyZWFzZSBieSBgciBtb2RlbDQkY29lZmZpY2llbnRzWzJdYCBpLmUuIHRoZSBjaGFuY2VzIG9mIHN1cnZpdmFsIGRlY3JlYXNlIGFzIHBhc3NlbmdlciBhZ2UgaW5jcmVhc2VzLgogICAqIEdpdmVuICRwIDwgMC41JCwgd2UgY2FuICoqcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMqKiAkYl8xPTAkIHRoYXQgb25lIHVuaXQgaW5jcmVhc2UgaW4gYWdlIGRvZXMgbm90IGFmZmVjdCBjaGFuY2VzIG9mIHN1cnZpdmFsLgogICAqIEZvciBldmVyeSB1bml0IGluY3JlYXNlIGluICpBZ2UqLCB0aGUgb2RkcyBvZiBzdXJ2aXZhbCBhcmUgYHIgZXhwKG1vZGVsNCRjb2VmZmljaWVudHNbMl0pYCB0aW1lcyB0aGUgb2RkcyBvZiB0aG9zZSB3aXRoIG9uZSAqQWdlKiB1bml0IGxlc3MgKGkuZS4gYHIgcm91bmQoKGV4cChtb2RlbDQkY29lZmZpY2llbnRzWzJdKSAtIDEpICoxMDAsIDMpYCAlKS4KICAgCjxicj4KCiMjIyMgTm93IGxldCdzIHRyeSB0aGUgc2FtZSB3aXRoIGltcHV0ZWQgYWdlczoKCmBgYHtyfQpkYXRhLmltcHV0ZSA8LSBkYXRhICU+JSBrTk4oKSAjIE5vdGU6IHRoZXJlIHdpbGwgYmUgaW1wdXRlZCBhZ2VzIDwgMSAuLi4KbW9kZWw1IDwtIGdsbShTdXJ2aXZlZCB+IEFnZSwgZmFtaWx5PWJpbm9taWFsKGxpbms9J2xvZ2l0JyksIGRhdGE9ZGF0YS5pbXB1dGUpCnN1bW1hcnkobW9kZWw1KQpgYGAKCiogVGhlIG1vZGVsIGhhcyB3b3JzZW5lZCBjb25zaWRlcmFibHkuIEdpdmVuICRwID4gMC41JCwgd2UgY2Fubm90IHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzICRiXzE9MCQgdGhhdCBvbmUgdW5pdCBpbmNyZWFzZSBpbiBhZ2UgZG9lcyBub3QgY2huYWdlIHRoZSBjaGFuY2VzIG9mIHN1cnZpdmFsLgoKPGJyPgoKIyMjIEVzdGltYXRpbmcgdGhlIE9kZHMgb2YgYW4gb3V0Y29tZQoKVG8gZXN0aW1hdGUgdGhlIG9kZHMgb2YgYW4gb3V0Y29tZSBmcm9tIHBsdWlnIGluIHRoZSByZWxldmFudCB2YWx1ZXMgaW50byB0aGUgbW9kZWwgZXF1YXRpb24gJGxuKG9kZHMpID0gYl8wICsgYl8xeF8xICsgLi4uICsgYl9reF9rJAoKRm9yIGV4YW1wbGUgbGV0J3MgZXN0aW1hdGUgdGhlIG9kZHMgb2Ygc3Vydml2YWwgZm9yIAoKKiBhIHBhc3NlbmdlciB3aG8gaXMgYWdlZCBiZXR3ZWVuIDIwLTI5LCBhbmQgCiogZm9yIGEgcGFzc2VuZ2VyIHdobyBpcyBub3QgaW4gdGhhdCBhZ2UgZ3JvdXAKCmBgYHtyfQptb2RlbDYgPC0gZ2xtKFN1cnZpdmVkIH4gQWdlR3JvdXAyMDI5LCBmYW1pbHk9Ymlub21pYWwobGluaz0nbG9naXQnKSwgZGF0YT1uYS5vbWl0KGRhdGEpKQptb2RlbDYkY29lZmZpY2llbnRzCmBgYAoqIFJlZmVyZW5jZSBncm91cDogKkFnZUdyb3VwMjAyOTAqIChpLmUuIHRob3NlIHdobyBhcmUgTk9UIGFnZWQgMjAtMjkpLgoqIFJlY2FsbCB0aGF0LCBmb3IgY2F0ZWdvcmljYWwgZXhwbGFuYXRvcnkgdmFyaWFibGVzLCB0aGUgaW50ZXJjZXB0IHJlcHJlc2VudHMgdGhlIGxvZyBvZGRzIG9mIHRoZSBvdXRjb21lIGZvciB0aGUgcmVmZXJlbmNlIGdyb3VwLiBUaHVzLCBpbiB0aGlzIGNhc2UsIHRoZSBsb2dnLW9kZHMgb2Ygc3Vydml2YWwsIGlmIHRoZSBwYXNzZW5nZXIgaXMgbm90IGFnZWQgMjAtMjkgYXJlIGBsbihvZGRzKT1gJGJfMD0kIGByIG1vZGVsNiRjb2VmZmljaWVudHNbMV1gIGFuZCB0aGUgb2RkcyBvZiBzdXJ2aXZhbCBpcyAkZV57Yl8wfSQ6IGByIGV4cChtb2RlbDYkY29lZmZpY2llbnRzWzFdKWAuCiogVGhlIGxvZy1vZGRzIG9mIHN1cnZpdmFsIG9mIHRob3NlIHRoYXQgYXJlIGluIHRoZSBhZ2UgcmFuZ2UgMjAgdG8gMjkgYXJlIGBsbihvZGRzKT1gJGJfMCArIGJfMSQ9IGByIG1vZGVsNiRjb2VmZmljaWVudHNbMV0gKyBtb2RlbDYkY29lZmZpY2llbnRzWzJdYCBhbmQgdGhlIG9kZHMgb2Ygc3Vydml2YWwgKGFrYSBvZGRzIHJhdGlvKSBpcyAkZV57Yl8wK2JfMX0kOiBgciBleHAobW9kZWw2JGNvZWZmaWNpZW50c1sxXSArIG1vZGVsNiRjb2VmZmljaWVudHNbMl0pYC4KCk5vdywgaW4gdGVybXMgb2YgKipwcm9iYWJpbGl0aWVzKio6CgoqIFRoZSBwcm9iYWJpbGl0eSBvZiBub3Qgc3Vydml2aW5nIGZvciBwYXNzZW5nZXJzIGFnZWQgMjAtMjkgaXMgYFA9ZXhwKGJfMCkvKDErZXhwKGJfMCkpYDogYHIgZXhwKG1vZGVsNiRjb2VmZmljaWVudFsxXSkvKDErZXhwKG1vZGVsNiRjb2VmZmljaWVudFsxXSkpYCUuCiogVGhlIHByb2JhYmlsaXR5IG9mIG5vdCBzdXJ2aXZpbmcgZm9yIHBhc3NlbmdlcnMgbm90IGFnZWQgMjAtMjkgaXMgYFA9ZXhwKGxvZy1vZGRzKS8oMStleHAoYl8wK2JfMSkpYDogYHIgZXhwKG1vZGVsNiRjb2VmZmljaWVudFsxXSttb2RlbDYkY29lZmZpY2llbnRbMl0pLygxK2V4cChtb2RlbDYkY29lZmZpY2llbnRbMV0rbW9kZWw2JGNvZWZmaWNpZW50WzJdKSlgJS4KCgogICA=