knitr::opts_chunk$set(echo = TRUE)

Definition of a distance

Exercice 1

Euclidean distance

\[d(\mathbf{x},\mathbf{y})=\sqrt{\sum_{i=1}^n (x_i-y_i)^2}.\] * A1 and A2 are onbvious. The proof of A3 is provided below.

Manhattan distance

\[d(\mathbf{x},\mathbf{y}) =\sum_{i=1}^n |x_i-y_i|. \]

Manhattan distance vs Euclidean distance Graph

x = c(0, 0)
y = c(6,6)
dist(rbind(x, y), method = "euclidian")
6*sqrt(2)
dist(rbind(x, y), method = "manhattan")

Canberra distance

\[d(\mathbf{x},\mathbf{y}) =\sum_{i=1}^n \frac{|x_i-y_i|}{|x_i|+|y_i|}.\]

x = c(0, 0)
y = c(6,6)
dist(rbind(x, y), method = "canberra")
6/6+6/6

Exercice 2

Minkowski distance

\[ d(\mathbf{x},\mathbf{y})= \left[\sum_{i=1} |x_i-y_i|^{p}\right]^{1/p}. \] * For \(p=1\), we get the Manhattan distance. * For \(p=2\), we get the Euclidian ditance.

Chebyshev distance

\[ d(\mathbf{x},\mathbf{y})=\max_{i=1,\cdots,n}(|x_i-y_i|)=\lim_{p\rightarrow\infty} \left[\sum_{i=1} |x_i-y_i|^{p}\right]^{1/p}. \]

Minkowski inequality

\[ \left[\sum_{i=1}^n (a_i+b_i)^{p}\right]^{1/p}\leq \left[\sum_{i=1}^n a_i^{p}\right]^{1/p} + \left[\sum_{i=1}^n b_i^{p}\right]^{1/p}. \]

\[ \sum_{i=1}^n|x_i-z_i|^{p}= \sum_{i=1}^n|(x_i-y_i)+(y_i-z_i)|^{p}. \] * Since for any reals \(x,y\), we have \(|x+y|\leq |x|+|y|\), and using the fact that \(x^p\) is increasing in \(x>0\), we obtain: \[ \sum_{i=1}^n|x_i-z_i|^{p}\leq \sum_{i=1}^n(|x_i-y_i|+|y_i-z_i|)^{p}. \]

Hölder inequality

\[ \sum_{i=1}^n a_ib_i\leq \left[\sum_{i=1}^n a_i^{p}\right]^{1/p} \left[\sum_{i=1}^n b_i^{q}\right]^{1/q} \] * The proof of the Hölder inequality relies on the Young inequality. * For any \(a,b>0\), we have \[ ab\leq \frac{a^p}{p}+\frac{b^q}{q}, \] with equality occuring iff: \(a^p=b^q\). * To prove the Young inequality, one can use the (strict) convexity of the exponential function. * For any reals \(x,y\), then \[ e^{\frac{x}{p}+\frac{y}{q} }\leq \frac{e^{x}}{p}+\frac{e^{y}}{q}. \] * We then set \(x=p\ln a\) and \(y=q\ln b\) to get the Young inequality. * A good reference on the inequalities topic is: Z. Cvetkovski, Inequalities: theorems, techniques and selected problems, 2012, Springer Science & Business Media. # Cauchy-Schwartz inequality * Note that the triangular inequality for the Minkowski distance implies

\[ \sum_{i=1}^n |x_i|\leq \left[\sum_{i=1}^n |x_i|^{p}\right]^{1/p}. \] * Note that for \(p=2\), we have \(q=2\). The Hölder inequality implies for that special case \[ \sum_{i=1}^n|x_iy_i|\leq\sqrt{\sum_{i=1}^n x_i^2}\sqrt{\sum_{i=1}^n y_i^2}. \] * Since the LHS od thes above inequality is greater then \(|\sum_{i=1}^nx_iy_i|\), we get the Cauchy-Schwartz inequality

\[ |\sum_{i=1}^nx_iy_i|\leq\sqrt{\sum_{i=1}^n x_i^2}\sqrt{\sum_{i=1}^n y_i^2}. \] * Using the dot product notation called also scalar product noation \(\mathbf{x\cdot y}=\sum_{i=1}^nx_iy_i\), and the norm notation \(\|\mathbf{\cdot}\|_2 \|\), the Cauchy-Schwart inequality is:

\[|\mathbf{x\cdot y} | \leq \|\mathbf{x}\|_2 \| \mathbf{y}\|_2.\]

Pearson correlation distance

Cosine correlation distance

Spearman correlation distance

x=c(3, 1, 4, 15, 92)
xr=rank(x)
xr
x=c(3, 1, 4, 15, 92)
xr=rank(x)
y=c(30,2 , 9, 20, 48)
yr=rank(y)
d=xr-yr
d
cor(xr,yr)
1-6*sum(d^2)/(5*(5^2-1))

Kendall tau distance

x=c(3, 1, 4, 15, 92)
y=c(30,2 , 9, 20, 48)
tau=0
for (i in 1:5)
{  
tau=tau+sign(x -x[i])%*%sign(y -y[i])
}
tau=tau/(5*4)
tau
cor(x,y, method="kendall")

Standardization of variables

x=c(3, 1, 4, 15, 92)
y=c(30,2 , 9, 20, 48)
(x-mean(x))/sd(x)
scale(x)
(y-mean(y))/sd(y)
scale(y)

Distance matrix computation

install.packages("FactoMineR")
library("FactoMineR")
data("USArrests") # Loading
head(USArrests, 3) # Print the first 3 rows
set.seed(123)
ss <- sample(1:50, 15) # Take 15 random rows
df <- USArrests[ss, ] # Subset the 15 rows
df.scaled <- scale(df) # Standardize the variables
Ci0tLQp0aXRsZTogIkRpc3RhbmNlIGFuZCBkaXNzaW1pbGFyaXRpZXMiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICAgIGRmX3ByaW50OiBwYWdlZAogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogeWVzCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9VFJVRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCgojIERlZmluaXRpb24gb2YgYSBkaXN0YW5jZQoKKiBBIGRpc3RhbmNlIGZ1bmN0aW9uIG9yIG1ldHJpYyBvbiB0aGUgc3BhY2UgJFxtYXRoYmJ7Un1ebixcOm5cZ2VxIDEkLCBpcyBhIGZ1bmN0aW9uICRkOlxtYXRoYmJ7Un1eblx0aW1lc1xtYXRoYmJ7Un1eblxyaWdodGFycm93IFxtYXRoYmJ7Un0kLgoqIEEgZGlzdGFuY2UgZnVuY3Rpb24gbXVzdCBzYXRpc2Z5IHNvbWUgcmVxdWlyZWQgcHJvcGVydGllcyBvciBheGlvbXMuIAoqIFRoZXJlIGFyZSB0aHJlZSBtYWluIGF4aW9tcy4KCiogQTEuICRkKFxtYXRoYmZ7eH0sXG1hdGhiZnt5fSk9IDBcaWZmIFxtYXRoYmZ7eH09XG1hdGhiZnt5fSQgKGlkZW50aXR5IG9mIGluZGlzY2VybmlibGVzKTsKCiogQTIuICRkKFxtYXRoYmZ7eH0sXG1hdGhiZnt5fSk9IGQoXG1hdGhiZnt5fSxcbWF0aGJme3h9KSQgKHN5bW1ldHJ5KTsKCiogQTMuICRkKFxtYXRoYmZ7eH0sXG1hdGhiZnt6fSlcbGVxIGQoXG1hdGhiZnt4fSxcbWF0aGJme3l9KStkKFxtYXRoYmZ7eX0sXG1hdGhiZnt6fSkkICAodHJpYW5nbGUgaW5lcXVhbGl0eSksCndoZXJlICRcbWF0aGJme3h9PSh4XzEsXGNkb3RzLHhfbikkLCAkXG1hdGhiZnt5fT0oeV8xLFxjZG90cyx5X24pJCBhbmQgJFxtYXRoYmZ7en09KHpfMSxcY2RvdHMsel9uKSQgYXJlIGFsbCB2ZWN0b3JzIG9mICRcbWF0aGJie1J9Xm4kLgoqIFdlIHNob3VsZCB1c2UgdGhlIHRlcm0gX2Rpc3NpbWlsYXJpdHlfIHJhdGhlciB0aGFuIF9kaXN0YW5jZV8gd2hlbiBub3QgYWxsIHRoZSB0aHJlZSBheGlvbXMgQTEtQTMgYXJlIHZhbGlkLgoqIE1vc3Qgb2YgdGhlIHRpbWUsIHdlIHNoYWxsIHVzZSwgd2l0aCBzb21lIGFidXNlIG9mIHZvY2FidWxhcnksIHRoZSB0ZXJtIGRpc3RhbmNlLgoKIyBFeGVyY2ljZSAxCgoqIFByb3ZlIHRoYXQgdGhlIHRocmVlIGF4aW9tcyBBMS1BMyBpbXBseSB0aGUgbm9uLW5lZ2F0aXZpdHkgY29uZGl0aW9uOiAkJGQoXG1hdGhiZnt4fSxcbWF0aGJme3l9KVxnZXEgMC4kJAoKCiMgRXVjbGlkZWFuIGRpc3RhbmNlCgoKKiBJdCBpcyBkZWZpbmVkIGJ5OgoKJCRkKFxtYXRoYmZ7eH0sXG1hdGhiZnt5fSk9XHNxcnR7XHN1bV97aT0xfV5uICh4X2kteV9pKV4yfS4kJAoqIEExIGFuZCBBMiBhcmUgb25idmlvdXMuIFRoZSBwcm9vZiBvZiBBMyBpcyBwcm92aWRlZCBiZWxvdy4KCgojIE1hbmhhdHRhbiBkaXN0YW5jZQoKKiBUaGUgTWFuaGF0dGFuIGRpc3RhbmNlIGFsc28gY2FsbGVkICB0YXhpLWNhYiBtZXRyaWMgb3IgY2l0eS1ibG9jayBtZXRyaWMgaXMgZGVmaW5lZCBieToKCiQkZChcbWF0aGJme3h9LFxtYXRoYmZ7eX0pCj1cc3VtX3tpPTF9Xm4gfHhfaS15X2l8LgokJAoKKiBBMSBhbmQgQTIgaG9sZC4KKiBBMyBpcyBhbHNvIGhvbGQgdXNpbmcgdGhlIGZhY3QgdGhhdCAkfGErYnxcbGVxIHxhfCt8YnwkIGZvciBhbnkgcmVhbHMgJGEsYiQuCiogVGhlcmUgZXhpc3RzIGFsc28gYSAgd2VpZ2h0ZWQgdmVyc2lvbiAgb2YgdGhlIGFib3ZlIGRpc3RhbmNlIGNhbGxlZCB0aGUgQ2FuYmVycmEgZGlzdGFuY2UuCgpbTWFuaGF0dGFuIGRpc3RhbmNlIHZzIEV1Y2xpZGVhbiBkaXN0YW5jZSBHcmFwaF0oaHR0cHM6Ly91cGxvYWQud2lraW1lZGlhLm9yZy93aWtpcGVkaWEvY29tbW9ucy8wLzA4L01hbmhhdHRhbl9kaXN0YW5jZS5zdmcpCgpgYGB7cn0KeCA9IGMoMCwgMCkKeSA9IGMoNiw2KQpkaXN0KHJiaW5kKHgsIHkpLCBtZXRob2QgPSAiZXVjbGlkaWFuIikKNipzcXJ0KDIpCmRpc3QocmJpbmQoeCwgeSksIG1ldGhvZCA9ICJtYW5oYXR0YW4iKQpgYGAKCgojIENhbmJlcnJhIGRpc3RhbmNlCgoqIEl0IGlzIGRlZmluZWQgYnk6CgokJGQoXG1hdGhiZnt4fSxcbWF0aGJme3l9KQo9XHN1bV97aT0xfV5uIFxmcmFje3x4X2kteV9pfH17fHhfaXwrfHlfaXx9LiQkCgoqIE5vdGUgdGhhdCB0aGUgdGVybSAkfHhfaSDiiJIgeV9pfC8ofHhfaXwrfHlfaXwpJCBpcyBub3QgcHJvcGVybHkgZGVmaW5lZCB3aGVuIGJvdGggJHhfaSQgYW5kICR5X2kkIGFyZSB6ZXJvLgoqIEJ5IGNvbnZlbnRpb24gd2Ugc2V0IHRoZSByYXRpbyB0byBiZSB6ZXJvIGluIHRoYXQgY2FzZS4KKiBUaGUgQ2FuYmVycmEgZGlzdGFuY2UgaXMgc3BlY2lhbGx5IHNlbnNpdGl2ZSB0byBzbWFsbCBjaGFuZ2VzIG5lYXIgemVyby4KCmBgYHtyfQp4ID0gYygwLCAwKQp5ID0gYyg2LDYpCmRpc3QocmJpbmQoeCwgeSksIG1ldGhvZCA9ICJjYW5iZXJyYSIpCjYvNis2LzYKYGBgCgoKIyBFeGVyY2ljZSAyCgoqIFByb3ZlIHRoYXQgdGhlIENhbmJlcnJhIGRpc3RhbmNlIGlzIGEgdHJ1ZSBkaXN0YW5jZS4KCiMgTWlua293c2tpIGRpc3RhbmNlCgoqIEJvdGggdGhlIEV1Y2xpZGlhbiBhbmQgdGhlIE1hbmF0dGFuIGRpc3RhbmNlcyBhcmUgc3BlY2lhbCBjYXNlcyBvZiAgdGhlIE1pbmtvd3NraSBkaXN0YW5jZSB3aGljaCBpcyBkZWZpbmVkLCBmb3IgJHBcZ2VxIDEkLCBieTogCgokJApkKFxtYXRoYmZ7eH0sXG1hdGhiZnt5fSk9ClxsZWZ0W1xzdW1fe2k9MX0gfHhfaS15X2l8XntwfVxyaWdodF1eezEvcH0uCiQkCiAqIEZvciAkcD0xJCwgd2UgZ2V0IHRoZSBNYW5oYXR0YW4gZGlzdGFuY2UuCiAqIEZvciAkcD0yJCwgd2UgZ2V0IHRoZSBFdWNsaWRpYW4gZGl0YW5jZS4KCgoqIExldCB1cyBkZWZpbmU6IAokJFx8XG1hdGhiZnt4fVx8X3BcZXF1aXZcbGVmdFtcc3VtX3tpPTF9Xm4gfHhfaXxee3B9XHJpZ2h0XV57MS9wfSwkJAp3aGVyZSAkXHxcbWF0aGJme1xjZG90fVx8X3AkIGlzIGtub3duIGFzIHRoZSAkcCQtbm9ybSBvciBNaW5rb3dza2kgbm9ybS4KCiogTm90ZSB0aGF0IHRoZSBNaW5rb3dza2kgZGlzdGFuY2UgYW5kIG5vcm0gYXJlIHJlbGF0ZWQgYnk6CiQkCmQoXG1hdGhiZnt4fSxcbWF0aGJme3l9KT1cfFxtYXRoYmZ7eH0tXG1hdGhiZnt5fVx8X3AsCiQkCm9yIGNvbnZlcnNlbHkgYnkKJCQKXHxcbWF0aGJme3h9XHxfcD1kKFxtYXRoYmZ7eH0sXG1hdGhiZnswfSksCiQkCndoZXJlICRcbWF0aGJmezB9JCBpcyB0aGUgbnVsbC12ZXRvciBvZiAkXG1hdGhiYntSfV5uJC4KCiMgQ2hlYnlzaGV2IGRpc3RhbmNlIAoKKiBBdCB0aGUgbGltaXQsIHdlIGdldCB0aGUgQ2hlYnlzaGV2IGRpc3RhbmNlIGRlZmluZWQgYnk6CgokJApkKFxtYXRoYmZ7eH0sXG1hdGhiZnt5fSk9XG1heF97aT0xLFxjZG90cyxufSh8eF9pLXlfaXwpPVxsaW1fe3BccmlnaHRhcnJvd1xpbmZ0eX0KXGxlZnRbXHN1bV97aT0xfSB8eF9pLXlfaXxee3B9XHJpZ2h0XV57MS9wfS4KJCQKCiogVGhlIGNvcnJlc3BvbmRpbmcgbm9ybSBpczoKJCQKXHxcbWF0aGJme3h9fF9caW5mdHk9XG1heF97aT0xLFxjZG90cyxufSh8eF9pfCkuCiQkCgojIE1pbmtvd3NraSBpbmVxdWFsaXR5CgoqIFRoZSBwcm9vZiBvZiB0aGUgdHJpYW5ndWxhciBpbmVxdWFsaXR5IFAzIGlzIGJhc2VkIG9uIHRoZSBNaW5rb3dza2kgaW5lcXVhbGl0eS4gCiogRm9yIGFueSBub25uZWdhdGl2ZSByZWFsIG51bWJlcnMgJGFfMSxcY2RvdHMsYV9uJDsgJGJfMSxcY2RvdHMsYl9uJCwgYW5kIGZvciAkcFxnZXEgMSQsIHdlIGhhdmU6CgokJApcbGVmdFtcc3VtX3tpPTF9Xm4gKGFfaStiX2kpXntwfVxyaWdodF1eezEvcH1cbGVxClxsZWZ0W1xzdW1fe2k9MX1ebiBhX2lee3B9XHJpZ2h0XV57MS9wfQorClxsZWZ0W1xzdW1fe2k9MX1ebiBiX2lee3B9XHJpZ2h0XV57MS9wfS4KJCQKCiogVG8gcHJvdmUgdGhhdCB0aGUgTWlua293c2tpIGRpc3RhbmNlIHNhdGlzZmllcyBQMywgbm90aWNlIHRoYXQgCgokJAogXHN1bV97aT0xfV5ufHhfaS16X2l8XntwfT0gXHN1bV97aT0xfV5ufCh4X2kteV9pKSsoeV9pLXpfaSl8XntwfS4KJCQKKiBTaW5jZSBmb3IgYW55IHJlYWxzICR4LHkkLCB3ZSBoYXZlICR8eCt5fFxsZXEgfHh8K3x5fCQsIGFuZCB1c2luZyB0aGUgZmFjdCB0aGF0ICR4XnAkIGlzIGluY3JlYXNpbmcgaW4gJHg+MCQsIHdlIG9idGFpbjoKJCQKIFxzdW1fe2k9MX1ebnx4X2ktel9pfF57cH1cbGVxIFxzdW1fe2k9MX1ebih8eF9pLXlfaXwrfHlfaS16X2l8KV57cH0uCiQkCgoqIEFwcGx5aW5nIHRoZSBNaW5rb3dza2kgaW5lcXVhbGl0eSB3aXRoICRhX2k9fHhfaS15X2l8JCBhbmQgJGJfaT18eV9pLXpfaXwkLCAkaT0xLFxjZG90cyxuJCwgd2UgZ2V0OgokJAogXHN1bV97aT0xfV5ufHhfaS16X2l8XntwfVxsZXEgXGxlZnQoXHN1bV97aT0xfV5uIHx4X2kteV9pfF57cH1ccmlnaHQpXnsxL3B9K1xsZWZ0KFxzdW1fe2k9MX1ebiB8eV9pLXpfaXxee3B9XHJpZ2h0KV57MS9wfS4KJCQKCgojIEjDtmxkZXIgaW5lcXVhbGl0eQoKKiBUaGUgcHJvb2Ygb2YgdGhlIE1pbmtvd3NraSBpbmVxdWFsaXR5IGl0c2VsZiByZXF1aXJlcyB0aGUgSMO2bGRlciBpbmVxdWFsaXR5LgoqIEl0IHN0YXQKKiBGb3IgYW55IG5vbm5lZ2F0aXZlIHJlYWwgbnVtYmVycyAkYV8xLFxjZG90cyxhX24kOyAkYl8xLFxjZG90cyxiX24kLCBhbmQgYW55ICRwLHE+MSQgd2l0aCAkMS9wKzEvcT0xJCwgd2UgaGF2ZQoKJCQKXHN1bV97aT0xfV5uIGFfaWJfaVxsZXEKXGxlZnRbXHN1bV97aT0xfV5uIGFfaV57cH1ccmlnaHRdXnsxL3B9ClxsZWZ0W1xzdW1fe2k9MX1ebiBiX2lee3F9XHJpZ2h0XV57MS9xfQokJAoqIFRoZSBwcm9vZiBvZiB0aGUgSMO2bGRlciBpbmVxdWFsaXR5IHJlbGllcyBvbiB0aGUgWW91bmcgaW5lcXVhbGl0eS4KKiBGb3IgYW55ICRhLGI+MCQsIHdlIGhhdmUKJCQKYWJcbGVxIFxmcmFje2FecH17cH0rXGZyYWN7Yl5xfXtxfSwKJCQKd2l0aCBlcXVhbGl0eSBvY2N1cmluZyBpZmY6ICRhXnA9Yl5xJC4gCiogVG8gcHJvdmUgdGhlIFlvdW5nIGluZXF1YWxpdHksIG9uZSBjYW4gdXNlIHRoZSAoc3RyaWN0KSBjb252ZXhpdHkgb2YgdGhlIGV4cG9uZW50aWFsIGZ1bmN0aW9uLgoqIEZvciBhbnkgcmVhbHMgJHgseSQsIHRoZW4gCiQkCmVee1xmcmFje3h9e3B9K1xmcmFje3l9e3F9IH1cbGVxIFxmcmFje2Vee3h9fXtwfStcZnJhY3tlXnt5fX17cX0uIAokJAoqIFdlIHRoZW4gc2V0ICR4PXBcbG4gYSQgYW5kICR5PXFcbG4gYiQgdG8gZ2V0IHRoZSBZb3VuZyBpbmVxdWFsaXR5LgoqIEEgZ29vZCByZWZlcmVuY2Ugb24gdGhlIGluZXF1YWxpdGllcyB0b3BpYyBpczogWi4gQ3ZldGtvdnNraSwgIEluZXF1YWxpdGllczogdGhlb3JlbXMsIHRlY2huaXF1ZXMgYW5kIHNlbGVjdGVkIHByb2JsZW1zLCAyMDEyLCBTcHJpbmdlciBTY2llbmNlICYgQnVzaW5lc3MgTWVkaWEuCiAjIENhdWNoeS1TY2h3YXJ0eiBpbmVxdWFsaXR5CiogTm90ZSB0aGF0IHRoZSB0cmlhbmd1bGFyIGluZXF1YWxpdHkgZm9yIHRoZSBNaW5rb3dza2kgZGlzdGFuY2UgaW1wbGllcyAKCiQkClxzdW1fe2k9MX1ebiB8eF9pfFxsZXEKXGxlZnRbXHN1bV97aT0xfV5uIHx4X2l8XntwfVxyaWdodF1eezEvcH0uCiQkCiogTm90ZSB0aGF0IGZvciAkcD0yJCwgd2UgaGF2ZSAkcT0yJC4gVGhlIEjDtmxkZXIgaW5lcXVhbGl0eSBpbXBsaWVzIGZvciB0aGF0IHNwZWNpYWwgY2FzZQokJApcc3VtX3tpPTF9Xm58eF9peV9pfFxsZXFcc3FydHtcc3VtX3tpPTF9Xm4geF9pXjJ9XHNxcnR7XHN1bV97aT0xfV5uIHlfaV4yfS4gCiQkCiogU2luY2UgdGhlIExIUyBvZCB0aGVzIGFib3ZlIGluZXF1YWxpdHkgaXMgZ3JlYXRlciB0aGVuICR8XHN1bV97aT0xfV5ueF9peV9pfCQsIHdlIGdldCB0aGUgQ2F1Y2h5LVNjaHdhcnR6IGluZXF1YWxpdHkKCiQkCnxcc3VtX3tpPTF9Xm54X2l5X2l8XGxlcVxzcXJ0e1xzdW1fe2k9MX1ebiB4X2leMn1cc3FydHtcc3VtX3tpPTF9Xm4geV9pXjJ9LiAKJCQKKiBVc2luZyB0aGUgZG90IHByb2R1Y3Qgbm90YXRpb24gY2FsbGVkIGFsc28gc2NhbGFyIHByb2R1Y3Qgbm9hdGlvbiAkXG1hdGhiZnt4XGNkb3QgeX09XHN1bV97aT0xfV5ueF9peV9pJCwgYW5kIHRoZSBub3JtIG5vdGF0aW9uICRcfFxtYXRoYmZ7XGNkb3R9XHxfMiBcfCQsIHRoZSBDYXVjaHktU2Nod2FydCBpbmVxdWFsaXR5IGlzOgoKJCR8XG1hdGhiZnt4XGNkb3QgeX0gfCBcbGVxIFx8XG1hdGhiZnt4fVx8XzIgXHwgXG1hdGhiZnt5fVx8XzIuJCQKCiMgUGVhcnNvbiBjb3JyZWxhdGlvbiBkaXN0YW5jZSAKCiogVGhlIFBlYXJzb24gY29ycmVsYXRpb24gY29lZmZpY2llbnQgaXMgYSBzaW1pbGFyaXR5IG1lYXN1cmUgb24gJFxtYXRoYmJ7Un1ebiQgZGVmaW5lZCBieToKJCQKXHJobyhcbWF0aGJme3h9LFxtYXRoYmZ7eX0pPQpcZnJhY3tcc3VtX3tpPTF9Xm4gKHhfaS1cYmFye1xtYXRoYmZ7eH19KSh5X2ktXGJhcntcbWF0aGJme3l9fSl9e3tcc3FydHtcc3VtX3tpPTF9Xm4gKHhfaS1cYmFye1xtYXRoYmZ7eH19KV4yXHN1bV97aT0xfV5uICh5X2ktXGJhcntcbWF0aGJme3l9fSleMn19fSwKJCQKd2hlcmUgJFxiYXJ7XG1hdGhiZnt4fX0kIGlzIHRoZSBtZWFuIG9mIHRoZSB2ZWN0b3IgJFxtYXRoYmZ7eH0kIGRlZmluZWQgYnk6IAokJFxiYXJ7XG1hdGhiZnt4fX09XGZyYWN7MX17bn1cc3VtX3tpPTF9Xm4geF9pLCQkCiogTm90ZSB0aGF0IHRoZSBQZWFyc29uIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IHNhdGlzZmllcyBQMiBhbmQgIGlzIGludmFyaWFudCB0byBhbnkgcG9zaXRpdmUgbGluZWFyIHRyYW5zZm9ybWF0aW9uLCBpLmUuOiAkJFxyaG8oXGFscGhhXG1hdGhiZnt4fSxcbWF0aGJme3l9KT1ccmhvKFxtYXRoYmZ7eH0sXG1hdGhiZnt5fSksJCQgZm9yIGFueSAkXGFscGhhPjAkLgoqIFRoZSBQZWFyc29uIGRpc3RhbmNlIChvciBjb3JyZWxhdGlvbiBkaXN0YW5jZSkgaXMgZGVmaW5lZCBieToKJCQKZChcbWF0aGJme3h9LFxtYXRoYmZ7eX0pPTEtXHJobyhcbWF0aGJme3h9LFxtYXRoYmZ7eX0pLiQkCgoqIE5vdGUgdGhhdCB0aGUgUGVhcnNvbiBkaXN0YW5jZSBkb2VzIG5vdCBzYXRpc2Z5IEExIHNpbmNlICRkKFxtYXRoYmZ7eH0sXG1hdGhiZnt4fSk9MCQgZm9yIGFueSBub24temVybyB2ZWN0b3IgJFxtYXRoYmZ7eH0kLiBJdCBuZWl0aGVyIHNhdGlzZmllcyB0aGUgdHJpYW5nbGUgaW5lcXVhbGl0eS4gSG93ZXZlciwgdGhlIHN5bW1ldHJ5IHByb3BlcnR5IGlzIGZ1bGxmaWxsZWQuIAoKIyBDb3NpbmUgY29ycmVsYXRpb24gZGlzdGFuY2UKCiogVGhlIGNvc2luZSBvZiB0aGUgYW5nbGUgJFx0aGV0YSQgYmV0d2VlbiB0d28gdmVjdG9ycyAkXG1hdGhiZnt4fSQgYW5kICRcbWF0aGJme3l9JCBpcyBhIG1lYXN1cmUgb2Ygc2ltaWxhcml0eSBnaXZlbiBieToKJCQKXGNvcyhcdGhldGEpPVxmcmFje1xtYXRoYmZ7eH1cY2RvdCBcbWF0aGJme3l9fXtcfFxtYXRoYmZ7eH1cfF8yXHxcbWF0aGJme3l9XHxfMn09XGZyYWN7XHN1bV97aT0xfV5uIHhfaSB5X2l9e3tcc3FydHtcc3VtX3tpPTF9Xm4geF9pXjJcc3VtX3tpPTF9Xm4geV9pXjJ9fX0uCiQkCiogTm90ZSB0aGF0IHRoZSBjb3NpbmUgb2YgdGhlIGFuZ2xlIGJldHdlZW4gdGhlIHR3byBjZW50cmVkIHZlY3RvcnMgJCh4XzEtXGJhcntcbWF0aGJme3h9fSxcY2RvdHMseF9uLVxiYXJ7XG1hdGhiZnt4fX0pJCBhbmQgJCh5XzEtXGJhcntcbWF0aGJme3l9fSxcY2RvdHMseV9uLVxiYXJ7XG1hdGhiZnt5fX0pJCBjb2luY2lkZXMgd2l0aCB0aGUgUGVhcnNvbiBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBvZiAkXG1hdGhiZnt4fSQgYW5kICRcbWF0aGJme3l9JC4gIAoKKiBUaGUgY29zaW5lIGNvcnJlbGF0aW9uIGRpc3RhbmNlIGlzIGRlZmluZWQgYnk6CiQkCmQoXG1hdGhiZnt4fSxcbWF0aGJme3l9KT0xLVxjb3MoXHRoZXRhKS4KJCQKKiBJdCBzaGFyZXMgc2ltaWxhciBwcm9wZXJ0aWVzIHRoYW4gdGhlIFBlYXJzb24gY29ycmVsYXRpb24gZGlzdGFuY2UuIExpa2V3aXNlLCBBeGlvbXMgUDEgYW5kIFAzIGFyZSBub3Qgc2F0aXNmaWVkLgoKIyBTcGVhcm1hbiBjb3JyZWxhdGlvbiBkaXN0YW5jZSAKCiogVG8gY2FsY3VsYXRlIHRoZSBTcGVhcm1hbidzIHJhbmstb3JkZXIgY29ycmVsYXRpb24gb3IgU3BlYXJtYW4ncyBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBmb3Igc2hvcnQsIHdlIG5lZWQgdG8gbWFwIHNlcGVyYXRlbHkgZWFjaCBvZiB0aGUgdmVjdG9ycyB0byByYW5rZWQgZGF0YSB2YWx1ZXM6ICRcbWF0aGJme3h9XHJpZ2h0YXJyb3cgXG1hdGhiZnt4fV5yPSh4XzFecixcY2RvdHMseF9uXnIpJC4gSGVyZSwgJHhfaV5yJCBpcyB0aGUgcmFuayBvZiAkeF9pJCBhbW9uZyB0aGUgc2V0IG9mIHZhbHVlcyBvZiAkXG1hdGhiZnt4fSQuCiogV2UgaWxsdXN0cmF0ZSB0aGlzIHRyYW5zZm9ybWF0aW9uIHdpdGggYSBzaW1wbGUgZXhhbXBsZS4gSWYgJFxtYXRoYmZ7eH09KDMsIDEsIDQsIDE1LCA5MikkLCB0aGVuIHRoZSByYW5rLW9yZGVyIHZlY3RvciBpcyAkXG1hdGhiZnt4fV5yPSgyLDEsMyw0LDUpJC4gIAoKCmBgYHtyfQp4PWMoMywgMSwgNCwgMTUsIDkyKQp4cj1yYW5rKHgpCnhyCmBgYAoKKiBUaGUgU3BlYXJtYW4ncyByYW5rIGNvcnJlbGF0aW9uIG9mIHR3byBudW1lcmljYWwgdmFyaWFibGVzICRcbWF0aGJme3h9JCAgYW5kICRcbWF0aGJme3l9JCBpcyBzaW1wbHkgdGhlIFBlYXJzb24gY29ycmVsYXRpb24gb2YgdGhlIHR3byBjb3JyZXNwbmRpbmcgcmFuay1vZXJkZXIgdmFyaWFibGVzICRcbWF0aGJme3h9XnIkIGFuZCAkXG1hdGhiZnt5fV5yJCwgaS5lLiAkXHJobyhcbWF0aGJme3h9XnIsXG1hdGhiZnt5fV5yKSQuIFRoaXMgbWVhc3VyZSBpcyBpcyB1c2VmdWwgYmVjYXVzZSBpdCBpcyBtb3JlIHJvYnVzdCBhZ2FpbnN0IG91dGxpZXJzIHRoYW4gdGhlIFBlYXJzb24gY29ycmVsYXRpb24uCiogSWYgYWxsICB0aGUgJG4kICByYW5rcyBhcmUgZGlzdGluY3QsIGl0IGNhbiBiZSBjb21wdXRlZCB1c2luZyB0aGUgZm9sbG93aW5nIGZvcm11bGE6CiQkClxyaG8oXG1hdGhiZnt4fV5yLFxtYXRoYmZ7eX1ecik9MS1cZnJhY3s2XHN1bV97aT0xfV5uIGRfaV4yfXtuKG5eMi0xKX0sCiQkCndoZXJlICRkX2k9eF9pXnIteV9pXnIsXDppPTEsXGNkb3RzLG4kLgogKiBUaGUgc3BlYXJtYW4gZGlzdGFuY2UgaXMgdGhlbiBkZWZpbmVkIGJ5OgokJApkKFxtYXRoYmZ7eH0sXG1hdGhiZnt5fSk9MS1ccmhvKFxtYXRoYmZ7eF5yfSxcbWF0aGJme3lecn0pLgokJAoqIEl0IGNhbiBiZSBzaG93biB0aGF0IGVhc2FseSB0aGF0IGl0IGlzIG5vdCBhIHByb3BlciBkaXN0YW5jZS4KCiogSWYgYWxsICB0aGUgJG4kICByYW5rcyBhcmUgZGlzdGluY3QsIHdlIGdldDoKJCQKZChcbWF0aGJme3h9LFxtYXRoYmZ7eX0pPVxmcmFjezZcc3VtX3tpPTF9Xm4gZF9pXjJ9e24obl4yLTEpfS4KJCQKCmBgYHtyfQp4PWMoMywgMSwgNCwgMTUsIDkyKQp4cj1yYW5rKHgpCnk9YygzMCwyICwgOSwgMjAsIDQ4KQp5cj1yYW5rKHkpCmQ9eHIteXIKZApjb3IoeHIseXIpCjEtNipzdW0oZF4yKS8oNSooNV4yLTEpKQpgYGAKCgojIEtlbmRhbGwgdGF1IGRpc3RhbmNlIAoKKiBUaGUgS2VuZGFsbCByYW5rIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IGlzIGNhbGN1bGF0ZWQgZnJvbSB0aGUgbnVtYmVyIG9mIGNvcnJlc3BvbmRhbmNlcyBiZXR3ZWVuIHRoZSByYW5raW5ncyBvZiAkXG1hdGhiZnt4fSQgYW5kIHRoZSByYW5raW5ncyBvZiAkXG1hdGhiZnt5fSQuCiogICBUaGUgbnVtYmVyIG9mIHBhaXJzIG9mIG9ic2VydmF0aW9ucyBhbW9uZyAkbiQgb2JzZXJ2YXRpb25zIG9yIHZhbHVlcyBpczogCiQke24gXGNob29zZSAyfSA9XGZyYWN7bihuLTEpfXsyfS4kJAoKKiBUaGUgcGFpcnMgb2Ygb2JzZXJ2YXRpb25zICQoeF97aX0seF97an0pJCAgYW5kICAkKHlfe2l9LHlfe2p9KSQgYXJlIHNhaWQgdG8gYmUgX2NvbmNvcmRhbnRfIGlmOiAkJFx0ZXh0e3NpZ259KHhfai14X2kpPVx0ZXh0e3NpZ259KHlfai15X2kpLCQkIGFuZCB0byBiZSBfZGlzY29yZGFudF8gaWY6ICAkJFx0ZXh0e3NpZ259KHhfai14X2kpPS1cdGV4dHtzaWdufSh5X2oteV9pKSwkJAp3aGVyZSAkXHRleHR7c2lnbn0oXGNkb3QpJCByZXR1cm5zICAkMSQgZm9yIHBvc2l0aXZlIG51bWJlcnMgYW5kICAkLTEkIG5lZ2F0aXZlIG51bWJlcnMgYW5kICQwJCBvdGhlcndpc2UuCiogSWYgJHhfaT14X2okIG9yICR5X2k9eV9qJCAob3IgYm90aCksIHRoZXJlIGlzIGEgdGllLgoqIFRoZSBLZW5kYWxsICRcdGF1JCBjb2VmZmljaWVudCBpcyBkZWZpbmVkIGJ5IChuZWdsZWN0aW5nIHRpZXMpOgokJFx0YXUgPVxmcmFjIHsxfXtuKG4tMSl9XHN1bV97aT0xfV57bn1cc3VtX3tqPTF9Xm5cdGV4dHtzaWdufSh4X2oteF9pKVx0ZXh0e3NpZ259KHlfai15X2kpLiQkCiogTGV0ICRuX2MkIChyZXNwLiAkbl9kJCkgYmUgdGhlIG51bWJlciBvZiBjb25jb3JkYW50IChyZXNwLiBkaXNjb3JkYW50KSBwYWlycywgd2UgaGF2ZSAkJFx0YXUgPVxmcmFjIHsyKG5fYy1uX2QpfXtuKG4tMSl9LiQkIAoqIFRoZSBLZW5kYWxsIHRhdSBkaXN0YW5jZSBpcyB0aGVuOiAkJGQoXG1hdGhiZnt4fSxcbWF0aGJme3l9KT0xLVx0YXUuICQkCiogUmVtYXJrOiB0aGUgdHJpYW5ndWxhciBpbmVxdWFsaXR5IG1heSBmYWlsIGluIGNhc2VzIHdoZXJlIHRoZXJlIGFyZSB0aWVzLgoKYGBge3J9Cng9YygzLCAxLCA0LCAxNSwgOTIpCnk9YygzMCwyICwgOSwgMjAsIDQ4KQp0YXU9MApmb3IgKGkgaW4gMTo1KQp7ICAKdGF1PXRhdStzaWduKHggLXhbaV0pJSolc2lnbih5IC15W2ldKQp9CnRhdT10YXUvKDUqNCkKdGF1CmNvcih4LHksIG1ldGhvZD0ia2VuZGFsbCIpCmBgYAoKIyBTdGFuZGFyZGl6YXRpb24gb2YgdmFyaWFibGVzIAoqIFZhcmlhYmxlcyBhcmUgb2Z0ZW4gc3RhbmRhcmRpemVkIGJlZm9yZSBtZWFzdXJpbmcgZGlzc2ltaWxhcml0aWVzLgoqIFN0YW5kYXJkaXphdGlvbiBjb252ZXJ0cyB0aGUgb3JpZ2luYWwgdmFyaWFibGVzIGludG8gdW5pdGVsZXNzIHZhcmlhYmxlcy4KKiBBIHdlbGwga25vd24gbWV0aG9kIGlzIHRoZSB6LXNjb3JlIHRyYW5zZm9ybWF0aW9uOiAKJCQKXG1hdGhiZnt4fVxyaWdodGFycm93IChcZnJhY3t4XzEtXGJhcntcbWF0aGJme3h9fX17c19cbWF0aGJme3h9fSxcY2RvdHMsXGZyYWN7eF9uLVxiYXJ7XG1hdGhiZnt4fX19e3NfXG1hdGhiZnt4fX0pLAokJCAKd2hlcmUgJHNfXG1hdGhiZnt4fSQgaXMgdGhlIHNhbXBsZSBzdGFuZGFyZCBkZXZpYXRpb24gZ2l2ZW4gYnk6CiQkCnNfXG1hdGhiZnt4fT1cZnJhY3sxfXtuLTF9XHN1bV97aT0xfV5uKHhfaS1cYmFye1xtYXRoYmZ7eH19KV4yLgokJCAKCiogVGhlIHRyYW5zZm9ybWVkIHZhcmlhYmxlIHdpbGwgaGF2ZSBhIG1lYW4gb2YgJDAkIGFuZCBhIHZhcmlhbmNlIG9mICQxJC4KKiBUaGUgcmVzdWx0IG9idGFpbmVkIHdpdGggUGVhcnNvbiBjb3JyZWxhdGlvbiBtZWFzdXJlcyBhbmQgc3RhbmRhcmRpemVkIEV1Y2xpZGVhbiBkaXN0YW5jZXMgYXJlIGNvbXBhcmFibGUuCiogRm9yIG90aGVyIG1ldGhvZHMsIHNlZTogTWlsbGlnYW4sIEcuIFcuLCAmIENvb3BlciwgTS4gQy4gKDE5ODgpLiBBIHN0dWR5IG9mIHN0YW5kYXJkaXphdGlvbiBvZiB2YXJpYWJsZXMgaW4gY2x1c3RlciBhbmFseXNpcy4gX0pvdXJuYWwgb2YgY2xhc3NpZmljYXRpb25fLCBfNV8oMiksIDE4MS0yMDQuCgpgYGB7cn0KeD1jKDMsIDEsIDQsIDE1LCA5MikKeT1jKDMwLDIgLCA5LCAyMCwgNDgpCih4LW1lYW4oeCkpL3NkKHgpCnNjYWxlKHgpCih5LW1lYW4oeSkpL3NkKHkpCnNjYWxlKHkpCmBgYAoKIyBEaXN0YW5jZSBtYXRyaXggY29tcHV0YXRpb24KKiBXZeKAmWxsIHVzZSBhIHN1YnNldCBvZiB0aGUgZGF0YSBVU0FycmVzdHMKKiAgV2XigJlsbCB1c2Ugb25seSBhIGJ5IHRha2luZyAxNSByYW5kb20gcm93cyBhbW9uZyB0aGUgNTAgcm93cyBpbiB0aGUgZGF0YSBzZXQuIAoqIE5leHQsIHdlIHN0YW5kYXJkaXplIHRoZSBkYXRhIHVzaW5nIHRoZSBmdW5jdGlvbiBzY2FsZSgpOgojIERhdGEKCmBgYHtyfQppbnN0YWxsLnBhY2thZ2VzKCJGYWN0b01pbmVSIikKbGlicmFyeSgiRmFjdG9NaW5lUiIpCmRhdGEoIlVTQXJyZXN0cyIpICMgTG9hZGluZwpoZWFkKFVTQXJyZXN0cywgMykgIyBQcmludCB0aGUgZmlyc3QgMyByb3dzCnNldC5zZWVkKDEyMykKc3MgPC0gc2FtcGxlKDE6NTAsIDE1KSAjIFRha2UgMTUgcmFuZG9tIHJvd3MKZGYgPC0gVVNBcnJlc3RzW3NzLCBdICMgU3Vic2V0IHRoZSAxNSByb3dzCmRmLnNjYWxlZCA8LSBzY2FsZShkZikgIyBTdGFuZGFyZGl6ZSB0aGUgdmFyaWFibGVzCmBgYAoKCgoKCjwhLS1zdGFja2VkaXRfZGF0YToKZXlKb2FYTjBiM0o1SWpwYk1USTVORE00TnpRNU1sMTkKLS0+