source: https://sebastiansauer.github.io/convert_logit2prob/

Setting up everything

data(titanic_train, package = "titanic")
dat <- titanic_train  
rm(titanic_train)
table(dat$Pclass)

  1   2   3 
216 184 491 
reg <- glm(Survived ~ Pclass, data = dat, family = "binomial")
summary(reg)

Call:
glm(formula = Survived ~ Pclass, family = "binomial", data = dat)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-1.4390  -0.7569  -0.7569   0.9367   1.6673  

Coefficients:
            Estimate Std. Error z value Pr(>|z|)    
(Intercept)  1.44679    0.20743   6.975 3.06e-12 ***
Pclass      -0.85011    0.08715  -9.755  < 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: 1084.4  on 889  degrees of freedom
AIC: 1088.4

Number of Fisher Scoring iterations: 4

The estimated coefficients are in logits

paste("the estimated cofficients in LOGITs are", coef(reg)[1], "for the intercept. And", coef(reg)[2], "for the slope for Pclass")
[1] "the estimated cofficients in LOGITs are 1.44678953058191 for the intercept. And -0.850106746726404 for the slope for Pclass"

For interpretation on the raw output, all we can say about logits is that:

  if the logit is +ve, the qualitative effect of this predicator on the binary outcome is also +ve
  if the logit is -ve, the qualitative effect of this predicator on the binary outcome is also -ve
  

Example of converting logit to probability:

Suppose logit = 1, then the odds ratio = exp(1) approx.= 2.71 then the probability = exp(1) / (1 + exp(1)) approx.= 2.71 / (1 + 2.71) approx.= 0.75

Suppose logit = 0, then the odds ratio = exp(0) = 1 then the probability = exp(0) / (1 + exp(0)) = 1 / (1 + 1) = 0.5

Therefore, more specificially

  if logit < 0, the associated probability < 0.5
  if logit > 0, the associated probability > 0.5
  

Step 1:

From the logistic regression output, we have the following estimated equation

  logit_survival = 1.44679 + (-0.85011) * Pclass; where Pclass = 1,2,3
  
logits_survival_1 <- coef(reg)[1] + coef(reg)[2] * 1
logits_survival_2 <- coef(reg)[1] + coef(reg)[2] * 2
logits_survival_3 <- coef(reg)[1] + coef(reg)[2] * 3

paste("the logits of survival for Pclass 1 is", logits_survival_1)
[1] "the logits of survival for Pclass 1 is 0.596682783855506"
paste("the logits of survival for Pclass 2 is", logits_survival_2)
[1] "the logits of survival for Pclass 2 is -0.253423962870898"
paste("the logits of survival for Pclass 3 is", logits_survival_3)
[1] "the logits of survival for Pclass 3 is -1.1035307095973"

Step 2:

Convert to logits of survival to the probabilities of survival

prob_survival_1 <- exp(logits_survival_1) / (1 + exp(logits_survival_1))
prob_survival_2 <- exp(logits_survival_2) / (1 + exp(logits_survival_2))
prob_survival_3 <- exp(logits_survival_3) / (1 + exp(logits_survival_3))

paste("the probabilities of survival for Pclass 1 is", prob_survival_1)
[1] "the probabilities of survival for Pclass 1 is 0.644897013275819"
paste("the probabilities of survival for Pclass 2 is", prob_survival_2)
[1] "the probabilities of survival for Pclass 2 is 0.43698092535236"
paste("the probabilities of survival for Pclass 3 is", prob_survival_3)
[1] "the probabilities of survival for Pclass 3 is 0.24907893048446"

Note that the following equation also works:

  prob = 0.5 * (1 + tanh(logit / 2))
  
prob_survival_1b <- 0.5 * (1 + tanh(logits_survival_1 / 2))
prob_survival_2b <- 0.5 * (1 + tanh(logits_survival_2 / 2))
prob_survival_3b <- 0.5 * (1 + tanh(logits_survival_3 / 2))

paste("the probabilities of survival for Pclass 1 is", prob_survival_1b)
[1] "the probabilities of survival for Pclass 1 is 0.644897013275819"
paste("the probabilities of survival for Pclass 2 is", prob_survival_2b)
[1] "the probabilities of survival for Pclass 2 is 0.43698092535236"
paste("the probabilities of survival for Pclass 3 is", prob_survival_3b)
[1] "the probabilities of survival for Pclass 3 is 0.24907893048446"

there is an in-built function for this:

paste("the probabilities of survival for Pclass 1 is",
      predict(reg, data.frame(Pclass = 1), type = "response")
      )
[1] "the probabilities of survival for Pclass 1 is 0.644897013275819"
paste("the probabilities of survival for Pclass 2 is",
      predict(reg, data.frame(Pclass = 2), type = "response")
      )
[1] "the probabilities of survival for Pclass 2 is 0.43698092535236"
paste("the probabilities of survival for Pclass 3 is",
      predict(reg, data.frame(Pclass = 3), type = "response")
      )
[1] "the probabilities of survival for Pclass 3 is 0.24907893048446"

Step 3:

For the marginal effects, let’s examine the effect on survival from i) changing from Pclass 1 to Pclass 2 ii) changing from Pclass 2 to Pclass 3 in terms of logits

paste("the effect on survivial in LOGIT from changing from Pclass 1 to Pclass 2 is", logits_survival_2 - logits_survival_1)
[1] "the effect on survivial in LOGIT from changing from Pclass 1 to Pclass 2 is -0.850106746726404"
paste("the effect on survivial in LOGIT from changing from Pclass 2 to Pclass 3 is", logits_survival_3 - logits_survival_2)
[1] "the effect on survivial in LOGIT from changing from Pclass 2 to Pclass 3 is -0.850106746726404"
paste("note that the difference, independent of actual Pclass value, is exactly the estimated SLOPE COEFFICIENT", coef(reg)[2])
[1] "note that the difference, independent of actual Pclass value, is exactly the estimated SLOPE COEFFICIENT -0.850106746726404"

Now we try to compute the marginal effects in terms of probabilities by using a) compute probability ME from the difference in logits (i.e. the slope coefficient) b) compute the incremental difference in probabilities at each Pclass

prob_ME_a <- exp(coef(reg)[2]) / (1 + exp(coef(reg)[2]))

paste("the result in probability ME from the slope cofficient is", prob_ME_a)
[1] "the result in probability ME from the slope cofficient is 0.299410465443492"
paste("the effect on survivial in PROB from changing from Pclass 1 to Pclass 2 is", prob_survival_2 - prob_survival_1)
[1] "the effect on survivial in PROB from changing from Pclass 1 to Pclass 2 is -0.207916087923458"
paste("the effect on survivial in PROB from changing from Pclass 2 to Pclass 3 is", prob_survival_3 - prob_survival_2)
[1] "the effect on survivial in PROB from changing from Pclass 2 to Pclass 3 is -0.1879019948679"

Explanation:

  logit(prob) = log(prob / (1 - prob)) = b0 + b1 * x
  
  prob = exp(b0 + b1 * x) / (1 + exp(b0 + b1 * x)) 
  => prob(logit) = exp(logit(prob)) / (1 + exp(logit(prob)))
  

For discrete marginal effects (no difference in the continuous case),

A 1-unit change in x, changes the LOGIT by

  logit(.|x = 2) - logit(.|x = 1)
  = b0 + b1 * 2 - (b0 + b1 * 1)
  = b1
  

A 1-unit change in x, changes the PROB by

  prob(.| x = 2) - prob(. |x = 1)
  = [exp(b0 + b1 * 2) / (1 + exp(b0 + b1 * 2))] - [exp(b0 + b1 * 1) / (1 + exp(b0 + b1 * 1))]
  != b1 
  furthermore, != a constant 
  
  That is, delta(logit) = constant
  but, delta(prob) = f(x)

Therefore, in step 3, approach a is WRONG and approach b is CORRECT

paste("the effect on survivial in PROB from changing from Pclass 1 to Pclass 2 is", 
      (exp(logits_survival_2) / (1 + exp(logits_survival_2))) - (exp(logits_survival_1) / (1 + exp(logits_survival_1))))
[1] "the effect on survivial in PROB from changing from Pclass 1 to Pclass 2 is -0.207916087923458"
paste("the effect on survivial in PROB from changing from Pclass 2 to Pclass 3 is", 
      (exp(logits_survival_3) / (1 + exp(logits_survival_3))) - (exp(logits_survival_2) / (1 + exp(logits_survival_2))))
[1] "the effect on survivial in PROB from changing from Pclass 2 to Pclass 3 is -0.1879019948679"
LS0tCnRpdGxlOiAibG9naXQgdG8gcHJvYiBJSSIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyMjIHNvdXJjZTogaHR0cHM6Ly9zZWJhc3RpYW5zYXVlci5naXRodWIuaW8vY29udmVydF9sb2dpdDJwcm9iLwoKU2V0dGluZyB1cCBldmVyeXRoaW5nCgpgYGB7cn0KZGF0YSh0aXRhbmljX3RyYWluLCBwYWNrYWdlID0gInRpdGFuaWMiKQpkYXQgPC0gdGl0YW5pY190cmFpbiAgCnJtKHRpdGFuaWNfdHJhaW4pCmBgYAoKYGBge3J9CnRhYmxlKGRhdCRQY2xhc3MpCgpyZWcgPC0gZ2xtKFN1cnZpdmVkIH4gUGNsYXNzLCBkYXRhID0gZGF0LCBmYW1pbHkgPSAiYmlub21pYWwiKQpzdW1tYXJ5KHJlZykKYGBgCgpUaGUgZXN0aW1hdGVkIGNvZWZmaWNpZW50cyBhcmUgaW4gKmxvZ2l0cyoKCmBgYHtyfQpwYXN0ZSgidGhlIGVzdGltYXRlZCBjb2ZmaWNpZW50cyBpbiBMT0dJVHMgYXJlIiwgY29lZihyZWcpWzFdLCAiZm9yIHRoZSBpbnRlcmNlcHQuIEFuZCIsIGNvZWYocmVnKVsyXSwgImZvciB0aGUgc2xvcGUgZm9yIFBjbGFzcyIpCmBgYAoKIyMgRm9yIGludGVycHJldGF0aW9uIG9uIHRoZSByYXcgb3V0cHV0LCBhbGwgd2UgY2FuIHNheSBhYm91dCBsb2dpdHMgaXMgdGhhdDoKCiAgICAgIGlmIHRoZSBsb2dpdCBpcyArdmUsIHRoZSBxdWFsaXRhdGl2ZSBlZmZlY3Qgb2YgdGhpcyBwcmVkaWNhdG9yIG9uIHRoZSBiaW5hcnkgb3V0Y29tZSBpcyBhbHNvICt2ZQogICAgICBpZiB0aGUgbG9naXQgaXMgLXZlLCB0aGUgcXVhbGl0YXRpdmUgZWZmZWN0IG9mIHRoaXMgcHJlZGljYXRvciBvbiB0aGUgYmluYXJ5IG91dGNvbWUgaXMgYWxzbyAtdmUKICAgICAgCiMjIyBFeGFtcGxlIG9mIGNvbnZlcnRpbmcgbG9naXQgdG8gcHJvYmFiaWxpdHk6CgpTdXBwb3NlIGxvZ2l0ID0gMSwKdGhlbiB0aGUgb2RkcyByYXRpbyA9IGV4cCgxKSBhcHByb3guPSAyLjcxCnRoZW4gdGhlIHByb2JhYmlsaXR5ID0gZXhwKDEpIC8gKDEgKyBleHAoMSkpIGFwcHJveC49IDIuNzEgLyAoMSArIDIuNzEpIGFwcHJveC49IDAuNzUKClN1cHBvc2UgbG9naXQgPSAwLAp0aGVuIHRoZSBvZGRzIHJhdGlvID0gZXhwKDApID0gMQp0aGVuIHRoZSBwcm9iYWJpbGl0eSA9IGV4cCgwKSAvICgxICsgZXhwKDApKSAgPSAxIC8gKDEgKyAxKSA9IDAuNQoKIyMjIFRoZXJlZm9yZSwgbW9yZSBzcGVjaWZpY2lhbGx5CgogICAgICBpZiBsb2dpdCA8IDAsIHRoZSBhc3NvY2lhdGVkIHByb2JhYmlsaXR5IDwgMC41CiAgICAgIGlmIGxvZ2l0ID4gMCwgdGhlIGFzc29jaWF0ZWQgcHJvYmFiaWxpdHkgPiAwLjUKICAgICAgCiMgU3RlcCAxOgpGcm9tIHRoZSBsb2dpc3RpYyByZWdyZXNzaW9uIG91dHB1dCwgd2UgaGF2ZSB0aGUgZm9sbG93aW5nIGVzdGltYXRlZCBlcXVhdGlvbgoKICAgICAgbG9naXRfc3Vydml2YWwgPSAxLjQ0Njc5ICsgKC0wLjg1MDExKSAqIFBjbGFzczsgd2hlcmUgUGNsYXNzID0gMSwyLDMKICAgICAgCmBgYHtyfQpsb2dpdHNfc3Vydml2YWxfMSA8LSBjb2VmKHJlZylbMV0gKyBjb2VmKHJlZylbMl0gKiAxCmxvZ2l0c19zdXJ2aXZhbF8yIDwtIGNvZWYocmVnKVsxXSArIGNvZWYocmVnKVsyXSAqIDIKbG9naXRzX3N1cnZpdmFsXzMgPC0gY29lZihyZWcpWzFdICsgY29lZihyZWcpWzJdICogMwoKcGFzdGUoInRoZSBsb2dpdHMgb2Ygc3Vydml2YWwgZm9yIFBjbGFzcyAxIGlzIiwgbG9naXRzX3N1cnZpdmFsXzEpCnBhc3RlKCJ0aGUgbG9naXRzIG9mIHN1cnZpdmFsIGZvciBQY2xhc3MgMiBpcyIsIGxvZ2l0c19zdXJ2aXZhbF8yKQpwYXN0ZSgidGhlIGxvZ2l0cyBvZiBzdXJ2aXZhbCBmb3IgUGNsYXNzIDMgaXMiLCBsb2dpdHNfc3Vydml2YWxfMykKYGBgCgojIFN0ZXAgMjoKQ29udmVydCB0byBsb2dpdHMgb2Ygc3Vydml2YWwgdG8gdGhlIHByb2JhYmlsaXRpZXMgb2Ygc3Vydml2YWwKCmBgYHtyfQpwcm9iX3N1cnZpdmFsXzEgPC0gZXhwKGxvZ2l0c19zdXJ2aXZhbF8xKSAvICgxICsgZXhwKGxvZ2l0c19zdXJ2aXZhbF8xKSkKcHJvYl9zdXJ2aXZhbF8yIDwtIGV4cChsb2dpdHNfc3Vydml2YWxfMikgLyAoMSArIGV4cChsb2dpdHNfc3Vydml2YWxfMikpCnByb2Jfc3Vydml2YWxfMyA8LSBleHAobG9naXRzX3N1cnZpdmFsXzMpIC8gKDEgKyBleHAobG9naXRzX3N1cnZpdmFsXzMpKQoKcGFzdGUoInRoZSBwcm9iYWJpbGl0aWVzIG9mIHN1cnZpdmFsIGZvciBQY2xhc3MgMSBpcyIsIHByb2Jfc3Vydml2YWxfMSkKcGFzdGUoInRoZSBwcm9iYWJpbGl0aWVzIG9mIHN1cnZpdmFsIGZvciBQY2xhc3MgMiBpcyIsIHByb2Jfc3Vydml2YWxfMikKcGFzdGUoInRoZSBwcm9iYWJpbGl0aWVzIG9mIHN1cnZpdmFsIGZvciBQY2xhc3MgMyBpcyIsIHByb2Jfc3Vydml2YWxfMykKYGBgCgojIyBOb3RlIHRoYXQgdGhlIGZvbGxvd2luZyBlcXVhdGlvbiBhbHNvIHdvcmtzOgoKICAgICAgcHJvYiA9IDAuNSAqICgxICsgdGFuaChsb2dpdCAvIDIpKQogICAgICAKYGBge3J9CnByb2Jfc3Vydml2YWxfMWIgPC0gMC41ICogKDEgKyB0YW5oKGxvZ2l0c19zdXJ2aXZhbF8xIC8gMikpCnByb2Jfc3Vydml2YWxfMmIgPC0gMC41ICogKDEgKyB0YW5oKGxvZ2l0c19zdXJ2aXZhbF8yIC8gMikpCnByb2Jfc3Vydml2YWxfM2IgPC0gMC41ICogKDEgKyB0YW5oKGxvZ2l0c19zdXJ2aXZhbF8zIC8gMikpCgpwYXN0ZSgidGhlIHByb2JhYmlsaXRpZXMgb2Ygc3Vydml2YWwgZm9yIFBjbGFzcyAxIGlzIiwgcHJvYl9zdXJ2aXZhbF8xYikKcGFzdGUoInRoZSBwcm9iYWJpbGl0aWVzIG9mIHN1cnZpdmFsIGZvciBQY2xhc3MgMiBpcyIsIHByb2Jfc3Vydml2YWxfMmIpCnBhc3RlKCJ0aGUgcHJvYmFiaWxpdGllcyBvZiBzdXJ2aXZhbCBmb3IgUGNsYXNzIDMgaXMiLCBwcm9iX3N1cnZpdmFsXzNiKQpgYGAKCiMjIHRoZXJlIGlzIGFuIGluLWJ1aWx0IGZ1bmN0aW9uIGZvciB0aGlzOgoKYGBge3J9CnBhc3RlKCJ0aGUgcHJvYmFiaWxpdGllcyBvZiBzdXJ2aXZhbCBmb3IgUGNsYXNzIDEgaXMiLAogICAgICBwcmVkaWN0KHJlZywgZGF0YS5mcmFtZShQY2xhc3MgPSAxKSwgdHlwZSA9ICJyZXNwb25zZSIpCiAgICAgICkKCnBhc3RlKCJ0aGUgcHJvYmFiaWxpdGllcyBvZiBzdXJ2aXZhbCBmb3IgUGNsYXNzIDIgaXMiLAogICAgICBwcmVkaWN0KHJlZywgZGF0YS5mcmFtZShQY2xhc3MgPSAyKSwgdHlwZSA9ICJyZXNwb25zZSIpCiAgICAgICkKCnBhc3RlKCJ0aGUgcHJvYmFiaWxpdGllcyBvZiBzdXJ2aXZhbCBmb3IgUGNsYXNzIDMgaXMiLAogICAgICBwcmVkaWN0KHJlZywgZGF0YS5mcmFtZShQY2xhc3MgPSAzKSwgdHlwZSA9ICJyZXNwb25zZSIpCiAgICAgICkKYGBgCgojIFN0ZXAgMzoKRm9yIHRoZSBtYXJnaW5hbCBlZmZlY3RzLCBsZXQncyBleGFtaW5lIHRoZSBlZmZlY3Qgb24gc3Vydml2YWwgZnJvbQppKSBjaGFuZ2luZyBmcm9tIFBjbGFzcyAxIHRvIFBjbGFzcyAyCmlpKSBjaGFuZ2luZyBmcm9tIFBjbGFzcyAyIHRvIFBjbGFzcyAzCmluIHRlcm1zIG9mIGxvZ2l0cwoKYGBge3J9CnBhc3RlKCJ0aGUgZWZmZWN0IG9uIHN1cnZpdmlhbCBpbiBMT0dJVCBmcm9tIGNoYW5naW5nIGZyb20gUGNsYXNzIDEgdG8gUGNsYXNzIDIgaXMiLCBsb2dpdHNfc3Vydml2YWxfMiAtIGxvZ2l0c19zdXJ2aXZhbF8xKQoKcGFzdGUoInRoZSBlZmZlY3Qgb24gc3Vydml2aWFsIGluIExPR0lUIGZyb20gY2hhbmdpbmcgZnJvbSBQY2xhc3MgMiB0byBQY2xhc3MgMyBpcyIsIGxvZ2l0c19zdXJ2aXZhbF8zIC0gbG9naXRzX3N1cnZpdmFsXzIpCgpwYXN0ZSgibm90ZSB0aGF0IHRoZSBkaWZmZXJlbmNlLCBpbmRlcGVuZGVudCBvZiBhY3R1YWwgUGNsYXNzIHZhbHVlLCBpcyBleGFjdGx5IHRoZSBlc3RpbWF0ZWQgU0xPUEUgQ09FRkZJQ0lFTlQiLCBjb2VmKHJlZylbMl0pCmBgYAoKTm93IHdlIHRyeSB0byBjb21wdXRlIHRoZSBtYXJnaW5hbCBlZmZlY3RzIGluIHRlcm1zIG9mIHByb2JhYmlsaXRpZXMgYnkgdXNpbmcKYSkgY29tcHV0ZSBwcm9iYWJpbGl0eSBNRSBmcm9tIHRoZSBkaWZmZXJlbmNlIGluIGxvZ2l0cyAoaS5lLiB0aGUgc2xvcGUgY29lZmZpY2llbnQpCmIpIGNvbXB1dGUgdGhlIGluY3JlbWVudGFsIGRpZmZlcmVuY2UgaW4gcHJvYmFiaWxpdGllcyBhdCBlYWNoIFBjbGFzcwoKYGBge3J9CnByb2JfTUVfYSA8LSBleHAoY29lZihyZWcpWzJdKSAvICgxICsgZXhwKGNvZWYocmVnKVsyXSkpCgpwYXN0ZSgidGhlIHJlc3VsdCBpbiBwcm9iYWJpbGl0eSBNRSBmcm9tIHRoZSBzbG9wZSBjb2ZmaWNpZW50IGlzIiwgcHJvYl9NRV9hKQpgYGAKCmBgYHtyfQpwYXN0ZSgidGhlIGVmZmVjdCBvbiBzdXJ2aXZpYWwgaW4gUFJPQiBmcm9tIGNoYW5naW5nIGZyb20gUGNsYXNzIDEgdG8gUGNsYXNzIDIgaXMiLCBwcm9iX3N1cnZpdmFsXzIgLSBwcm9iX3N1cnZpdmFsXzEpCgpwYXN0ZSgidGhlIGVmZmVjdCBvbiBzdXJ2aXZpYWwgaW4gUFJPQiBmcm9tIGNoYW5naW5nIGZyb20gUGNsYXNzIDIgdG8gUGNsYXNzIDMgaXMiLCBwcm9iX3N1cnZpdmFsXzMgLSBwcm9iX3N1cnZpdmFsXzIpCmBgYAoKIyBFeHBsYW5hdGlvbjoKCiAgICAgIGxvZ2l0KHByb2IpID0gbG9nKHByb2IgLyAoMSAtIHByb2IpKSA9IGIwICsgYjEgKiB4CiAgICAgIAogICAgICBwcm9iID0gZXhwKGIwICsgYjEgKiB4KSAvICgxICsgZXhwKGIwICsgYjEgKiB4KSkgCiAgICAgID0+IHByb2IobG9naXQpID0gZXhwKGxvZ2l0KHByb2IpKSAvICgxICsgZXhwKGxvZ2l0KHByb2IpKSkKICAgICAgCkZvciBkaXNjcmV0ZSBtYXJnaW5hbCBlZmZlY3RzIChubyBkaWZmZXJlbmNlIGluIHRoZSBjb250aW51b3VzIGNhc2UpLAoKQSAxLXVuaXQgY2hhbmdlIGluIHgsIGNoYW5nZXMgdGhlIExPR0lUIGJ5CgogICAgICBsb2dpdCgufHggPSAyKSAtIGxvZ2l0KC58eCA9IDEpCiAgICAgID0gYjAgKyBiMSAqIDIgLSAoYjAgKyBiMSAqIDEpCiAgICAgID0gYjEKICAgICAgCkEgMS11bml0IGNoYW5nZSBpbiB4LCBjaGFuZ2VzIHRoZSBQUk9CIGJ5CgogICAgICBwcm9iKC58IHggPSAyKSAtIHByb2IoLiB8eCA9IDEpCiAgICAgID0gW2V4cChiMCArIGIxICogMikgLyAoMSArIGV4cChiMCArIGIxICogMikpXSAtIFtleHAoYjAgKyBiMSAqIDEpIC8gKDEgKyBleHAoYjAgKyBiMSAqIDEpKV0KICAgICAgIT0gYjEgCiAgICAgIGZ1cnRoZXJtb3JlLCAhPSBhIGNvbnN0YW50IAogICAgICAKICAgICAgVGhhdCBpcywgZGVsdGEobG9naXQpID0gY29uc3RhbnQKICAgICAgYnV0LCBkZWx0YShwcm9iKSA9IGYoeCkKClRoZXJlZm9yZSwgaW4gc3RlcCAzLCBhcHByb2FjaCBhIGlzIFdST05HIGFuZCBhcHByb2FjaCBiIGlzIENPUlJFQ1QKICAgICAgCmBgYHtyfQpwYXN0ZSgidGhlIGVmZmVjdCBvbiBzdXJ2aXZpYWwgaW4gUFJPQiBmcm9tIGNoYW5naW5nIGZyb20gUGNsYXNzIDEgdG8gUGNsYXNzIDIgaXMiLCAKICAgICAgKGV4cChsb2dpdHNfc3Vydml2YWxfMikgLyAoMSArIGV4cChsb2dpdHNfc3Vydml2YWxfMikpKSAtIChleHAobG9naXRzX3N1cnZpdmFsXzEpIC8gKDEgKyBleHAobG9naXRzX3N1cnZpdmFsXzEpKSkpCgpwYXN0ZSgidGhlIGVmZmVjdCBvbiBzdXJ2aXZpYWwgaW4gUFJPQiBmcm9tIGNoYW5naW5nIGZyb20gUGNsYXNzIDIgdG8gUGNsYXNzIDMgaXMiLCAKICAgICAgKGV4cChsb2dpdHNfc3Vydml2YWxfMykgLyAoMSArIGV4cChsb2dpdHNfc3Vydml2YWxfMykpKSAtIChleHAobG9naXRzX3N1cnZpdmFsXzIpIC8gKDEgKyBleHAobG9naXRzX3N1cnZpdmFsXzIpKSkpCmBgYAo=