Clustering intro

Notas sobre correr este notebook desde código

Deberá tener instalado los paquetes:

  • tidyverse
  • factoextra
  • clue

Deberá contar con Internet para descargar, tanto los paquetes a instalar como el dataset de trabajo.

Clustering: Intuición

Intuición inicial

De un conjunto de datos “desordenado” o “desagrupado”

Cajón desordenado

Cajón desordenado

Intuición: agrupar

Pasar a un conjunto de datos “agrupado”

Cajón ordenado

Cajón ordenado

Intuición: resumen

  • Agrupación de ítems “más cercanos”
  • Se debe tener una definición de “distancia”
  • Una técnica muy utilizada en minería de datos, ejemplos:
    • Grupos de clientes o consumidores
    • En genética: identificación de fenotipos
  • Ventaja: no hace falta tener una “etiqueta” previa en los datos.
  • Utilizado para “descubrir conocimiento” en los datos
  • Utilizado para encontrar observaciones relacionadas en los datos.

K-means

Intro

Algo de info o intro https://en.wikipedia.org/wiki/K-means_clustering https://es.wikipedia.org/wiki/K-medias

  • Ventajas:
    • algoritmo sencillo y fácil de computar
    • uno de los algortimos de clustering más rápidos para computar.

K-means notación

  • \(x_i\) es un data point u observación asignada al clúster \(C_k\),
  • \(\mu_k\) es el valor promedio de las observaciones o data points asignadas al clúster \(C_k\)
  • Cada observación \(x_i\) es asignada a un clúster según la suma de las distancias al cuadrado de cada observación al centro del clúster \(\mu_k\) cuya distancia euclidiana sea mínima.

\[ \arg min \sum_{i}^k\sum_{x_i \in C_k} ||x_i - \mu_k||^2\]

Distancia intra clúster

La total within-cluster variation o distancia intra-clúster se define como:

\[tot.within=\sum_{k=1}^kW(C_k) = \sum_{k=1}^k\sum_{x_i \in C_k} (x_i - \mu_k)^2\] La suma total de las distancias cuadradas intra-clúster es una medida de cuan compacto se vuelve el clúster (agrupación de observaciones) que desearíamos que sea lo más pequeño posible

K-means algoritmo

  1. Indicar un número \(k\) de clústeres
  2. Seleccionar de forma aleatoria \(k\) observacioens del datasets como centros iniciales
  3. Asignar a cada observación a su centroide \(\mu_k\) más cercano según la distancia euclidiana.
  4. Para cada uno de los \(k\) clústeres: 3.1 Actualizar el valor del centroide: \(W(C_k) = \sum_{x_i \in C_k} (x_i - \mu_k)^2\)
  5. Actualizar/guardar valor \(tot.within\)
  6. Repetir 3 - 4 y 5 hasta: 6.1 un número determinado de iteraciones. En la función kmeans en R es el argumento n.iter 6.2 Hasta que “no varía mucho” el \(tot.within\)

K-means en acción: ejemplo 1

K-means en acción Fuente: http://shabal.in/visuals/kmeans/3.html

K-means en acción: ejemplo 2

K-means en acción

K-means en acción

Fuente: https://gph.is/2pi97BQ

Sintaxis de función kmeans

La función kmeans ya viene incluida en R. Revise su sintaxis llamando a la ayuda, tipee en consola:

help(kmeans)

O

?kmeans

Sintaxis de función kmeans: mínimo

Como mínimo, hay que pasarle dos parámetros: x y centers.

  • x es una matriz numérica donde cada columna son nuestras variables o features. Al calcularse distancias en el algoritmo, se requieren que los datos sean numéricos.

  • centers es el número de clústers que queremos que considere.

Ejempĺo de uso con un dataset

Pre-procesamiento

Note que debe estar conectado a Internet para descargar el siguiente dataset

# Detalles sobre el dataset en https://archive.ics.uci.edu/ml/datasets/Wholesale+customers
df_raw <- read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/00292/Wholesale%20customers%20data.csv")
## Parsed with column specification:
## cols(
##   Channel = col_integer(),
##   Region = col_integer(),
##   Fresh = col_integer(),
##   Milk = col_integer(),
##   Grocery = col_integer(),
##   Frozen = col_integer(),
##   Detergents_Paper = col_integer(),
##   Delicassen = col_integer()
## )

Chusmeamos un poquito:

head(df_raw)
## # A tibble: 6 x 8
##   Channel Region Fresh  Milk Grocery Frozen Detergents_Paper Delicassen
##     <int>  <int> <int> <int>   <int>  <int>            <int>      <int>
## 1       2      3 12669  9656    7561    214             2674       1338
## 2       2      3  7057  9810    9568   1762             3293       1776
## 3       2      3  6353  8808    7684   2405             3516       7844
## 4       1      3 13265  1196    4221   6404              507       1788
## 5       2      3 22615  5410    7198   3915             1777       5185
## 6       2      3  9413  8259    5126    666             1795       1451

Me voy a quedar sólo con las variables numéricas.

data <- df_raw %>% 
  select(-c(1,2))

En muchos casos se aconseja escalar las observaciones, ¿por qué piensa que esto es necesario?. Por variables cuyas unidades o cantidades difieren mucho, ejemplo km/h vs la temperatura. ¿Cómo cree que podría afectar en el cálculo de la distancia?

data <- df_raw %>% 
  select(-c(1,2)) %>%
  scale()

Aplicamos kmeans

set.seed(1234)
result <- kmeans(data,centers = 2)

Observemos que es lo que regresa kmeans, que se guarda en la variable result. La explicación está en la ayuda, que volvemos a consultar.

help(kmeans)
str(result)
## List of 9
##  $ cluster     : int [1:440] 1 1 1 1 2 1 1 1 1 1 ...
##  $ centers     : num [1:2, 1:6] 7944 35401 5152 9514 7536 ...
##   ..- attr(*, "dimnames")=List of 2
##   .. ..$ : chr [1:2] "1" "2"
##   .. ..$ : chr [1:6] "Fresh" "Milk" "Grocery" "Frozen" ...
##  $ totss       : num 1.58e+11
##  $ withinss    : num [1:2] 6.03e+10 5.29e+10
##  $ tot.withinss: num 1.13e+11
##  $ betweenss   : num 4.44e+10
##  $ size        : int [1:2] 375 65
##  $ iter        : int 1
##  $ ifault      : int 0
##  - attr(*, "class")= chr "kmeans"

Al utilizar centers = 2, hicimos el experimento con dos centros, es decir, que kmeans creara dos clústeres.

A continuación mostramos los valores de dichos centros.

result$centers
##       Fresh     Milk   Grocery   Frozen Detergents_Paper Delicassen
## 1  7944.112 5151.819  7536.128 2484.131         2872.557   1214.261
## 2 35401.369 9514.231 10346.369 6463.092         2933.046   3316.846

Observamos que el cluster 1 los valores medios son menores al clúster 2. Podríamos deducir que dividió entre quienes gastan más y quienes menos en el mayorista.

En result$clusters indica a qué clúster a quedado asignada cada observación. ¿Cuántas observaciones quedaron en cada clúster?

result$cluster %>%
  table()
## .
##   1   2 
## 375  65

Realizaremos el mismo experimento pero con k=5

set.seed(1234)
result <- kmeans(data,centers = 5)
result$centers
##       Fresh      Milk   Grocery   Frozen Detergents_Paper Delicassen
## 1 21337.549  3933.853  5176.069 4182.784        1138.1078  1713.0294
## 2 49296.087  4983.783  5590.304 8285.783         962.2609  2543.6957
## 3 21263.700 37443.300 46710.600 6287.200       21699.4000  8743.3000
## 4  4667.582 11639.101 18289.785 1525.241        8060.3165  1594.4557
## 5  6143.872  3276.792  4115.164 2438.350        1220.7035   992.5398

¿a qué clúster fue agregado cada observación?

cbind(data,result$cluster)
##      Fresh  Milk Grocery Frozen Detergents_Paper Delicassen result$cluster
## 1    12669  9656    7561    214             2674       1338              5
## 2     7057  9810    9568   1762             3293       1776              5
## 3     6353  8808    7684   2405             3516       7844              5
## 4    13265  1196    4221   6404              507       1788              5
## 5    22615  5410    7198   3915             1777       5185              1
## 6     9413  8259    5126    666             1795       1451              5
## 7    12126  3199    6975    480             3140        545              5
## 8     7579  4956    9426   1669             3321       2566              5
## 9     5963  3648    6192    425             1716        750              5
## 10    6006 11093   18881   1159             7425       2098              4
## 11    3366  5403   12974   4400             5977       1744              4
## 12   13146  1124    4523   1420              549        497              5
## 13   31714 12319   11757    287             3881       2931              1
## 14   21217  6208   14982   3095             6707        602              1
## 15   24653  9465   12091    294             5058       2168              1
## 16   10253  1114    3821    397              964        412              5
## 17    1020  8816   12121    134             4508       1080              4
## 18    5876  6157    2933    839              370       4478              5
## 19   18601  6327   10099   2205             2767       3181              1
## 20    7780  2495    9464    669             2518        501              5
## 21   17546  4519    4602   1066             2259       2124              1
## 22    5567   871    2010   3383              375        569              5
## 23   31276  1917    4469   9408             2381       4334              1
## 24   26373 36423   22019   5154             4337      16523              3
## 25   22647  9776   13792   2915             4482       5778              1
## 26   16165  4230    7595    201             4003         57              1
## 27    9898   961    2861   3151              242        833              5
## 28   14276   803    3045    485              100        518              5
## 29    4113 20484   25957   1158             8604       5206              4
## 30   43088  2100    2609   1200             1107        823              2
## 31   18815  3610   11107   1148             2134       2963              1
## 32    2612  4339    3133   2088              820        985              5
## 33   21632  1318    2886    266              918        405              1
## 34   29729  4786    7326   6130              361       1083              1
## 35    1502  1979    2262    425              483        395              5
## 36     688  5491   11091    833             4239        436              5
## 37   29955  4362    5428   1729              862       4626              1
## 38   15168 10556   12477   1920             6506        714              4
## 39    4591 15729   16709     33             6956        433              4
## 40   56159   555     902  10002              212       2916              2
## 41   24025  4332    4757   9510             1145       5864              1
## 42   19176  3065    5956   2033             2575       2802              1
## 43   10850  7555   14961    188             6899         46              4
## 44     630 11095   23998    787             9529         72              4
## 45    9670  7027   10471    541             4618         65              5
## 46    5181 22044   21531   1740             7353       4985              4
## 47    3103 14069   21955   1668             6792       1452              4
## 48   44466 54259   55571   7782            24171       6465              3
## 49   11519  6152   10868    584             5121       1476              5
## 50    4967 21412   28921   1798            13583       1163              4
## 51    6269  1095    1980   3860              609       2162              5
## 52    3347  4051    6996    239             1538        301              5
## 53   40721  3916    5876    532             2587       1278              2
## 54     491 10473   11532    744             5611        224              4
## 55   27329  1449    1947   2436              204       1333              1
## 56    5264  3683    5005   1057             2024       1130              5
## 57    4098 29892   26866   2616            17740       1340              4
## 58    5417  9933   10487     38             7572       1282              4
## 59   13779  1970    1648    596              227        436              5
## 60    6137  5360    8040    129             3084       1603              5
## 61    8590  3045    7854     96             4095        225              5
## 62   35942 38369   59598   3254            26701       2017              3
## 63    7823  6245    6544   4154             4074        964              5
## 64    9396 11601   15775   2896             7677       1295              4
## 65    4760  1227    3250   3724             1247       1145              5
## 66      85 20959   45828     36            24231       1423              3
## 67       9  1534    7417    175             3468         27              5
## 68   19913  6759   13462   1256             5141        834              1
## 69    2446  7260    3993   5870              788       3095              5
## 70    8352  2820    1293    779              656        144              5
## 71   16705  2037    3202  10643              116       1365              1
## 72   18291  1266   21042   5373             4173      14472              1
## 73    4420  5139    2661   8872             1321        181              5
## 74   19899  5332    8713   8132              764        648              1
## 75    8190  6343    9794   1285             1901       1780              5
## 76   20398  1137       3   4407                3        975              1
## 77     717  3587    6532   7530              529        894              5
## 78   12205 12697   28540    869            12034       1009              4
## 79   10766  1175    2067   2096              301        167              5
## 80    1640  3259    3655    868             1202       1653              5
## 81    7005   829    3009    430              610        529              5
## 82     219  9540   14403    283             7818        156              4
## 83   10362  9232   11009    737             3537       2342              5
## 84   20874  1563    1783   2320              550        772              1
## 85   11867  3327    4814   1178             3837        120              5
## 86   16117 46197   92780   1026            40827       2944              3
## 87   22925 73498   32114    987            20070        903              3
## 88   43265  5025    8117   6312             1579      14351              2
## 89    7864   542    4042   9735              165         46              5
## 90   24904  3836    5330   3443              454       3178              1
## 91   11405   596    1638   3347               69        360              5
## 92   12754  2762    2530   8693              627       1117              5
## 93    9198 27472   32034   3232            18906       5130              3
## 94   11314  3090    2062  35009               71       2698              1
## 95    5626 12220   11323    206             5038        244              4
## 96       3  2920    6252    440              223        709              5
## 97      23  2616    8118    145             3874        217              5
## 98     403   254     610    774               54         63              5
## 99     503   112     778    895               56        132              5
## 100   9658  2182    1909   5639              215        323              5
## 101  11594  7779   12144   3252             8035       3029              4
## 102   1420 10810   16267   1593             6766       1838              4
## 103   2932  6459    7677   2561             4573       1386              5
## 104  56082  3504    8906  18028             1480       2498              2
## 105  14100  2132    3445   1336             1491        548              5
## 106  15587  1014    3970    910              139       1378              1
## 107   1454  6337   10704    133             6830       1831              4
## 108   8797 10646   14886   2471             8969       1438              4
## 109   1531  8397    6981    247             2505       1236              5
## 110   1406 16729   28986    673              836          3              4
## 111  11818  1648    1694   2276              169       1647              5
## 112  12579 11114   17569    805             6457       1519              4
## 113  19046  2770    2469   8853              483       2708              1
## 114  14438  2295    1733   3220              585       1561              1
## 115  18044  1080    2000   2555              118       1266              1
## 116  11134   793    2988   2715              276        610              5
## 117  11173  2521    3355   1517              310        222              5
## 118   6990  3880    5380   1647              319       1160              5
## 119  20049  1891    2362   5343              411        933              1
## 120   8258  2344    2147   3896              266        635              5
## 121  17160  1200    3412   2417              174       1136              1
## 122   4020  3234    1498   2395              264        255              5
## 123  12212   201     245   1991               25        860              5
## 124  11170 10769    8814   2194             1976        143              5
## 125  36050  1642    2961   4787              500       1621              2
## 126  76237  3473    7102  16538              778        918              2
## 127  19219  1840    1658   8195              349        483              1
## 128  21465  7243   10685    880             2386       2749              1
## 129    140  8847    3823    142             1062          3              5
## 130  42312   926    1510   1718              410       1819              2
## 131   7149  2428     699   6316              395        911              5
## 132   2101   589     314    346               70        310              5
## 133  14903  2032    2479    576              955        328              1
## 134   9434  1042    1235    436              256        396              5
## 135   7388  1882    2174    720               47        537              5
## 136   6300  1289    2591   1170              199        326              5
## 137   4625  8579    7030   4575             2447       1542              5
## 138   3087  8080    8282    661              721         36              5
## 139  13537  4257    5034    155              249       3271              5
## 140   5387  4979    3343    825              637        929              5
## 141  17623  4280    7305   2279              960       2616              1
## 142  30379 13252    5189    321               51       1450              1
## 143  37036  7152    8253   2995               20          3              2
## 144  10405  1596    1096   8425              399        318              5
## 145  18827  3677    1988    118              516        201              1
## 146  22039  8384   34792     42            12591       4430              4
## 147   7769  1936    2177    926               73        520              5
## 148   9203  3373    2707   1286             1082        526              5
## 149   5924   584     542   4052              283        434              5
## 150  31812  1433    1651    800              113       1440              1
## 151  16225  1825    1765    853              170       1067              1
## 152   1289  3328    2022    531              255       1774              5
## 153  18840  1371    3135   3001              352        184              1
## 154   3463  9250    2368    779              302       1627              5
## 155    622    55     137     75                7          8              5
## 156   1989 10690   19460    233            11577       2153              4
## 157   3830  5291   14855    317             6694       3182              4
## 158  17773  1366    2474   3378              811        418              1
## 159   2861  6570    9618    930             4004       1682              5
## 160    355  7704   14682    398             8077        303              4
## 161   1725  3651   12822    824             4424       2157              5
## 162  12434   540     283   1092                3       2233              5
## 163  15177  2024    3810   2665              232        610              1
## 164   5531 15726   26870   2367            13726        446              4
## 165   5224  7603    8584   2540             3674        238              5
## 166  15615 12653   19858   4425             7108       2379              4
## 167   4822  6721    9170    993             4973       3637              5
## 168   2926  3195    3268    405             1680        693              5
## 169   5809   735     803   1393               79        429              5
## 170   5414   717    2155   2399               69        750              5
## 171    260  8675   13430   1116             7015        323              4
## 172    200 25862   19816    651             8773       6250              4
## 173    955  5479    6536    333             2840        707              5
## 174    514  7677   19805    937             9836        716              4
## 175    286  1208    5241   2515              153       1442              5
## 176   2343  7845   11874     52             4196       1697              4
## 177  45640  6958    6536   7368             1532        230              2
## 178  12759  7330    4533   1752               20       2631              5
## 179  11002  7075    4945   1152              120        395              5
## 180   3157  4888    2500   4477              273       2165              5
## 181  12356  6036    8887    402             1382       2794              5
## 182 112151 29627   18148  16745             4948       8550              2
## 183    694  8533   10518    443             6907        156              4
## 184  36847 43950   20170  36534              239      47943              3
## 185    327   918    4710     74              334         11              5
## 186   8170  6448    1139   2181               58        247              5
## 187   3009   521     854   3470              949        727              5
## 188   2438  8002    9819   6269             3459          3              5
## 189   8040  7639   11687   2758             6839        404              4
## 190    834 11577   11522    275             4027       1856              4
## 191  16936  6250    1981   7332              118         64              1
## 192  13624   295    1381    890               43         84              5
## 193   5509  1461    2251    547              187        409              5
## 194    180  3485   20292    959             5618        666              4
## 195   7107  1012    2974    806              355       1142              5
## 196  17023  5139    5230   7888              330       1755              1
## 197  30624  7209    4897  18711              763       2876              1
## 198   2427  7097   10391   1127             4314       1468              5
## 199  11686  2154    6824   3527              592        697              5
## 200   9670  2280    2112    520              402        347              5
## 201   3067 13240   23127   3941             9959        731              4
## 202   4484 14399   24708   3549            14235       1681              4
## 203  25203 11487    9490   5065              284       6854              1
## 204    583   685    2216    469              954         18              5
## 205   1956   891    5226   1383                5       1328              5
## 206   1107 11711   23596    955             9265        710              4
## 207   6373   780     950    878              288        285              5
## 208   2541  4737    6089   2946             5316        120              5
## 209   1537  3748    5838   1859             3381        806              5
## 210   5550 12729   16767    864            12420        797              4
## 211  18567  1895    1393   1801              244       2100              1
## 212  12119 28326   39694   4736            19410       2870              3
## 213   7291  1012    2062   1291              240       1775              5
## 214   3317  6602    6861   1329             3961       1215              5
## 215   2362  6551   11364    913             5957        791              4
## 216   2806 10765   15538   1374             5828       2388              4
## 217   2532 16599   36486    179            13308        674              4
## 218  18044  1475    2046   2532              130       1158              1
## 219     18  7504   15205   1285             4797       6372              4
## 220   4155   367    1390   2306               86        130              5
## 221  14755   899    1382   1765               56        749              1
## 222   5396  7503   10646     91             4167        239              5
## 223   5041  1115    2856   7496              256        375              5
## 224   2790  2527    5265   5612              788       1360              5
## 225   7274   659    1499    784               70        659              5
## 226  12680  3243    4157    660              761        786              5
## 227  20782  5921    9212   1759             2568       1553              1
## 228   4042  2204    1563   2286              263        689              5
## 229   1869   577     572    950             4762        203              5
## 230   8656  2746    2501   6845              694        980              5
## 231  11072  5989    5615   8321              955       2137              5
## 232   2344 10678    3828   1439             1566        490              5
## 233  25962  1780    3838    638              284        834              1
## 234    964  4984    3316    937              409          7              5
## 235  15603  2703    3833   4260              325       2563              1
## 236   1838  6380    2824   1218             1216        295              5
## 237   8635   820    3047   2312              415        225              5
## 238  18692  3838     593   4634               28       1215              1
## 239   7363   475     585   1112               72        216              5
## 240  47493  2567    3779   5243              828       2253              2
## 241  22096  3575    7041  11422              343       2564              1
## 242  24929  1801    2475   2216              412       1047              1
## 243  18226   659    2914   3752              586        578              1
## 244  11210  3576    5119    561             1682       2398              5
## 245   6202  7775   10817   1183             3143       1970              5
## 246   3062  6154   13916    230             8933       2784              4
## 247   8885  2428    1777   1777              430        610              5
## 248  13569   346     489   2077               44        659              5
## 249  15671  5279    2406    559              562        572              1
## 250   8040  3795    2070   6340              918        291              5
## 251   3191  1993    1799   1730              234        710              5
## 252   6134 23133   33586   6746            18594       5121              4
## 253   6623  1860    4740   7683              205       1693              5
## 254  29526  7961   16966    432              363       1391              1
## 255  10379 17972    4748   4686             1547       3265              5
## 256  31614   489    1495   3242              111        615              1
## 257  11092  5008    5249    453              392        373              5
## 258   8475  1931    1883   5004             3593        987              5
## 259  56083  4563    2124   6422              730       3321              2
## 260  53205  4959    7336   3012              967        818              2
## 261   9193  4885    2157    327              780        548              5
## 262   7858  1110    1094   6818               49        287              5
## 263  23257  1372    1677    982              429        655              1
## 264   2153  1115    6684   4324             2894        411              5
## 265   1073  9679   15445     61             5980       1265              4
## 266   5909 23527   13699  10155              830       3636              4
## 267    572  9763   22182   2221             4882       2563              4
## 268  20893  1222    2576   3975              737       3628              1
## 269  11908  8053   19847   1069             6374        698              4
## 270  15218   258    1138   2516              333        204              1
## 271   4720  1032     975   5500              197         56              5
## 272   2083  5007    1563   1120              147       1550              5
## 273    514  8323    6869    529               93       1040              5
## 274  36817  3045    1493   4802              210       1824              2
## 275    894  1703    1841    744              759       1153              5
## 276    680  1610     223    862               96        379              5
## 277  27901  3749    6964   4479              603       2503              1
## 278   9061   829     683  16919              621        139              5
## 279  11693  2317    2543   5845              274       1409              5
## 280  17360  6200    9694   1293             3620       1721              1
## 281   3366  2884    2431    977              167       1104              5
## 282  12238  7108    6235   1093             2328       2079              5
## 283  49063  3965    4252   5970             1041       1404              2
## 284  25767  3613    2013  10303              314       1384              1
## 285  68951  4411   12609   8692              751       2406              2
## 286  40254   640    3600   1042              436         18              2
## 287   7149  2247    1242   1619             1226        128              5
## 288  15354  2102    2828   8366              386       1027              1
## 289  16260   594    1296    848              445        258              1
## 290  42786   286     471   1388               32         22              2
## 291   2708  2160    2642    502              965       1522              5
## 292   6022  3354    3261   2507              212        686              5
## 293   2838  3086    4329   3838              825       1060              5
## 294   3996 11103   12469    902             5952        741              4
## 295  21273  2013    6550    909              811       1854              1
## 296   7588  1897    5234    417             2208        254              5
## 297  19087  1304    3643   3045              710        898              1
## 298   8090  3199    6986   1455             3712        531              5
## 299   6758  4560    9965    934             4538       1037              5
## 300    444   879    2060    264              290        259              5
## 301  16448  6243    6360    824             2662       2005              1
## 302   5283 13316   20399   1809             8752        172              4
## 303   2886  5302    9785    364             6236        555              5
## 304   2599  3688   13829    492            10069         59              4
## 305    161  7460   24773    617            11783       2410              4
## 306    243 12939    8852    799             3909        211              4
## 307   6468 12867   21570   1840             7558       1543              4
## 308  17327  2374    2842   1149              351        925              1
## 309   6987  1020    3007    416              257        656              5
## 310    918 20655   13567   1465             6846        806              4
## 311   7034  1492    2405  12569              299       1117              5
## 312  29635  2335    8280   3046              371        117              1
## 313   2137  3737   19172   1274            17120        142              4
## 314   9784   925    2405   4447              183        297              5
## 315  10617  1795    7647   1483              857       1233              5
## 316   1479 14982   11924    662             3891       3508              4
## 317   7127  1375    2201   2679               83       1059              5
## 318   1182  3088    6114    978              821       1637              5
## 319  11800  2713    3558   2121              706         51              5
## 320   9759 25071   17645   1128            12408       1625              4
## 321   1774  3696    2280    514              275        834              5
## 322   9155  1897    5167   2714              228       1113              5
## 323  15881   713    3315   3703             1470        229              1
## 324  13360   944   11593    915             1679        573              5
## 325  25977  3587    2464   2369              140       1092              1
## 326  32717 16784   13626  60869             1272       5609              2
## 327   4414  1610    1431   3498              387        834              5
## 328    542   899    1664    414               88        522              5
## 329  16933  2209    3389   7849              210       1534              1
## 330   5113  1486    4583   5127              492        739              5
## 331   9790  1786    5109   3570              182       1043              5
## 332  11223 14881   26839   1234             9606       1102              4
## 333  22321  3216    1447   2208              178       2602              1
## 334   8565  4980   67298    131            38102       1215              3
## 335  16823   928    2743  11559              332       3486              1
## 336  27082  6817   10790   1365             4111       2139              1
## 337  13970  1511    1330    650              146        778              5
## 338   9351  1347    2611   8170              442        868              5
## 339      3   333    7021  15601               15        550              5
## 340   2617  1188    5332   9584              573       1942              5
## 341    381  4025    9670    388             7271       1371              5
## 342   2320  5763   11238    767             5162       2158              5
## 343    255  5758    5923    349             4595       1328              5
## 344   1689  6964   26316   1456            15469         37              4
## 345   3043  1172    1763   2234              217        379              5
## 346   1198  2602    8335    402             3843        303              5
## 347   2771  6939   15541   2693             6600       1115              4
## 348  27380  7184   12311   2809             4621       1022              1
## 349   3428  2380    2028   1341             1184        665              5
## 350   5981 14641   20521   2005            12218        445              4
## 351   3521  1099    1997   1796              173        995              5
## 352   1210 10044   22294   1741            12638       3137              4
## 353    608  1106    1533    830               90        195              5
## 354    117  6264   21203    228             8682       1111              4
## 355  14039  7393    2548   6386             1333       2341              1
## 356    190   727    2012    245              184        127              5
## 357  22686   134     218   3157                9        548              1
## 358     37  1275   22272    137             6747        110              4
## 359    759 18664    1660   6114              536       4100              5
## 360    796  5878    2109    340              232        776              5
## 361  19746  2872    2006   2601              468        503              1
## 362   4734   607     864   1206              159        405              5
## 363   2121  1601    2453    560              179        712              5
## 364   4627   997    4438    191             1335        314              5
## 365   2615   873    1524   1103              514        468              5
## 366   4692  6128    8025   1619             4515       3105              5
## 367   9561  2217    1664   1173              222        447              5
## 368   3477   894     534   1457              252        342              5
## 369  22335  1196    2406   2046              101        558              1
## 370   6211   337     683   1089               41        296              5
## 371  39679  3944    4955   1364              523       2235              2
## 372  20105  1887    1939   8164              716        790              1
## 373   3884  3801    1641    876              397       4829              5
## 374  15076  6257    7398   1504             1916       3113              1
## 375   6338  2256    1668   1492              311        686              5
## 376   5841  1450    1162    597              476         70              5
## 377   3136  8630   13586   5641             4666       1426              4
## 378  38793  3154    2648   1034               96       1242              2
## 379   3225  3294    1902    282               68       1114              5
## 380   4048  5164   10391    130              813        179              5
## 381  28257   944    2146   3881              600        270              1
## 382  17770  4591    1617   9927              246        532              1
## 383  34454  7435    8469   2540             1711       2893              1
## 384   1821  1364    3450   4006              397        361              5
## 385  10683 21858   15400   3635              282       5120              4
## 386  11635   922    1614   2583              192       1068              5
## 387   1206  3620    2857   1945              353        967              5
## 388  20918  1916    1573   1960              231        961              1
## 389   9785   848    1172   1677              200        406              5
## 390   9385  1530    1422   3019              227        684              5
## 391   3352  1181    1328   5502              311       1000              5
## 392   2647  2761    2313    907               95       1827              5
## 393    518  4180    3600    659              122        654              5
## 394  23632  6730    3842   8620              385        819              1
## 395  12377   865    3204   1398              149        452              5
## 396   9602  1316    1263   2921              841        290              5
## 397   4515 11991    9345   2644             3378       2213              4
## 398  11535  1666    1428   6838               64        743              5
## 399  11442  1032     582   5390               74        247              5
## 400   9612   577     935   1601              469        375              5
## 401   4446   906    1238   3576              153       1014              5
## 402  27167  2801    2128  13223               92       1902              1
## 403  26539  4753    5091    220               10        340              1
## 404  25606 11006    4604    127              632        288              1
## 405  18073  4613    3444   4324              914        715              1
## 406   6884  1046    1167   2069              593        378              5
## 407  25066  5010    5026   9806             1092        960              1
## 408   7362 12844   18683   2854             7883        553              4
## 409   8257  3880    6407   1646             2730        344              5
## 410   8708  3634    6100   2349             2123       5137              5
## 411   6633  2096    4563   1389             1860       1892              5
## 412   2126  3289    3281   1535              235       4365              5
## 413     97  3605   12400     98             2970         62              5
## 414   4983  4859    6633  17866              912       2435              5
## 415   5969  1990    3417   5679             1135        290              5
## 416   7842  6046    8552   1691             3540       1874              5
## 417   4389 10940   10908    848             6728        993              4
## 418   5065  5499   11055    364             3485       1063              5
## 419    660  8494   18622    133             6740        776              4
## 420   8861  3783    2223    633             1580       1521              5
## 421   4456  5266   13227     25             6818       1393              4
## 422  17063  4847    9053   1031             3415       1784              1
## 423  26400  1377    4172    830              948       1218              1
## 424  17565  3686    4657   1059             1803        668              1
## 425  16980  2884   12232    874             3213        249              1
## 426  11243  2408    2593  15348              108       1886              5
## 427  13134  9347   14316   3141             5079       1894              4
## 428  31012 16687    5429  15082              439       1163              1
## 429   3047  5970    4910   2198              850        317              5
## 430   8607  1750    3580     47               84       2501              5
## 431   3097  4230   16483    575              241       2080              4
## 432   8533  5506    5160  13486             1377       1498              5
## 433  21117  1162    4754    269             1328        395              1
## 434   1982  3218    1493   1541              356       1449              5
## 435  16731  3922    7994    688             2371        838              1
## 436  29703 12051   16027  13135              182       2204              1
## 437  39228  1431     764   4510               93       2346              2
## 438  14531 15488   30243    437            14841       1867              4
## 439  10290  1981    2232   1038              168       2125              5
## 440   2787  1698    2510     65              477         52              5

¿Cuántas observaciones fueron a cada clúster?

table(result$cluster)
## 
##   1   2   3   4   5 
## 102  23  10  79 226

Total withings vs número K

¿Cuál es la cantidad “ideal” de clústeres? ¿Cómo elegimos k? Depende mucho del problema con el que trabajemos. No hay una única respuesta.

Una alternativa es correr kmeans para distintos valores de k y analizar la variación de \(tot.within\)

Aquí un ejemplo de código que podrían utilizar

set.seed(1234)
max_k <- 10

my_x <- 2:max_k

# uso data ya previamente cargada
# función que llama a kmeans y regresa tot.withinss
kmean_withinss <- function( k) {
    cluster <- kmeans(scale(data), k)
    return (cluster$tot.withinss)
}

wss <- map_dbl(my_x,kmean_withinss)

Ahora graficamos

elbow <-data.frame(clusters=my_x, wss)

ggplot(elbow, aes(x = clusters , y = wss)) +
    geom_point() +
    geom_line() +
    scale_x_continuous(breaks = seq(1, 20, by = 1))

Observamos en el gráfico que a medida que aumenta el número de clústers (eje x), la distancia entre los elementos de un mismo clúster disminuye. Esto es esperable ya que los clústers serán cada vez más pequeños. Este es el método de Elbow que informalmente podríamos resumir en la regla del codo, cuando ya no haya más variación en la disminución de wss, no tiene sentido aumentar k.

También podemos usar la librería factoextra para calcular el número de clusters según el método Elbow

set.seed(1234)

fviz_nbclust(data, kmeans, method = "wss")

Existen otros métodos para calcular o estimar el número de clusters. Ver en la ayuda los mencionados en fvix_nblust

help("fviz_nbclust")

Usando silhoutte

fviz_nbclust(data, kmeans, method = "silhouette")

Visualización

Una librería que nos puede ayudar a visualizar mejor los clústeres cuando son varias dimenciones es factoextra

fviz_cluster(result,data=data)
## Warning in prcomp.default(data, scale = FALSE, center = FALSE): partial argument
## match of 'scale' to 'scale.'

Conclusiones.

Una desventaja de kmeans es que requiere fijar previamente el número de clústeres.

El clustering jerárquico es un enfoque que nos permitiría no fijar de antemano el valor k y una leve mejora ante kmeans. Además podría resultar atractiva su presentación basada en árboles, llamada dendograma.

Un desventaja adicional es que k-means es muy afectado por los valores extremos. Existen otros métodos que sortean mejor esta dificultad como PAM (partitioning around medoids) o clustering como DBSCAM.

Existen muchos otros enfoques o algoritmos de clustering. Por ejemplo, en el caso de que alguna observación pueda estar en más de un cluster, en este ejemplo se utilizaría un enfoque de fuzzy clustering o clusterización difusa. En fuzzy clustering permite asignarles grados de pertenencia a cada observación hacia cada clúster.

Caso de uso

¿Qué pasa cuando queremos saber a que centro va una nueva observación? Ya teniendo los clusters definidos podemos usar cl_predict del paquete clue.

Ejecute y observe

library(clue)
cl_predict(result,data)
## Class ids:
##   [1] 5 5 5 5 1 5 5 5 5 4 4 5 1 1 1 5 4 5 1 5 1 5 1 3 1 1 5 5 4 2 1 5 1 1 5 5 1
##  [38] 4 4 2 1 1 4 4 5 4 4 3 5 4 5 5 2 4 1 5 4 4 5 5 5 3 5 4 5 3 5 1 5 5 1 1 5 1
##  [75] 5 1 5 4 5 5 5 4 5 1 5 3 3 2 5 1 5 5 3 1 4 5 5 5 5 5 4 4 5 2 5 1 4 4 5 4 5
## [112] 4 1 1 1 5 5 5 1 5 1 5 5 5 2 2 1 1 5 2 5 5 1 5 5 5 5 5 5 5 1 1 2 5 1 4 5 5
## [149] 5 1 1 5 1 5 5 4 4 1 5 4 5 5 1 4 5 4 5 5 5 5 4 4 5 4 5 4 2 5 5 5 5 2 4 3 5
## [186] 5 5 5 4 4 1 5 5 4 5 1 1 5 5 5 4 4 1 5 5 4 5 5 5 4 1 3 5 5 4 4 4 1 4 5 1 5
## [223] 5 5 5 5 1 5 5 5 5 5 1 5 1 5 5 1 5 2 1 1 1 5 5 4 5 5 1 5 5 4 5 1 5 1 5 5 2
## [260] 2 5 5 1 5 4 4 4 1 4 1 5 5 5 2 5 5 1 5 5 1 5 5 2 1 2 2 5 1 1 2 5 5 5 4 1 5
## [297] 1 5 5 5 1 4 5 4 4 4 4 1 5 4 5 1 4 5 5 4 5 5 5 4 5 5 1 5 1 2 5 5 1 5 5 4 1
## [334] 3 1 1 5 5 5 5 5 5 5 4 5 5 4 1 5 4 5 4 5 4 1 5 1 4 5 5 1 5 5 5 5 5 5 5 1 5
## [371] 2 1 5 1 5 5 4 2 5 5 1 1 1 5 4 5 5 1 5 5 5 5 5 1 5 5 4 5 5 5 5 1 1 1 1 5 1
## [408] 4 5 5 5 5 5 5 5 5 4 5 4 5 4 1 1 1 1 5 4 1 5 5 4 5 1 5 1 1 2 4 5 5

¿Es distinto o lo mismo a lo que regresa result$clusters?

result$cluster
##   [1] 5 5 5 5 1 5 5 5 5 4 4 5 1 1 1 5 4 5 1 5 1 5 1 3 1 1 5 5 4 2 1 5 1 1 5 5 1
##  [38] 4 4 2 1 1 4 4 5 4 4 3 5 4 5 5 2 4 1 5 4 4 5 5 5 3 5 4 5 3 5 1 5 5 1 1 5 1
##  [75] 5 1 5 4 5 5 5 4 5 1 5 3 3 2 5 1 5 5 3 1 4 5 5 5 5 5 4 4 5 2 5 1 4 4 5 4 5
## [112] 4 1 1 1 5 5 5 1 5 1 5 5 5 2 2 1 1 5 2 5 5 1 5 5 5 5 5 5 5 1 1 2 5 1 4 5 5
## [149] 5 1 1 5 1 5 5 4 4 1 5 4 5 5 1 4 5 4 5 5 5 5 4 4 5 4 5 4 2 5 5 5 5 2 4 3 5
## [186] 5 5 5 4 4 1 5 5 4 5 1 1 5 5 5 4 4 1 5 5 4 5 5 5 4 1 3 5 5 4 4 4 1 4 5 1 5
## [223] 5 5 5 5 1 5 5 5 5 5 1 5 1 5 5 1 5 2 1 1 1 5 5 4 5 5 1 5 5 4 5 1 5 1 5 5 2
## [260] 2 5 5 1 5 4 4 4 1 4 1 5 5 5 2 5 5 1 5 5 1 5 5 2 1 2 2 5 1 1 2 5 5 5 4 1 5
## [297] 1 5 5 5 1 4 5 4 4 4 4 1 5 4 5 1 4 5 5 4 5 5 5 4 5 5 1 5 1 2 5 5 1 5 5 4 1
## [334] 3 1 1 5 5 5 5 5 5 5 4 5 5 4 1 5 4 5 4 5 4 1 5 1 4 5 5 1 5 5 5 5 5 5 5 1 5
## [371] 2 1 5 1 5 5 4 2 5 5 1 1 1 5 4 5 5 1 5 5 5 5 5 1 5 5 4 5 5 5 5 1 1 1 1 5 1
## [408] 4 5 5 5 5 5 5 5 5 4 5 4 5 4 1 1 1 1 5 4 1 5 5 4 5 1 5 1 1 2 4 5 5

Tiene sentido cuando son observaciones nuevas y queremos saber a que cluster pertenecerían.

Veamos con el ejemplo del dataset anterior.

# Detalles sobre el dataset en https://archive.ics.uci.edu/ml/datasets/Wholesale+customers

df_raw <- read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/00292/Wholesale%20customers%20data.csv")
## Parsed with column specification:
## cols(
##   Channel = col_integer(),
##   Region = col_integer(),
##   Fresh = col_integer(),
##   Milk = col_integer(),
##   Grocery = col_integer(),
##   Frozen = col_integer(),
##   Detergents_Paper = col_integer(),
##   Delicassen = col_integer()
## )
data <- df_raw %>% 
  select(-c(1,2)) %>%
  scale()

set.seed(1234)

modelo <- kmeans(data[1:400,],5) # "ejemplo: uso kmeans con una porción de mi dataset"

Me indica a que clusters asigna las nuevas observaciones. Puedo usar la función cl_predict del paquete clue. Esto nos evita de realizar una función o código para calcular esto.

cl_predict(modelo,data[401:nrow(data),])
## Class ids:
##  [1] 4 3 4 2 4 4 3 5 4 2 4 4 2 4 4 2 2 2 5 4 2 2 4 4 2 4 2 3 4 4 2 4 4 4 4 3 3 5
## [39] 4 4

Anexos

Existen otras librerías en R, otros algoritmos de clustering también, algunos recursos para mirar:

Info entorno

sessionInfo()
## R version 3.4.4 (2018-03-15)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 18.04.4 LTS
## 
## Matrix products: default
## BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.7.1
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.7.1
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
##  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
##  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] clue_0.3-57      factoextra_1.0.5 forcats_0.3.0    stringr_1.3.1   
##  [5] dplyr_1.0.0      purrr_0.3.2      readr_1.1.1      tidyr_1.0.0.9000
##  [9] tibble_2.1.3     ggplot2_3.1.0    tidyverse_1.2.1 
## 
## loaded via a namespace (and not attached):
##  [1] tidyselect_1.1.0 xfun_0.14        haven_2.1.0      lattice_0.20-38 
##  [5] colorspace_1.3-2 vctrs_0.3.1      generics_0.0.2   htmltools_0.3.6 
##  [9] yaml_2.2.0       base64enc_0.1-3  utf8_1.1.4       rlang_0.4.6     
## [13] ggpubr_0.2       pillar_1.4.2     glue_1.4.0       withr_2.2.0     
## [17] modelr_0.1.2     readxl_1.1.0     lifecycle_0.2.0  plyr_1.8.4      
## [21] munsell_0.5.0    gtable_0.3.0     cellranger_1.1.0 rvest_0.3.2     
## [25] evaluate_0.14    labeling_0.3     knitr_1.28       curl_3.3        
## [29] fansi_0.4.1      broom_0.5.0      Rcpp_1.0.4.6     scales_1.0.0    
## [33] backports_1.1.5  jsonlite_1.6     hms_0.3          digest_0.6.25   
## [37] stringi_1.4.6    ggrepel_0.8.0    grid_3.4.4       cli_1.1.0       
## [41] tools_3.4.4      magrittr_1.5     lazyeval_0.2.1   cluster_2.0.7-1 
## [45] crayon_1.3.4     pkgconfig_2.0.3  ellipsis_0.3.0   xml2_1.2.0      
## [49] lubridate_1.7.4  assertthat_0.2.1 rmarkdown_2.1    httr_1.3.1      
## [53] rstudioapi_0.11  R6_2.4.1         nlme_3.1-137     compiler_3.4.4
LS0tCnRpdGxlOiAiVHV0b3JpYWwgZGUgS21lYW5zIgphdXRob3I6ICJBbmEgRGllZHJpY2hzIgpkYXRlOiAiMjAyMC0wNi0xNiIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiBUUlVFIAogICAgdG9jX2Zsb2F0OiBUUlVFCiAgICB0b2NfZGVwdGg6IDYKICAgIHNlbGZfY29udGFpbmVkIDogVFJVRQogICAgY29kZV9kb3dubG9hZCA6IFRSVUUKCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKYGBgCgoKYGBge3IgY2FyZ2EtbGlicmVyaWFzLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShmYWN0b2V4dHJhKQpgYGAKCiMgQ2x1c3RlcmluZyBpbnRybwoKIyMgTm90YXMgc29icmUgY29ycmVyIGVzdGUgbm90ZWJvb2sgZGVzZGUgY8OzZGlnbwoKRGViZXLDoSB0ZW5lciBpbnN0YWxhZG8gbG9zIHBhcXVldGVzOgoKKiB0aWR5dmVyc2UKKiBmYWN0b2V4dHJhCiogY2x1ZQoKRGViZXLDoSBjb250YXIgY29uIEludGVybmV0IHBhcmEgZGVzY2FyZ2FyLCB0YW50byBsb3MgcGFxdWV0ZXMgYSBpbnN0YWxhciBjb21vIGVsIGRhdGFzZXQgZGUgdHJhYmFqby4KCgoKIyMgQ2x1c3RlcmluZzogSW50dWljacOzbgoKIyMjIEludHVpY2nDs24gaW5pY2lhbAoKRGUgdW4gY29uanVudG8gZGUgZGF0b3MgImRlc29yZGVuYWRvIiBvICJkZXNhZ3J1cGFkbyIKCiFbQ2Fqw7NuIGRlc29yZGVuYWRvXShjYWpvbi1kZXNvcmRlbmFkby5qcGcpCgojIyMgSW50dWljacOzbjogYWdydXBhcgoKUGFzYXIgYSB1biBjb25qdW50byBkZSBkYXRvcyAiYWdydXBhZG8iCgohW0NhasOzbiBvcmRlbmFkb10oY2Fqb24tb3JkZW5hZG8uanBnKQoKIyMjIEludHVpY2nDs246IHJlc3VtZW4KCiogQWdydXBhY2nDs24gZGUgw610ZW1zICJtw6FzIGNlcmNhbm9zIgoqIFNlIGRlYmUgdGVuZXIgdW5hIGRlZmluaWNpw7NuIGRlICJkaXN0YW5jaWEiCiogVW5hIHTDqWNuaWNhIG11eSB1dGlsaXphZGEgZW4gbWluZXLDrWEgZGUgZGF0b3MsIGVqZW1wbG9zOgogICsgR3J1cG9zIGRlIGNsaWVudGVzIG8gY29uc3VtaWRvcmVzCiAgKyBFbiBnZW7DqXRpY2E6IGlkZW50aWZpY2FjacOzbiBkZSBmZW5vdGlwb3MKKiBWZW50YWphOiBubyBoYWNlIGZhbHRhIHRlbmVyIHVuYSAiZXRpcXVldGEiIHByZXZpYSBlbiBsb3MgZGF0b3MuCiogVXRpbGl6YWRvIHBhcmEgImRlc2N1YnJpciBjb25vY2ltaWVudG8iIGVuIGxvcyBkYXRvcwoqIFV0aWxpemFkbyBwYXJhIGVuY29udHJhciBvYnNlcnZhY2lvbmVzIHJlbGFjaW9uYWRhcyBlbiBsb3MgZGF0b3MuCgojIyBLLW1lYW5zCgojIyMgSW50cm8KCkFsZ28gZGUgaW5mbyBvIGludHJvCmh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0stbWVhbnNfY2x1c3RlcmluZwpodHRwczovL2VzLndpa2lwZWRpYS5vcmcvd2lraS9LLW1lZGlhcwoKKiBWZW50YWphczoKICArIGFsZ29yaXRtbyBzZW5jaWxsbyB5IGbDoWNpbCBkZSBjb21wdXRhcgogICsgdW5vIGRlIGxvcyBhbGdvcnRpbW9zIGRlIGNsdXN0ZXJpbmcgbcOhcyByw6FwaWRvcyBwYXJhIGNvbXB1dGFyLgoKIyMjIEstbWVhbnMgbm90YWNpw7NuCgoqICR4X2kkIGVzIHVuIGRhdGEgcG9pbnQgdSBvYnNlcnZhY2nDs24gYXNpZ25hZGEgYWwgY2zDunN0ZXIgJENfayQsIAoqICRcbXVfayQgZXMgZWwgdmFsb3IgcHJvbWVkaW8gZGUgbGFzIG9ic2VydmFjaW9uZXMgbyBkYXRhIHBvaW50cyBhc2lnbmFkYXMgYWwgY2zDunN0ZXIgJENfayQKKiBDYWRhIG9ic2VydmFjacOzbiAkeF9pJCBlcyBhc2lnbmFkYSBhIHVuIGNsw7pzdGVyIHNlZ8O6biBsYSBzdW1hIGRlIGxhcyBkaXN0YW5jaWFzIGFsIGN1YWRyYWRvCmRlIGNhZGEgb2JzZXJ2YWNpw7NuIGFsIGNlbnRybyBkZWwgY2zDunN0ZXIgJFxtdV9rJCBjdXlhIGRpc3RhbmNpYSBldWNsaWRpYW5hIHNlYSBtw61uaW1hLgoKJCQgXGFyZyBtaW4gXHN1bV97aX1ea1xzdW1fe3hfaSBcaW4gQ19rfSB8fHhfaSAtIFxtdV9rfHxeMiQkCgoKIyMjIERpc3RhbmNpYSBpbnRyYSBjbMO6c3RlcgoKTGEgKnRvdGFsIHdpdGhpbi1jbHVzdGVyIHZhcmlhdGlvbiogbyBkaXN0YW5jaWEgaW50cmEtY2zDunN0ZXIgc2UgZGVmaW5lIGNvbW86CgokJHRvdC53aXRoaW49XHN1bV97az0xfV5rVyhDX2spID0gXHN1bV97az0xfV5rXHN1bV97eF9pIFxpbiBDX2t9ICh4X2kgLSBcbXVfayleMiQkCkxhIHN1bWEgdG90YWwgZGUgbGFzIGRpc3RhbmNpYXMgY3VhZHJhZGFzIGludHJhLWNsw7pzdGVyIGVzIHVuYSBtZWRpZGEgZGUgY3VhbiBjb21wYWN0bwpzZSB2dWVsdmUgZWwgY2zDunN0ZXIgKGFncnVwYWNpw7NuIGRlIG9ic2VydmFjaW9uZXMpIHF1ZSBkZXNlYXLDrWFtb3MgcXVlIHNlYSBsbyBtw6FzIHBlcXVlw7FvIHBvc2libGUgCgojIyMgSy1tZWFucyBhbGdvcml0bW8KCjEuIEluZGljYXIgdW4gbsO6bWVybyAkayQgZGUgY2zDunN0ZXJlcwoyLiBTZWxlY2Npb25hciBkZSBmb3JtYSBhbGVhdG9yaWEgJGskIG9ic2VydmFjaW9lbnMgZGVsIGRhdGFzZXRzIGNvbW8gY2VudHJvcyBpbmljaWFsZXMKMy4gQXNpZ25hciBhIGNhZGEgb2JzZXJ2YWNpw7NuIGEgc3UgY2VudHJvaWRlICRcbXVfayQgbcOhcyBjZXJjYW5vIHNlZ8O6biBsYSBkaXN0YW5jaWEgZXVjbGlkaWFuYS4KNC4gUGFyYSBjYWRhIHVubyBkZSBsb3MgJGskIGNsw7pzdGVyZXM6CiAgMy4xIEFjdHVhbGl6YXIgZWwgdmFsb3IgZGVsIGNlbnRyb2lkZTogICRXKENfaykgPSBcc3VtX3t4X2kgXGluIENfa30gKHhfaSAtIFxtdV9rKV4yJAo1LiBBY3R1YWxpemFyL2d1YXJkYXIgdmFsb3IgJHRvdC53aXRoaW4kCjYuIFJlcGV0aXIgMyAtIDQgeSA1IGhhc3RhOgogIDYuMSB1biBuw7ptZXJvIGRldGVybWluYWRvIGRlIGl0ZXJhY2lvbmVzLiBFbiBsYSBmdW5jacOzbiBrbWVhbnMgZW4gUiBlcyBlbCBhcmd1bWVudG8gKm4uaXRlcioKICA2LjIgSGFzdGEgcXVlICJubyB2YXLDrWEgbXVjaG8iIGVsICR0b3Qud2l0aGluJAogIAojIyMgSy1tZWFucyBlbiBhY2Npw7NuOiBlamVtcGxvIDEKCiFbSy1tZWFucyBlbiBhY2Npw7NuXShodHRwOi8vc2hhYmFsLmluL3Zpc3VhbHMva21lYW5zL2xlZnQuZ2lmKQpGdWVudGU6IGh0dHA6Ly9zaGFiYWwuaW4vdmlzdWFscy9rbWVhbnMvMy5odG1sCgojIyMgSy1tZWFucyBlbiBhY2Npw7NuOiBlamVtcGxvIDIKCiFbSy1tZWFucyBlbiBhY2Npw7NuXShrbWVhbnMuZ2lmKQoKRnVlbnRlOiBodHRwczovL2dwaC5pcy8ycGk5N0JRCgojIyMgU2ludGF4aXMgZGUgZnVuY2nDs24ga21lYW5zCgpMYSBmdW5jacOzbiBrbWVhbnMgeWEgdmllbmUgaW5jbHVpZGEgZW4gUi4gUmV2aXNlIHN1IHNpbnRheGlzIGxsYW1hbmRvIGEgbGEgYXl1ZGEsCnRpcGVlIGVuIGNvbnNvbGE6CgpgYGB7cixldmFsPUZBTFNFfQpoZWxwKGttZWFucykKYGBgCgpPCgpgYGB7cixldmFsPUZBTFNFfQo/a21lYW5zCmBgYAoKIyMjIFNpbnRheGlzIGRlIGZ1bmNpw7NuIGttZWFuczogbcOtbmltbwoKQ29tbyBtw61uaW1vLCBoYXkgcXVlIHBhc2FybGUgZG9zIHBhcsOhbWV0cm9zOiAqeCogeSAqY2VudGVycyouCgoqICp4KiBlcyB1bmEgbWF0cml6IG51bcOpcmljYSBkb25kZSBjYWRhIGNvbHVtbmEgc29uIG51ZXN0cmFzIHZhcmlhYmxlcyBvIGZlYXR1cmVzLiAKQWwgY2FsY3VsYXJzZSBkaXN0YW5jaWFzIGVuIGVsIGFsZ29yaXRtbywgc2UgcmVxdWllcmVuIHF1ZSBsb3MgZGF0b3Mgc2VhbiBudW3DqXJpY29zLgoKKiAqY2VudGVycyogZXMgZWwgbsO6bWVybyBkZSBjbMO6c3RlcnMgcXVlIHF1ZXJlbW9zIHF1ZSBjb25zaWRlcmUuCgojIyMgRWplbXDEum8gZGUgdXNvIGNvbiB1biBkYXRhc2V0IAoKIyMjIyBQcmUtcHJvY2VzYW1pZW50bwoKTm90ZSBxdWUgZGViZSBlc3RhciBjb25lY3RhZG8gYSBJbnRlcm5ldCBwYXJhIGRlc2NhcmdhciBlbCAKc2lndWllbnRlIGRhdGFzZXQgCgpgYGB7ciBjYXJnYXItZGF0YXNldH0KIyBEZXRhbGxlcyBzb2JyZSBlbCBkYXRhc2V0IGVuIGh0dHBzOi8vYXJjaGl2ZS5pY3MudWNpLmVkdS9tbC9kYXRhc2V0cy9XaG9sZXNhbGUrY3VzdG9tZXJzCmRmX3JhdyA8LSByZWFkX2NzdigiaHR0cHM6Ly9hcmNoaXZlLmljcy51Y2kuZWR1L21sL21hY2hpbmUtbGVhcm5pbmctZGF0YWJhc2VzLzAwMjkyL1dob2xlc2FsZSUyMGN1c3RvbWVycyUyMGRhdGEuY3N2IikKCmBgYAoKQ2h1c21lYW1vcyB1biBwb3F1aXRvOgoKYGBge3IgbW9zdHJhcl9kYXRvc19jcnVkb3N9CmhlYWQoZGZfcmF3KQpgYGAKCk1lIHZveSBhIHF1ZWRhciBzw7NsbyBjb24gbGFzIHZhcmlhYmxlcyBudW3DqXJpY2FzLiAKCmBgYHtyIGRmX2xpbXBpZXphfQpkYXRhIDwtIGRmX3JhdyAlPiUgCiAgc2VsZWN0KC1jKDEsMikpCmBgYAoKRW4gbXVjaG9zIGNhc29zIHNlIGFjb25zZWphCmVzY2FsYXIgbGFzIG9ic2VydmFjaW9uZXMsIMK/cG9yIHF1w6kgcGllbnNhIHF1ZSBlc3RvIGVzIG5lY2VzYXJpbz8uClBvciB2YXJpYWJsZXMgY3V5YXMgdW5pZGFkZXMgbyBjYW50aWRhZGVzIGRpZmllcmVuIG11Y2hvLCBlamVtcGxvIGttL2ggCnZzIGxhIHRlbXBlcmF0dXJhLiAKwr9Dw7NtbyBjcmVlIHF1ZSBwb2Ryw61hIGFmZWN0YXIgZW4gZWwgY8OhbGN1bG8gZGUgbGEgZGlzdGFuY2lhPwoKYGBge3IgZGZfbGltcGllemFfc2NhbGUsIGV2YWw9RkFMU0V9CmRhdGEgPC0gZGZfcmF3ICU+JSAKICBzZWxlY3QoLWMoMSwyKSkgJT4lCiAgc2NhbGUoKQpgYGAKCiMjIyMgQXBsaWNhbW9zIGttZWFucwoKYGBge3Iga21lYW5zLWJhc2V9CnNldC5zZWVkKDEyMzQpCnJlc3VsdCA8LSBrbWVhbnMoZGF0YSxjZW50ZXJzID0gMikKYGBgCgpPYnNlcnZlbW9zIHF1ZSBlcyBsbyBxdWUgcmVncmVzYSBrbWVhbnMsIHF1ZSBzZSBndWFyZGEgZW4gbGEgdmFyaWFibGUgcmVzdWx0LgpMYSBleHBsaWNhY2nDs24gZXN0w6EgZW4gbGEgYXl1ZGEsIHF1ZSB2b2x2ZW1vcyBhIGNvbnN1bHRhci4KCmBgYHtyfQpoZWxwKGttZWFucykKc3RyKHJlc3VsdCkKYGBgCgpBbCB1dGlsaXphciBjZW50ZXJzID0gMiwgaGljaW1vcyBlbCBleHBlcmltZW50byBjb24gZG9zIGNlbnRyb3MsIGVzIGRlY2lyLCBxdWUgCmttZWFucyBjcmVhcmEgZG9zIGNsw7pzdGVyZXMuCgpBIGNvbnRpbnVhY2nDs24gbW9zdHJhbW9zIGxvcyB2YWxvcmVzIGRlIGRpY2hvcyBjZW50cm9zLgoKYGBge3J9CnJlc3VsdCRjZW50ZXJzCmBgYAoKT2JzZXJ2YW1vcyBxdWUgZWwgY2x1c3RlciAxIGxvcyB2YWxvcmVzIG1lZGlvcyBzb24gbWVub3JlcyBhbCBjbMO6c3RlciAyLgpQb2Ryw61hbW9zIGRlZHVjaXIgcXVlIGRpdmlkacOzIGVudHJlIHF1aWVuZXMgZ2FzdGFuIG3DoXMgeSBxdWllbmVzIG1lbm9zIAplbiBlbCBtYXlvcmlzdGEuCgpFbiAqcmVzdWx0JGNsdXN0ZXJzKiBpbmRpY2EgYSBxdcOpIGNsw7pzdGVyIGEgcXVlZGFkbyBhc2lnbmFkYSBjYWRhIG9ic2VydmFjacOzbi4Kwr9DdcOhbnRhcyBvYnNlcnZhY2lvbmVzIHF1ZWRhcm9uIGVuIGNhZGEgY2zDunN0ZXI/CgpgYGB7cn0KcmVzdWx0JGNsdXN0ZXIgJT4lCiAgdGFibGUoKQpgYGAKClJlYWxpemFyZW1vcyBlbCBtaXNtbyBleHBlcmltZW50byBwZXJvIGNvbiBrPTUKCmBgYHtyfQpzZXQuc2VlZCgxMjM0KQpyZXN1bHQgPC0ga21lYW5zKGRhdGEsY2VudGVycyA9IDUpCnJlc3VsdCRjZW50ZXJzCmBgYAoKwr9hIHF1w6kgY2zDunN0ZXIgZnVlIGFncmVnYWRvIGNhZGEgb2JzZXJ2YWNpw7NuPwoKYGBge3J9CmNiaW5kKGRhdGEscmVzdWx0JGNsdXN0ZXIpCgpgYGAKCsK/Q3XDoW50YXMgb2JzZXJ2YWNpb25lcyBmdWVyb24gYSBjYWRhIGNsw7pzdGVyPwoKYGBge3J9CnRhYmxlKHJlc3VsdCRjbHVzdGVyKQpgYGAKCiMjIFRvdGFsIHdpdGhpbmdzIHZzIG7Dum1lcm8gSwoKwr9DdcOhbCBlcyBsYSBjYW50aWRhZCAiaWRlYWwiIGRlIGNsw7pzdGVyZXM/IMK/Q8OzbW8gZWxlZ2ltb3Mgaz8KRGVwZW5kZSBtdWNobyBkZWwgcHJvYmxlbWEgY29uIGVsIHF1ZSB0cmFiYWplbW9zLiBObyBoYXkgdW5hIMO6bmljYSByZXNwdWVzdGEuIAoKVW5hIGFsdGVybmF0aXZhIGVzIGNvcnJlciBrbWVhbnMgcGFyYSBkaXN0aW50b3MgdmFsb3JlcyBkZSBrCnkgYW5hbGl6YXIgbGEgdmFyaWFjacOzbiBkZSAkdG90LndpdGhpbiQKCkFxdcOtIHVuIGVqZW1wbG8gZGUgY8OzZGlnbyBxdWUgcG9kcsOtYW4gdXRpbGl6YXIKCmBgYHtyfQpzZXQuc2VlZCgxMjM0KQptYXhfayA8LSAxMAoKbXlfeCA8LSAyOm1heF9rCgojIHVzbyBkYXRhIHlhIHByZXZpYW1lbnRlIGNhcmdhZGEKIyBmdW5jacOzbiBxdWUgbGxhbWEgYSBrbWVhbnMgeSByZWdyZXNhIHRvdC53aXRoaW5zcwprbWVhbl93aXRoaW5zcyA8LSBmdW5jdGlvbiggaykgewogICAgY2x1c3RlciA8LSBrbWVhbnMoc2NhbGUoZGF0YSksIGspCiAgICByZXR1cm4gKGNsdXN0ZXIkdG90LndpdGhpbnNzKQp9Cgp3c3MgPC0gbWFwX2RibChteV94LGttZWFuX3dpdGhpbnNzKQoKYGBgCgpBaG9yYSBncmFmaWNhbW9zCgoKYGBge3J9CmVsYm93IDwtZGF0YS5mcmFtZShjbHVzdGVycz1teV94LCB3c3MpCgpnZ3Bsb3QoZWxib3csIGFlcyh4ID0gY2x1c3RlcnMgLCB5ID0gd3NzKSkgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGdlb21fbGluZSgpICsKICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMSwgMjAsIGJ5ID0gMSkpCmBgYAoKT2JzZXJ2YW1vcyBlbiBlbCBncsOhZmljbyBxdWUgYSBtZWRpZGEgcXVlIGF1bWVudGEgZWwgbsO6bWVybyBkZSBjbMO6c3RlcnMgKGVqZSB4KSwKbGEgZGlzdGFuY2lhIGVudHJlIGxvcyBlbGVtZW50b3MgZGUgdW4gbWlzbW8gY2zDunN0ZXIgZGlzbWludXllLiAKRXN0byBlcyBlc3BlcmFibGUgeWEgcXVlIGxvcyBjbMO6c3RlcnMgc2Vyw6FuIGNhZGEgdmV6IG3DoXMgcGVxdWXDsW9zLgpFc3RlIGVzIGVsIG3DqXRvZG8gZGUgRWxib3cgcXVlIGluZm9ybWFsbWVudGUgcG9kcsOtYW1vcyByZXN1bWlyIGVuIGxhIHJlZ2xhIGRlbCBjb2RvLCAKY3VhbmRvIHlhIG5vIGhheWEgbcOhcyB2YXJpYWNpw7NuIGVuIGxhIGRpc21pbnVjacOzbiBkZSB3c3MsIG5vIHRpZW5lIHNlbnRpZG8gYXVtZW50YXIgay4KClRhbWJpw6luIHBvZGVtb3MgdXNhciBsYSBsaWJyZXLDrWEgZmFjdG9leHRyYSBwYXJhIGNhbGN1bGFyIAplbCBuw7ptZXJvIGRlIGNsdXN0ZXJzIHNlZ8O6biBlbCBtw6l0b2RvIEVsYm93CgoKYGBge3J9CnNldC5zZWVkKDEyMzQpCgpmdml6X25iY2x1c3QoZGF0YSwga21lYW5zLCBtZXRob2QgPSAid3NzIikKYGBgCgpFeGlzdGVuIG90cm9zIG3DqXRvZG9zIHBhcmEgY2FsY3VsYXIgbyBlc3RpbWFyIGVsIG7Dum1lcm8gZGUgY2x1c3RlcnMuClZlciBlbiBsYSBheXVkYSBsb3MgbWVuY2lvbmFkb3MgZW4gKmZ2aXhfbmJsdXN0KgoKYGBge3J9CmhlbHAoImZ2aXpfbmJjbHVzdCIpCmBgYAoKClVzYW5kbyBzaWxob3V0dGUKCgpgYGB7cn0KZnZpel9uYmNsdXN0KGRhdGEsIGttZWFucywgbWV0aG9kID0gInNpbGhvdWV0dGUiKQpgYGAKCiMjIFZpc3VhbGl6YWNpw7NuCgpVbmEgbGlicmVyw61hIHF1ZSBub3MgcHVlZGUgYXl1ZGFyIGEgdmlzdWFsaXphciBtZWpvciBsb3MgY2zDunN0ZXJlcyBjdWFuZG8Kc29uIHZhcmlhcyBkaW1lbmNpb25lcyBlcyAqZmFjdG9leHRyYSoKCgpgYGB7cn0KZnZpel9jbHVzdGVyKHJlc3VsdCxkYXRhPWRhdGEpCmBgYAoKCiMgQ29uY2x1c2lvbmVzLgoKClVuYSBkZXN2ZW50YWphIGRlIGttZWFucyBlcyBxdWUgcmVxdWllcmUgZmlqYXIgcHJldmlhbWVudGUgZWwgbsO6bWVybyBkZSBjbMO6c3RlcmVzLgoKRWwgY2x1c3RlcmluZyBqZXLDoXJxdWljbyBlcyB1biBlbmZvcXVlIHF1ZSBub3MgcGVybWl0aXLDrWEgbm8gZmlqYXIgZGUgYW50ZW1hbm8gZWwgdmFsb3IgayB5CnVuYSBsZXZlIG1lam9yYSBhbnRlIGttZWFucy4gQWRlbcOhcyBwb2Ryw61hIHJlc3VsdGFyIGF0cmFjdGl2YSBzdSBwcmVzZW50YWNpw7NuIGJhc2FkYSBlbiDDoXJib2xlcywgbGxhbWFkYSBkZW5kb2dyYW1hLgoKVW4gZGVzdmVudGFqYSBhZGljaW9uYWwgZXMgcXVlIGstbWVhbnMgZXMgbXV5IGFmZWN0YWRvIHBvciBsb3MgdmFsb3JlcyBleHRyZW1vcy4gCkV4aXN0ZW4gb3Ryb3MgbcOpdG9kb3MgcXVlIHNvcnRlYW4gbWVqb3IgZXN0YSBkaWZpY3VsdGFkIGNvbW8gUEFNIChwYXJ0aXRpb25pbmcgYXJvdW5kCm1lZG9pZHMpIG8gY2x1c3RlcmluZyBjb21vIERCU0NBTS4KCkV4aXN0ZW4gbXVjaG9zIG90cm9zIGVuZm9xdWVzIG8gYWxnb3JpdG1vcyBkZSBjbHVzdGVyaW5nLiBQb3IgZWplbXBsbywgZW4gZWwgCmNhc28gZGUgcXVlIGFsZ3VuYSBvYnNlcnZhY2nDs24gcHVlZGEgZXN0YXIgZW4gbcOhcyBkZSB1biBjbHVzdGVyLCBlbiBlc3RlIGVqZW1wbG8gc2UgdXRpbGl6YXLDrWEgdW4gZW5mb3F1ZSBkZSAqZnV6enkgY2x1c3RlcmluZyogbyBjbHVzdGVyaXphY2nDs24gZGlmdXNhLiBFbiAqZnV6enkgY2x1c3RlcmluZyogcGVybWl0ZSBhc2lnbmFybGVzIGdyYWRvcyBkZSBwZXJ0ZW5lbmNpYSAKYSBjYWRhIG9ic2VydmFjacOzbiBoYWNpYSBjYWRhIGNsw7pzdGVyLiAKCgoKIyBDYXNvIGRlIHVzbyAKCsK/UXXDqSBwYXNhIGN1YW5kbyBxdWVyZW1vcyBzYWJlciBhIHF1ZSBjZW50cm8gdmEgdW5hIG51ZXZhIG9ic2VydmFjacOzbj8KWWEgdGVuaWVuZG8gbG9zIGNsdXN0ZXJzIGRlZmluaWRvcyBwb2RlbW9zIHVzYXIgY2xfcHJlZGljdCBkZWwgcGFxdWV0ZSBjbHVlLgoKRWplY3V0ZSB5IG9ic2VydmUKCmBgYHtyfQpsaWJyYXJ5KGNsdWUpCmNsX3ByZWRpY3QocmVzdWx0LGRhdGEpCmBgYAoKwr9FcyBkaXN0aW50byBvIGxvIG1pc21vIGEgbG8gcXVlIHJlZ3Jlc2EgcmVzdWx0JGNsdXN0ZXJzPwoKYGBge3J9CnJlc3VsdCRjbHVzdGVyCmBgYAoKVGllbmUgc2VudGlkbyBjdWFuZG8gc29uIG9ic2VydmFjaW9uZXMgbnVldmFzIHkgcXVlcmVtb3Mgc2FiZXIgYSBxdWUgY2x1c3RlciBwZXJ0ZW5lY2Vyw61hbi4KClZlYW1vcyBjb24gZWwgZWplbXBsbyBkZWwgZGF0YXNldCBhbnRlcmlvci4KCgpgYGB7ciBlamVtcGxvMX0KCiMgRGV0YWxsZXMgc29icmUgZWwgZGF0YXNldCBlbiBodHRwczovL2FyY2hpdmUuaWNzLnVjaS5lZHUvbWwvZGF0YXNldHMvV2hvbGVzYWxlK2N1c3RvbWVycwoKZGZfcmF3IDwtIHJlYWRfY3N2KCJodHRwczovL2FyY2hpdmUuaWNzLnVjaS5lZHUvbWwvbWFjaGluZS1sZWFybmluZy1kYXRhYmFzZXMvMDAyOTIvV2hvbGVzYWxlJTIwY3VzdG9tZXJzJTIwZGF0YS5jc3YiKQoKZGF0YSA8LSBkZl9yYXcgJT4lIAogIHNlbGVjdCgtYygxLDIpKSAlPiUKICBzY2FsZSgpCgpzZXQuc2VlZCgxMjM0KQoKbW9kZWxvIDwtIGttZWFucyhkYXRhWzE6NDAwLF0sNSkgIyAiZWplbXBsbzogdXNvIGttZWFucyBjb24gdW5hIHBvcmNpw7NuIGRlIG1pIGRhdGFzZXQiCmBgYAoKTWUgaW5kaWNhIGEgcXVlIGNsdXN0ZXJzIGFzaWduYSBsYXMgbnVldmFzIG9ic2VydmFjaW9uZXMuClB1ZWRvIHVzYXIgbGEgZnVuY2nDs24gKmNsX3ByZWRpY3QqIGRlbCBwYXF1ZXRlIGNsdWUuIApFc3RvIG5vcyBldml0YSBkZSByZWFsaXphciB1bmEgZnVuY2nDs24gbyBjw7NkaWdvIHBhcmEgY2FsY3VsYXIgZXN0by4KCmBgYHtyfQpjbF9wcmVkaWN0KG1vZGVsbyxkYXRhWzQwMTpucm93KGRhdGEpLF0pCmBgYAoKIyBBbmV4b3MKCkV4aXN0ZW4gb3RyYXMgbGlicmVyw61hcyBlbiBSLCBvdHJvcyBhbGdvcml0bW9zIGRlIGNsdXN0ZXJpbmcgdGFtYmnDqW4sIGFsZ3Vub3MgcmVjdXJzb3MgcGFyYSBtaXJhcjoKCiogaHR0cHM6Ly93d3cuc3RhdG1ldGhvZHMubmV0L2FkdnN0YXRzL2NsdXN0ZXIuaHRtbAoqIGh0dHBzOi8vd3d3LmRhdGFub3ZpYS5jb20vZW4vYmxvZy90eXBlcy1vZi1jbHVzdGVyaW5nLW1ldGhvZHMtb3ZlcnZpZXctYW5kLXF1aWNrLXN0YXJ0LXItY29kZS8KKiBQYXF1ZXRlIGNsdXN0ZXIgeSBwYXF1ZXRlIGNsdWUKKiBQYXF1ZXRlIGZhY3RvZXh0cmEKKiBQYXF1ZXRlIGZwYyAKKiBGdXp6eSBjbHVzdGVyaW5nOgogICsgbm90YXMgZGUgY2xhc2VzIGh0dHA6Ly9wcm8xLnVuaWJ6Lml0L3Byb2plY3RzL0NsdXN0ZXJpbmdfTWV0aG9kc18yMDE0L0ZlcnJhcm8ucGRmCiAgKyBQYXF1ZXRlIGZjbHVzdCB5IGZhbm55IGVuIFIgCiogQ2x1c3RlcmluZyBub3RhcyBkZSBjbGFzZSBDb2x1bWJpYTogaHR0cDovL3d3dy5zdGF0LmNvbHVtYmlhLmVkdS9+bWFkaWdhbi9XMjAyNS9ub3Rlcy9jbHVzdGVyaW5nLnBkZgoqIENsdXN0ZXJpbmcgbm90YXMgZGUgY2xhc2UgVW5zdXBlcnZpc2VkIGxlYXJuaW5nIGNsdXN0ZXJpbmc6IGh0dHA6Ly93d3cubWl0LmVkdS9+OS41NC9mYWxsMTQvc2xpZGVzL0NsYXNzMTMucGRmCgoKIyBJbmZvIGVudG9ybm8KCmBgYHtyfQpzZXNzaW9uSW5mbygpCmBgYAoK