#library(devtools)
#session_info()
#?daisy()
#artigo base para criar cluster com variáveis quali e quanti - Gower, J. C. (1971) A general coefficient of similarity and some of its properties, Biometrics 27, 857–874.
# dados qualificação
#dados<- read_excel("dados_tab.xlsx")
# dados defesa
dados<- read_excel("dados.xlsx")
row.names(dados) <- (c(
"Produtor 1", "Produtor 2",
"Produtor 3", "Produtor 4",
"Produtor 5", "Produtor 6",
"Produtor 7", "Produtor 8",
"Produtor 9", "PrOdutor 10"))
Setting row names on a tibble is deprecated.
#View(dados6)
str(dados)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 10 obs. of 3 variables:
$ a: num 1 1 1 1 1 2 2 2 2 2
$ b: num 20 22 23 20 21 40 42 45 44 48
$ c: num 1 1 2 2 2 3 3 3 3 3
dados$`a`<-factor(dados$`a`, levels = c("1","2"), labels = c("Proprietário","Arrendada"))
dados$`c`<-factor(dados$`c`, levels = c("1","2","3"), labels = c("Leiteira","Leiteira e cria","Leiteira, cria, recria e engorda"))
#somente qualitativos
dados_quali <- dados[,c('a','c')]
#somente quantitativos
dados_quanti <- dados[,c('b')]
#str(dados)
# escolher o que vai empregar
#dados=dados_quanti
#dados = dados_quali
dados=dados
Descrição
glimpse(dados)
Observations: 10
Variables: 3
$ a <fct> Proprietário, Proprietário, Proprietário, Proprietário, Proprietário, Arrendada, Arrendada, Arrendada, Arrendada, Ar...
$ b <dbl> 20, 22, 23, 20, 21, 40, 42, 45, 44, 48
$ c <fct> Leiteira, Leiteira, Leiteira e cria, Leiteira e cria, Leiteira e cria, Leiteira, cria, recria e engorda, Leiteira, ...
dados
#stats4::summary(dados)
gower_dist <- daisy(dados, metric = "gower")
# Check attributes to ensure the correct methods are being used
# (I = interval',' N = nominal)
gower_dist
Dissimilarities :
Produtor 1 Produtor 2 Produtor 3 Produtor 4 Produtor 5 Produtor 6 Produtor 7 Produtor 8 Produtor 9
Produtor 2 0.02380952
Produtor 3 0.36904762 0.34523810
Produtor 4 0.33333333 0.35714286 0.03571429
Produtor 5 0.34523810 0.34523810 0.02380952 0.01190476
Produtor 6 0.90476190 0.88095238 0.86904762 0.90476190 0.89285714
Produtor 7 0.92857143 0.90476190 0.89285714 0.92857143 0.91666667 0.02380952
Produtor 8 0.96428571 0.94047619 0.92857143 0.96428571 0.95238095 0.05952381 0.03571429
Produtor 9 0.95238095 0.92857143 0.91666667 0.95238095 0.94047619 0.04761905 0.02380952 0.01190476
PrOdutor 10 1.00000000 0.97619048 0.96428571 1.00000000 0.98809524 0.09523810 0.07142857 0.03571429 0.04761905
Metric : mixed ; Types = N, I, N
Number of objects : 10
summary(gower_dist)
45 dissimilarities, summarized :
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.01191 0.05952 0.89286 0.57857 0.94048 1.00000
Metric : mixed ; Types = N, I, N
Number of objects : 10
verificar a mais similar e mais dissimilar
gower_mat <- as.matrix(gower_dist)
# Output most similar pair
dados[
which(gower_mat == min(gower_mat[gower_mat != min(gower_mat)]),
arr.ind = TRUE)[1, ], ]
dados[
which(gower_mat == max(gower_mat[gower_mat != max(gower_mat)]),
arr.ind = TRUE)[1, ], ]
ASSESSING CLUSTERING TENDENCY
fviz_dist(gower_dist, show_labels = FALSE)+ labs(title = "")

#The algorithm of the visual assessment of cluster tendency (VAT) approach (Bezdek and Hathaway, 2002) is as follow:
#The algorithm of VAT is as follow:
# 1. Compute the dissimilarity (DM) matrix between the objects in the data set using the Euclidean distance measure (3)
# 2. Reorder the DM so that similar objects are close to one another. This process create an ordered dissimilarity matrix (ODM)
# 3. The ODM is displayed as an ordered dissimilarity image (ODI), which is the visual output of VAT
#The color level is proportional to the value of the dissimilarity between observations: pure red if dist(xi, xj) = 0 and pure blue if dist(xi, xj) = 1. Objects belonging to the same cluster are displayed in consecutive order.
algoritmo não hierárquico PAM
# Calculate silhouette width for many k using PAM
#gower_dist - matriz com as distâncias
sil_width <- c(NA)
for(i in 2:3){
pam_fit <- pam(gower_dist,
diss = TRUE,
k = i)
sil_width[i] <- pam_fit$silinfo$avg.width
}
# Plot sihouette width (higher is better)
plot(1:3, sil_width,
xlab = "Number of clusters",
ylab = "Silhouette Width")
lines(1:3, sil_width)

library(fpc)
pamk(gower_dist, diss=T,krange=2:3,criterion="asw", usepam=TRUE)
$`pamobject`
Medoids:
ID
[1,] "2" "Produtor 2"
[2,] "5" "Produtor 5"
[3,] "9" "Produtor 9"
Clustering vector:
Produtor 1 Produtor 2 Produtor 3 Produtor 4 Produtor 5 Produtor 6 Produtor 7 Produtor 8 Produtor 9 PrOdutor 10
1 1 2 2 2 3 3 3 3 3
Objective function:
build swap
0.02857143 0.01904762
Available components:
[1] "medoids" "id.med" "clustering" "objective" "isolation" "clusinfo" "silinfo" "diss" "call"
$nc
[1] 3
$crit
[1] 0.0000000 0.8587771 0.9417483
k=3
pam_fit <- pam(gower_dist, diss = TRUE, k)
dados[pam_fit$medoids, ]
print(pam_fit)
Medoids:
ID
[1,] "2" "Produtor 2"
[2,] "5" "Produtor 5"
[3,] "9" "Produtor 9"
Clustering vector:
Produtor 1 Produtor 2 Produtor 3 Produtor 4 Produtor 5 Produtor 6 Produtor 7 Produtor 8 Produtor 9 PrOdutor 10
1 1 2 2 2 3 3 3 3 3
Objective function:
build swap
0.02857143 0.01904762
Available components:
[1] "medoids" "id.med" "clustering" "objective" "isolation" "clusinfo" "silinfo" "diss" "call"
grp = pam_fit$clustering
# como fazer com as dist? só lançar data como matriz de distâncias
fviz_cluster(list(data = gower_dist, cluster = grp),
#palette = c("orange", "green","red","brown", "blue"),
ellipse.type = "convex", # Concentration ellipse
repel = TRUE, # Avoid label overplotting (slow)
show.clust.cent = FALSE, ggtheme = theme_minimal())

Descrição dos grupos pelo PAM
pam_results <- dados %>%
dplyr::mutate(cluster = pam_fit$clustering) %>%
group_by(cluster) %>%
do(the_summary = summary(.))
pam_results$the_summary
[[1]]
a b c cluster
Proprietário:2 Min. :20.0 Leiteira :2 Min. :1
Arrendada :0 1st Qu.:20.5 Leiteira e cria :0 1st Qu.:1
Median :21.0 Leiteira, cria, recria e engorda:0 Median :1
Mean :21.0 Mean :1
3rd Qu.:21.5 3rd Qu.:1
Max. :22.0 Max. :1
[[2]]
a b c cluster
Proprietário:3 Min. :20.00 Leiteira :0 Min. :2
Arrendada :0 1st Qu.:20.50 Leiteira e cria :3 1st Qu.:2
Median :21.00 Leiteira, cria, recria e engorda:0 Median :2
Mean :21.33 Mean :2
3rd Qu.:22.00 3rd Qu.:2
Max. :23.00 Max. :2
[[3]]
a b c cluster
Proprietário:0 Min. :40.0 Leiteira :0 Min. :3
Arrendada :5 1st Qu.:42.0 Leiteira e cria :0 1st Qu.:3
Median :44.0 Leiteira, cria, recria e engorda:5 Median :3
Mean :43.8 Mean :3
3rd Qu.:45.0 3rd Qu.:3
Max. :48.0 Max. :3
Algoritmo Hierárquico
res.hc <- hclust(d = gower_dist, method = "ward.D2")
#Ward’s minimum variance method: It minimizes the total within-cluster variance. At each step the pair of clusters with minimum between-cluster distance are merged.
fviz_dist(gower_dist)

fviz_dend(res.hc, cex = 0.5)

# Compute cophentic distance
res.coph <- cophenetic(res.hc)
# Correlation between cophenetic distance and
# the original distance
cor(gower_dist, res.coph)
[1] 0.9950055
res.hc2 <- hclust(gower_dist, method = "average")
cor(gower_dist, cophenetic(res.hc2))
[1] 0.9977315
# Cut tree into k groups
#k=4
grp <- cutree(res.hc, k )
grp
Produtor 1 Produtor 2 Produtor 3 Produtor 4 Produtor 5 Produtor 6 Produtor 7 Produtor 8 Produtor 9 PrOdutor 10
1 1 2 2 2 3 3 3 3 3
table(grp)
grp
1 2 3
2 3 5
# Cut in 3 groups and color by groups
fviz_dend(res.hc, k , # Cut in k groups
cex = 0.5, # label size
k_colors = c("#2E9FDF", "#00AFBB", "#FC4E07", "#E7B800"),
color_labels_by_k = TRUE, # color labels by groups
rect = TRUE # Add rectangle around groups
)
Length of color vector was longer than the number of clusters - first k elements are used

# como fazer com as dist? só lançar data como matriz de distâncias
fviz_cluster(list(data = gower_dist, cluster = grp),
palette = c("#2E9FDF", "#00AFBB", "#E7B800", "#FC4E07", "red"),
ellipse.type = "convex", # Concentration ellipse
repel = TRUE, # Avoid label overplotting (slow)
show.clust.cent = FALSE, ggtheme = theme_minimal())

LS0tDQp0aXRsZTogIkFuw6FsaXNlIGRlIENvbmdsb21lcmFkb3MgLSBFeGVtcGxvIGNsdXN0ZXIgbWl4ZWQgZGF0YSB0eXBlIg0KYXV0aG9yOiAiTGVvbmksIFIuIEMuIFByb2YuIERyLiINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCg0KYGBge3Igc2V0dXAsIGVjaG89RkFMU0V9DQoNCg0Kcm0obGlzdD1scyhhbGw9VFJVRSkpDQoNCmxpYnJhcnkoZmFjdG9leHRyYSkNCmxpYnJhcnkocHN5Y2gpDQpsaWJyYXJ5KGNsdXN0ZXIpDQpsaWJyYXJ5KE5iQ2x1c3QpDQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkocm9idXN0WCkNCmxpYnJhcnkoZGVuZGV4dGVuZCkNCmxpYnJhcnkoY29ycnBsb3QpDQpsaWJyYXJ5KGNsdXN0TWl4VHlwZSkNCmxpYnJhcnkoZHBseXIpICMgZm9yIGRhdGEgY2xlYW5pbmcNCmxpYnJhcnkoSVNMUikgIyBmb3IgY29sbGVnZSBkYXRhc2V0DQpsaWJyYXJ5KFJ0c25lKSAjIGZvciB0LVNORSBwbG90DQpsaWJyYXJ5KGdncGxvdDIpICMgZm9yIHZpc3VhbGl6YXRpb24NCiNsaWJyYXJ5KENsdU1peCkNCmBgYA0KDQpgYGB7cn0NCiNsaWJyYXJ5KGRldnRvb2xzKQ0KI3Nlc3Npb25faW5mbygpDQpgYGANCg0KYGBge3J9DQojP2RhaXN5KCkNCiNhcnRpZ28gYmFzZSBwYXJhIGNyaWFyIGNsdXN0ZXIgY29tIHZhcmnDoXZlaXMgcXVhbGkgZSBxdWFudGkgLSBHb3dlciwgSi4gQy4gKDE5NzEpIEEgZ2VuZXJhbCBjb2VmZmljaWVudCBvZiBzaW1pbGFyaXR5IGFuZCBzb21lIG9mIGl0cyBwcm9wZXJ0aWVzLCBCaW9tZXRyaWNzIDI3LCA4NTfigJM4NzQuDQpgYGANCg0KDQpgYGB7cn0NCiMgZGFkb3MgcXVhbGlmaWNhw6fDo28NCiNkYWRvczwtIHJlYWRfZXhjZWwoImRhZG9zX3RhYi54bHN4IikNCiMgZGFkb3MgZGVmZXNhDQpkYWRvczwtIHJlYWRfZXhjZWwoImRhZG9zLnhsc3giKQ0KDQpyb3cubmFtZXMoZGFkb3MpIDwtIChjKA0KICAgICAgICAgICAgICAgICAgICAgIlByb2R1dG9yIDEiLCAgICAgICAgICAgICAgICAgICAgICJQcm9kdXRvciAyIiwNCiAgICAgICAgICAgICAgICAgICAgICJQcm9kdXRvciAzIiwgICAgICAgICAgICAgICAgICAgICAiUHJvZHV0b3IgNCIsDQogICAgICAgICAgICAgICAgICAgICAiUHJvZHV0b3IgNSIsICAgICAgICAgICAgICAgICAgICAgIlByb2R1dG9yIDYiLA0KICAgICAgICAgICAgICAgICAgICAgIlByb2R1dG9yIDciLCAgICAgICAgICAgICAgICAgICAgICJQcm9kdXRvciA4IiwNCiAgICAgICAgICAgICAgICAgICAgICJQcm9kdXRvciA5IiwgICAgICAgICAgICAgICAgICAgICAiUHJPZHV0b3IgMTAiKSkNCiNWaWV3KGRhZG9zNikNCnN0cihkYWRvcykNCg0KZGFkb3MkYGFgPC1mYWN0b3IoZGFkb3MkYGFgLCBsZXZlbHMgPSBjKCIxIiwiMiIpLCBsYWJlbHMgPSBjKCJQcm9wcmlldMOhcmlvIiwiQXJyZW5kYWRhIikpDQpkYWRvcyRgY2A8LWZhY3RvcihkYWRvcyRgY2AsIGxldmVscyA9IGMoIjEiLCIyIiwiMyIpLCBsYWJlbHMgPSBjKCJMZWl0ZWlyYSIsIkxlaXRlaXJhIGUgY3JpYSIsIkxlaXRlaXJhLCAgY3JpYSwgcmVjcmlhIGUgZW5nb3JkYSIpKQ0KDQojc29tZW50ZSBxdWFsaXRhdGl2b3MNCmRhZG9zX3F1YWxpIDwtIGRhZG9zWyxjKCdhJywnYycpXQ0KDQojc29tZW50ZSBxdWFudGl0YXRpdm9zDQoNCmRhZG9zX3F1YW50aSA8LSAgZGFkb3NbLGMoJ2InKV0NCiNzdHIoZGFkb3MpDQoNCiMgIGVzY29saGVyIG8gcXVlIHZhaSBlbXByZWdhcg0KDQojZGFkb3M9ZGFkb3NfcXVhbnRpDQojZGFkb3MgPSBkYWRvc19xdWFsaQ0KZGFkb3M9ZGFkb3MNCmBgYA0KDQojIERlc2NyacOnw6NvDQoNCmBgYHtyfQ0KZ2xpbXBzZShkYWRvcykNCmRhZG9zIA0KI3N0YXRzNDo6c3VtbWFyeShkYWRvcykNCmBgYA0KDQpgYGB7cn0NCmdvd2VyX2Rpc3QgPC0gZGFpc3koZGFkb3MsIG1ldHJpYyA9ICJnb3dlciIpDQojIENoZWNrIGF0dHJpYnV0ZXMgdG8gZW5zdXJlIHRoZSBjb3JyZWN0IG1ldGhvZHMgYXJlIGJlaW5nIHVzZWQNCiMgKEkgPSBpbnRlcnZhbCcsJyBOID0gbm9taW5hbCkNCmdvd2VyX2Rpc3QNCnN1bW1hcnkoZ293ZXJfZGlzdCkNCmBgYA0KDQojIHZlcmlmaWNhciBhIG1haXMgc2ltaWxhciBlIG1haXMgZGlzc2ltaWxhcg0KDQpgYGB7cn0NCmdvd2VyX21hdCA8LSBhcy5tYXRyaXgoZ293ZXJfZGlzdCkNCg0KIyBPdXRwdXQgbW9zdCBzaW1pbGFyIHBhaXINCg0KZGFkb3NbDQogIHdoaWNoKGdvd2VyX21hdCA9PSBtaW4oZ293ZXJfbWF0W2dvd2VyX21hdCAhPSBtaW4oZ293ZXJfbWF0KV0pLA0KICAgICAgICBhcnIuaW5kID0gVFJVRSlbMSwgXSwgXQ0KDQpkYWRvc1sNCiAgd2hpY2goZ293ZXJfbWF0ID09IG1heChnb3dlcl9tYXRbZ293ZXJfbWF0ICE9IG1heChnb3dlcl9tYXQpXSksDQogICAgICAgIGFyci5pbmQgPSBUUlVFKVsxLCBdLCBdDQpgYGANCg0KIyBBU1NFU1NJTkcgQ0xVU1RFUklORyBURU5ERU5DWQ0KDQpgYGB7cn0NCmZ2aXpfZGlzdChnb3dlcl9kaXN0LCBzaG93X2xhYmVscyA9IEZBTFNFKSsgbGFicyh0aXRsZSA9ICIiKQ0KDQojVGhlIGFsZ29yaXRobSBvZiB0aGUgdmlzdWFsIGFzc2Vzc21lbnQgb2YgY2x1c3RlciB0ZW5kZW5jeSAoVkFUKSBhcHByb2FjaCAoQmV6ZGVrIGFuZCBIYXRoYXdheSwgMjAwMikgaXMgYXMgZm9sbG93Og0KI1RoZSBhbGdvcml0aG0gb2YgVkFUIGlzIGFzIGZvbGxvdzogDQojIDEuIENvbXB1dGUgdGhlIGRpc3NpbWlsYXJpdHkgKERNKSBtYXRyaXggYmV0d2VlbiB0aGUgb2JqZWN0cyBpbiB0aGUgZGF0YSBzZXQgdXNpbmcgdGhlIEV1Y2xpZGVhbiBkaXN0YW5jZSBtZWFzdXJlICgzKQ0KIyAyLiBSZW9yZGVyIHRoZSBETSBzbyB0aGF0IHNpbWlsYXIgb2JqZWN0cyBhcmUgY2xvc2UgdG8gb25lIGFub3RoZXIuIFRoaXMgcHJvY2VzcyBjcmVhdGUgYW4gb3JkZXJlZCBkaXNzaW1pbGFyaXR5IG1hdHJpeCAoT0RNKQ0KIyAzLiBUaGUgT0RNIGlzIGRpc3BsYXllZCBhcyBhbiBvcmRlcmVkIGRpc3NpbWlsYXJpdHkgaW1hZ2UgKE9ESSksIHdoaWNoIGlzIHRoZSB2aXN1YWwgb3V0cHV0IG9mIFZBVA0KI1RoZSBjb2xvciBsZXZlbCBpcyBwcm9wb3J0aW9uYWwgdG8gdGhlIHZhbHVlIG9mIHRoZSBkaXNzaW1pbGFyaXR5IGJldHdlZW4gb2JzZXJ2YXRpb25zOiBwdXJlIHJlZCBpZiBkaXN0KHhpLCB4aikgPSAwIGFuZCBwdXJlIGJsdWUgaWYgZGlzdCh4aSwgeGopID0gMS4gT2JqZWN0cyBiZWxvbmdpbmcgdG8gdGhlIHNhbWUgY2x1c3RlciBhcmUgZGlzcGxheWVkIGluIGNvbnNlY3V0aXZlIG9yZGVyLg0KDQoNCg0KDQpgYGANCg0KIyBhbGdvcml0bW8gbsOjbyBoaWVyw6FycXVpY28gUEFNDQoNCmBgYHtyfQ0KIyBDYWxjdWxhdGUgc2lsaG91ZXR0ZSB3aWR0aCBmb3IgbWFueSBrIHVzaW5nIFBBTQ0KI2dvd2VyX2Rpc3QgLSBtYXRyaXogY29tIGFzIGRpc3TDom5jaWFzDQpzaWxfd2lkdGggPC0gYyhOQSkNCmZvcihpIGluIDI6Myl7DQogIHBhbV9maXQgPC0gcGFtKGdvd2VyX2Rpc3QsDQogICAgICAgICAgICAgICAgIGRpc3MgPSBUUlVFLA0KICAgICAgICAgICAgICAgICBrID0gaSkNCiAgc2lsX3dpZHRoW2ldIDwtIHBhbV9maXQkc2lsaW5mbyRhdmcud2lkdGgNCn0NCiMgUGxvdCBzaWhvdWV0dGUgd2lkdGggKGhpZ2hlciBpcyBiZXR0ZXIpDQpwbG90KDE6Mywgc2lsX3dpZHRoLA0KICAgICB4bGFiID0gIk51bWJlciBvZiBjbHVzdGVycyIsDQogICAgIHlsYWIgPSAiU2lsaG91ZXR0ZSBXaWR0aCIpDQpsaW5lcygxOjMsIHNpbF93aWR0aCkNCg0KYGBgDQoNCmBgYHtyfQ0KbGlicmFyeShmcGMpDQoNCnBhbWsoZ293ZXJfZGlzdCwgZGlzcz1ULGtyYW5nZT0yOjMsY3JpdGVyaW9uPSJhc3ciLCB1c2VwYW09VFJVRSkNCg0KDQpgYGANCg0KDQoNCg0KYGBge3J9DQprPTMNCnBhbV9maXQgPC0gcGFtKGdvd2VyX2Rpc3QsIGRpc3MgPSBUUlVFLCBrKQ0KDQpkYWRvc1twYW1fZml0JG1lZG9pZHMsIF0NCnByaW50KHBhbV9maXQpDQoNCmdycCA9IHBhbV9maXQkY2x1c3RlcmluZw0KDQojICBjb21vIGZhemVyIGNvbSBhcyBkaXN0PyAgc8OzIGxhbsOnYXIgZGF0YSBjb21vIG1hdHJpeiBkZSBkaXN0w6JuY2lhcw0KDQpmdml6X2NsdXN0ZXIobGlzdChkYXRhID0gZ293ZXJfZGlzdCwgY2x1c3RlciA9IGdycCksDQojcGFsZXR0ZSA9IGMoIm9yYW5nZSIsICJncmVlbiIsInJlZCIsImJyb3duIiwgImJsdWUiKSwNCmVsbGlwc2UudHlwZSA9ICJjb252ZXgiLCAjIENvbmNlbnRyYXRpb24gZWxsaXBzZQ0KcmVwZWwgPSBUUlVFLCAjIEF2b2lkIGxhYmVsIG92ZXJwbG90dGluZyAoc2xvdykNCnNob3cuY2x1c3QuY2VudCA9IEZBTFNFLCBnZ3RoZW1lID0gdGhlbWVfbWluaW1hbCgpKQ0KYGBgDQoNCiMgRGVzY3Jpw6fDo28gZG9zIGdydXBvcyBwZWxvIFBBTQ0KYGBge3J9DQpwYW1fcmVzdWx0cyA8LSBkYWRvcyAlPiUNCiAgZHBseXI6Om11dGF0ZShjbHVzdGVyID0gcGFtX2ZpdCRjbHVzdGVyaW5nKSAlPiUNCiAgZ3JvdXBfYnkoY2x1c3RlcikgJT4lDQogIGRvKHRoZV9zdW1tYXJ5ID0gc3VtbWFyeSguKSkNCg0KcGFtX3Jlc3VsdHMkdGhlX3N1bW1hcnkNCg0KYGBgDQoNCg0KDQojIEFsZ29yaXRtbyBIaWVyw6FycXVpY28gDQpgYGB7cn0NCg0KcmVzLmhjIDwtIGhjbHVzdChkID0gZ293ZXJfZGlzdCwgbWV0aG9kID0gIndhcmQuRDIiKQ0KI1dhcmTigJlzIG1pbmltdW0gdmFyaWFuY2UgbWV0aG9kOiBJdCBtaW5pbWl6ZXMgdGhlIHRvdGFsIHdpdGhpbi1jbHVzdGVyIHZhcmlhbmNlLiBBdCBlYWNoIHN0ZXAgdGhlIHBhaXIgb2YgY2x1c3RlcnMgd2l0aCBtaW5pbXVtIGJldHdlZW4tY2x1c3RlciBkaXN0YW5jZSBhcmUgbWVyZ2VkLg0KDQpmdml6X2Rpc3QoZ293ZXJfZGlzdCkNCmZ2aXpfZGVuZChyZXMuaGMsIGNleCA9IDAuNSkNCg0KIyBDb21wdXRlIGNvcGhlbnRpYyBkaXN0YW5jZQ0KcmVzLmNvcGggPC0gY29waGVuZXRpYyhyZXMuaGMpDQojIENvcnJlbGF0aW9uIGJldHdlZW4gY29waGVuZXRpYyBkaXN0YW5jZSBhbmQNCiMgdGhlIG9yaWdpbmFsIGRpc3RhbmNlDQpjb3IoZ293ZXJfZGlzdCwgcmVzLmNvcGgpDQoNCnJlcy5oYzIgPC0gaGNsdXN0KGdvd2VyX2Rpc3QsIG1ldGhvZCA9ICJhdmVyYWdlIikNCmNvcihnb3dlcl9kaXN0LCBjb3BoZW5ldGljKHJlcy5oYzIpKQ0KDQojIEN1dCB0cmVlIGludG8gayBncm91cHMNCiNrPTQNCmdycCA8LSBjdXRyZWUocmVzLmhjLCBrICkNCmdycA0KdGFibGUoZ3JwKQ0KDQojIEN1dCBpbiAzIGdyb3VwcyBhbmQgY29sb3IgYnkgZ3JvdXBzDQpmdml6X2RlbmQocmVzLmhjLCBrICwgIyBDdXQgaW4gayBncm91cHMNCmNleCA9IDAuNSwgIyBsYWJlbCBzaXplDQprX2NvbG9ycyA9IGMoIiMyRTlGREYiLCAiIzAwQUZCQiIsICIjRkM0RTA3IiwgIiNFN0I4MDAiKSwNCmNvbG9yX2xhYmVsc19ieV9rID0gVFJVRSwgIyBjb2xvciBsYWJlbHMgYnkgZ3JvdXBzDQpyZWN0ID0gVFJVRSAjIEFkZCByZWN0YW5nbGUgYXJvdW5kIGdyb3Vwcw0KKQ0KDQoNCiMgIGNvbW8gZmF6ZXIgY29tIGFzIGRpc3Q/ICBzw7MgbGFuw6dhciBkYXRhIGNvbW8gbWF0cml6IGRlIGRpc3TDom5jaWFzDQoNCmZ2aXpfY2x1c3RlcihsaXN0KGRhdGEgPSBnb3dlcl9kaXN0LCBjbHVzdGVyID0gZ3JwKSwNCnBhbGV0dGUgPSBjKCIjMkU5RkRGIiwgIiMwMEFGQkIiLCAiI0U3QjgwMCIsICIjRkM0RTA3IiwgInJlZCIpLA0KZWxsaXBzZS50eXBlID0gImNvbnZleCIsICMgQ29uY2VudHJhdGlvbiBlbGxpcHNlDQpyZXBlbCA9IFRSVUUsICMgQXZvaWQgbGFiZWwgb3ZlcnBsb3R0aW5nIChzbG93KQ0Kc2hvdy5jbHVzdC5jZW50ID0gRkFMU0UsIGdndGhlbWUgPSB0aGVtZV9taW5pbWFsKCkpDQoNCg0KDQpgYGANCg0KDQoNCg==