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
CgoKLS0tCnRpdGxlOiAiRGlzdGFuY2UgYW5kIGRpc3NpbWlsYXJpdGllcyIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgcGRmX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1UUlVFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmBgYAoKCiMgRGVmaW5pdGlvbiBvZiBhIGRpc3RhbmNlCgoqIEEgZGlzdGFuY2UgZnVuY3Rpb24gb3IgbWV0cmljIG9uIHRoZSBzcGFjZSAkXG1hdGhiYntSfV5uLFw6blxnZXEgMSQsIGlzIGEgZnVuY3Rpb24gJGQ6XG1hdGhiYntSfV5uXHRpbWVzXG1hdGhiYntSfV5uXHJpZ2h0YXJyb3cgXG1hdGhiYntSfSQuCiogQSBkaXN0YW5jZSBmdW5jdGlvbiBtdXN0IHNhdGlzZnkgc29tZSByZXF1aXJlZCBwcm9wZXJ0aWVzIG9yIGF4aW9tcy4gCiogVGhlcmUgYXJlIHRocmVlIG1haW4gYXhpb21zLgoKKiBBMS4gJGQoXG1hdGhiZnt4fSxcbWF0aGJme3l9KT0gMFxpZmYgXG1hdGhiZnt4fT1cbWF0aGJme3l9JCAoaWRlbnRpdHkgb2YgaW5kaXNjZXJuaWJsZXMpOwoKKiBBMi4gJGQoXG1hdGhiZnt4fSxcbWF0aGJme3l9KT0gZChcbWF0aGJme3l9LFxtYXRoYmZ7eH0pJCAoc3ltbWV0cnkpOwoKKiBBMy4gJGQoXG1hdGhiZnt4fSxcbWF0aGJme3p9KVxsZXEgZChcbWF0aGJme3h9LFxtYXRoYmZ7eX0pK2QoXG1hdGhiZnt5fSxcbWF0aGJme3p9KSQgICh0cmlhbmdsZSBpbmVxdWFsaXR5KSwKd2hlcmUgJFxtYXRoYmZ7eH09KHhfMSxcY2RvdHMseF9uKSQsICRcbWF0aGJme3l9PSh5XzEsXGNkb3RzLHlfbikkIGFuZCAkXG1hdGhiZnt6fT0oel8xLFxjZG90cyx6X24pJCBhcmUgYWxsIHZlY3RvcnMgb2YgJFxtYXRoYmJ7Un1ebiQuCiogV2Ugc2hvdWxkIHVzZSB0aGUgdGVybSBfZGlzc2ltaWxhcml0eV8gcmF0aGVyIHRoYW4gX2Rpc3RhbmNlXyB3aGVuIG5vdCBhbGwgdGhlIHRocmVlIGF4aW9tcyBBMS1BMyBhcmUgdmFsaWQuCiogTW9zdCBvZiB0aGUgdGltZSwgd2Ugc2hhbGwgdXNlLCB3aXRoIHNvbWUgYWJ1c2Ugb2Ygdm9jYWJ1bGFyeSwgdGhlIHRlcm0gZGlzdGFuY2UuCgojIEV4ZXJjaWNlIDEKCiogUHJvdmUgdGhhdCB0aGUgdGhyZWUgYXhpb21zIEExLUEzIGltcGx5IHRoZSBub24tbmVnYXRpdml0eSBjb25kaXRpb246ICQkZChcbWF0aGJme3h9LFxtYXRoYmZ7eX0pXGdlcSAwLiQkCgoKIyBFdWNsaWRlYW4gZGlzdGFuY2UKCgoqIEl0IGlzIGRlZmluZWQgYnk6CgokJGQoXG1hdGhiZnt4fSxcbWF0aGJme3l9KT1cc3FydHtcc3VtX3tpPTF9Xm4gKHhfaS15X2kpXjJ9LiQkCiogQTEgYW5kIEEyIGFyZSBvbmJ2aW91cy4gVGhlIHByb29mIG9mIEEzIGlzIHByb3ZpZGVkIGJlbG93LgoKCiMgTWFuaGF0dGFuIGRpc3RhbmNlCgoqIFRoZSBNYW5oYXR0YW4gZGlzdGFuY2UgYWxzbyBjYWxsZWQgIHRheGktY2FiIG1ldHJpYyBvciBjaXR5LWJsb2NrIG1ldHJpYyBpcyBkZWZpbmVkIGJ5OgoKJCRkKFxtYXRoYmZ7eH0sXG1hdGhiZnt5fSkKPVxzdW1fe2k9MX1ebiB8eF9pLXlfaXwuCiQkCgoqIEExIGFuZCBBMiBob2xkLgoqIEEzIGlzIGFsc28gaG9sZCB1c2luZyB0aGUgZmFjdCB0aGF0ICR8YStifFxsZXEgfGF8K3xifCQgZm9yIGFueSByZWFscyAkYSxiJC4KKiBUaGVyZSBleGlzdHMgYWxzbyBhICB3ZWlnaHRlZCB2ZXJzaW9uICBvZiB0aGUgYWJvdmUgZGlzdGFuY2UgY2FsbGVkIHRoZSBDYW5iZXJyYSBkaXN0YW5jZS4KCltNYW5oYXR0YW4gZGlzdGFuY2UgdnMgRXVjbGlkZWFuIGRpc3RhbmNlIEdyYXBoXShodHRwczovL3VwbG9hZC53aWtpbWVkaWEub3JnL3dpa2lwZWRpYS9jb21tb25zLzAvMDgvTWFuaGF0dGFuX2Rpc3RhbmNlLnN2ZykKCmBgYHtyfQp4ID0gYygwLCAwKQp5ID0gYyg2LDYpCmRpc3QocmJpbmQoeCwgeSksIG1ldGhvZCA9ICJldWNsaWRpYW4iKQo2KnNxcnQoMikKZGlzdChyYmluZCh4LCB5KSwgbWV0aG9kID0gIm1hbmhhdHRhbiIpCmBgYAoKCiMgQ2FuYmVycmEgZGlzdGFuY2UKCiogSXQgaXMgZGVmaW5lZCBieToKCiQkZChcbWF0aGJme3h9LFxtYXRoYmZ7eX0pCj1cc3VtX3tpPTF9Xm4gXGZyYWN7fHhfaS15X2l8fXt8eF9pfCt8eV9pfH0uJCQKCiogTm90ZSB0aGF0IHRoZSB0ZXJtICR8eF9pIOKIkiB5X2l8Lyh8eF9pfCt8eV9pfCkkIGlzIG5vdCBwcm9wZXJseSBkZWZpbmVkIHdoZW4gYm90aCAkeF9pJCBhbmQgJHlfaSQgYXJlIHplcm8uCiogQnkgY29udmVudGlvbiB3ZSBzZXQgdGhlIHJhdGlvIHRvIGJlIHplcm8gaW4gdGhhdCBjYXNlLgoqIFRoZSBDYW5iZXJyYSBkaXN0YW5jZSBpcyBzcGVjaWFsbHkgc2Vuc2l0aXZlIHRvIHNtYWxsIGNoYW5nZXMgbmVhciB6ZXJvLgoKYGBge3J9CnggPSBjKDAsIDApCnkgPSBjKDYsNikKZGlzdChyYmluZCh4LCB5KSwgbWV0aG9kID0gImNhbmJlcnJhIikKNi82KzYvNgpgYGAKCgojIEV4ZXJjaWNlIDIKCiogUHJvdmUgdGhhdCB0aGUgQ2FuYmVycmEgZGlzdGFuY2UgaXMgYSB0cnVlIGRpc3RhbmNlLgoKIyBNaW5rb3dza2kgZGlzdGFuY2UKCiogQm90aCB0aGUgRXVjbGlkaWFuIGFuZCB0aGUgTWFuYXR0YW4gZGlzdGFuY2VzIGFyZSBzcGVjaWFsIGNhc2VzIG9mICB0aGUgTWlua293c2tpIGRpc3RhbmNlIHdoaWNoIGlzIGRlZmluZWQsIGZvciAkcFxnZXEgMSQsIGJ5OiAKCiQkCmQoXG1hdGhiZnt4fSxcbWF0aGJme3l9KT0KXGxlZnRbXHN1bV97aT0xfSB8eF9pLXlfaXxee3B9XHJpZ2h0XV57MS9wfS4KJCQKICogRm9yICRwPTEkLCB3ZSBnZXQgdGhlIE1hbmhhdHRhbiBkaXN0YW5jZS4KICogRm9yICRwPTIkLCB3ZSBnZXQgdGhlIEV1Y2xpZGlhbiBkaXRhbmNlLgoKCiogTGV0IHVzIGRlZmluZTogCiQkXHxcbWF0aGJme3h9XHxfcFxlcXVpdlxsZWZ0W1xzdW1fe2k9MX1ebiB8eF9pfF57cH1ccmlnaHRdXnsxL3B9LCQkCndoZXJlICRcfFxtYXRoYmZ7XGNkb3R9XHxfcCQgaXMga25vd24gYXMgdGhlICRwJC1ub3JtIG9yIE1pbmtvd3NraSBub3JtLgoKKiBOb3RlIHRoYXQgdGhlIE1pbmtvd3NraSBkaXN0YW5jZSBhbmQgbm9ybSBhcmUgcmVsYXRlZCBieToKJCQKZChcbWF0aGJme3h9LFxtYXRoYmZ7eX0pPVx8XG1hdGhiZnt4fS1cbWF0aGJme3l9XHxfcCwKJCQKb3IgY29udmVyc2VseSBieQokJApcfFxtYXRoYmZ7eH1cfF9wPWQoXG1hdGhiZnt4fSxcbWF0aGJmezB9KSwKJCQKd2hlcmUgJFxtYXRoYmZ7MH0kIGlzIHRoZSBudWxsLXZldG9yIG9mICRcbWF0aGJie1J9Xm4kLgoKIyBDaGVieXNoZXYgZGlzdGFuY2UgCgoqIEF0IHRoZSBsaW1pdCwgd2UgZ2V0IHRoZSBDaGVieXNoZXYgZGlzdGFuY2UgZGVmaW5lZCBieToKCiQkCmQoXG1hdGhiZnt4fSxcbWF0aGJme3l9KT1cbWF4X3tpPTEsXGNkb3RzLG59KHx4X2kteV9pfCk9XGxpbV97cFxyaWdodGFycm93XGluZnR5fQpcbGVmdFtcc3VtX3tpPTF9IHx4X2kteV9pfF57cH1ccmlnaHRdXnsxL3B9LgokJAoKKiBUaGUgY29ycmVzcG9uZGluZyBub3JtIGlzOgokJApcfFxtYXRoYmZ7eH18X1xpbmZ0eT1cbWF4X3tpPTEsXGNkb3RzLG59KHx4X2l8KS4KJCQKCiMgTWlua293c2tpIGluZXF1YWxpdHkKCiogVGhlIHByb29mIG9mIHRoZSB0cmlhbmd1bGFyIGluZXF1YWxpdHkgUDMgaXMgYmFzZWQgb24gdGhlIE1pbmtvd3NraSBpbmVxdWFsaXR5LiAKKiBGb3IgYW55IG5vbm5lZ2F0aXZlIHJlYWwgbnVtYmVycyAkYV8xLFxjZG90cyxhX24kOyAkYl8xLFxjZG90cyxiX24kLCBhbmQgZm9yICRwXGdlcSAxJCwgd2UgaGF2ZToKCiQkClxsZWZ0W1xzdW1fe2k9MX1ebiAoYV9pK2JfaSlee3B9XHJpZ2h0XV57MS9wfVxsZXEKXGxlZnRbXHN1bV97aT0xfV5uIGFfaV57cH1ccmlnaHRdXnsxL3B9CisKXGxlZnRbXHN1bV97aT0xfV5uIGJfaV57cH1ccmlnaHRdXnsxL3B9LgokJAoKKiBUbyBwcm92ZSB0aGF0IHRoZSBNaW5rb3dza2kgZGlzdGFuY2Ugc2F0aXNmaWVzIFAzLCBub3RpY2UgdGhhdCAKCiQkCiBcc3VtX3tpPTF9Xm58eF9pLXpfaXxee3B9PSBcc3VtX3tpPTF9Xm58KHhfaS15X2kpKyh5X2ktel9pKXxee3B9LgokJAoqIFNpbmNlIGZvciBhbnkgcmVhbHMgJHgseSQsIHdlIGhhdmUgJHx4K3l8XGxlcSB8eHwrfHl8JCwgYW5kIHVzaW5nIHRoZSBmYWN0IHRoYXQgJHhecCQgaXMgaW5jcmVhc2luZyBpbiAkeD4wJCwgd2Ugb2J0YWluOgokJAogXHN1bV97aT0xfV5ufHhfaS16X2l8XntwfVxsZXEgXHN1bV97aT0xfV5uKHx4X2kteV9pfCt8eV9pLXpfaXwpXntwfS4KJCQKCiogQXBwbHlpbmcgdGhlIE1pbmtvd3NraSBpbmVxdWFsaXR5IHdpdGggJGFfaT18eF9pLXlfaXwkIGFuZCAkYl9pPXx5X2ktel9pfCQsICRpPTEsXGNkb3RzLG4kLCB3ZSBnZXQ6CiQkCiBcc3VtX3tpPTF9Xm58eF9pLXpfaXxee3B9XGxlcSBcbGVmdChcc3VtX3tpPTF9Xm4gfHhfaS15X2l8XntwfVxyaWdodCleezEvcH0rXGxlZnQoXHN1bV97aT0xfV5uIHx5X2ktel9pfF57cH1ccmlnaHQpXnsxL3B9LgokJAoKCiMgSMO2bGRlciBpbmVxdWFsaXR5CgoqIFRoZSBwcm9vZiBvZiB0aGUgTWlua293c2tpIGluZXF1YWxpdHkgaXRzZWxmIHJlcXVpcmVzIHRoZSBIw7ZsZGVyIGluZXF1YWxpdHkuCiogSXQgc3RhdAoqIEZvciBhbnkgbm9ubmVnYXRpdmUgcmVhbCBudW1iZXJzICRhXzEsXGNkb3RzLGFfbiQ7ICRiXzEsXGNkb3RzLGJfbiQsIGFuZCBhbnkgJHAscT4xJCB3aXRoICQxL3ArMS9xPTEkLCB3ZSBoYXZlCgokJApcc3VtX3tpPTF9Xm4gYV9pYl9pXGxlcQpcbGVmdFtcc3VtX3tpPTF9Xm4gYV9pXntwfVxyaWdodF1eezEvcH0KXGxlZnRbXHN1bV97aT0xfV5uIGJfaV57cX1ccmlnaHRdXnsxL3F9CiQkCiogVGhlIHByb29mIG9mIHRoZSBIw7ZsZGVyIGluZXF1YWxpdHkgcmVsaWVzIG9uIHRoZSBZb3VuZyBpbmVxdWFsaXR5LgoqIEZvciBhbnkgJGEsYj4wJCwgd2UgaGF2ZQokJAphYlxsZXEgXGZyYWN7YV5wfXtwfStcZnJhY3tiXnF9e3F9LAokJAp3aXRoIGVxdWFsaXR5IG9jY3VyaW5nIGlmZjogJGFecD1iXnEkLiAKKiBUbyBwcm92ZSB0aGUgWW91bmcgaW5lcXVhbGl0eSwgb25lIGNhbiB1c2UgdGhlIChzdHJpY3QpIGNvbnZleGl0eSBvZiB0aGUgZXhwb25lbnRpYWwgZnVuY3Rpb24uCiogRm9yIGFueSByZWFscyAkeCx5JCwgdGhlbiAKJCQKZV57XGZyYWN7eH17cH0rXGZyYWN7eX17cX0gfVxsZXEgXGZyYWN7ZV57eH19e3B9K1xmcmFje2Vee3l9fXtxfS4gCiQkCiogV2UgdGhlbiBzZXQgJHg9cFxsbiBhJCBhbmQgJHk9cVxsbiBiJCB0byBnZXQgdGhlIFlvdW5nIGluZXF1YWxpdHkuCiogQSBnb29kIHJlZmVyZW5jZSBvbiB0aGUgaW5lcXVhbGl0aWVzIHRvcGljIGlzOiBaLiBDdmV0a292c2tpLCAgSW5lcXVhbGl0aWVzOiB0aGVvcmVtcywgdGVjaG5pcXVlcyBhbmQgc2VsZWN0ZWQgcHJvYmxlbXMsIDIwMTIsIFNwcmluZ2VyIFNjaWVuY2UgJiBCdXNpbmVzcyBNZWRpYS4KICMgQ2F1Y2h5LVNjaHdhcnR6IGluZXF1YWxpdHkKKiBOb3RlIHRoYXQgdGhlIHRyaWFuZ3VsYXIgaW5lcXVhbGl0eSBmb3IgdGhlIE1pbmtvd3NraSBkaXN0YW5jZSBpbXBsaWVzIAoKJCQKXHN1bV97aT0xfV5uIHx4X2l8XGxlcQpcbGVmdFtcc3VtX3tpPTF9Xm4gfHhfaXxee3B9XHJpZ2h0XV57MS9wfS4KJCQKKiBOb3RlIHRoYXQgZm9yICRwPTIkLCB3ZSBoYXZlICRxPTIkLiBUaGUgSMO2bGRlciBpbmVxdWFsaXR5IGltcGxpZXMgZm9yIHRoYXQgc3BlY2lhbCBjYXNlCiQkClxzdW1fe2k9MX1ebnx4X2l5X2l8XGxlcVxzcXJ0e1xzdW1fe2k9MX1ebiB4X2leMn1cc3FydHtcc3VtX3tpPTF9Xm4geV9pXjJ9LiAKJCQKKiBTaW5jZSB0aGUgTEhTIG9kIHRoZXMgYWJvdmUgaW5lcXVhbGl0eSBpcyBncmVhdGVyIHRoZW4gJHxcc3VtX3tpPTF9Xm54X2l5X2l8JCwgd2UgZ2V0IHRoZSBDYXVjaHktU2Nod2FydHogaW5lcXVhbGl0eQoKJCQKfFxzdW1fe2k9MX1ebnhfaXlfaXxcbGVxXHNxcnR7XHN1bV97aT0xfV5uIHhfaV4yfVxzcXJ0e1xzdW1fe2k9MX1ebiB5X2leMn0uIAokJAoqIFVzaW5nIHRoZSBkb3QgcHJvZHVjdCBub3RhdGlvbiBjYWxsZWQgYWxzbyBzY2FsYXIgcHJvZHVjdCBub2F0aW9uICRcbWF0aGJme3hcY2RvdCB5fT1cc3VtX3tpPTF9Xm54X2l5X2kkLCBhbmQgdGhlIG5vcm0gbm90YXRpb24gJFx8XG1hdGhiZntcY2RvdH1cfF8yIFx8JCwgdGhlIENhdWNoeS1TY2h3YXJ0IGluZXF1YWxpdHkgaXM6CgokJHxcbWF0aGJme3hcY2RvdCB5fSB8IFxsZXEgXHxcbWF0aGJme3h9XHxfMiBcfCBcbWF0aGJme3l9XHxfMi4kJAoKIyBQZWFyc29uIGNvcnJlbGF0aW9uIGRpc3RhbmNlIAoKKiBUaGUgUGVhcnNvbiBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBpcyBhIHNpbWlsYXJpdHkgbWVhc3VyZSBvbiAkXG1hdGhiYntSfV5uJCBkZWZpbmVkIGJ5OgokJApccmhvKFxtYXRoYmZ7eH0sXG1hdGhiZnt5fSk9ClxmcmFje1xzdW1fe2k9MX1ebiAoeF9pLVxiYXJ7XG1hdGhiZnt4fX0pKHlfaS1cYmFye1xtYXRoYmZ7eX19KX17e1xzcXJ0e1xzdW1fe2k9MX1ebiAoeF9pLVxiYXJ7XG1hdGhiZnt4fX0pXjJcc3VtX3tpPTF9Xm4gKHlfaS1cYmFye1xtYXRoYmZ7eX19KV4yfX19LAokJAp3aGVyZSAkXGJhcntcbWF0aGJme3h9fSQgaXMgdGhlIG1lYW4gb2YgdGhlIHZlY3RvciAkXG1hdGhiZnt4fSQgZGVmaW5lZCBieTogCiQkXGJhcntcbWF0aGJme3h9fT1cZnJhY3sxfXtufVxzdW1fe2k9MX1ebiB4X2ksJCQKKiBOb3RlIHRoYXQgdGhlIFBlYXJzb24gY29ycmVsYXRpb24gY29lZmZpY2llbnQgc2F0aXNmaWVzIFAyIGFuZCAgaXMgaW52YXJpYW50IHRvIGFueSBwb3NpdGl2ZSBsaW5lYXIgdHJhbnNmb3JtYXRpb24sIGkuZS46ICQkXHJobyhcYWxwaGFcbWF0aGJme3h9LFxtYXRoYmZ7eX0pPVxyaG8oXG1hdGhiZnt4fSxcbWF0aGJme3l9KSwkJCBmb3IgYW55ICRcYWxwaGE+MCQuCiogVGhlIFBlYXJzb24gZGlzdGFuY2UgKG9yIGNvcnJlbGF0aW9uIGRpc3RhbmNlKSBpcyBkZWZpbmVkIGJ5OgokJApkKFxtYXRoYmZ7eH0sXG1hdGhiZnt5fSk9MS1ccmhvKFxtYXRoYmZ7eH0sXG1hdGhiZnt5fSkuJCQKCiogTm90ZSB0aGF0IHRoZSBQZWFyc29uIGRpc3RhbmNlIGRvZXMgbm90IHNhdGlzZnkgQTEgc2luY2UgJGQoXG1hdGhiZnt4fSxcbWF0aGJme3h9KT0wJCBmb3IgYW55IG5vbi16ZXJvIHZlY3RvciAkXG1hdGhiZnt4fSQuIEl0IG5laXRoZXIgc2F0aXNmaWVzIHRoZSB0cmlhbmdsZSBpbmVxdWFsaXR5LiBIb3dldmVyLCB0aGUgc3ltbWV0cnkgcHJvcGVydHkgaXMgZnVsbGZpbGxlZC4gCgojIENvc2luZSBjb3JyZWxhdGlvbiBkaXN0YW5jZQoKKiBUaGUgY29zaW5lIG9mIHRoZSBhbmdsZSAkXHRoZXRhJCBiZXR3ZWVuIHR3byB2ZWN0b3JzICRcbWF0aGJme3h9JCBhbmQgJFxtYXRoYmZ7eX0kIGlzIGEgbWVhc3VyZSBvZiBzaW1pbGFyaXR5IGdpdmVuIGJ5OgokJApcY29zKFx0aGV0YSk9XGZyYWN7XG1hdGhiZnt4fVxjZG90IFxtYXRoYmZ7eX19e1x8XG1hdGhiZnt4fVx8XzJcfFxtYXRoYmZ7eX1cfF8yfT1cZnJhY3tcc3VtX3tpPTF9Xm4geF9pIHlfaX17e1xzcXJ0e1xzdW1fe2k9MX1ebiB4X2leMlxzdW1fe2k9MX1ebiB5X2leMn19fS4KJCQKKiBOb3RlIHRoYXQgdGhlIGNvc2luZSBvZiB0aGUgYW5nbGUgYmV0d2VlbiB0aGUgdHdvIGNlbnRyZWQgdmVjdG9ycyAkKHhfMS1cYmFye1xtYXRoYmZ7eH19LFxjZG90cyx4X24tXGJhcntcbWF0aGJme3h9fSkkIGFuZCAkKHlfMS1cYmFye1xtYXRoYmZ7eX19LFxjZG90cyx5X24tXGJhcntcbWF0aGJme3l9fSkkIGNvaW5jaWRlcyB3aXRoIHRoZSBQZWFyc29uIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IG9mICRcbWF0aGJme3h9JCBhbmQgJFxtYXRoYmZ7eX0kLiAgCgoqIFRoZSBjb3NpbmUgY29ycmVsYXRpb24gZGlzdGFuY2UgaXMgZGVmaW5lZCBieToKJCQKZChcbWF0aGJme3h9LFxtYXRoYmZ7eX0pPTEtXGNvcyhcdGhldGEpLgokJAoqIEl0IHNoYXJlcyBzaW1pbGFyIHByb3BlcnRpZXMgdGhhbiB0aGUgUGVhcnNvbiBjb3JyZWxhdGlvbiBkaXN0YW5jZS4gTGlrZXdpc2UsIEF4aW9tcyBQMSBhbmQgUDMgYXJlIG5vdCBzYXRpc2ZpZWQuCgojIFNwZWFybWFuIGNvcnJlbGF0aW9uIGRpc3RhbmNlIAoKKiBUbyBjYWxjdWxhdGUgdGhlIFNwZWFybWFuJ3MgcmFuay1vcmRlciBjb3JyZWxhdGlvbiBvciBTcGVhcm1hbidzIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IGZvciBzaG9ydCwgd2UgbmVlZCB0byBtYXAgc2VwZXJhdGVseSBlYWNoIG9mIHRoZSB2ZWN0b3JzIHRvIHJhbmtlZCBkYXRhIHZhbHVlczogJFxtYXRoYmZ7eH1ccmlnaHRhcnJvdyBcbWF0aGJme3h9XnI9KHhfMV5yLFxjZG90cyx4X25ecikkLiBIZXJlLCAkeF9pXnIkIGlzIHRoZSByYW5rIG9mICR4X2kkIGFtb25nIHRoZSBzZXQgb2YgdmFsdWVzIG9mICRcbWF0aGJme3h9JC4KKiBXZSBpbGx1c3RyYXRlIHRoaXMgdHJhbnNmb3JtYXRpb24gd2l0aCBhIHNpbXBsZSBleGFtcGxlLiBJZiAkXG1hdGhiZnt4fT0oMywgMSwgNCwgMTUsIDkyKSQsIHRoZW4gdGhlIHJhbmstb3JkZXIgdmVjdG9yIGlzICRcbWF0aGJme3h9XnI9KDIsMSwzLDQsNSkkLiAgCgoKYGBge3J9Cng9YygzLCAxLCA0LCAxNSwgOTIpCnhyPXJhbmsoeCkKeHIKYGBgCgoqIFRoZSBTcGVhcm1hbidzIHJhbmsgY29ycmVsYXRpb24gb2YgdHdvIG51bWVyaWNhbCB2YXJpYWJsZXMgJFxtYXRoYmZ7eH0kICBhbmQgJFxtYXRoYmZ7eX0kIGlzIHNpbXBseSB0aGUgUGVhcnNvbiBjb3JyZWxhdGlvbiBvZiB0aGUgdHdvIGNvcnJlc3BuZGluZyByYW5rLW9lcmRlciB2YXJpYWJsZXMgJFxtYXRoYmZ7eH1eciQgYW5kICRcbWF0aGJme3l9XnIkLCBpLmUuICRccmhvKFxtYXRoYmZ7eH1ecixcbWF0aGJme3l9XnIpJC4gVGhpcyBtZWFzdXJlIGlzIGlzIHVzZWZ1bCBiZWNhdXNlIGl0IGlzIG1vcmUgcm9idXN0IGFnYWluc3Qgb3V0bGllcnMgdGhhbiB0aGUgUGVhcnNvbiBjb3JyZWxhdGlvbi4KKiBJZiBhbGwgIHRoZSAkbiQgIHJhbmtzIGFyZSBkaXN0aW5jdCwgaXQgY2FuIGJlIGNvbXB1dGVkIHVzaW5nIHRoZSBmb2xsb3dpbmcgZm9ybXVsYToKJCQKXHJobyhcbWF0aGJme3h9XnIsXG1hdGhiZnt5fV5yKT0xLVxmcmFjezZcc3VtX3tpPTF9Xm4gZF9pXjJ9e24obl4yLTEpfSwKJCQKd2hlcmUgJGRfaT14X2leci15X2lecixcOmk9MSxcY2RvdHMsbiQuCiAqIFRoZSBzcGVhcm1hbiBkaXN0YW5jZSBpcyB0aGVuIGRlZmluZWQgYnk6CiQkCmQoXG1hdGhiZnt4fSxcbWF0aGJme3l9KT0xLVxyaG8oXG1hdGhiZnt4XnJ9LFxtYXRoYmZ7eV5yfSkuCiQkCiogSXQgY2FuIGJlIHNob3duIHRoYXQgZWFzYWx5IHRoYXQgaXQgaXMgbm90IGEgcHJvcGVyIGRpc3RhbmNlLgoKKiBJZiBhbGwgIHRoZSAkbiQgIHJhbmtzIGFyZSBkaXN0aW5jdCwgd2UgZ2V0OgokJApkKFxtYXRoYmZ7eH0sXG1hdGhiZnt5fSk9XGZyYWN7NlxzdW1fe2k9MX1ebiBkX2leMn17bihuXjItMSl9LgokJAoKYGBge3J9Cng9YygzLCAxLCA0LCAxNSwgOTIpCnhyPXJhbmsoeCkKeT1jKDMwLDIgLCA5LCAyMCwgNDgpCnlyPXJhbmsoeSkKZD14ci15cgpkCmNvcih4cix5cikKMS02KnN1bShkXjIpLyg1Kig1XjItMSkpCmBgYAoKCiMgS2VuZGFsbCB0YXUgZGlzdGFuY2UgCgoqIFRoZSBLZW5kYWxsIHJhbmsgY29ycmVsYXRpb24gY29lZmZpY2llbnQgaXMgY2FsY3VsYXRlZCBmcm9tIHRoZSBudW1iZXIgb2YgY29ycmVzcG9uZGFuY2VzIGJldHdlZW4gdGhlIHJhbmtpbmdzIG9mICRcbWF0aGJme3h9JCBhbmQgdGhlIHJhbmtpbmdzIG9mICRcbWF0aGJme3l9JC4KKiAgIFRoZSBudW1iZXIgb2YgcGFpcnMgb2Ygb2JzZXJ2YXRpb25zIGFtb25nICRuJCBvYnNlcnZhdGlvbnMgb3IgdmFsdWVzIGlzOiAKJCR7biBcY2hvb3NlIDJ9ID1cZnJhY3tuKG4tMSl9ezJ9LiQkCgoqIFRoZSBwYWlycyBvZiBvYnNlcnZhdGlvbnMgJCh4X3tpfSx4X3tqfSkkICBhbmQgICQoeV97aX0seV97an0pJCBhcmUgc2FpZCB0byBiZSBfY29uY29yZGFudF8gaWY6ICQkXHRleHR7c2lnbn0oeF9qLXhfaSk9XHRleHR7c2lnbn0oeV9qLXlfaSksJCQgYW5kIHRvIGJlIF9kaXNjb3JkYW50XyBpZjogICQkXHRleHR7c2lnbn0oeF9qLXhfaSk9LVx0ZXh0e3NpZ259KHlfai15X2kpLCQkCndoZXJlICRcdGV4dHtzaWdufShcY2RvdCkkIHJldHVybnMgICQxJCBmb3IgcG9zaXRpdmUgbnVtYmVycyBhbmQgICQtMSQgbmVnYXRpdmUgbnVtYmVycyBhbmQgJDAkIG90aGVyd2lzZS4KKiBJZiAkeF9pPXhfaiQgb3IgJHlfaT15X2okIChvciBib3RoKSwgdGhlcmUgaXMgYSB0aWUuCiogVGhlIEtlbmRhbGwgJFx0YXUkIGNvZWZmaWNpZW50IGlzIGRlZmluZWQgYnkgKG5lZ2xlY3RpbmcgdGllcyk6CiQkXHRhdSA9XGZyYWMgezF9e24obi0xKX1cc3VtX3tpPTF9XntufVxzdW1fe2o9MX1eblx0ZXh0e3NpZ259KHhfai14X2kpXHRleHR7c2lnbn0oeV9qLXlfaSkuJCQKKiBMZXQgJG5fYyQgKHJlc3AuICRuX2QkKSBiZSB0aGUgbnVtYmVyIG9mIGNvbmNvcmRhbnQgKHJlc3AuIGRpc2NvcmRhbnQpIHBhaXJzLCB3ZSBoYXZlICQkXHRhdSA9XGZyYWMgezIobl9jLW5fZCl9e24obi0xKX0uJCQgCiogVGhlIEtlbmRhbGwgdGF1IGRpc3RhbmNlIGlzIHRoZW46ICQkZChcbWF0aGJme3h9LFxtYXRoYmZ7eX0pPTEtXHRhdS4gJCQKKiBSZW1hcms6IHRoZSB0cmlhbmd1bGFyIGluZXF1YWxpdHkgbWF5IGZhaWwgaW4gY2FzZXMgd2hlcmUgdGhlcmUgYXJlIHRpZXMuCgpgYGB7cn0KeD1jKDMsIDEsIDQsIDE1LCA5MikKeT1jKDMwLDIgLCA5LCAyMCwgNDgpCnRhdT0wCmZvciAoaSBpbiAxOjUpCnsgIAp0YXU9dGF1K3NpZ24oeCAteFtpXSklKiVzaWduKHkgLXlbaV0pCn0KdGF1PXRhdS8oNSo0KQp0YXUKY29yKHgseSwgbWV0aG9kPSJrZW5kYWxsIikKYGBgCgojIFN0YW5kYXJkaXphdGlvbiBvZiB2YXJpYWJsZXMgCiogVmFyaWFibGVzIGFyZSBvZnRlbiBzdGFuZGFyZGl6ZWQgYmVmb3JlIG1lYXN1cmluZyBkaXNzaW1pbGFyaXRpZXMuCiogU3RhbmRhcmRpemF0aW9uIGNvbnZlcnRzIHRoZSBvcmlnaW5hbCB2YXJpYWJsZXMgaW50byB1bml0ZWxlc3MgdmFyaWFibGVzLgoqIEEgd2VsbCBrbm93biBtZXRob2QgaXMgdGhlIHotc2NvcmUgdHJhbnNmb3JtYXRpb246IAokJApcbWF0aGJme3h9XHJpZ2h0YXJyb3cgKFxmcmFje3hfMS1cYmFye1xtYXRoYmZ7eH19fXtzX1xtYXRoYmZ7eH19LFxjZG90cyxcZnJhY3t4X24tXGJhcntcbWF0aGJme3h9fX17c19cbWF0aGJme3h9fSksCiQkIAp3aGVyZSAkc19cbWF0aGJme3h9JCBpcyB0aGUgc2FtcGxlIHN0YW5kYXJkIGRldmlhdGlvbiBnaXZlbiBieToKJCQKc19cbWF0aGJme3h9PVxmcmFjezF9e24tMX1cc3VtX3tpPTF9Xm4oeF9pLVxiYXJ7XG1hdGhiZnt4fX0pXjIuCiQkIAoKKiBUaGUgdHJhbnNmb3JtZWQgdmFyaWFibGUgd2lsbCBoYXZlIGEgbWVhbiBvZiAkMCQgYW5kIGEgdmFyaWFuY2Ugb2YgJDEkLgoqIFRoZSByZXN1bHQgb2J0YWluZWQgd2l0aCBQZWFyc29uIGNvcnJlbGF0aW9uIG1lYXN1cmVzIGFuZCBzdGFuZGFyZGl6ZWQgRXVjbGlkZWFuIGRpc3RhbmNlcyBhcmUgY29tcGFyYWJsZS4KKiBGb3Igb3RoZXIgbWV0aG9kcywgc2VlOiBNaWxsaWdhbiwgRy4gVy4sICYgQ29vcGVyLCBNLiBDLiAoMTk4OCkuIEEgc3R1ZHkgb2Ygc3RhbmRhcmRpemF0aW9uIG9mIHZhcmlhYmxlcyBpbiBjbHVzdGVyIGFuYWx5c2lzLiBfSm91cm5hbCBvZiBjbGFzc2lmaWNhdGlvbl8sIF81XygyKSwgMTgxLTIwNC4KCmBgYHtyfQp4PWMoMywgMSwgNCwgMTUsIDkyKQp5PWMoMzAsMiAsIDksIDIwLCA0OCkKKHgtbWVhbih4KSkvc2QoeCkKc2NhbGUoeCkKKHktbWVhbih5KSkvc2QoeSkKc2NhbGUoeSkKYGBgCgojIERpc3RhbmNlIG1hdHJpeCBjb21wdXRhdGlvbgoqIFdl4oCZbGwgdXNlIGEgc3Vic2V0IG9mIHRoZSBkYXRhIFVTQXJyZXN0cwoqICBXZeKAmWxsIHVzZSBvbmx5IGEgYnkgdGFraW5nIDE1IHJhbmRvbSByb3dzIGFtb25nIHRoZSA1MCByb3dzIGluIHRoZSBkYXRhIHNldC4gCiogTmV4dCwgd2Ugc3RhbmRhcmRpemUgdGhlIGRhdGEgdXNpbmcgdGhlIGZ1bmN0aW9uIHNjYWxlKCk6CiMgRGF0YQoKYGBge3J9Cmluc3RhbGwucGFja2FnZXMoIkZhY3RvTWluZVIiKQpsaWJyYXJ5KCJGYWN0b01pbmVSIikKZGF0YSgiVVNBcnJlc3RzIikgIyBMb2FkaW5nCmhlYWQoVVNBcnJlc3RzLCAzKSAjIFByaW50IHRoZSBmaXJzdCAzIHJvd3MKc2V0LnNlZWQoMTIzKQpzcyA8LSBzYW1wbGUoMTo1MCwgMTUpICMgVGFrZSAxNSByYW5kb20gcm93cwpkZiA8LSBVU0FycmVzdHNbc3MsIF0gIyBTdWJzZXQgdGhlIDE1IHJvd3MKZGYuc2NhbGVkIDwtIHNjYWxlKGRmKSAjIFN0YW5kYXJkaXplIHRoZSB2YXJpYWJsZXMKYGBgCgoKCgo=