Deriving components (modified from Jackson 2003)

There are two strategies for extracting eigenvectors (components) and their eigenvalues from a multivariate data set of n objects by p variables. First, we can use an eigenanalysis (spectral decomposition) of a p x p association matrix between variables. Second, we can use a singular value decomposition (SVD) of the n x p data matrix, with variables standardized as necessary.

Consider the matrix (Y) of raw data from Clevenger and Waltho (2000), who recorded the numbers of seven taxa of wildlife for eleven underpasses in Alberta, Canada.

Load the vegan package

library(tidyverse)
library(vegan)
#datasets: clevenger.csv
clevenger <- read_csv("../data/clevenger.csv")
Rows: 11 Columns: 22── Column specification ────────────────────────────────────────────────────────────
Delimiter: ","
chr  (1): underpass
dbl (21): width, height, length, openness, noise, egdist, forcov, draindist, rai...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
head(clevenger,10)

Illustrate centroid using relationship between human activity index (hui) and elk numbers

Plots used for QK use the ggplot classic theme, with some tweaks. Tweaks are consolidated into theme_QK; use this theme for figures and tweak the theme to avoid repetitive code changes.

Fig 14.2

f14_2<-ggplot(data=clevenger,aes(x=hui, y=elk))+
  geom_point(color=sc, size=ss, alpha= 1) +
  theme_qk()+
  geom_point(aes(x=mean(hui),y=mean(elk)), pch=8, size=3)
f14_2

Get centered and standardized raw data matrices

# centered
clevenger.cen <- scale(clevenger[,c('bbear','gbear','cougar','wolf','deer','elk','moose')], scale=F)
clevenger.cen
           bbear      gbear     cougar        wolf        deer         elk
 [1,]  -7.545455 -0.6363636  -5.636364 -27.2727273  334.818182   10.545455
 [2,]   2.454545 -0.6363636  18.363636 -21.2727273 -177.181818 -613.454545
 [3,]  25.454545 -0.6363636  -7.636364 -25.2727273   74.818182 -483.454545
 [4,]  19.454545  1.3636364  19.363636  -0.2727273   33.818182  384.545455
 [5,]  -4.545455 -0.6363636  -3.636364 -25.2727273   -4.181818  247.545455
 [6,]  -9.545455 -0.6363636 -10.636364 -23.2727273 -198.181818 -347.454545
 [7,] -17.545455 -0.6363636  -6.636364 -27.2727273 -158.181818  761.545455
 [8,] -13.545455 -0.6363636  -6.636364 -23.2727273  118.818182  707.545455
 [9,]  -9.545455 -0.6363636   9.363636  48.7272727   68.818182    6.545455
[10,]  16.454545  4.3636364   4.363636 117.7272727   71.818182 -131.454545
[11,]  -1.545455 -0.6363636 -10.636364   6.7272727 -165.181818 -542.454545
           moose
 [1,]  0.8181818
 [2,] -0.1818182
 [3,]  0.8181818
 [4,] -0.1818182
 [5,] -0.1818182
 [6,] -0.1818182
 [7,] -0.1818182
 [8,] -0.1818182
 [9,] -0.1818182
[10,] -0.1818182
[11,] -0.1818182
attr(,"scaled:center")
      bbear       gbear      cougar        wolf        deer         elk       moose 
 17.5454545   0.6363636  10.6363636  28.2727273 219.1818182 814.4545455   0.1818182 
# get standardized raw data
clevenger.stan <- scale(clevenger[,c('bbear','gbear','cougar','wolf','deer','elk','moose')], scale=T)
clevenger.stan
           bbear      gbear     cougar         wolf        deer         elk
 [1,] -0.5261348 -0.4061812 -0.5068669 -0.601179227  2.05348246  0.02183648
 [2,]  0.1711523 -0.4061812  1.6514052 -0.468919797 -1.08667861 -1.27028099
 [3,]  1.7749127 -0.4061812 -0.6867229 -0.557092751  0.45886942 -1.00108985
 [4,]  1.3565404  0.8703883  1.7413332 -0.006011792  0.20741121  0.79627869
 [5,] -0.3169487 -0.4061812 -0.3270109 -0.557092751 -0.02564762  0.51259264
 [6,] -0.6655923 -0.4061812 -0.9565070 -0.513006274 -1.21547428 -0.71947450
 [7,] -1.2234220 -0.4061812 -0.5967949 -0.601179227 -0.97014920  1.57693299
 [8,] -0.9445071 -0.4061812 -0.5967949 -0.513006274  0.72872701  1.46511513
 [9,] -0.6655923 -0.4061812  0.8420531  1.074106886  0.42207066  0.01355368
[10,]  1.1473543  2.7852425  0.3924131  2.595090331  0.44047004 -0.27220307
[11,] -0.1077626 -0.4061812 -0.9565070  0.148290876 -1.01308109 -1.12326121
           moose
 [1,]  2.0225996
 [2,] -0.4494666
 [3,]  2.0225996
 [4,] -0.4494666
 [5,] -0.4494666
 [6,] -0.4494666
 [7,] -0.4494666
 [8,] -0.4494666
 [9,] -0.4494666
[10,] -0.4494666
[11,] -0.4494666
attr(,"scaled:center")
      bbear       gbear      cougar        wolf        deer         elk       moose 
 17.5454545   0.6363636  10.6363636  28.2727273 219.1818182 814.4545455   0.1818182 
attr(,"scaled:scale")
      bbear       gbear      cougar        wolf        deer         elk       moose 
 14.3412945   1.5666989  11.1200065  45.3653853 163.0489609 482.9282273   0.4045199 

Generate covariance and correlation matrices

Covariance matrix for wildlife

clevenger.cov <- cov(clevenger[,c('bbear','gbear','cougar','wolf','deer','elk','moose')])

Correlation matrix for wildlife

clevenger.cor <- cor(clevenger[,c('bbear','gbear','cougar','wolf','deer','elk','moose')])

Derive eigenvectors and eigenvalues based on correlation matrix

clevenger.eigen <- eigen(clevenger.cor)
clevenger.eigen
eigen() decomposition
$values
[1] 2.48262264 1.79202546 1.33144952 0.81062441 0.42903804 0.08769838 0.06654156

$vectors
           [,1]        [,2]        [,3]         [,4]         [,5]        [,6]
[1,] -0.4480426 -0.32853418  0.28726775 -0.195436794  0.586304172 -0.47611634
[2,] -0.5734521  0.04251404 -0.20081526  0.255898326  0.277980195  0.61766855
[3,] -0.3798802  0.16723268  0.02083960 -0.817320247 -0.324352619  0.19419176
[4,] -0.5355751  0.11425393 -0.14514937  0.430423505 -0.377378599 -0.28984791
[5,] -0.0895651 -0.53785185 -0.53718087 -0.082108683 -0.345693443 -0.27316305
[6,]  0.1440767  0.19264407 -0.75205162 -0.190408179  0.460246579 -0.06783799
[7,]  0.1023762 -0.72307729  0.03876746 -0.006827542 -0.004932548  0.43687126
            [,7]
[1,]  0.01286228
[2,] -0.32364656
[3,]  0.12791605
[4,]  0.51705536
[5,] -0.46180770
[6,]  0.35194368
[7,]  0.52368693

Do PCA

clevenger.pca <- princomp(~bbear+gbear+cougar+wolf+deer+elk+moose, cor=T, data=clevenger)
summary(clevenger.pca)
Importance of components:
                          Comp.1    Comp.2    Comp.3    Comp.4     Comp.5
Standard deviation     1.5756340 1.3386656 1.1538845 0.9003468 0.65500995
Proportion of Variance 0.3546604 0.2560036 0.1902071 0.1158035 0.06129115
Cumulative Proportion  0.3546604 0.6106640 0.8008711 0.9166746 0.97796572
                           Comp.6      Comp.7
Standard deviation     0.29613912 0.257956501
Proportion of Variance 0.01252834 0.009505937
Cumulative Proportion  0.99049406 1.000000000

Calculate dissimilarities for raw and standardized (by object and variables) and presence/absence

Calculate Euclidean, Chisq and Bray-Curtis measures

# raw data
clev1 <- clevenger[c(16:22)]
vegdist(clev1, method="euclidean")
            1          2          3          4          5          6          7
2   807.60944                                                                  
3   559.22536  285.70264                                                       
4   482.24994 1020.42148  869.77008                                            
5   413.65203  878.52092  735.87975  148.14520                                 
6   642.10513  268.67452  307.02443  769.36467  625.89057                      
7   898.41638 1375.51699 1267.34723  426.34610  536.74389 1109.76439           
8   729.73899 1354.08345 1192.45293  337.41962  476.25938 1101.61064  282.27115
9   277.08843  670.85095  497.11870  383.99870  262.83074  449.65431  792.24365
10  333.25666  560.41324  380.28016  530.91148  412.79050  374.65050  934.17129
11  746.34241   82.61961  250.68706  948.85405  806.90954  200.19491 1304.56621
            8          9         10
2                                  
3                                  
4                                  
5                                  
6                                  
7                                  
8                                  
9   706.65197                      
10  852.67637  156.65248           
11 1282.26986  598.65265  487.83706
vegdist(clev1, method="chisq")
            1          2          3          4          5          6          7
2  1.21475615                                                                  
3  0.47318577 1.17635422                                                       
4  0.61384857 0.86798529 0.78818807                                            
5  0.58227734 1.05366620 0.83599435 0.21674323                                 
6  0.89187108 1.12775158 1.09118378 0.39319617 0.31798393                      
7  0.91245764 1.17435640 1.16260729 0.45273730 0.34119097 0.14487655           
8  0.55123078 1.11106385 0.84408915 0.27447668 0.07803388 0.35930254 0.36290581
9  0.55537285 0.99969109 0.77917948 0.37637843 0.45788835 0.64890817 0.69433371
10 0.87912364 1.14433514 0.93156102 0.73629009 0.86127129 0.96885842 1.04763957
11 0.86727424 1.09145007 0.91740896 0.53301980 0.63188889 0.64730790 0.75690369
            8          9         10
2                                  
3                                  
4                                  
5                                  
6                                  
7                                  
8                                  
9  0.45353095                      
10 0.86766247 0.46840925           
11 0.65817925 0.43340441 0.42203679
vegdist(clev1, method="bray")
            1          2          3          4          5          6          7
2  0.69439528                                                                  
3  0.38194109 0.44763860                                                       
4  0.25704584 0.67640693 0.43615108                                            
5  0.21661721 0.66729206 0.42784810 0.08739909                                 
6  0.47601476 0.41250000 0.38265306 0.51121951 0.44586341                      
7  0.41342989 0.74446162 0.65817868 0.20714510 0.23317471 0.54363042           
8  0.28296115 0.76427256 0.50156986 0.14377557 0.18815002 0.58129739 0.09644381
9  0.13946360 0.63251818 0.32980413 0.18204850 0.16149562 0.41574344 0.37885154
10 0.22957198 0.61303462 0.28393726 0.25449871 0.25545675 0.40179104 0.46803977
11 0.61985336 0.21301775 0.34410646 0.61578401 0.59212880 0.30296128 0.67607727
            8          9         10
2                                  
3                                  
4                                  
5                                  
6                                  
7                                  
8                                  
9  0.27308066                      
10 0.35214966 0.10301508           
11 0.70222222 0.53614079 0.51386202
# standardized by object totals
clev1$total <- rowSums(clev1)
clev2 <- clev1
clev2$bbeart <- clev2$bbear/clev2$total
clev2$gbeart <- clev2$gbear/clev2$total
clev2$cougart <- clev2$cougar/clev2$total
clev2$wolft <- clev2$wolf/clev2$total
clev2$deert <- clev2$deer/clev2$total
clev2$elkt <- clev2$elk/clev2$total
clev2$mooset <- clev2$moose/clev2$total
clev3 <- clev2[c(9:15)]
vegdist(clev3, method="euclidean")
            1          2          3          4          5          6          7
2  0.29179246                                                                  
3  0.12178440 0.35929117                                                       
4  0.29812496 0.13708413 0.39569783                                            
5  0.32348508 0.18337700 0.42722446 0.04981133                                 
6  0.49248814 0.29906244 0.59366647 0.20059515 0.16923915                      
7  0.51524001 0.32757067 0.61901148 0.22713767 0.19227850 0.03372006           
8  0.30979659 0.18687072 0.41558090 0.05280824 0.01784560 0.18366346 0.20546479
9  0.19197240 0.14525707 0.28422021 0.13185757 0.16974574 0.32684568 0.35299841
10 0.19530845 0.19611057 0.24342704 0.23556628 0.27826144 0.42261729 0.45121044
11 0.30182196 0.13136818 0.38360445 0.09734980 0.13739012 0.24941037 0.27993555
            8          9         10
2                                  
3                                  
4                                  
5                                  
6                                  
7                                  
8                                  
9  0.16038740                      
10 0.27108275 0.11528079           
11 0.13945202 0.11532916 0.17839581
vegdist(clev3, method="chisq")
            1          2          3          4          5          6          7
2  1.04480761                                                                  
3  0.39517291 1.04001877                                                       
4  0.60305175 0.70863697 0.76350072                                            
5  0.58507556 0.86215541 0.80156474 0.18679083                                 
6  0.89540748 0.94138220 1.07368158 0.37617696 0.31635064                      
7  0.91715806 0.98417343 1.13041746 0.42787726 0.33966677 0.12188311           
8  0.55354775 0.90889652 0.79773472 0.23202001 0.06650063 0.35481352 0.36496751
9  0.52716675 0.82688142 0.71506346 0.35025941 0.42619090 0.62838501 0.67298864
10 0.81600325 0.98389894 0.86660229 0.68588704 0.80144200 0.92462096 0.99390701
11 0.82056558 0.90283478 0.88548124 0.47730196 0.56841064 0.60119998 0.69403213
            8          9         10
2                                  
3                                  
4                                  
5                                  
6                                  
7                                  
8                                  
9  0.41801288                      
10 0.80255881 0.43516350           
11 0.58842686 0.38209782 0.40990737
vegdist(clev3, method="bray")
            1          2          3          4          5          6          7
2  0.25709624                                                                  
3  0.10060384 0.29656881                                                       
4  0.23423329 0.12596108 0.31352318                                            
5  0.23217985 0.16959866 0.32749288 0.04492874                                 
6  0.35922996 0.25989493 0.44730095 0.15808796 0.12885306                      
7  0.36883090 0.28756431 0.46943475 0.18575734 0.14288204 0.03010544           
8  0.22357908 0.18035023 0.32222974 0.05568031 0.01543636 0.14067860 0.14750545
9  0.16090572 0.14081535 0.25691866 0.11925162 0.14405652 0.26523724 0.28352834
10 0.15889643 0.21261103 0.22390939 0.19886655 0.23515136 0.35036401 0.37803340
11 0.25791006 0.12143928 0.31950879 0.09331596 0.12297082 0.21065032 0.24075576
            8          9         10
2                                  
3                                  
4                                  
5                                  
6                                  
7                                  
8                                  
9  0.13632334                      
10 0.23082839 0.09820268           
11 0.13047339 0.11047068 0.15319319
# standardized by variable totals
clev1$bbeart <- clev1$bbear/sum(clev2$bbear)
clev1$gbeart <- clev1$gbear/sum(clev2$gbear)
clev1$cougart <- clev1$cougar/sum(clev2$cougar)
clev1$wolft <- clev1$wolf/sum(clev2$wolf)
clev1$deert <- clev1$deer/sum(clev2$deer)
clev1$elkt <- clev1$elk/sum(clev2$elk)
clev1$mooset <- clev1$moose/sum(clev2$moose)
clev4 <- clev1[c(9:15)]
vegdist(clev4, method="euclidean")
           1         2         3         4         5         6         7         8
2  0.5874372                                                                      
3  0.2103305 0.5699869                                                            
4  0.6494049 0.3377750 0.6340280                                                  
5  0.5206197 0.2263239 0.5320355 0.3777360                                        
6  0.5500617 0.2574895 0.5446442 0.4374485 0.1231964                              
7  0.5491779 0.2835227 0.5730657 0.4282729 0.1122824 0.1365675                    
8  0.5150571 0.2989734 0.5558359 0.4101989 0.0900685 0.1809769 0.1176054          
9  0.5817512 0.2750346 0.6030030 0.3719280 0.2669713 0.3108749 0.3100064 0.2815680
10 1.0062311 0.8620352 0.9929078 0.5898117 0.8607697 0.8737626 0.8868434 0.8705775
11 0.5581777 0.2646868 0.5392290 0.4210031 0.1632272 0.1080943 0.2029463 0.2183625
           9        10
2                     
3                     
4                     
5                     
6                     
7                     
8                     
9                     
10 0.7613418          
11 0.2497030 0.8212754
vegdist(clev4, method="chisq")
           1         2         3         4         5         6         7         8
2  2.1918656                                                                      
3  0.6060261 2.1062286                                                            
4  1.7774812 1.2249504 1.7410878                                                  
5  1.6550584 1.4861911 1.7333325 1.0365979                                        
6  1.9594176 1.9177901 1.8499636 1.3528694 0.8747182                              
7  2.2679736 2.2799015 2.4479938 1.8581292 1.2332715 1.3157014                    
8  1.7397774 1.9752053 1.9751799 1.4191550 0.5881129 1.1561780 1.0587556          
9  1.8312148 1.3956048 1.9103379 1.1027533 1.1541210 1.4626882 1.8867908 1.3639082
10 2.0304452 1.9180098 2.0047472 0.8446477 1.6407999 1.7194328 2.2843090 1.8454187
11 2.0549749 1.9295504 1.8915082 1.4251156 1.4681142 1.1908051 2.2198998 1.7491817
           9        10
2                     
3                     
4                     
5                     
6                     
7                     
8                     
9                     
10 1.2995151          
11 1.0384181 1.3874031
vegdist(clev4, method="bray")
           1         2         3         4         5         6         7         8
2  0.7935939                                                                      
3  0.1946466 0.7313399                                                            
4  0.7025767 0.4394077 0.6273209                                                  
5  0.5585673 0.5340500 0.6373176 0.5103013                                        
6  0.7967183 0.6667775 0.8130980 0.7995520 0.5163939                              
7  0.7327162 0.7631796 0.8423259 0.6979275 0.3784111 0.6411470                    
8  0.5534611 0.7211135 0.6688852 0.5708830 0.2495338 0.6089989 0.2493285          
9  0.6247022 0.4935050 0.7063851 0.4243562 0.4254924 0.7001292 0.6606665 0.4637913
10 0.7737168 0.7196663 0.7162999 0.3730783 0.7021629 0.8687325 0.8555458 0.7406492
11 0.8154067 0.5611676 0.7505849 0.6556519 0.5621685 0.4729512 0.7700434 0.7153495
           9        10
2                     
3                     
4                     
5                     
6                     
7                     
8                     
9                     
10 0.4797086          
11 0.5501897 0.7432297

create pres/abs datafile

clev5 <- clevenger[c(16:22)]
clev5[clev5>0] <-1
clev5
vegdist(clev5, method="jaccard")
           1         2         3         4         5         6         7         8
2  0.1666667                                                                      
3  0.0000000 0.1666667                                                            
4  0.2857143 0.1666667 0.2857143                                                  
5  0.1666667 0.0000000 0.1666667 0.1666667                                        
6  0.3333333 0.2000000 0.3333333 0.3333333 0.2000000                              
7  0.3333333 0.2000000 0.3333333 0.3333333 0.2000000 0.4000000                    
8  0.1666667 0.0000000 0.1666667 0.1666667 0.0000000 0.2000000 0.2000000          
9  0.1666667 0.0000000 0.1666667 0.1666667 0.0000000 0.2000000 0.2000000 0.0000000
10 0.2857143 0.1666667 0.2857143 0.0000000 0.1666667 0.3333333 0.3333333 0.1666667
11 0.3333333 0.2000000 0.3333333 0.3333333 0.2000000 0.0000000 0.4000000 0.2000000
           9        10
2                     
3                     
4                     
5                     
6                     
7                     
8                     
9                     
10 0.1666667          
11 0.2000000 0.3333333
vegdist(clev5, method="bray")
            1          2          3          4          5          6          7
2  0.09090909                                                                  
3  0.00000000 0.09090909                                                       
4  0.16666667 0.09090909 0.16666667                                            
5  0.09090909 0.00000000 0.09090909 0.09090909                                 
6  0.20000000 0.11111111 0.20000000 0.20000000 0.11111111                      
7  0.20000000 0.11111111 0.20000000 0.20000000 0.11111111 0.25000000           
8  0.09090909 0.00000000 0.09090909 0.09090909 0.00000000 0.11111111 0.11111111
9  0.09090909 0.00000000 0.09090909 0.09090909 0.00000000 0.11111111 0.11111111
10 0.16666667 0.09090909 0.16666667 0.00000000 0.09090909 0.20000000 0.20000000
11 0.20000000 0.11111111 0.20000000 0.20000000 0.11111111 0.00000000 0.25000000
            8          9         10
2                                  
3                                  
4                                  
5                                  
6                                  
7                                  
8                                  
9  0.00000000                      
10 0.09090909 0.09090909           
11 0.11111111 0.11111111 0.20000000

Check outliers with Mahalanobis distances - no particularly unusual objects

# Problem with code; needs to be fixed
#mahalanobis(clev1, colMeans(clev1), cov(clev1))

Fig 14.3 - ordination with BC MDS

clev6 <- clevenger[c(1,16:22)]
clev6.stand <- decostand(clev6[,2:8], "total")
clev6.stand.bc <- vegdist(clev6.stand,"bray")
clev6.mds <- metaMDS(clev6.stand.bc,k=2)
Run 0 stress 0.03076215 
Run 1 stress 0.05949932 
Run 2 stress 0.0541 
Run 3 stress 0.05411455 
Run 4 stress 0.3407335 
Run 5 stress 0.03076228 
... Procrustes: rmse 0.0001732853  max resid 0.0002983285 
... Similar to previous best
Run 6 stress 0.03076217 
... Procrustes: rmse 0.0001250452  max resid 0.0002150335 
... Similar to previous best
Run 7 stress 0.03076224 
... Procrustes: rmse 0.0002129152  max resid 0.0003668702 
... Similar to previous best
Run 8 stress 0.05410005 
Run 9 stress 0.03076216 
... Procrustes: rmse 3.156241e-05  max resid 5.317318e-05 
... Similar to previous best
Run 10 stress 0.03076228 
... Procrustes: rmse 0.0001713665  max resid 0.0002951362 
... Similar to previous best
Run 11 stress 0.05949931 
Run 12 stress 0.03076222 
... Procrustes: rmse 0.0001142774  max resid 0.0001958333 
... Similar to previous best
Run 13 stress 0.05409998 
Run 14 stress 0.03076215 
... Procrustes: rmse 2.215246e-05  max resid 3.596323e-05 
... Similar to previous best
Run 15 stress 0.05410003 
Run 16 stress 0.03076223 
... Procrustes: rmse 0.0001307716  max resid 0.000224776 
... Similar to previous best
Run 17 stress 0.03076222 
... Procrustes: rmse 0.0001136536  max resid 0.0001950247 
... Similar to previous best
Run 18 stress 0.03076229 
... Procrustes: rmse 0.0001758204  max resid 0.0003030112 
... Similar to previous best
Run 19 stress 0.05410003 
Run 20 stress 0.05410004 
*** Best solution repeated 10 times
plot(clev6.mds$points,type="n", )
text(clev6.mds$points,lab=clev6$underpass, col="black")

mdsplot <- as.data.frame(scores(clev6.mds))
mdsplot$underpass<-clev6$underpass
f14_3<-ggplot(data=mdsplot,aes(x=NMDS1, y=NMDS2, label=underpass))+
  geom_text()+
  theme_qk()+
  theme(axis.text = element_blank())
f14_3

LS0tCnRpdGxlOiAiUSAmIEsgQm94IDE0LjEiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgaHRtbF9ub3RlYm9vazoKICAgIHRoZW1lOiBmbGF0bHkKLS0tCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmBgYAojIERlcml2aW5nIGNvbXBvbmVudHMgKG1vZGlmaWVkIGZyb20gSmFja3NvbiAyMDAzKQpUaGVyZSBhcmUgdHdvIHN0cmF0ZWdpZXMgZm9yIGV4dHJhY3RpbmcgZWlnZW52ZWN0b3JzIChjb21wb25lbnRzKSBhbmQgdGhlaXIgZWlnZW52YWx1ZXMgZnJvbSBhIG11bHRpdmFyaWF0ZSBkYXRhIHNldCBvZiBuIG9iamVjdHMgYnkgcCB2YXJpYWJsZXMuIEZpcnN0LCB3ZSBjYW4gdXNlIGFuIGVpZ2VuYW5hbHlzaXMgKHNwZWN0cmFsIGRlY29tcG9zaXRpb24pIG9mIGEgcCB4IHAgYXNzb2NpYXRpb24gbWF0cml4IGJldHdlZW4gdmFyaWFibGVzLiBTZWNvbmQsIHdlIGNhbiB1c2UgYSBzaW5ndWxhciB2YWx1ZSBkZWNvbXBvc2l0aW9uIChTVkQpIG9mIHRoZSBuIHggcCBkYXRhIG1hdHJpeCwgd2l0aCB2YXJpYWJsZXMgc3RhbmRhcmRpemVkIGFzIG5lY2Vzc2FyeS4KCkNvbnNpZGVyIHRoZSBtYXRyaXggKFkpIG9mIHJhdyBkYXRhIGZyb20gQ2xldmVuZ2VyIGFuZCBXYWx0aG8gKDIwMDApLCB3aG8gcmVjb3JkZWQgdGhlIG51bWJlcnMgb2Ygc2V2ZW4gdGF4YSBvZiB3aWxkbGlmZSBmb3IgZWxldmVuIHVuZGVycGFzc2VzIGluIEFsYmVydGEsIENhbmFkYS4KCkxvYWQgdGhlIHZlZ2FuIHBhY2thZ2UKYGBge3IgcmVzdWx0cz0naGlkZSd9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHZlZ2FuKQpgYGAKCmBgYHtyfQojZGF0YXNldHM6IGNsZXZlbmdlci5jc3YKY2xldmVuZ2VyIDwtIHJlYWRfY3N2KCIuLi9kYXRhL2NsZXZlbmdlci5jc3YiKQpoZWFkKGNsZXZlbmdlciwxMCkKYGBgCiMjIyBJbGx1c3RyYXRlIGNlbnRyb2lkIHVzaW5nIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGh1bWFuIGFjdGl2aXR5IGluZGV4IChodWkpIGFuZCBlbGsgbnVtYmVycwpQbG90cyB1c2VkIGZvciBRSyB1c2UgdGhlIGdncGxvdCBjbGFzc2ljIHRoZW1lLCB3aXRoIHNvbWUgdHdlYWtzLiBUd2Vha3MgYXJlIGNvbnNvbGlkYXRlZCBpbnRvIHRoZW1lX1FLOyB1c2UgdGhpcyB0aGVtZSBmb3IgZmlndXJlcyBhbmQgdHdlYWsgdGhlIHRoZW1lIHRvIGF2b2lkIHJlcGV0aXRpdmUgY29kZSBjaGFuZ2VzLgpgYGB7ciBlY2hvPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KZGV2dG9vbHM6OnNvdXJjZV91cmwoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9tamtlb3VnaC9tamtlb3VnaC5naXRodWIuaW8vcmVmcy9oZWFkcy9tYWluL1IvYXBwZWFyYW5jZS5SIikgICNHcmFwaGljcyB0d2Vha3MKYGBgCkZpZyAxNC4yCmBgYHtyfQpmMTRfMjwtZ2dwbG90KGRhdGE9Y2xldmVuZ2VyLGFlcyh4PWh1aSwgeT1lbGspKSsKICBnZW9tX3BvaW50KGNvbG9yPXNjLCBzaXplPXNzLCBhbHBoYT0gMSkgKwogIHRoZW1lX3FrKCkrCiAgZ2VvbV9wb2ludChhZXMoeD1tZWFuKGh1aSkseT1tZWFuKGVsaykpLCBwY2g9OCwgc2l6ZT0zKQpmMTRfMgpgYGAKCiMjIyBHZXQgY2VudGVyZWQgYW5kIHN0YW5kYXJkaXplZCByYXcgZGF0YSBtYXRyaWNlcwpgYGB7cn0KIyBjZW50ZXJlZApjbGV2ZW5nZXIuY2VuIDwtIHNjYWxlKGNsZXZlbmdlclssYygnYmJlYXInLCdnYmVhcicsJ2NvdWdhcicsJ3dvbGYnLCdkZWVyJywnZWxrJywnbW9vc2UnKV0sIHNjYWxlPUYpCmNsZXZlbmdlci5jZW4KIyBnZXQgc3RhbmRhcmRpemVkIHJhdyBkYXRhCmNsZXZlbmdlci5zdGFuIDwtIHNjYWxlKGNsZXZlbmdlclssYygnYmJlYXInLCdnYmVhcicsJ2NvdWdhcicsJ3dvbGYnLCdkZWVyJywnZWxrJywnbW9vc2UnKV0sIHNjYWxlPVQpCmNsZXZlbmdlci5zdGFuCmBgYAojIyMgR2VuZXJhdGUgY292YXJpYW5jZSBhbmQgY29ycmVsYXRpb24gbWF0cmljZXMKQ292YXJpYW5jZSBtYXRyaXggZm9yIHdpbGRsaWZlCmBgYHtyfQpjbGV2ZW5nZXIuY292IDwtIGNvdihjbGV2ZW5nZXJbLGMoJ2JiZWFyJywnZ2JlYXInLCdjb3VnYXInLCd3b2xmJywnZGVlcicsJ2VsaycsJ21vb3NlJyldKQpgYGAKQ29ycmVsYXRpb24gbWF0cml4IGZvciB3aWxkbGlmZQpgYGB7cn0KY2xldmVuZ2VyLmNvciA8LSBjb3IoY2xldmVuZ2VyWyxjKCdiYmVhcicsJ2diZWFyJywnY291Z2FyJywnd29sZicsJ2RlZXInLCdlbGsnLCdtb29zZScpXSkKYGBgCgojIyMgRGVyaXZlIGVpZ2VudmVjdG9ycyBhbmQgZWlnZW52YWx1ZXMgYmFzZWQgb24gY29ycmVsYXRpb24gbWF0cml4CmBgYHtyfQpjbGV2ZW5nZXIuZWlnZW4gPC0gZWlnZW4oY2xldmVuZ2VyLmNvcikKY2xldmVuZ2VyLmVpZ2VuCmBgYAojIyMgRG8gUENBCmBgYHtyfQpjbGV2ZW5nZXIucGNhIDwtIHByaW5jb21wKH5iYmVhcitnYmVhcitjb3VnYXIrd29sZitkZWVyK2Vsayttb29zZSwgY29yPVQsIGRhdGE9Y2xldmVuZ2VyKQpzdW1tYXJ5KGNsZXZlbmdlci5wY2EpCmBgYAojIyMgQ2FsY3VsYXRlIGRpc3NpbWlsYXJpdGllcyBmb3IgcmF3IGFuZCBzdGFuZGFyZGl6ZWQgKGJ5IG9iamVjdCBhbmQgdmFyaWFibGVzKSBhbmQgcHJlc2VuY2UvYWJzZW5jZQpDYWxjdWxhdGUgRXVjbGlkZWFuLCBDaGlzcSBhbmQgQnJheS1DdXJ0aXMgbWVhc3VyZXMKYGBge3J9CiMgcmF3IGRhdGEKY2xldjEgPC0gY2xldmVuZ2VyW2MoMTY6MjIpXQp2ZWdkaXN0KGNsZXYxLCBtZXRob2Q9ImV1Y2xpZGVhbiIpCnZlZ2Rpc3QoY2xldjEsIG1ldGhvZD0iY2hpc3EiKQp2ZWdkaXN0KGNsZXYxLCBtZXRob2Q9ImJyYXkiKQojIHN0YW5kYXJkaXplZCBieSBvYmplY3QgdG90YWxzCmNsZXYxJHRvdGFsIDwtIHJvd1N1bXMoY2xldjEpCmNsZXYyIDwtIGNsZXYxCmNsZXYyJGJiZWFydCA8LSBjbGV2MiRiYmVhci9jbGV2MiR0b3RhbApjbGV2MiRnYmVhcnQgPC0gY2xldjIkZ2JlYXIvY2xldjIkdG90YWwKY2xldjIkY291Z2FydCA8LSBjbGV2MiRjb3VnYXIvY2xldjIkdG90YWwKY2xldjIkd29sZnQgPC0gY2xldjIkd29sZi9jbGV2MiR0b3RhbApjbGV2MiRkZWVydCA8LSBjbGV2MiRkZWVyL2NsZXYyJHRvdGFsCmNsZXYyJGVsa3QgPC0gY2xldjIkZWxrL2NsZXYyJHRvdGFsCmNsZXYyJG1vb3NldCA8LSBjbGV2MiRtb29zZS9jbGV2MiR0b3RhbApjbGV2MyA8LSBjbGV2MltjKDk6MTUpXQp2ZWdkaXN0KGNsZXYzLCBtZXRob2Q9ImV1Y2xpZGVhbiIpCnZlZ2Rpc3QoY2xldjMsIG1ldGhvZD0iY2hpc3EiKQp2ZWdkaXN0KGNsZXYzLCBtZXRob2Q9ImJyYXkiKQojIHN0YW5kYXJkaXplZCBieSB2YXJpYWJsZSB0b3RhbHMKY2xldjEkYmJlYXJ0IDwtIGNsZXYxJGJiZWFyL3N1bShjbGV2MiRiYmVhcikKY2xldjEkZ2JlYXJ0IDwtIGNsZXYxJGdiZWFyL3N1bShjbGV2MiRnYmVhcikKY2xldjEkY291Z2FydCA8LSBjbGV2MSRjb3VnYXIvc3VtKGNsZXYyJGNvdWdhcikKY2xldjEkd29sZnQgPC0gY2xldjEkd29sZi9zdW0oY2xldjIkd29sZikKY2xldjEkZGVlcnQgPC0gY2xldjEkZGVlci9zdW0oY2xldjIkZGVlcikKY2xldjEkZWxrdCA8LSBjbGV2MSRlbGsvc3VtKGNsZXYyJGVsaykKY2xldjEkbW9vc2V0IDwtIGNsZXYxJG1vb3NlL3N1bShjbGV2MiRtb29zZSkKY2xldjQgPC0gY2xldjFbYyg5OjE1KV0KdmVnZGlzdChjbGV2NCwgbWV0aG9kPSJldWNsaWRlYW4iKQp2ZWdkaXN0KGNsZXY0LCBtZXRob2Q9ImNoaXNxIikKdmVnZGlzdChjbGV2NCwgbWV0aG9kPSJicmF5IikKYGBgCioqY3JlYXRlIHByZXMvYWJzIGRhdGFmaWxlKioKYGBge3IgZXJyb3I9VFJVRX0KY2xldjUgPC0gY2xldmVuZ2VyW2MoMTY6MjIpXQpjbGV2NVtjbGV2NT4wXSA8LTEKY2xldjUKdmVnZGlzdChjbGV2NSwgbWV0aG9kPSJqYWNjYXJkIikKdmVnZGlzdChjbGV2NSwgbWV0aG9kPSJicmF5IikKYGBgCkNoZWNrIG91dGxpZXJzIHdpdGggTWFoYWxhbm9iaXMgZGlzdGFuY2VzIC0gbm8gcGFydGljdWxhcmx5IHVudXN1YWwgb2JqZWN0cwpgYGB7cn0KIyBQcm9ibGVtIHdpdGggY29kZTsgbmVlZHMgdG8gYmUgZml4ZWQKI21haGFsYW5vYmlzKGNsZXYxLCBjb2xNZWFucyhjbGV2MSksIGNvdihjbGV2MSkpCmBgYAoKIyMjIEZpZyAxNC4zIC0gb3JkaW5hdGlvbiB3aXRoIEJDIE1EUwpgYGB7cn0KY2xldjYgPC0gY2xldmVuZ2VyW2MoMSwxNjoyMildCmNsZXY2LnN0YW5kIDwtIGRlY29zdGFuZChjbGV2NlssMjo4XSwgInRvdGFsIikKY2xldjYuc3RhbmQuYmMgPC0gdmVnZGlzdChjbGV2Ni5zdGFuZCwiYnJheSIpCmNsZXY2Lm1kcyA8LSBtZXRhTURTKGNsZXY2LnN0YW5kLmJjLGs9MikKcGxvdChjbGV2Ni5tZHMkcG9pbnRzLHR5cGU9Im4iLCApCnRleHQoY2xldjYubWRzJHBvaW50cyxsYWI9Y2xldjYkdW5kZXJwYXNzLCBjb2w9ImJsYWNrIikKYGBgCmBgYHtyLCBlcnJvcj1UUlVFfQptZHNwbG90IDwtIGFzLmRhdGEuZnJhbWUoc2NvcmVzKGNsZXY2Lm1kcykpCm1kc3Bsb3QkdW5kZXJwYXNzPC1jbGV2NiR1bmRlcnBhc3MKZjE0XzM8LWdncGxvdChkYXRhPW1kc3Bsb3QsYWVzKHg9Tk1EUzEsIHk9Tk1EUzIsIGxhYmVsPXVuZGVycGFzcykpKwogIGdlb21fdGV4dCgpKwogIHRoZW1lX3FrKCkrCiAgdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpKQpmMTRfMwpgYGAK