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
- As primeiras variávais canônicas (\(\eta_1\) e \(\phi_1\)) tem uma correlação de 0.45.
- As segundas variáveis canônicas (\(\eta_2\) e \(\phi_2\)) tem uma correlação de 0.15.
- As terceiras variáveis canônicas (\(\eta_3\) e \(\phi_3\)) tem uma correlação de 0.02.
# 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
- A uma unidade de aumento em
locus_of_control
a primeira
variável canônica diminui em 1.25 pontos.
- A uma unidade de aumento em
motivation
a primeira
variável canônica diminui em 1.249 pontos.
- A uma unidade de aumento em
self_concept
a primeira
variável canônica aumenta em 0.24 pontos.
- A primeira variável canônica é formada, principalmente por,
locus_of_control
e motivation
.
# 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
- Quando
read
aumenta em uma unidade, a primeira variável
canônica diminui em 0.044 unidades.
- Quando
write
aumenta em uma unidade, a primeira
variável canônica diminui em 0.055 unidades.
- Quando
math
aumenta em uma unidade, a primeira variável
canônica diminui em 0.019 unidades.
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
- As primeiras variáveis canônicas tem uma correlação de 0.99.
- As segundas variáveis canônicas tem uma correlação de 0.88.
- As terceiras variáveis canônicas tem uma correlação de 0.28.
# 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