Análise de correspondência
Análise de correspondência (ANACOR) é necessária para a tabela de contingência grande.
Aplica-se para visualizar pontos da linha e pontos da coluna em um espaço dimensional reduzido.
ANACOR é um método de redução dimensional aplicado a uma tabela de contingência.
A informação retida por cada dimensão é chamada autovalor.
A análise de correspondência é usada para representar graficamente a tabela de distâncias entre variáveis de linha ou entre variáveis de coluna.
A abordagem ANACOR inclui as seguintes etapas:
1.Calcular os resíduos padronizados
Os resíduos padronizados (S) são:
\(S = \frac{o - e}{\sqrt{e}}\)
De fato, S é apenas a raíz quadrada dos termos que compõem a estatística \(\chi^2\).
2. Calcule a decomposição do valor singular (SVD) dos resíduos padronizados.
\(M = \frac{1}{sqrt(grand.total)} \times S\)
O autovalor de um determinado eixo é:
\(\lambda = \delta^2\)
\(\delta\) É o valor singular
As coordenadas das variáveis de linha em um determinado eixo são:
\(row.coord = \frac{U * \delta }{\sqrt{row.mass}}\)
As coordenadas das colunas são
\(col.coord = \frac{V * \delta }{\sqrt{col.mass}}\)
cálculo SVD
### Grand total
n <- sum(tab)
### Standardized residuals
residuals <- chisq$residuals/sqrt(n)
### Number of dimensions
nb.axes <- min(nrow(residuals)-1, ncol(residuals)-1)
### Singular value decomposition
res.svd <- svd(residuals, nu = nb.axes, nv = nb.axes)
res.svd
$d
[1] 3.682595e-01 1.336053e-01 1.766556e-17
$u
[,1] [,2]
[1,] -0.2123970 -0.13641520
[2,] 0.4812011 0.54991331
[3,] -0.6910928 -0.04463595
[4,] 0.1576045 0.26465257
[5,] 0.4699837 -0.77907182
$v
[,1] [,2]
[1,] 0.4349627 0.69433693
[2,] 0.3699150 -0.71829008
[3,] -0.8209570 0.04422198
### singular value
sv <- res.svd$d[1:nb.axes]
u <-res.svd$u
v <- res.svd$v
# inércia total
sum(sv^2)
[1] 0.1534655
### Eigenvalues
eig <- sv^2
### Variances in percentage
variance <- eig*100/sum(eig)
### Cumulative variances
cumvar <- cumsum(variance)
eig<- data.frame(eig = eig, variance = variance,
cumvariance = cumvar)
head(eig)
barplot(eig[, 2], names.arg=1:nrow(eig),
main = "Variances",
xlab = "Dimensions",
ylab = "Percentage of variances",
col ="steelblue")
### Add connected line segments to the plot
lines(x = 1:nrow(eig), eig[, 2],
type="b", pch=19, col = "red")

Quantas dimensões reter ?
1. O número máximo de eixos na ANACOR é:
\(nb.axes = min(r-1, c-1)\)
r e c são respectivamente o número de linhas e colunas na tabela.
Row coordinates
### row sum
row.sum <- apply(tab, 1, sum)
### row mass
row.mass <- row.sum/n
### row coord = sv * u /sqrt(row.mass)
cc <- t(apply(u, 1, '*', sv)) ### each row X sv
row.coord <- apply(cc, 2, '/', sqrt(row.mass))
rownames(row.coord) <- rownames(tab)
colnames(row.coord) <- paste0("Dim.", 1:nb.axes)
round(row.coord,3)
Dim.1 Dim.2
asiático -0.206 -0.048
brasileiro 0.301 0.125
americano -0.435 -0.010
europeu 0.348 0.212
latino 0.464 -0.279
### plot
plot(row.coord, pch=19, col = "blue")
text(row.coord, labels =rownames(row.coord), pos = 3, col ="blue")
abline(v=0, h=0, lty = 2)

Column coordinates
### Coordinates of columns
col.sum <- apply(tab, 2, sum)
col.mass <- col.sum/n
### coordinates sv * v /sqrt(col.mass)
cc <- t(apply(v, 1, '*', sv))
col.coord <- apply(cc, 2, '/', sqrt(col.mass))
rownames(col.coord) <- colnames(tab)
colnames(col.coord) <- paste0("Dim", 1:nb.axes)
head(col.coord)
Dim1 Dim2
baixo 0.2793854 0.16180484
médio 0.2311811 -0.16286196
alto -0.5310706 0.01037862
### plot
plot(col.coord, pch=17, col = "red")
text(col.coord, labels =rownames(col.coord), pos = 3, col ="red")
abline(v=0, h=0, lty = 2)

Biplot de linhas e colunas para ver a associação
xlim <- range(c(row.coord[,1], col.coord[,1]))*1.1
ylim <- range(c(row.coord[,2], col.coord[,2]))*1.1
### Plot of rows
plot(row.coord, pch=19, col = "blue", xlim = xlim, ylim = ylim)
text(row.coord, labels =rownames(row.coord), pos = 3, col ="blue")
### plot off columns
points(col.coord, pch=17, col = "red")
text(col.coord, labels =rownames(col.coord), pos = 3, col ="red")
abline(v=0, h=0, lty = 2)

Diagnóstico
Lembre-se que, a inércia total contida nos dados é:
\(\phi^2 = \frac{\chi^2}{n}\)
Nosso gráfico bidimensional captura cerca de 88% da inércia total da tabela.
Contribuição de linhas e colunas
As contribuições de uma linha / coluna para a definição de um eixo principal são:
\(row.contrib = \frac{row.mass * row.coord^2}{eigenvalue}\)
\(col.contrib = \frac{col.mass * col.coord^2}{eigenvalue}\)
Contribuição de linhas em %
### contrib <- row.mass * row.coord^2/eigenvalue
cc <- apply(row.coord^2, 2, "*", row.mass)
row.contrib <- t(apply(cc, 1, "/", eig[1:nb.axes,1])) *100
round(row.contrib, 2)
Dim.1 Dim.2
asiático 4.51 1.86
brasileiro 23.16 30.24
americano 47.76 0.20
europeu 2.48 7.00
latino 22.09 60.70
corrplot(row.contrib, is.cor = FALSE)

Contribuição das colunas em %
### contrib <- col.mass * col.coord^2/eigenvalue
cc <- apply(col.coord^2, 2, "*", col.mass)
col.contrib <- t(apply(cc, 1, "/", eig[1:nb.axes,1])) *100
round(col.contrib, 2)
Dim1 Dim2
baixo 18.92 48.21
médio 13.68 51.59
alto 67.40 0.20
corrplot(col.contrib, is.cor = FALSE)

Qualidade da representação
A qualidade da representação é chamada COS2.
A qualidade da representação de uma linha em um eixo é:
\(row.cos2 = \frac{row.coord^2}{d^2}\)
- Row.coord é a coordenada da linha no eixo
- \(d^2\) É a distância ao quadrado do perfil médio
Lembre-se de que a distância entre cada perfil de linha e o perfil de linha médio é:
\(d^2(row_i, average.profile) = \sum{\frac{(row.profile_i - average.profile)^2}{average.profile}}\)
row.profile <- tab/row.sum
head(round(row.profile, 3))
disclosure
pais baixo médio alto
asiático 0.258 0.323 0.419
brasileiro 0.453 0.360 0.187
americano 0.216 0.257 0.527
europeu 0.500 0.333 0.167
latino 0.333 0.567 0.100
average.profile <- col.sum/n
head(round(average.profile, 3))
baixo médio alto
0.329 0.347 0.324
O código R abaixo calcula a distância do perfil médio para todas as variáveis de linha
average.rp <- col.sum/n
d2.row <- apply(row.profile, 1,
function(row.p, av.p){sum(((row.p - av.p)^2)/av.p)},
average.rp)
head(round(d2.row,3))
asiático brasileiro americano europeu latino
0.045 0.106 0.189 0.166 0.294
O cos2 de linhas no mapa de fatores são:
row.cos2 <- apply(row.coord^2, 2, "/", d2.row)
round(row.cos2, 3)
Dim.1 Dim.2
asiático 0.949 0.051
brasileiro 0.853 0.147
americano 0.999 0.001
europeu 0.729 0.271
latino 0.734 0.266
corrplot(row.cos2, is.cor = FALSE)

Cos2 das colunas
\(col.cos2 = \frac{col.coord^2}{d^2}\)
col.profile <- t(tab)/col.sum
col.profile <- t(col.profile)
###head(round(col.profile, 3))
average.profile <- row.sum/n
###head(round(average.profile, 3))
O código R abaixo calcula a distância do perfil médio para todas as variáveis da coluna
d2.col <- apply(col.profile, 2,
function(col.p, av.p){sum(((col.p - av.p)^2)/av.p)},
average.profile)
round(d2.col,3)
baixo médio alto
0.104 0.080 0.282
O cos2 das colunas no mapa de fatores são:
col.cos2 <- apply(col.coord^2, 2, "/", d2.col)
round(col.cos2, 3)
Dim1 Dim2
baixo 0.749 0.251
médio 0.668 0.332
alto 1.000 0.000
corrplot(col.cos2, is.cor = FALSE)

Pacotes no R para ANACOR
-FactoMineR -ade4 -ca
library(FactoMineR)
res.ca <- CA(tab, graph = F)
summary(res.ca)
Call:
CA(X = tab, graph = F)
The chi square of independence between the two variables is equal to 33.14854 (p-value = 5.790601e-05 ).
Eigenvalues
Dim.1 Dim.2
Variance 0.136 0.018
% of var. 88.368 11.632
Cumulative % of var. 88.368 100.000
Rows
Iner*1000 Dim.1 ctr cos2 Dim.2 ctr cos2
asiático | 6.450 | 0.206 4.511 0.949 | -0.048 1.861 0.051 |
brasileiro | 36.800 | -0.301 23.155 0.853 | 0.125 30.240 0.147 |
americano | 64.807 | 0.435 47.761 0.999 | -0.010 0.199 0.001 |
europeu | 4.619 | -0.348 2.484 0.729 | 0.212 7.004 0.271 |
latino | 40.790 | -0.464 22.088 0.734 | -0.279 60.695 0.266 |
Columns
Iner*1000 Dim.1 ctr cos2 Dim.2 ctr cos2
baixo | 34.263 | -0.279 18.919 0.749 | 0.162 48.210 0.251 |
médio | 27.767 | -0.231 13.684 0.668 | -0.163 51.594 0.332 |
alto | 91.435 | 0.531 67.397 1.000 | 0.010 0.196 0.000 |
### Plot row points
plot(res.ca, invisible ="col")

### Plot column points
plot(res.ca, invisible ="row")

### Biplot of rows and columns
plot(res.ca)

LS0tDQp0aXRsZTogJ0Fuw6FsaXNlIGRlIENvcnJlc3BvbmTDqm5jaWEgLSBkaXNjbG9zdXJlIC0gQU5BQ09SICcNCmF1dGhvcjogIkxlb25pLCBSLiBDLiBQcm9mZXNzb3IgRHIuIg0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOiBkZWZhdWx0DQogIGh0bWxfZG9jdW1lbnQ6IGRlZmF1bHQNCi0tLQ0KKioqDQoNCiMjIyBJbWFnaW5lIHF1ZSB1bSBwZXNxdWlzYWRvciBlc3RlamEgaW50ZXJlc3NhZG8gZW0gaW52ZXN0aWdhciBzZSBleGlzdGUgYWxndW0gdGlwbyBkZSByZWxhw6fDo28gZW50cmUgYSBvcmlnZW0gZGUgY2FwaXRhbCAoY29udHJvbGUgYWNpb27DoXJpbzogYXNpw6F0aWNvLCBicmFzaWxlaXJvLCBhbWVyaWNhbm8sIGV1cm9wZXUgb3UgbGF0aW5vKSBlIG8gbsOtdmVsIGRlIHRyYW5zcGFyw6puY2lhIChkaXNjbG9zdXJlKSBkYXMgaW5mb3JtYcOnw7VlcyBjb250w6FiZWlzIChhbHRvLCBtw6lkaW8gb3UgYmFpeG8pIGRhcyBlbXByZXNhcyBwZXJ0ZW5jZW50ZXMgYSB1bWEgYW1vc3RyYSBjb20gMjE2IGVtcHJlc2FzICAgIA0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gRikNCmBgYA0KDQpgYGB7cn0NCiMgaW5zdGFsbC5wYWNrYWdlcygiRmFjdG9NaW5lUiIsICJnZ2xvdDIiLCAicmVhZHhsIikNCiMgaW5zdGFsbC5wYWNrYWdlcygiZGV2dG9vbHMiKQ0KIyBkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoImthc3NhbWJhcmEvZmFjdG9leHRyYSIpDQpybShsaXN0PWxzKGFsbD1UUlVFKSkNCmxpYnJhcnkoImdncGxvdDIiKQ0KbGlicmFyeSgiRmFjdG9NaW5lUiIpDQpsaWJyYXJ5KCJmYWN0b2V4dHJhIikNCmxpYnJhcnkoInJlYWR4bCIpDQpsaWJyYXJ5KCJncGxvdHMiKQ0KbGlicmFyeSgiY29ycnBsb3QiKQ0KbGlicmFyeSgiZ3JhcGhpY3MiKQ0KYGBgDQoNCmBgYHtyfQ0KIyBsZXIgZSBjYXJyZWdhciBvcyBkYWRvcw0KZGlzY2xvc3VyZSA8LSByZWFkX2V4Y2VsKCJkaXNjbG9zdXJlLnhscyIpDQpoZWFkKGRpc2Nsb3N1cmUpDQpzdHIoZGlzY2xvc3VyZSkNCmBgYA0KDQpgYGB7cn0NCiMgYXRyaWJ1aW5kbyBjYXRlZ29yaWFzIGFvcyBuw7ptZXJvcyAoVkEgcXVhbGl0YXRpdmEpDQpkaXNjbG9zdXJlJHBhaXMgPC0gZmFjdG9yKGRpc2Nsb3N1cmUkcGFpcywgbGFiZWxzID0gYygiYXNpw6F0aWNvIiwgImJyYXNpbGVpcm8iLCAiYW1lcmljYW5vIiwgImV1cm9wZXUiLCAibGF0aW5vIikpDQpkaXNjbG9zdXJlJGRpc2Nsb3N1cmUgPC0gZmFjdG9yKGRpc2Nsb3N1cmUkZGlzY2xvc3VyZSwgbGFiZWxzID0gYygiYmFpeG8iLCAibcOpZGlvIiwgImFsdG8iKSkNCmhlYWQoZGlzY2xvc3VyZSkNCmBgYA0KDQpgYGB7cn0NCnRhYiA8LSB0YWJsZShkaXNjbG9zdXJlKQ0KdGFiDQoNCiMjIyAxLiBjb252ZXJ0IHRoZSBkYXRhIGFzIGEgdGFibGUNCmR0IDwtIGFzLnRhYmxlKGFzLm1hdHJpeCh0YWIpKQ0KIyMjIDIuIEdyYXBoDQpiYWxsb29ucGxvdCh0KGR0KSwgbWFpbiA9IlBhw61zIC0gRGlzY2xvc3VyZSIsIHhsYWIgPSIiLCB5bGFiPSIiLA0KICAgICAgICAgICAgbGFiZWwgPSBULCBzaG93Lm1hcmdpbnMgPSBUKQ0KDQpgYGANCg0KIyMjIEFzIGPDqWx1bGFzIGNvbSBvcyByZXPDrWR1b3MgcGFkcm9uaXphZG9zIGFic29sdXRvcyBtYWlzIGVsZXZhZG9zIGNvbnRyaWJ1ZW0gbWFpcyBwYXJhIGEgcG9udHVhw6fDo28gdG90YWwgZG8gUXVpLXF1YWRyYWRvLg0KDQpgYGB7cn0NCmNoaXNxIDwtIGNoaXNxLnRlc3QodGFiKQ0KY2hpc3ENCiMjIyBPYnNlcnZlZCBjb3VudHMNCmNoaXNxJG9ic2VydmVkDQojIyMgRXhwZWN0ZWQgY291bnRzDQpyb3VuZChjaGlzcSRleHBlY3RlZCwyKQ0KIyByZXNpZHVhbHMNCnJvdW5kKGNoaXNxJHJlc2lkdWFscywgMykNCiNvdSANCiMoY2hpc3Ekb2JzZXJ2ZWQtY2hpc3EkZXhwZWN0ZWQpXjIvY2hpc3EkZXhwZWN0ZWQNCg0KY29ycnBsb3QoY2hpc3EkcmVzaWR1YWxzLCBpcy5jb3IgPSBGQUxTRSkNCg0KYGBgDQoNCiMjIyBBIGNvbnRyaWJ1acOnw6NvIChlbSAlKSBkZSB1bWEgZGFkYSBjw6lsdWxhIHBhcmEgYSBwb250dWHDp8OjbyB0b3RhbCBkbyBRdWktcXVhZHJhZG8gw6kgY2FsY3VsYWRhIGRhIHNlZ3VpbnRlIGZvcm1hOg0KDQpgYGB7cn0NCiMjIyBDb250aWJ1dGlvbiBpbiBwZXJjZW50YWdlICglKQ0KY29udHJpYiA8LSAxMDAqY2hpc3EkcmVzaWR1YWxzXjIvY2hpc3Ekc3RhdGlzdGljDQpyb3VuZChjb250cmliLCAzKQ0KIyMjIFZpc3VhbGl6ZSB0aGUgY29udHJpYnV0aW9uDQpjb3JycGxvdChjb250cmliLCBpcy5jb3IgPSBGQUxTRSkNCmBgYA0KDQojIyMgQSBpbsOpcmNpYSB0b3RhbCAoJFxwaGleMiQpIMOpIGEgcXVhbnRpZGFkZSBkZSBpbmZvcm1hw6fDo28gY29udGlkYSBuYSB0YWJlbGEgZGUgZGFkb3MNCiANCmBgYHtyfQ0KcGhpMiA8LSBhcy5udW1lcmljKGNoaXNxJHN0YXRpc3RpYy9zdW0odGFiKSkNCnBoaTINCmBgYA0KDQojIyMgQSByYWl6IHF1YWRyYWRhIGRlICRccGhpXjIkIMOpIGNoYW1hZGEgdHJhw6dvIGUgcG9kZSBzZXIgaW50ZXJwcmV0YWRhIGNvbW8gdW0gY29lZmljaWVudGUgZGUgY29ycmVsYcOnw6NvIA0KIyMjIG8gdmFsb3IgJFxwaGkkID4gMCwyIGluZGljYSB1bWEgZGVwZW5kw6puY2lhIHNpZ25pZmljYXRpdmEgZW50cmUgbGluaGFzIGUgY29sdW5hcyANCiMjIyBPIGdyw6FmaWNvIG1vc2FpY28gw6kgdXNhZG8gcGFyYSB2aXN1YWxpemFyIHVtYSB0YWJlbGEgZGUgY29udGluZ8OqbmNpYSBwYXJhIGV4YW1pbmFyIGEgYXNzb2NpYcOnw6NvIGVudHJlIGFzIHZhcmnDoXZlaXMgY2F0ZWfDs3JpY2FzLg0KDQpgYGB7cn0NCiMjIyBNb3NhaWMgcGxvdCBvZiBvYnNlcnZlZCB2YWx1ZXMNCm1vc2FpY3Bsb3QodGFiLCAgbGFzPTIsIGNvbD0ic3RlZWxibHVlIiwNCiAgICAgICAgICAgbWFpbiA9ICJQYcOtc2VzLkRpc2Nsb3N1cmUgLSBvYnNlcnZlZCBjb3VudHMiKQ0KDQojIyMgTW9zYWljIHBsb3Qgb2YgZXhwZWN0ZWQgdmFsdWVzDQptb3NhaWNwbG90KGNoaXNxJGV4cGVjdGVkLCAgbGFzPTIsIGNvbCA9ICJncmF5IiwNCiAgICAgICAgICAgbWFpbiA9ICJQYcOtc2VzLkRpc2Nsb3N1cmUgLSBleHBlY3RlZCBjb3VudHMiKQ0KYGBgDQoNCiMjIyBOZXNzYXMgcGFyY2VsYXMsIGFzIHZhcmnDoXZlaXMgZGUgY29sdW5hIHPDo28gcHJpbWVpcmFtZW50ZSBkaXZpZGlkYXMgKGRpdmlzw6NvIHZlcnRpY2FsKSBlLCBlbSBzZWd1aWRhLCBhcyB2YXJpw6F2ZWlzIGRlIGxpbmhhIHPDo28gZGl2aWRpZGFzIChkaXZpc8OjbyBob3Jpem9udGFsKS4gDQojIyMgUGFyYSBjYWRhIGPDqWx1bGEsIGEgYWx0dXJhIGRhcyBiYXJyYXMgw6kgcHJvcG9yY2lvbmFsIMOgIGZyZXF1w6puY2lhIHJlbGF0aXZhIG9ic2VydmFkYSBxdWUgY29udMOpbToNCiMjIyBPIGdyw6FmaWNvIGF6dWwsIMOpIG8gZ3LDoWZpY28gZGUgbW9zYWljbyBkb3MgdmFsb3JlcyBvYnNlcnZhZG9zLg0KIyMjIE8gY2luemVudG8gw6kgbyBncsOhZmljbyBlbSBtb3NhaWNvIGRvcyB2YWxvcmVzIGVzcGVyYWRvcyBzb2IgaGlww7N0ZXNlIG51bGEuDQojIyMgU2UgYXMgdmFyacOhdmVpcyBkZSBsaW5oYSBlIGNvbHVuYSBmb3NzZW0gY29tcGxldGFtZW50ZSBpbmRlcGVuZGVudGVzLCBhcyBiYXJyYXMgZGUgbW9zYWljbyBwYXJhIG9zIHZhbG9yZXMgb2JzZXJ2YWRvcyAoZ3LDoWZpY28gYXp1bCkgc2VyaWFtIGFsaW5oYWRhcyBjb21vIGFzIGJhcnJhcyBkZSBtb3NhaWNvIHBhcmEgb3MgdmFsb3JlcyBlc3BlcmFkb3MgKGdyw6FmaWNvIGNpbnphKS4NCiMjIyBUYW1iw6ltIMOpIHBvc3PDrXZlbCBjb2xvcmlyIG8gbW9zYWljbyBkZSBhY29yZG8gY29tIG8gdmFsb3IgZG9zIHJlc8OtZHVvcyBwYWRyb25pemFkb3M6DQoNCmBgYHtyfQ0KbW9zYWljcGxvdCh0YWIsIHNoYWRlID0gVFJVRSwgbGFzPTIsbWFpbiA9ICJQYcOtc2VzLkRpc2Nsb3N1cmUiKQ0KYGBgDQoNCg0KDQojIyAgQW7DoWxpc2UgZGUgY29ycmVzcG9uZMOqbmNpYQ0KIyMjIEFuw6FsaXNlIGRlIGNvcnJlc3BvbmTDqm5jaWEgKEFOQUNPUikgw6kgbmVjZXNzw6FyaWEgcGFyYSBhIHRhYmVsYSBkZSBjb250aW5nw6puY2lhIGdyYW5kZS4NCiMjIyBBcGxpY2Etc2UgcGFyYSB2aXN1YWxpemFyIHBvbnRvcyBkYSBsaW5oYSBlIHBvbnRvcyBkYSBjb2x1bmEgZW0gdW0gZXNwYcOnbyBkaW1lbnNpb25hbCByZWR1emlkby4NCiMjIyBBTkFDT1Igw6kgdW0gbcOpdG9kbyBkZSByZWR1w6fDo28gZGltZW5zaW9uYWwgYXBsaWNhZG8gYSB1bWEgdGFiZWxhIGRlIGNvbnRpbmfDqm5jaWEuIA0KIyMjIEEgaW5mb3JtYcOnw6NvIHJldGlkYSBwb3IgY2FkYSBkaW1lbnPDo28gw6kgY2hhbWFkYSBhdXRvdmFsb3IuDQojIyMgQSBpbmZvcm1hw6fDo28gdG90YWwgKG91IGluw6lyY2lhKSBjb250aWRhIG5vcyBkYWRvcyDDqSBjaGFtYWRhIHBoaSAoJFxwaGleMiQpIGUgcG9kZSBzZXIgY2FsY3VsYWRvIGRhIHNlZ3VpbnRlIGZvcm1hOg0KDQokXHBoaV4yID0gXGZyYWN7XGNoaV4yfXtncmFuZC50b3RhbH0kDQoNCiMjIyBQYXJhIHVtIGRldGVybWluYWRvIGVpeG8sIG8gYXV0b3ZhbG9yICjOuykgw6kgY2FsY3VsYWRvIGRhIHNlZ3VpbnRlIGZvcm1hOg0KDQokXGxhbWJkYV97YXhpc30gPSBcc3Vte1xmcmFje3Jvdy5zdW19e2dyYW5kLnRvdGFsfSAqIHJvdy5jb29yZF4yfSQNCg0KJFxsYW1iZGFfe2F4aXN9ID0gXHN1bXtcZnJhY3tjb2wuc3VtfXtncmFuZC50b3RhbH0gKiBjb2wuY29vcmReMn0kDQoNCiMjIyBBIGFuw6FsaXNlIGRlIGNvcnJlc3BvbmTDqm5jaWEgw6kgdXNhZGEgcGFyYSByZXByZXNlbnRhciBncmFmaWNhbWVudGUgYSB0YWJlbGEgZGUgZGlzdMOibmNpYXMgZW50cmUgdmFyacOhdmVpcyBkZSBsaW5oYSBvdSBlbnRyZSB2YXJpw6F2ZWlzIGRlIGNvbHVuYS4NCiMjIyBBIGFib3JkYWdlbSBBTkFDT1IgaW5jbHVpIGFzIHNlZ3VpbnRlcyBldGFwYXM6DQoNCiMjIyAxLkNhbGN1bGFyIG9zIHJlc8OtZHVvcyBwYWRyb25pemFkb3MNCg0KIyMjIE9zIHJlc8OtZHVvcyBwYWRyb25pemFkb3MgKFMpIHPDo286DQoNCiRTID0gXGZyYWN7byAtIGV9e1xzcXJ0e2V9fSQNCg0KIyMjIERlIGZhdG8sIFMgw6kgYXBlbmFzIGEgcmHDrXogcXVhZHJhZGEgZG9zIHRlcm1vcyBxdWUgY29tcMO1ZW0gYSBlc3RhdMOtc3RpY2EgJFxjaGleMiQuDQoNCiMjIyAyLiBDYWxjdWxlIGEgZGVjb21wb3Npw6fDo28gZG8gdmFsb3Igc2luZ3VsYXIgKFNWRCkgZG9zIHJlc8OtZHVvcyBwYWRyb25pemFkb3MuDQoNCiRNID0gXGZyYWN7MX17c3FydChncmFuZC50b3RhbCl9IFx0aW1lcyBTJA0KDQojIyMgU1ZEIHNpZ25pZmljYSBxdWUgcXVlcmVtb3MgZW5jb250cmFyIG1hdHJpemVzIG9ydG9nb25haXMgVSBlIFYsIGVtIGNvbmp1bnRvIGNvbSB1bWEgbWF0cml6IGRpYWdvbmFsICRcRGVsdGEkLCB0YWwgcXVlOg0KDQokTSA9IFUgXERlbHRhIFZeVCQNCg0KLSBVIMOJIHVtYSBtYXRyaXogY29udGVuZG8gYXV0b3ZldG9yZXMgZGUgbGluaGFzDQotIM6UIMOJIGEgbWF0cml6IGRpYWdvbmFsLiBPcyBuw7ptZXJvcyBuYSBkaWFnb25hbCBkYSBtYXRyaXogc8OjbyBjaGFtYWRvcyBkZSB2YWxvcmVzIHNpbmd1bGFyZXMgKFNWKS4gT3MgYXV0b3ZhbG9yZXMgc8OjbyBvIFNWIHF1YWRyYWRvLg0KLSBWIMOJIHVtYSBtYXRyaXogY29udGVuZG8gYXV0b3ZldG9yZXMgZGUgY29sdW5hDQoNCiMjIyBPIGF1dG92YWxvciBkZSB1bSBkZXRlcm1pbmFkbyBlaXhvIMOpOg0KDQokXGxhbWJkYSA9IFxkZWx0YV4yJA0KDQokXGRlbHRhJCDDiSBvIHZhbG9yIHNpbmd1bGFyDQoNCiMjIyBBcyBjb29yZGVuYWRhcyBkYXMgdmFyacOhdmVpcyBkZSBsaW5oYSBlbSB1bSBkZXRlcm1pbmFkbyBlaXhvIHPDo286DQoNCiRyb3cuY29vcmQgPSBcZnJhY3tVICogXGRlbHRhIH17XHNxcnR7cm93Lm1hc3N9fSQNCg0KIyMjIEFzIGNvb3JkZW5hZGFzIGRhcyBjb2x1bmFzIHPDo28NCg0KJGNvbC5jb29yZCA9IFxmcmFje1YgKiBcZGVsdGEgfXtcc3FydHtjb2wubWFzc319JA0KDQojIyMgY8OhbGN1bG8gU1ZEDQoNCmBgYHtyfQ0KIyMjIEdyYW5kIHRvdGFsDQpuIDwtIHN1bSh0YWIpDQojIyMgU3RhbmRhcmRpemVkIHJlc2lkdWFscw0KcmVzaWR1YWxzIDwtIGNoaXNxJHJlc2lkdWFscy9zcXJ0KG4pDQojIyMgTnVtYmVyIG9mIGRpbWVuc2lvbnMNCm5iLmF4ZXMgPC0gbWluKG5yb3cocmVzaWR1YWxzKS0xLCBuY29sKHJlc2lkdWFscyktMSkNCiMjIyBTaW5ndWxhciB2YWx1ZSBkZWNvbXBvc2l0aW9uDQpyZXMuc3ZkIDwtIHN2ZChyZXNpZHVhbHMsIG51ID0gbmIuYXhlcywgbnYgPSBuYi5heGVzKQ0KcmVzLnN2ZA0KDQojIyMgc2luZ3VsYXIgdmFsdWUNCnN2IDwtIHJlcy5zdmQkZFsxOm5iLmF4ZXNdIA0KdSA8LXJlcy5zdmQkdQ0KdiA8LSByZXMuc3ZkJHYNCg0KIyBpbsOpcmNpYSB0b3RhbA0Kc3VtKHN2XjIpDQpgYGANCg0KDQoNCmBgYHtyfQ0KIyMjIEVpZ2VudmFsdWVzDQplaWcgPC0gc3ZeMg0KIyMjIFZhcmlhbmNlcyBpbiBwZXJjZW50YWdlDQp2YXJpYW5jZSA8LSBlaWcqMTAwL3N1bShlaWcpDQojIyMgQ3VtdWxhdGl2ZSB2YXJpYW5jZXMNCmN1bXZhciA8LSBjdW1zdW0odmFyaWFuY2UpDQplaWc8LSBkYXRhLmZyYW1lKGVpZyA9IGVpZywgdmFyaWFuY2UgPSB2YXJpYW5jZSwNCiAgICAgICAgICAgICAgICAgICAgIGN1bXZhcmlhbmNlID0gY3VtdmFyKQ0KaGVhZChlaWcpDQpgYGANCg0KYGBge3J9DQpiYXJwbG90KGVpZ1ssIDJdLCBuYW1lcy5hcmc9MTpucm93KGVpZyksIA0KICAgICAgIG1haW4gPSAiVmFyaWFuY2VzIiwNCiAgICAgICB4bGFiID0gIkRpbWVuc2lvbnMiLA0KICAgICAgIHlsYWIgPSAiUGVyY2VudGFnZSBvZiB2YXJpYW5jZXMiLA0KICAgICAgIGNvbCA9InN0ZWVsYmx1ZSIpDQojIyMgQWRkIGNvbm5lY3RlZCBsaW5lIHNlZ21lbnRzIHRvIHRoZSBwbG90DQpsaW5lcyh4ID0gMTpucm93KGVpZyksIGVpZ1ssIDJdLCANCiAgICAgIHR5cGU9ImIiLCBwY2g9MTksIGNvbCA9ICJyZWQiKQ0KYGBgDQoNCiMjIyBRdWFudGFzIGRpbWVuc8O1ZXMgcmV0ZXIgPw0KDQojIyMgMS4gTyBuw7ptZXJvIG3DoXhpbW8gZGUgZWl4b3MgbmEgQU5BQ09SIMOpOg0KDQokbmIuYXhlcyA9IG1pbihyLTEsIGMtMSkkDQoNCiMjIyByIGUgYyBzw6NvIHJlc3BlY3RpdmFtZW50ZSBvIG7Dum1lcm8gZGUgbGluaGFzIGUgY29sdW5hcyBuYSB0YWJlbGEuDQoNCiMjIyBSb3cgY29vcmRpbmF0ZXMNCmBgYHtyfQ0KIyMjIHJvdyBzdW0NCnJvdy5zdW0gPC0gYXBwbHkodGFiLCAxLCBzdW0pDQojIyMgcm93IG1hc3MNCnJvdy5tYXNzIDwtIHJvdy5zdW0vbg0KIyMjIHJvdyBjb29yZCA9IHN2ICogdSAvc3FydChyb3cubWFzcykNCmNjIDwtIHQoYXBwbHkodSwgMSwgJyonLCBzdikpICMjIyBlYWNoIHJvdyBYIHN2DQpyb3cuY29vcmQgPC0gYXBwbHkoY2MsIDIsICcvJywgc3FydChyb3cubWFzcykpDQpyb3duYW1lcyhyb3cuY29vcmQpIDwtIHJvd25hbWVzKHRhYikNCmNvbG5hbWVzKHJvdy5jb29yZCkgPC0gcGFzdGUwKCJEaW0uIiwgMTpuYi5heGVzKQ0Kcm91bmQocm93LmNvb3JkLDMpDQoNCg0KIyMjIHBsb3QNCnBsb3Qocm93LmNvb3JkLCBwY2g9MTksIGNvbCA9ICJibHVlIikNCnRleHQocm93LmNvb3JkLCBsYWJlbHMgPXJvd25hbWVzKHJvdy5jb29yZCksIHBvcyA9IDMsIGNvbCA9ImJsdWUiKQ0KYWJsaW5lKHY9MCwgaD0wLCBsdHkgPSAyKQ0KYGBgDQoNCiMjIyAgQ29sdW1uIGNvb3JkaW5hdGVzDQoNCmBgYHtyfQ0KIyMjIENvb3JkaW5hdGVzIG9mIGNvbHVtbnMNCmNvbC5zdW0gPC0gYXBwbHkodGFiLCAyLCBzdW0pDQpjb2wubWFzcyA8LSBjb2wuc3VtL24NCiMjIyBjb29yZGluYXRlcyBzdiAqIHYgL3NxcnQoY29sLm1hc3MpDQpjYyA8LSB0KGFwcGx5KHYsIDEsICcqJywgc3YpKQ0KY29sLmNvb3JkIDwtIGFwcGx5KGNjLCAyLCAnLycsIHNxcnQoY29sLm1hc3MpKQ0Kcm93bmFtZXMoY29sLmNvb3JkKSA8LSBjb2xuYW1lcyh0YWIpDQpjb2xuYW1lcyhjb2wuY29vcmQpIDwtIHBhc3RlMCgiRGltIiwgMTpuYi5heGVzKQ0KaGVhZChjb2wuY29vcmQpDQoNCiMjIyBwbG90DQpwbG90KGNvbC5jb29yZCwgcGNoPTE3LCBjb2wgPSAicmVkIikNCnRleHQoY29sLmNvb3JkLCBsYWJlbHMgPXJvd25hbWVzKGNvbC5jb29yZCksIHBvcyA9IDMsIGNvbCA9InJlZCIpDQphYmxpbmUodj0wLCBoPTAsIGx0eSA9IDIpDQpgYGANCg0KIyMjIEJpcGxvdCBkZSBsaW5oYXMgZSBjb2x1bmFzIHBhcmEgdmVyIGEgYXNzb2NpYcOnw6NvDQoNCmBgYHtyfQ0KeGxpbSA8LSByYW5nZShjKHJvdy5jb29yZFssMV0sIGNvbC5jb29yZFssMV0pKSoxLjENCnlsaW0gPC0gcmFuZ2UoYyhyb3cuY29vcmRbLDJdLCBjb2wuY29vcmRbLDJdKSkqMS4xDQojIyMgUGxvdCBvZiByb3dzDQpwbG90KHJvdy5jb29yZCwgcGNoPTE5LCBjb2wgPSAiYmx1ZSIsIHhsaW0gPSB4bGltLCB5bGltID0geWxpbSkNCnRleHQocm93LmNvb3JkLCBsYWJlbHMgPXJvd25hbWVzKHJvdy5jb29yZCksIHBvcyA9IDMsIGNvbCA9ImJsdWUiKQ0KIyMjIHBsb3Qgb2ZmIGNvbHVtbnMNCnBvaW50cyhjb2wuY29vcmQsIHBjaD0xNywgY29sID0gInJlZCIpDQp0ZXh0KGNvbC5jb29yZCwgbGFiZWxzID1yb3duYW1lcyhjb2wuY29vcmQpLCBwb3MgPSAzLCBjb2wgPSJyZWQiKQ0KYWJsaW5lKHY9MCwgaD0wLCBsdHkgPSAyKQ0KYGBgDQoNCg0KIyMjIERpYWduw7NzdGljbw0KDQojIyNMZW1icmUtc2UgcXVlLCBhIGluw6lyY2lhIHRvdGFsIGNvbnRpZGEgbm9zIGRhZG9zIMOpOg0KDQokXHBoaV4yID0gXGZyYWN7XGNoaV4yfXtufSQNCg0KIyMjTm9zc28gZ3LDoWZpY28gYmlkaW1lbnNpb25hbCBjYXB0dXJhIGNlcmNhIGRlIDg4JSBkYSBpbsOpcmNpYSB0b3RhbCBkYSB0YWJlbGEuDQoNCiMjIyBDb250cmlidWnDp8OjbyBkZSBsaW5oYXMgZSBjb2x1bmFzDQoNCiMjI0FzIGNvbnRyaWJ1acOnw7VlcyBkZSB1bWEgbGluaGEgLyBjb2x1bmEgcGFyYSBhIGRlZmluacOnw6NvIGRlIHVtIGVpeG8gcHJpbmNpcGFsIHPDo286DQoNCiRyb3cuY29udHJpYiA9IFxmcmFje3Jvdy5tYXNzICogcm93LmNvb3JkXjJ9e2VpZ2VudmFsdWV9JA0KDQokY29sLmNvbnRyaWIgPSBcZnJhY3tjb2wubWFzcyAqIGNvbC5jb29yZF4yfXtlaWdlbnZhbHVlfSQNCg0KIyMjQ29udHJpYnVpw6fDo28gZGUgbGluaGFzIGVtICUNCg0KYGBge3J9DQojIyMgY29udHJpYiA8LSByb3cubWFzcyAqIHJvdy5jb29yZF4yL2VpZ2VudmFsdWUNCmNjIDwtIGFwcGx5KHJvdy5jb29yZF4yLCAyLCAiKiIsIHJvdy5tYXNzKQ0Kcm93LmNvbnRyaWIgPC0gdChhcHBseShjYywgMSwgIi8iLCBlaWdbMTpuYi5heGVzLDFdKSkgKjEwMA0Kcm91bmQocm93LmNvbnRyaWIsIDIpDQoNCmNvcnJwbG90KHJvdy5jb250cmliLCBpcy5jb3IgPSBGQUxTRSkNCmBgYA0KDQojIyNDb250cmlidWnDp8OjbyBkYXMgY29sdW5hcyBlbSAlDQoNCmBgYHtyfQ0KIyMjIGNvbnRyaWIgPC0gY29sLm1hc3MgKiBjb2wuY29vcmReMi9laWdlbnZhbHVlDQpjYyA8LSBhcHBseShjb2wuY29vcmReMiwgMiwgIioiLCBjb2wubWFzcykNCmNvbC5jb250cmliIDwtIHQoYXBwbHkoY2MsIDEsICIvIiwgZWlnWzE6bmIuYXhlcywxXSkpICoxMDANCnJvdW5kKGNvbC5jb250cmliLCAyKQ0KDQpjb3JycGxvdChjb2wuY29udHJpYiwgaXMuY29yID0gRkFMU0UpDQpgYGANCg0KIyMjIFF1YWxpZGFkZSBkYSByZXByZXNlbnRhw6fDo28NCg0KIyMjQSBxdWFsaWRhZGUgZGEgcmVwcmVzZW50YcOnw6NvIMOpIGNoYW1hZGEgQ09TMi4NCg0KIyMjQSBxdWFsaWRhZGUgZGEgcmVwcmVzZW50YcOnw6NvIGRlIHVtYSBsaW5oYSBlbSB1bSBlaXhvIMOpOg0KDQokcm93LmNvczIgPSBcZnJhY3tyb3cuY29vcmReMn17ZF4yfSQNCg0KLSBSb3cuY29vcmQgw6kgYSBjb29yZGVuYWRhIGRhIGxpbmhhIG5vIGVpeG8NCi0gJGReMiQgw4kgYSBkaXN0w6JuY2lhIGFvIHF1YWRyYWRvIGRvIHBlcmZpbCBtw6lkaW8NCg0KIyMjTGVtYnJlLXNlIGRlIHF1ZSBhIGRpc3TDom5jaWEgZW50cmUgY2FkYSBwZXJmaWwgZGUgbGluaGEgZSBvIHBlcmZpbCBkZSBsaW5oYSBtw6lkaW8gw6k6DQoNCiRkXjIocm93X2ksIGF2ZXJhZ2UucHJvZmlsZSkgPSBcc3Vte1xmcmFjeyhyb3cucHJvZmlsZV9pIC0gYXZlcmFnZS5wcm9maWxlKV4yfXthdmVyYWdlLnByb2ZpbGV9fSQNCg0KYGBge3J9DQpyb3cucHJvZmlsZSA8LSB0YWIvcm93LnN1bQ0KaGVhZChyb3VuZChyb3cucHJvZmlsZSwgMykpDQoNCmF2ZXJhZ2UucHJvZmlsZSA8LSBjb2wuc3VtL24NCmhlYWQocm91bmQoYXZlcmFnZS5wcm9maWxlLCAzKSkNCmBgYA0KDQojIyNPIGPDs2RpZ28gUiBhYmFpeG8gY2FsY3VsYSBhIGRpc3TDom5jaWEgZG8gcGVyZmlsIG3DqWRpbyBwYXJhIHRvZGFzIGFzIHZhcmnDoXZlaXMgZGUgbGluaGENCg0KYGBge3J9DQphdmVyYWdlLnJwIDwtIGNvbC5zdW0vbiANCmQyLnJvdyA8LSBhcHBseShyb3cucHJvZmlsZSwgMSwgDQogICAgICAgICAgICAgICAgZnVuY3Rpb24ocm93LnAsIGF2LnApe3N1bSgoKHJvdy5wIC0gYXYucCleMikvYXYucCl9LCANCiAgICAgICAgICAgICAgICBhdmVyYWdlLnJwKQ0KaGVhZChyb3VuZChkMi5yb3csMykpDQpgYGANCg0KIyMjTyBjb3MyIGRlIGxpbmhhcyBubyBtYXBhIGRlIGZhdG9yZXMgc8OjbzoNCg0KYGBge3J9DQpyb3cuY29zMiA8LSBhcHBseShyb3cuY29vcmReMiwgMiwgIi8iLCBkMi5yb3cpDQpyb3VuZChyb3cuY29zMiwgMykNCg0KY29ycnBsb3Qocm93LmNvczIsIGlzLmNvciA9IEZBTFNFKQ0KYGBgDQoNCiMjI0NvczIgZGFzIGNvbHVuYXMNCg0KJGNvbC5jb3MyID0gXGZyYWN7Y29sLmNvb3JkXjJ9e2ReMn0kDQoNCmBgYHtyfQ0KY29sLnByb2ZpbGUgPC0gdCh0YWIpL2NvbC5zdW0NCmNvbC5wcm9maWxlIDwtIHQoY29sLnByb2ZpbGUpDQojIyNoZWFkKHJvdW5kKGNvbC5wcm9maWxlLCAzKSkNCmF2ZXJhZ2UucHJvZmlsZSA8LSByb3cuc3VtL24NCiMjI2hlYWQocm91bmQoYXZlcmFnZS5wcm9maWxlLCAzKSkNCmBgYA0KDQojIyNPIGPDs2RpZ28gUiBhYmFpeG8gY2FsY3VsYSBhIGRpc3TDom5jaWEgZG8gcGVyZmlsIG3DqWRpbyBwYXJhIHRvZGFzIGFzIHZhcmnDoXZlaXMgZGEgY29sdW5hDQoNCmBgYHtyfQ0KDQpkMi5jb2wgPC0gYXBwbHkoY29sLnByb2ZpbGUsIDIsIA0KICAgICAgICBmdW5jdGlvbihjb2wucCwgYXYucCl7c3VtKCgoY29sLnAgLSBhdi5wKV4yKS9hdi5wKX0sIA0KICAgICAgICBhdmVyYWdlLnByb2ZpbGUpDQpyb3VuZChkMi5jb2wsMykNCmBgYA0KDQojIyNPIGNvczIgZGFzIGNvbHVuYXMgbm8gbWFwYSBkZSBmYXRvcmVzIHPDo286DQoNCmBgYHtyfQ0KY29sLmNvczIgPC0gYXBwbHkoY29sLmNvb3JkXjIsIDIsICIvIiwgZDIuY29sKQ0Kcm91bmQoY29sLmNvczIsIDMpDQoNCmNvcnJwbG90KGNvbC5jb3MyLCBpcy5jb3IgPSBGQUxTRSkNCmBgYA0KDQoNCg0KIyMjIFBhY290ZXMgbm8gUiBwYXJhIEFOQUNPUg0KDQotRmFjdG9NaW5lUg0KLWFkZTQNCi1jYQ0KDQpgYGB7cn0NCmxpYnJhcnkoRmFjdG9NaW5lUikNCnJlcy5jYSA8LSBDQSh0YWIsIGdyYXBoID0gRikNCnN1bW1hcnkocmVzLmNhKQ0KYGBgDQoNCmBgYHtyfQ0KIyMjIFBsb3Qgcm93IHBvaW50cw0KcGxvdChyZXMuY2EsIGludmlzaWJsZSA9ImNvbCIpDQpgYGANCg0KYGBge3J9DQojIyMgUGxvdCBjb2x1bW4gcG9pbnRzDQpwbG90KHJlcy5jYSwgaW52aXNpYmxlID0icm93IikNCmBgYA0KDQpgYGB7cn0NCiMjIyBCaXBsb3Qgb2Ygcm93cyBhbmQgY29sdW1ucw0KcGxvdChyZXMuY2EpDQpgYGANCg0KDQoNCg==