Case 1:

Dados referentes a três variáveis psicológicas (locus_of_control, self_concept, motivation), quatro variáveis acadêmicas (read, write, math, science) e uma varáveis demográfica (female) foram coletados de 600 calouros da UNICAMP. O SAE (serviço de apoio ao estudante) está interessado em saber como as variáveis psicológicas se relacionam com as variáveis acadêmicas.

O data set está disponível aqui mas está em formado *.dta (STATA) 😞.

library(dplyr)
library(haven) 
library(corrplot)
library(CCA)
# Importar data set
unicamp <- read_dta("datasets/mmreg.dta")
glimpse(unicamp)
Rows: 600
Columns: 9
$ id               <dbl> 303, 404, 225, 553, 433, 189, 336, 321, 358,…
$ locus_of_control <dbl> -0.84, -0.38, 0.89, 0.71, -0.64, 1.11, 0.06,…
$ self_concept     <dbl> -0.24, -0.47, 0.59, 0.28, 0.03, 0.90, 0.03, …
$ motivation       <dbl> 1.00, 0.67, 0.67, 0.67, 1.00, 0.33, 0.67, 0.…
$ read             <dbl> 54.8, 62.7, 60.6, 62.7, 41.6, 62.7, 41.6, 44…
$ write            <dbl> 64.5, 43.7, 56.7, 56.7, 46.3, 64.5, 39.1, 39…
$ math             <dbl> 44.5, 44.7, 70.5, 54.7, 38.4, 61.4, 56.3, 46…
$ science          <dbl> 52.6, 52.6, 58.0, 58.0, 36.3, 58.0, 45.0, 36…
$ female           <dbl> 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1,…
# Separamos os conjuntos de dados em X e Y
X <- unicamp %>% dplyr::select(locus_of_control, self_concept, motivation)
Y <- unicamp %>% dplyr::select(read, write, math, science)
# Como passo prévio, veremos se existe correlação entre as variáveis de ambos os conjuntos
unicamp %>% 
  dplyr::select(-id, -female) %>% 
  cor() %>% 
  corrplot(method = "color")

# Aplicamos CC
cc_resultados <- cc(X, Y)
# Correlação das variáveis canônicas
cc_resultados$cor
[1] 0.44643648 0.15335902 0.02250348
# Quais as combinações lineares para formar as variáves canónicas?
cc_resultados$xcoef
                       [,1]       [,2]       [,3]
locus_of_control -1.2501212  0.7659633  0.4966529
self_concept      0.2367331  0.8421110 -1.2051226
motivation       -1.2491434 -2.6359626 -1.0935084
# Quais as combinações lineares para formar as variáves canónicas?
cc_resultados$ycoef
                [,1]         [,2]        [,3]
read    -0.044047126 -0.001592913 -0.08833162
write   -0.055088843 -0.090414603  0.09612884
math    -0.019401099 -0.002955461 -0.08782254
science  0.003797757  0.124208982  0.08849518

Até aqui, temos feito tudo o visto nos slides. Contudo, sob normalidade multivariada, podemos ir além e fazer inferência estatística.

Testar se X e Y são não correlacionados.

  • Sob normalidade e utilizando o TRV chegamos na seguinte estatística de teste \[|\textbf{I} - \textbf{S}_{YY}^{-1}\textbf{S}_{YX} \textbf{S}_{XX}^{-1} \textbf{SY}| = \displaystyle \prod_{i = 1}^k(1-l_i).\]
  • Utilizando a aproximação de Barlett (1939), temos que \[-[n - (p + q + 3)/2] \displaystyle \sum_{i = 1}^k \log(1-l_i) \sim \chi^2_{pq}\]
mvnormalTest::mardia(cbind(X,Y))
$mv.test

$uv.shapiro
                 W      p-value UV.Normality
locus_of_control 0.971  0       No          
self_concept     0.941  0       No          
motivation       0.8238 0       No          
read             0.9816 0       No          
write            0.9533 0       No          
math             0.9835 0       No          
science          0.983  0       No          
aux <- as.matrix(cbind(X,Y))
mnt::test.BHEP(aux, MC.rep = 1000)  # Rejeitamos H0

Os dados não são normalmente distribuidos. Apenas a maneira de exemplo continuaremos com inferência estatística.

n <- nrow(unicamp)
p <- ncol(X)
q <- ncol(Y)
l <- cc_resultados$cor^2 #(Lembre que SVD fornece em D a raiz dos autovalores)
e_teste <- -(n - (p + q + 3)/2)*sum(log(1 - l))
e_teste
[1] 146.7165
x2 <- qchisq(0.95, p*q)
ifelse(e_teste > x2, "Rejeitamos H0", "Não rejeitamos H0")
[1] "Rejeitamos H0"

Testar que a correlaão de apenas k - s variáveis canônicas são diferentes de zero.

\[-[n - (p + q + 3)/2] \displaystyle \sum_{i = s + 1}^k \log(1-l_i) \sim \chi^2_{(p - s)(q - s)}\]

s <- 0  # Caso anterior
k <- 3
e_teste <- -(n - (p + q + 3)/2)*sum(log(1 - l)[(s + 1):k])
e_teste
[1] 146.7165
x2 <- qchisq(0.95, (p - s)*(q - s))
ifelse(e_teste > x2, "Rejeitamos H0", "Não rejeitamos H0")
[1] "Rejeitamos H0"
s <- 1  
k <- 3
e_teste <- -(n - (p + q + 3)/2)*sum(log(1 - l)[(s + 1):k])
e_teste
[1] 14.46237
x2 <- qchisq(0.95, (p - s)*(q - s))
ifelse(e_teste > x2, "Rejeitamos H0", "Não rejeitamos H0")
[1] "Rejeitamos H0"
s <- 2  
k <- 3
e_teste <- -(n - (p + q + 3)/2)*sum(log(1 - l)[(s + 1):k])
e_teste
[1] 0.3013883
x2 <- qchisq(0.95, (p - s)*(q - s))
ifelse(e_teste > x2, "Rejeitamos H0", "Não rejeitamos H0")
[1] "Não rejeitamos H0"
  • Apenas as 2 primeiras variáveis canônicas tem correlação diferentes de zero.

Case 2:

Roberto Fulcherberguer, o CEO das Casas Bahia, está interessado em saber se existe alguma relação entre o desempenho das vendas (mensurado através das variáveis Sales Growth, Sales Profitability, New Account Sales) e a inteligência dos gerentes da loja (mensurado através das variáveis Creativity, Mechanical Reasoning, Abstract Reasoning, Mathematics). Para fazer as análises, \(n = 50\) lojas são selecionadas aleatoriamente e as variáveis de interesse são obtidas.

O data set está disponível aqui.

# Importar dados
casas_bahia <- read.table("datasets/sales.txt")
colnames(casas_bahia) <- c("growth", "profit", "new",
                           "create", "mechanical", "abs", "math")
glimpse(casas_bahia)
Rows: 50
Columns: 7
$ growth     <dbl> 93.0, 88.8, 95.0, 101.3, 1…
$ profit     <dbl> 96.0, 91.8, 100.3, 103.8, …
$ new        <dbl> 97.8, 96.8, 99.0, 106.8, 1…
$ create     <int> 9, 7, 8, 13, 10, 10, 9, 18…
$ mechanical <int> 12, 10, 12, 14, 15, 14, 12…
$ abs        <int> 9, 10, 9, 12, 12, 11, 9, 1…
$ math       <int> 20, 15, 26, 29, 32, 21, 25…
# Separamos os conjuntos de dados em X e Y
X <- casas_bahia %>% dplyr::select(growth, profit, new)
Y <- casas_bahia %>% dplyr::select(create, mechanical, abs, math)
# Correlação entre as variáveis
casas_bahia %>% 
  cor() %>% 
  corrplot(method = "color")

# Aplicamos CC
cc_cb <- cc(X, Y)
# Correlação das variáveis canônicas
cc_cb$cor
[1] 0.9944827 0.8781065 0.3836057
# Quais as combinações lineares para formar as variáves canónicas?
cc_cb$xcoef
              [,1]       [,2]       [,3]
growth -0.06237788 -0.1740703  0.3771529
profit -0.02092564  0.2421641 -0.1035150
new    -0.07825817 -0.2382940 -0.3834151
# Quais as combinações lineares para formar as variáves canónicas?
cc_cb$ycoef
                  [,1]        [,2]        [,3]
create     -0.06974814 -0.19239132 -0.24655659
mechanical -0.03073830  0.20157438  0.14189528
abs        -0.08956418 -0.49576326  0.28022405
math       -0.06282997  0.06831607 -0.01133259
mvnormalTest::mardia(cbind(X,Y))
$mv.test

$uv.shapiro
           W      p-value UV.Normality
growth     0.9401 0.0135  No          
profit     0.9557 0.0589  Yes         
new        0.9781 0.4732  Yes         
create     0.9604 0.0921  Yes         
mechanical 0.9723 0.287   Yes         
abs        0.9482 0.0287  No          
math       0.9768 0.4255  Yes         
LS0tCnRpdGxlOiAiQW7DoWxpc2UgZGUgQ29ycmVsYcOnw6NvIENhbsO0bmljYSIKYXV0aG9yOiAiUHJvZi4gQ2FybG9zIFRydWPDrW9zIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgojIyBDYXNlIDE6CgpEYWRvcyByZWZlcmVudGVzIGEgdHLDqnMgdmFyacOhdmVpcyBwc2ljb2zDs2dpY2FzIChsb2N1c19vZl9jb250cm9sLCBzZWxmX2NvbmNlcHQsIG1vdGl2YXRpb24pLCBxdWF0cm8gdmFyacOhdmVpcyBhY2Fkw6ptaWNhcyAocmVhZCwgd3JpdGUsIG1hdGgsIHNjaWVuY2UpIGUgdW1hIHZhcsOhdmVpcyBkZW1vZ3LDoWZpY2EgKGZlbWFsZSkgZm9yYW0gY29sZXRhZG9zIGRlIDYwMCBjYWxvdXJvcyBkYSBVTklDQU1QLiBPIFNBRSAoc2VydmnDp28gZGUgYXBvaW8gYW8gZXN0dWRhbnRlKSBlc3TDoSBpbnRlcmVzc2FkbyBlbSBzYWJlciBjb21vIGFzIHZhcmnDoXZlaXMgcHNpY29sw7NnaWNhcyBzZSByZWxhY2lvbmFtIGNvbSBhcyB2YXJpw6F2ZWlzIGFjYWTDqm1pY2FzLiAKCj4gTyBfZGF0YSBzZXRfIGVzdMOhIGRpc3BvbsOtdmVsIFthcXVpXShodHRwczovL2dpdGh1Yi5jb20vbWFya3MvY29udmVydF90b19jc3YvYmxvYi9tYXN0ZXIvc2FtcGxlX2RhdGEvZnJvbV93d3cuYXRzLnVjbGEuZWR1OnN0YXQ6L21tcmVnLmR0YSkgbWFzIGVzdMOhIGVtIGZvcm1hZG8gYCouZHRhYCAoU1RBVEEpIGByIGVtbzo6amkoInNhZCIpYC4KCgpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0V9CiMgQ2FycmVnYW1vcyBvcyBwYWNvdGVzIG5lY2Vzc8OhcmlvcwpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGhhdmVuKSAKbGlicmFyeShjb3JycGxvdCkKbGlicmFyeShDQ0EpCmBgYAoKCmBgYHtyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0KIyBJbXBvcnRhciBkYXRhIHNldAp1bmljYW1wIDwtIHJlYWRfZHRhKCJkYXRhc2V0cy9tbXJlZy5kdGEiKQpnbGltcHNlKHVuaWNhbXApCmBgYApgYGB7cn0KIyBTZXBhcmFtb3Mgb3MgY29uanVudG9zIGRlIGRhZG9zIGVtIFggZSBZClggPC0gdW5pY2FtcCAlPiUgZHBseXI6OnNlbGVjdChsb2N1c19vZl9jb250cm9sLCBzZWxmX2NvbmNlcHQsIG1vdGl2YXRpb24pClkgPC0gdW5pY2FtcCAlPiUgZHBseXI6OnNlbGVjdChyZWFkLCB3cml0ZSwgbWF0aCwgc2NpZW5jZSkKYGBgCgpgYGB7cn0KIyBDb21vIHBhc3NvIHByw6l2aW8sIHZlcmVtb3Mgc2UgZXhpc3RlIGNvcnJlbGHDp8OjbyBlbnRyZSBhcyB2YXJpw6F2ZWlzIGRlIGFtYm9zIG9zIGNvbmp1bnRvcwp1bmljYW1wICU+JSAKICBkcGx5cjo6c2VsZWN0KC1pZCwgLWZlbWFsZSkgJT4lIAogIGNvcigpICU+JSAKICBjb3JycGxvdChtZXRob2QgPSAiY29sb3IiKQpgYGAKCmBgYHtyfQojIEFwbGljYW1vcyBDQwpjY19yZXN1bHRhZG9zIDwtIGNjKFgsIFkpCmBgYAoKCmBgYHtyfQojIENvcnJlbGHDp8OjbyBkYXMgdmFyacOhdmVpcyBjYW7DtG5pY2FzCmNjX3Jlc3VsdGFkb3MkY29yCmBgYAoKLSBBcyBwcmltZWlyYXMgdmFyacOhdmFpcyBjYW7DtG5pY2FzICgkXGV0YV8xJCBlICRccGhpXzEkKSB0ZW0gdW1hIGNvcnJlbGHDp8OjbyBkZSAwLjQ1LgotIEFzIHNlZ3VuZGFzIHZhcmnDoXZlaXMgY2Fuw7RuaWNhcyAoJFxldGFfMiQgZSAkXHBoaV8yJCkgdGVtIHVtYSBjb3JyZWxhw6fDo28gZGUgMC4xNS4KLSBBcyB0ZXJjZWlyYXMgdmFyacOhdmVpcyBjYW7DtG5pY2FzICgkXGV0YV8zJCBlICRccGhpXzMkKSB0ZW0gdW1hIGNvcnJlbGHDp8OjbyBkZSAwLjAyLgoKCmBgYHtyfQojIFF1YWlzIGFzIGNvbWJpbmHDp8O1ZXMgbGluZWFyZXMgcGFyYSBmb3JtYXIgYXMgdmFyacOhdmVzIGNhbsOzbmljYXM/CmNjX3Jlc3VsdGFkb3MkeGNvZWYKYGBgCgotIEEgdW1hIHVuaWRhZGUgZGUgYXVtZW50byBlbSBgbG9jdXNfb2ZfY29udHJvbGAgYSBwcmltZWlyYSB2YXJpw6F2ZWwgY2Fuw7RuaWNhIGRpbWludWkgZW0gMS4yNSBwb250b3MuCi0gQSB1bWEgdW5pZGFkZSBkZSBhdW1lbnRvIGVtIGBtb3RpdmF0aW9uYCBhIHByaW1laXJhIHZhcmnDoXZlbCBjYW7DtG5pY2EgZGltaW51aSBlbSAxLjI0OSBwb250b3MuCi0gQSB1bWEgdW5pZGFkZSBkZSBhdW1lbnRvIGVtIGBzZWxmX2NvbmNlcHRgIGEgcHJpbWVpcmEgdmFyacOhdmVsIGNhbsO0bmljYSBhdW1lbnRhIGVtIDAuMjQgcG9udG9zLgotIEEgcHJpbWVpcmEgdmFyacOhdmVsIGNhbsO0bmljYSDDqSBmb3JtYWRhLCBwcmluY2lwYWxtZW50ZSBwb3IsIGBsb2N1c19vZl9jb250cm9sYCBlIGBtb3RpdmF0aW9uYC4KCgpgYGB7cn0KIyBRdWFpcyBhcyBjb21iaW5hw6fDtWVzIGxpbmVhcmVzIHBhcmEgZm9ybWFyIGFzIHZhcmnDoXZlcyBjYW7Ds25pY2FzPwpjY19yZXN1bHRhZG9zJHljb2VmCmBgYAoKLSAgUXVhbmRvIGByZWFkYCBhdW1lbnRhIGVtIHVtYSB1bmlkYWRlLCBhIHByaW1laXJhIHZhcmnDoXZlbCBjYW7DtG5pY2EgZGltaW51aSBlbSAwLjA0NCB1bmlkYWRlcy4KLSAgUXVhbmRvIGB3cml0ZWAgYXVtZW50YSBlbSB1bWEgdW5pZGFkZSwgYSBwcmltZWlyYSB2YXJpw6F2ZWwgY2Fuw7RuaWNhIGRpbWludWkgZW0gMC4wNTUgdW5pZGFkZXMuCi0gIFF1YW5kbyBgbWF0aGAgYXVtZW50YSBlbSB1bWEgdW5pZGFkZSwgYSBwcmltZWlyYSB2YXJpw6F2ZWwgY2Fuw7RuaWNhIGRpbWludWkgZW0gMC4wMTkgdW5pZGFkZXMuCgo+IEF0w6kgYXF1aSwgdGVtb3MgZmVpdG8gdHVkbyBvIHZpc3RvIG5vcyBzbGlkZXMuIENvbnR1ZG8sIHNvYiBub3JtYWxpZGFkZSBtdWx0aXZhcmlhZGEsIHBvZGVtb3MgaXIgYWzDqW0gZSBmYXplciBpbmZlcsOqbmNpYSBlc3RhdMOtc3RpY2EuCgojIyMgVGVzdGFyIHNlIFggZSBZIHPDo28gbsOjbyBjb3JyZWxhY2lvbmFkb3MuCgotIFNvYiBub3JtYWxpZGFkZSBlIHV0aWxpemFuZG8gbyBUUlYgY2hlZ2Ftb3MgbmEgc2VndWludGUgZXN0YXTDrXN0aWNhIGRlIHRlc3RlICQkfFx0ZXh0YmZ7SX0gLSBcdGV4dGJme1N9X3tZWX1eey0xfVx0ZXh0YmZ7U31fe1lYfSBcdGV4dGJme1N9X3tYWH1eey0xfSBcdGV4dGJme1NZfXwgPSBcZGlzcGxheXN0eWxlIFxwcm9kX3tpID0gMX1eaygxLWxfaSkuJCQKLSBVdGlsaXphbmRvIGEgYXByb3hpbWHDp8OjbyBkZSBCYXJsZXR0ICgxOTM5KSwgdGVtb3MgcXVlICQkLVtuIC0gKHAgKyBxICsgMykvMl0gXGRpc3BsYXlzdHlsZSBcc3VtX3tpID0gMX1eayBcbG9nKDEtbF9pKSBcc2ltIFxjaGleMl97cHF9JCQKCgpgYGB7cn0KbXZub3JtYWxUZXN0OjptYXJkaWEoY2JpbmQoWCxZKSkKYGBgCmBgYHtyfQphdXggPC0gYXMubWF0cml4KGNiaW5kKFgsWSkpCm1udDo6dGVzdC5CSEVQKGF1eCwgTUMucmVwID0gMTAwMCkgICMgUmVqZWl0YW1vcyBIMApgYGAKCk9zIGRhZG9zIG7Do28gc8OjbyBub3JtYWxtZW50ZSBkaXN0cmlidWlkb3MuICoqQXBlbmFzIGEgbWFuZWlyYSBkZSBleGVtcGxvKiogY29udGludWFyZW1vcyBjb20gaW5mZXLDqm5jaWEgZXN0YXTDrXN0aWNhLgoKYGBge3J9Cm4gPC0gbnJvdyh1bmljYW1wKQpwIDwtIG5jb2woWCkKcSA8LSBuY29sKFkpCmwgPC0gY2NfcmVzdWx0YWRvcyRjb3JeMiAjKExlbWJyZSBxdWUgU1ZEIGZvcm5lY2UgZW0gRCBhIHJhaXogZG9zIGF1dG92YWxvcmVzKQplX3Rlc3RlIDwtIC0obiAtIChwICsgcSArIDMpLzIpKnN1bShsb2coMSAtIGwpKQplX3Rlc3RlCngyIDwtIHFjaGlzcSgwLjk1LCBwKnEpCmlmZWxzZShlX3Rlc3RlID4geDIsICJSZWplaXRhbW9zIEgwIiwgIk7Do28gcmVqZWl0YW1vcyBIMCIpCmBgYAoKCiMjIyBUZXN0YXIgcXVlIGEgY29ycmVsYcOjbyBkZSBhcGVuYXMgayAtIHMgdmFyacOhdmVpcyBjYW7DtG5pY2FzIHPDo28gZGlmZXJlbnRlcyBkZSB6ZXJvLgoKJCQtW24gLSAocCArIHEgKyAzKS8yXSBcZGlzcGxheXN0eWxlIFxzdW1fe2kgPSBzICsgMX1eayBcbG9nKDEtbF9pKSBcc2ltIFxjaGleMl97KHAgLSBzKShxIC0gcyl9JCQKCmBgYHtyfQpzIDwtIDAgICMgQ2FzbyBhbnRlcmlvcgprIDwtIDMKZV90ZXN0ZSA8LSAtKG4gLSAocCArIHEgKyAzKS8yKSpzdW0obG9nKDEgLSBsKVsocyArIDEpOmtdKQplX3Rlc3RlCngyIDwtIHFjaGlzcSgwLjk1LCAocCAtIHMpKihxIC0gcykpCmlmZWxzZShlX3Rlc3RlID4geDIsICJSZWplaXRhbW9zIEgwIiwgIk7Do28gcmVqZWl0YW1vcyBIMCIpCmBgYAoKYGBge3J9CnMgPC0gMSAgCmsgPC0gMwplX3Rlc3RlIDwtIC0obiAtIChwICsgcSArIDMpLzIpKnN1bShsb2coMSAtIGwpWyhzICsgMSk6a10pCmVfdGVzdGUKeDIgPC0gcWNoaXNxKDAuOTUsIChwIC0gcykqKHEgLSBzKSkKaWZlbHNlKGVfdGVzdGUgPiB4MiwgIlJlamVpdGFtb3MgSDAiLCAiTsOjbyByZWplaXRhbW9zIEgwIikKYGBgCgpgYGB7cn0KcyA8LSAyICAKayA8LSAzCmVfdGVzdGUgPC0gLShuIC0gKHAgKyBxICsgMykvMikqc3VtKGxvZygxIC0gbClbKHMgKyAxKTprXSkKZV90ZXN0ZQp4MiA8LSBxY2hpc3EoMC45NSwgKHAgLSBzKSoocSAtIHMpKQppZmVsc2UoZV90ZXN0ZSA+IHgyLCAiUmVqZWl0YW1vcyBIMCIsICJOw6NvIHJlamVpdGFtb3MgSDAiKQpgYGAKCgotIEFwZW5hcyBhcyAyIHByaW1laXJhcyB2YXJpw6F2ZWlzIGNhbsO0bmljYXMgdGVtIGNvcnJlbGHDp8OjbyBkaWZlcmVudGVzIGRlIHplcm8uIAoKCiMjIENhc2UgMjoKClJvYmVydG8gRnVsY2hlcmJlcmd1ZXIsIG8gQ0VPIGRhcyBDYXNhcyBCYWhpYSwgZXN0w6EgaW50ZXJlc3NhZG8gZW0gc2FiZXIgc2UgZXhpc3RlIGFsZ3VtYSByZWxhw6fDo28gZW50cmUgbyBkZXNlbXBlbmhvIGRhcyB2ZW5kYXMgKG1lbnN1cmFkbyBhdHJhdsOpcyBkYXMgdmFyacOhdmVpcyBgU2FsZXMgR3Jvd3RoYCwgYFNhbGVzIFByb2ZpdGFiaWxpdHlgLCBgTmV3IEFjY291bnQgU2FsZXNgKSBlIGEgaW50ZWxpZ8OqbmNpYSBkb3MgZ2VyZW50ZXMgZGEgbG9qYSAobWVuc3VyYWRvIGF0cmF2w6lzIGRhcyB2YXJpw6F2ZWlzIGBDcmVhdGl2aXR5YCwgYE1lY2hhbmljYWwgUmVhc29uaW5nYCwgYEFic3RyYWN0IFJlYXNvbmluZ2AsIGBNYXRoZW1hdGljc2ApLiBQYXJhIGZhemVyIGFzIGFuw6FsaXNlcywgJG4gPSA1MCQgbG9qYXMgc8OjbyBzZWxlY2lvbmFkYXMgYWxlYXRvcmlhbWVudGUgZSBhcyB2YXJpw6F2ZWlzIGRlIGludGVyZXNzZSBzw6NvIG9idGlkYXMuIAoKPiBPIF9kYXRhIHNldF8gZXN0w6EgZGlzcG9uw612ZWwgW2FxdWldKGh0dHBzOi8vb25saW5lLnN0YXQucHN1LmVkdS9vbmxpbmVjb3Vyc2VzL3NpdGVzL3N0YXQ1MDUvZmlsZXMvZGF0YS9zYWxlcy50eHQpLgoKCmBgYHtyfQojIEltcG9ydGFyIGRhZG9zCmNhc2FzX2JhaGlhIDwtIHJlYWQudGFibGUoImRhdGFzZXRzL3NhbGVzLnR4dCIpCmNvbG5hbWVzKGNhc2FzX2JhaGlhKSA8LSBjKCJncm93dGgiLCAicHJvZml0IiwgIm5ldyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJjcmVhdGUiLCAibWVjaGFuaWNhbCIsICJhYnMiLCAibWF0aCIpCmdsaW1wc2UoY2FzYXNfYmFoaWEpCmBgYAoKCgoKYGBge3J9CiMgU2VwYXJhbW9zIG9zIGNvbmp1bnRvcyBkZSBkYWRvcyBlbSBYIGUgWQpYIDwtIGNhc2FzX2JhaGlhICU+JSBkcGx5cjo6c2VsZWN0KGdyb3d0aCwgcHJvZml0LCBuZXcpClkgPC0gY2FzYXNfYmFoaWEgJT4lIGRwbHlyOjpzZWxlY3QoY3JlYXRlLCBtZWNoYW5pY2FsLCBhYnMsIG1hdGgpCmBgYAoKCmBgYHtyfQojIENvcnJlbGHDp8OjbyBlbnRyZSBhcyB2YXJpw6F2ZWlzCmNhc2FzX2JhaGlhICU+JSAKICBjb3IoKSAlPiUgCiAgY29ycnBsb3QobWV0aG9kID0gImNvbG9yIikKYGBgCgoKYGBge3J9CiMgQXBsaWNhbW9zIENDCmNjX2NiIDwtIGNjKFgsIFkpCmBgYAoKCmBgYHtyfQojIENvcnJlbGHDp8OjbyBkYXMgdmFyacOhdmVpcyBjYW7DtG5pY2FzCmNjX2NiJGNvcgpgYGAKCgotIEFzIHByaW1laXJhcyB2YXJpw6F2ZWlzIGNhbsO0bmljYXMgdGVtIHVtYSBjb3JyZWxhw6fDo28gZGUgMC45OS4KLSBBcyBzZWd1bmRhcyB2YXJpw6F2ZWlzIGNhbsO0bmljYXMgdGVtIHVtYSBjb3JyZWxhw6fDo28gZGUgMC44OC4KLSBBcyB0ZXJjZWlyYXMgdmFyacOhdmVpcyBjYW7DtG5pY2FzIHRlbSB1bWEgY29ycmVsYcOnw6NvIGRlIDAuMjguCgoKYGBge3J9CiMgUXVhaXMgYXMgY29tYmluYcOnw7VlcyBsaW5lYXJlcyBwYXJhIGZvcm1hciBhcyB2YXJpw6F2ZXMgY2Fuw7NuaWNhcz8KY2NfY2IkeGNvZWYKYGBgCgoKCmBgYHtyfQojIFF1YWlzIGFzIGNvbWJpbmHDp8O1ZXMgbGluZWFyZXMgcGFyYSBmb3JtYXIgYXMgdmFyacOhdmVzIGNhbsOzbmljYXM/CmNjX2NiJHljb2VmCmBgYAoKYGBge3J9Cm12bm9ybWFsVGVzdDo6bWFyZGlhKGNiaW5kKFgsWSkpCmBgYAoK