We introduce the geometric interpretation of the svd by using a toy example.

1 Iris dataset

The iris dataset is a dataset on iris flowers.

  • Three species (setosa, virginica and versicolor)
  • Length and width of Sepal leafs
  • Length and width of Petal Leafs

For didactical purposes we will use a subset of the data.

  • Virginica Species
  • 3 Variables: Sepal Length, Sepal Width, Petal Length
  • This allows us to visualise the data in 3D plots
  • Illustrate the data compression of the SVD from 3 to two dimensions.

1.1 Subset the data

library(tidyverse)
library(plotly)
## 
## Attaching package: 'plotly'
## The following object is masked from 'package:imager':
## 
##     highlight
## The following object is masked from 'package:ggmap':
## 
##     wind
## The following object is masked from 'package:latex2exp':
## 
##     TeX
## The following object is masked from 'package:biomaRt':
## 
##     select
## The following objects are masked from 'package:plyr':
## 
##     arrange, mutate, rename, summarise
## The following object is masked from 'package:IRanges':
## 
##     slice
## The following object is masked from 'package:S4Vectors':
## 
##     rename
## The following object is masked from 'package:MASS':
## 
##     select
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:graphics':
## 
##     layout
irisSub <- iris %>%
  filter(Species == "virginica") %>%
  dplyr::select("Sepal.Length","Sepal.Width","Petal.Length")

1.2 Center the data

X <- irisSub %>% scale(scale=FALSE)

The data is translated to a mean of [0, 0, 0].

We zoom in and add the original axis in grey in the origin.

2 SVD

  1. We adopt the SVD on the centered data
irisSvd <- svd(X)
  1. We extract
  • the right singular vectors \(\mathbf{V}\) and
  • the projections \(\mathbf{Z}\)
V <- irisSvd$v  
Z <- irisSvd$u %*% diag(irisSvd$d)

Note, that

  • the SVD is essentially a rotation to a new coordinate system.
  • we plotted \(\mathbf{V}_3\) with dots because we will use the SVD for dimension reduction \[\text{3D} \rightarrow \text{2D}\]

Rotate the plot

  • Note, that

    • V1 points in the direction of the largest variability in the data
    • V2 points in a direction orthogal on V1 pointing in the direction of the second largest variability in the data.

3 Geometric Interpretation?

Write the truncated SVD as \[ \mathbf{X}_k = \mathbf{U}_k \boldsymbol{\Delta}_k \mathbf{V}_k^T = \mathbf{Z}_k \mathbf{V}_k^T \] with \[ \mathbf{Z}_k = \mathbf{U}_k \boldsymbol{\Delta}_k \] an \(n \times k\) matrix.

Each of the \(n\) rows of \(\mathbf{Z}_k\), say \(\mathbf{z}^T_{k,i}\), represents a point in a \(k\)-dimensional space.

V2 <- V[,1:2]
Z2 <- Z[,1:2]
X2 <- Z2 %*% t(V2)

Because of the orthonormality of the singular vectors, we also have \[\begin{eqnarray*} \mathbf{X}_k\mathbf{V}_k &=& \mathbf{Z}_k \mathbf{V}_k^T\mathbf{V}_k \\ \mathbf{X}_k\mathbf{V}_k &=& \mathbf{Z}_k. \end{eqnarray*}\]

Thus the matrix \(\mathbf{V}_k\) is a transformation matrix that may be used to transform \(\mathbf{X}_k\) into \(\mathbf{Z}_k\), and \(\mathbf{Z}_k\) into \(\mathbf{X}_k\).


More importantly, it can be shown that (thanks to orthonormality of \(\mathbf{V}\)) \[ \mathbf{X}\mathbf{V}_k = \mathbf{Z}_k. \]

This follows from (w.l.g. rank(\(\mathbf{X}\))=\(r\)) \[\begin{eqnarray*} \mathbf{X}\mathbf{V}_k &=& \mathbf{UDV}^T\mathbf{V}_k = \mathbf{UD}\begin{pmatrix} \mathbf{v}_1^T \\ \vdots \\ \mathbf{v}_r^T \end{pmatrix} \begin{pmatrix} \mathbf{v}_1 \ldots \mathbf{v}_k \end{pmatrix} \\ &=& \mathbf{UDV}^T\mathbf{V}_k = \mathbf{UD}\begin{pmatrix} 1 & 0 & \ldots & 0 \\ 0 & 1 & \ldots & 0 \\ \vdots & \vdots & \ddots & 0 \\ 0 & 0 & \ldots & 1 \\ 0 & 0 & \ldots & 0 \\ \vdots & \vdots & \vdots & \vdots \\ 0 & 0 & \ldots & 0 \end{pmatrix} \ = \mathbf{U}_k\boldsymbol{\Delta}_k = \mathbf{Z}_k \end{eqnarray*}\]

The \(p \times k\) matrix \(\mathbf{V}_k\) acts as a transformation matrix: transforming \(n\) points in a \(p\) dimensional space to \(n\) points in a \(k\) dimensional space.

Z2proj <- X %*% V2
range(Z2 - Z2proj)
## [1] -8.881784e-16  1.082467e-15

3.1 Projection of a single data point

  • Zoom in to see projection.
  • The projection is indicated for the blue point \(X_{44}\) to the red point \(X_{2,44}\) in the plane spaned by V2.

3.2 Projection of all datapoints: project all rows of X on V2

  • Zoom in first look orthonal via direction V2 (rotate until text V2 is viewed in the origin)
  • Zoom in first look orthonal via direction V1 (rotate until text V1 is viewed in the origin)
  • Note, that
    • V1 points in the direction of the largest variability in the data
    • V2 points in a direction orthogal on V1 pointing in the direction of the second largest variability in the data.
  • Projection only.
  • This clearly shows that the projected points X2 (X projected on V2) live in a two dimensional space
LS0tCnRpdGxlOiAiMi4zLiBTaW5ndWxhciBWYWx1ZSBEZWNvbXBvc2l0aW9uIC0gR2VvbWV0cmljIGludGVycHJldGF0aW9uIgphdXRob3I6ICJMaWV2ZW4gQ2xlbWVudCIKZGF0ZTogInN0YXRPbWljcywgR2hlbnQgVW5pdmVyc2l0eSAoaHR0cHM6Ly9zdGF0b21pY3MuZ2l0aHViLmlvKSIKb3V0cHV0OgogICAgaHRtbF9kb2N1bWVudDoKICAgICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgICB0aGVtZTogY29zbW8KICAgICAgdG9jOiB0cnVlCiAgICAgIHRvY19mbG9hdDogdHJ1ZQogICAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQotLS0KCjxpZnJhbWUgd2lkdGg9IjU2MCIgaGVpZ2h0PSIzMTUiIHNyYz0iaHR0cHM6Ly93d3cueW91dHViZS5jb20vZW1iZWQvc3JVREJ3UDlJVzgKIiBmcmFtZWJvcmRlcj0iMCIgc3R5bGU9ImRpc3BsYXk6IGJsb2NrOyBtYXJnaW46IGF1dG87IiBhbGxvdz0iYXV0b3BsYXk7IGVuY3J5cHRlZC1tZWRpYSIgYWxsb3dmdWxsc2NyZWVuPjwvaWZyYW1lPgoKV2UgaW50cm9kdWNlIHRoZSBnZW9tZXRyaWMgaW50ZXJwcmV0YXRpb24gb2YgdGhlIHN2ZCBieSB1c2luZyBhIHRveSBleGFtcGxlLgoKIyBJcmlzIGRhdGFzZXQKClRoZSBpcmlzIGRhdGFzZXQgaXMgYSBkYXRhc2V0IG9uIGlyaXMgZmxvd2Vycy4KCi0gVGhyZWUgc3BlY2llcyAoc2V0b3NhLCB2aXJnaW5pY2EgYW5kIHZlcnNpY29sb3IpCi0gTGVuZ3RoIGFuZCB3aWR0aCBvZiBTZXBhbCBsZWFmcwotIExlbmd0aCBhbmQgd2lkdGggb2YgUGV0YWwgTGVhZnMKCkZvciBkaWRhY3RpY2FsIHB1cnBvc2VzIHdlIHdpbGwgdXNlIGEgc3Vic2V0IG9mIHRoZSBkYXRhLgoKLSBWaXJnaW5pY2EgU3BlY2llcwotIDMgVmFyaWFibGVzOiBTZXBhbCBMZW5ndGgsIFNlcGFsIFdpZHRoLCBQZXRhbCBMZW5ndGgKLSBUaGlzIGFsbG93cyB1cyB0byB2aXN1YWxpc2UgdGhlIGRhdGEgaW4gM0QgcGxvdHMKLSBJbGx1c3RyYXRlIHRoZSBkYXRhIGNvbXByZXNzaW9uIG9mIHRoZSBTVkQgZnJvbSAzIHRvIHR3byBkaW1lbnNpb25zLgoKIyMgU3Vic2V0IHRoZSBkYXRhCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocGxvdGx5KQppcmlzU3ViIDwtIGlyaXMgJT4lCiAgZmlsdGVyKFNwZWNpZXMgPT0gInZpcmdpbmljYSIpICU+JQogIGRwbHlyOjpzZWxlY3QoIlNlcGFsLkxlbmd0aCIsIlNlcGFsLldpZHRoIiwiUGV0YWwuTGVuZ3RoIikKYGBgCgpgYGB7ciBlY2hvPUZBTFNFfQpwMSA8LSBwbG90X2x5KAogICAgaXJpc1N1YiwKICAgIHggPSB+U2VwYWwuV2lkdGgsCiAgICB5ID0gflNlcGFsLkxlbmd0aCwKICAgIHo9IH5QZXRhbC5MZW5ndGgpICU+JQogIGFkZF9tYXJrZXJzKHR5cGU9InNjYXR0ZXIzZCIpICU+JQogIGxheW91dCgKICAgIHNjZW5lID0gbGlzdCgKICAgICAgYXNwZWN0bW9kZT0iY3ViZSIsCiAgICAgIHhheGlzID0gbGlzdChyYW5nZT1jKC0xLDEpKm1heChhYnMoaXJpc1N1YikpKSwgeWF4aXMgPSBsaXN0KHJhbmdlPWMoLTEsMSkqbWF4KGFicyhpcmlzU3ViKSkpLCB6YXhpcyA9IGxpc3QocmFuZ2U9YygtMSwxKSptYXgoYWJzKGlyaXNTdWIpKSkKICAgICAgKQogICAgKQpwMQpgYGAKCiMjIENlbnRlciB0aGUgZGF0YQoKYGBge3J9ClggPC0gaXJpc1N1YiAlPiUgc2NhbGUoc2NhbGU9RkFMU0UpCmBgYAoKVGhlIGRhdGEgaXMgdHJhbnNsYXRlZCB0byBhIG1lYW4gb2YgWzAsIDAsIDBdLgoKYGBge3IgZWNobyA9IEZBTFNFfQpwMiA8LSBwbG90X2x5KFggJT4lIGFzLmRhdGEuZnJhbWUsIHggPSB+U2VwYWwuTGVuZ3RoLCB5ID0gflNlcGFsLldpZHRoLCB6PSB+UGV0YWwuTGVuZ3RoKSAlPiUKICBhZGRfbWFya2Vycyh0eXBlPSJzY2F0dGVyM2QiKSAlPiUKICBsYXlvdXQoICAKICAgIHNjZW5lID0gbGlzdCgKICAgICAgYXNwZWN0bW9kZT0iY3ViZSIsCiAgICAgIHhheGlzID0gIGxpc3QocmFuZ2U9YygtMSwxKSptYXgoYWJzKGlyaXNTdWIpKSksIHlheGlzID0gbGlzdChyYW5nZT1jKC0xLDEpKm1heChhYnMoaXJpc1N1YikpKSwgemF4aXMgPSBsaXN0KHJhbmdlPWMoLTEsMSkqbWF4KGFicyhpcmlzU3ViKSkpCiAgICAgICkKICAgICkKcDIKYGBgCgpXZSB6b29tIGluIGFuZCBhZGQgdGhlIG9yaWdpbmFsIGF4aXMgaW4gZ3JleSBpbiB0aGUgb3JpZ2luLgoKYGBge3IgZWNobz1GQUxTRX0KcDMgPC0gcGxvdF9seShYICU+JSBhcy5kYXRhLmZyYW1lLAogICAgeCA9IH5TZXBhbC5MZW5ndGgsCiAgICB5ID0gflNlcGFsLldpZHRoLAogICAgej0gflBldGFsLkxlbmd0aCkgJT4lCiAgbGF5b3V0KCAgCiAgICBzY2VuZSA9IGxpc3QoCiAgICAgIGFzcGVjdG1vZGU9ImN1YmUiLAogICAgICB4YXhpcyA9ICBsaXN0KHJhbmdlPWMoLTEsMSkqbWF4KGFicyhpcmlzU3ViKSkpLCB5YXhpcyA9IGxpc3QocmFuZ2U9YygtMSwxKSptYXgoYWJzKGlyaXNTdWIpKSksIHpheGlzID0gbGlzdChyYW5nZT1jKC0xLDEpKm1heChhYnMoaXJpc1N1YikpKQogICAgICApCiAgICApICU+JSBsYXlvdXQoICAKICAgIHNjZW5lID0gbGlzdChhc3BlY3Rtb2RlPSJjdWJlIiwKICAgIHhheGlzID0gbGlzdChyYW5nZT1jKC0xLDEpKm1heChhYnMoWCkpKSwKICAgIHlheGlzID0gbGlzdChyYW5nZT1jKC0xLDEpKm1heChhYnMoWCkpKSwKICAgIHpheGlzID0gbGlzdChyYW5nZT1jKC0xLDEpKm1heChhYnMoWCkpKSkpICU+JQogIGFkZF90cmFjZSgKICAgIHggPSBjKDAsMSksCiAgICB5ID0gYygwLDApLAogICAgeiA9IGMoMCwwKSwKICAgIG1vZGUgPSAibGluZXMiLAogICAgbGluZSA9IGxpc3Qod2lkdGggPSA1LCBjb2xvciA9ICJncmV5IiksCiAgICB0eXBlPSJzY2F0dGVyM2QiKSAlPiUKICBhZGRfdHJhY2UoCiAgICB4ID0gYygwLCAwKSwKICAgIHkgPSBjKDAsIDEpLCB6ID0gYygwLCAwKSwKICAgIG1vZGUgPSAibGluZXMiLAogICAgbGluZSA9IGxpc3QoCiAgICAgIHdpZHRoID0gNSwKICAgICAgY29sb3IgPSAiZ3JleSIpLAogICAgdHlwZT0ic2NhdHRlcjNkIikgJT4lCiAgYWRkX3RyYWNlKAogICAgeCA9IGMoMCwgMCksCiAgICB5ID0gYygwLCAwKSwKICAgIHogPSBjKDAsIDEpLAogICAgbW9kZSA9ICJsaW5lcyIsCiAgICBsaW5lID0gbGlzdCh3aWR0aCA9IDUsIGNvbG9yICA9ICJncmV5IiksCiAgICB0eXBlID0gInNjYXR0ZXIzZCIpICU+JQpoaWRlX2xlZ2VuZCgpCnAzICU+JQogIGFkZF9tYXJrZXJzKAogICAgdHlwZSA9ICJzY2F0dGVyM2QiLAogICAgdHlwZSA9ICJtYXJrZXJzIiwKICAgIG1hcmtlciA9IGxpc3QoY29sb3I9IiMxZjc3YjQiKQogICAgKQpgYGAKCiMgU1ZECgoxLiBXZSBhZG9wdCB0aGUgU1ZEIG9uIHRoZSBjZW50ZXJlZCBkYXRhCgpgYGB7cn0KaXJpc1N2ZCA8LSBzdmQoWCkKYGBgCgoyLiBXZSBleHRyYWN0CgogIC0gdGhlIHJpZ2h0IHNpbmd1bGFyIHZlY3RvcnMgJFxtYXRoYmZ7Vn0kIGFuZAogIC0gdGhlIHByb2plY3Rpb25zICRcbWF0aGJme1p9JAoKYGBge3J9ClYgPC0gaXJpc1N2ZCR2ICAKWiA8LSBpcmlzU3ZkJHUgJSolIGRpYWcoaXJpc1N2ZCRkKQpgYGAKCk5vdGUsIHRoYXQKCi0gdGhlIFNWRCBpcyBlc3NlbnRpYWxseSBhIHJvdGF0aW9uIHRvIGEgbmV3IGNvb3JkaW5hdGUgc3lzdGVtLgotIHdlIHBsb3R0ZWQgJFxtYXRoYmZ7Vn1fMyQgd2l0aCBkb3RzIGJlY2F1c2Ugd2Ugd2lsbCB1c2UgdGhlIFNWRCBmb3IgZGltZW5zaW9uIHJlZHVjdGlvbiBcW1x0ZXh0ezNEfSBccmlnaHRhcnJvdyBcdGV4dHsyRH1cXQoKYGBge3IgZWNobz1GQUxTRX0KcDQgPC0gcDMgJT4lCiAgYWRkX3RyYWNlKAogICAgeCA9IGMoMCwgVlsxLDFdKSwKICAgIHkgPSBjKDAsIFZbMiwxXSksCiAgICB6ID0gYygwLCBWWzMsMV0pLAogICAgbW9kZSA9ICJsaW5lcyIsCiAgICBsaW5lID0gbGlzdCh3aWR0aCA9IDUsCiAgICAgIGNvbG9yID0gInJlZCIpLAogICAgdHlwZT0ic2NhdHRlcjNkIikgJT4lCiAgYWRkX3RyYWNlKAogICAgeCA9IGMoMCwgVlsxLDJdKSwKICAgIHkgPSBjKDAsIFZbMiwyXSksCiAgICB6ID0gYygwLCBWWzMsMl0pLAogICAgbW9kZSA9ICJsaW5lcyIsCiAgICBsaW5lID0gbGlzdCh3aWR0aCA9IDUsIGNvbG9yID0gInJlZCIpLAogICAgdHlwZSA9ICJzY2F0dGVyM2QiKSAlPiUKICBhZGRfdHJhY2UoCiAgICB4ID0gYygwLCBWWzEsM10pLAogICAgeSA9IGMoMCwgVlsyLDNdKSwKICAgIHogPSBjKDAsIFZbMywzXSksCiAgICBtb2RlID0gImxpbmVzIiwKICAgIGxpbmUgPSBsaXN0KAogICAgICB3aWR0aCA9IDUsCiAgICAgIGNvbG9yID0gInJlZCIsCiAgICAgIGRhc2ggPSAiZGFzaCIpLAogICAgdHlwZT0ic2NhdHRlcjNkIikgJT4lCiAgICBoaWRlX2xlZ2VuZCgpICU+JQogICAgbGF5b3V0KAogICAgICBzY2VuZSA9IGxpc3QoCiAgICAgICAgYXNwZWN0bW9kZT0iY3ViZSIsCiAgICAgICAgYW5ub3RhdGlvbnMgPSBsaXN0KAogICAgICAgICAgbGlzdCgKICAgICAgICAgICAgeCA9IFZbMSwxXSwKICAgICAgICAgICAgeSA9IFZbMiwxXSwKICAgICAgICAgICAgeiA9IFZbMywxXSwKICAgICAgICAgICAgdGV4dCA9ICJWMSIsCiAgICAgICAgICAgIHRleHRhbmdsZT0gMCwKICAgICAgICAgICAgYXggPSAwLAogICAgICAgICAgICBheSA9IDAsCiAgICAgICAgICAgIGF6ID0gMCwKICAgICAgICAgICAgeHJlZj0neCcsCiAgICAgICAgICAgIGF4cmVmPSd4JywKICAgICAgICAgICAgeXJlZiA9ICd5JywKICAgICAgICAgICAgYXlyZWYgPSAneScsCiAgICAgICAgICAgIHpyZWYgPSAneicsCiAgICAgICAgICAgIGF6cmVmPSd6JywKICAgICAgICAgICAgc2hvd2Fycm93PUZBTFNFCiAgICAgICAgICAgICksCiAgICAgICAgICBsaXN0KAogICAgICAgICAgICB4ID0gVlsxLDJdLAogICAgICAgICAgICB5ID0gVlsyLDJdLAogICAgICAgICAgICB6ID0gVlszLDJdLAogICAgICAgICAgICB0ZXh0ID0gIlYyIiwKICAgICAgICAgICAgdGV4dGFuZ2xlPSAwLAogICAgICAgICAgICBheCA9IDAsCiAgICAgICAgICAgIGF5ID0gMCwKICAgICAgICAgICAgYXogPSAwLAogICAgICAgICAgICB4cmVmPSd4JywKICAgICAgICAgICAgYXhyZWY9J3gnLAogICAgICAgICAgICB5cmVmID0gJ3knLAogICAgICAgICAgICBheXJlZiA9ICd5JywKICAgICAgICAgICAgenJlZiA9ICd6JywKICAgICAgICAgICAgYXpyZWY9J3onLAogICAgICAgICAgICBzaG93YXJyb3c9RkFMU0UKICAgICAgICAgICAgKSwKICAgICAgICAgIGxpc3QoCiAgICAgICAgICAgIHggPSBWWzEsM10sCiAgICAgICAgICAgIHkgPSBWWzIsM10sCiAgICAgICAgICAgIHogPSBWWzMsM10sCiAgICAgICAgICAgIHRleHQgPSAiVjMiLAogICAgICAgICAgICB0ZXh0YW5nbGU9IDAsCiAgICAgICAgICAgIGF4ID0gMCwKICAgICAgICAgICAgYXkgPSAwLAogICAgICAgICAgICBheiA9IDAsCiAgICAgICAgICAgIHhyZWY9J3gnLAogICAgICAgICAgICBheHJlZj0neCcsCiAgICAgICAgICAgIHlyZWYgPSAneScsCiAgICAgICAgICAgIGF5cmVmID0gJ3knLAogICAgICAgICAgICB6cmVmID0gJ3onLAogICAgICAgICAgICBhenJlZj0neicsCiAgICAgICAgICAgIHNob3dhcnJvdz1GQUxTRSkKICAgICAgICAgICkKICAgICAgICApCiAgICAgICkKcDQKcDQgPC0gcDQgJT4lCiAgYWRkX21hcmtlcnMoCiAgICB0eXBlID0gInNjYXR0ZXIzZCIsCiAgICB0eXBlID0gIm1hcmtlcnMiLAogICAgbWFya2VyID0gbGlzdChjb2xvcj0iIzFmNzdiNCIpCiAgICApCnA0CmBgYAoKUm90YXRlIHRoZSBwbG90CgotIE5vdGUsIHRoYXQKCiAgLSBWMSBwb2ludHMgaW4gdGhlIGRpcmVjdGlvbiBvZiB0aGUgbGFyZ2VzdCB2YXJpYWJpbGl0eSBpbiB0aGUgZGF0YQogIC0gVjIgcG9pbnRzIGluIGEgZGlyZWN0aW9uIG9ydGhvZ2FsIG9uIFYxIHBvaW50aW5nIGluIHRoZSBkaXJlY3Rpb24gb2YgdGhlIHNlY29uZCBsYXJnZXN0IHZhcmlhYmlsaXR5IGluIHRoZSBkYXRhLgoKCiMgR2VvbWV0cmljIEludGVycHJldGF0aW9uPwoKV3JpdGUgdGhlICoqdHJ1bmNhdGVkIFNWRCoqIGFzClxbCiAgXG1hdGhiZntYfV9rID0gXG1hdGhiZntVfV9rIFxib2xkc3ltYm9se1xEZWx0YX1fayBcbWF0aGJme1Z9X2teVCA9IFxtYXRoYmZ7Wn1fayBcbWF0aGJme1Z9X2teVApcXQp3aXRoClxbCiAgXG1hdGhiZntafV9rID0gXG1hdGhiZntVfV9rIFxib2xkc3ltYm9se1xEZWx0YX1fawpcXQphbiAkbiBcdGltZXMgayQgbWF0cml4LgoKRWFjaCBvZiB0aGUgJG4kIHJvd3Mgb2YgJFxtYXRoYmZ7Wn1fayQsIHNheSAkXG1hdGhiZnt6fV5UX3trLGl9JCwgcmVwcmVzZW50cyBhIHBvaW50IGluIGEgJGskLWRpbWVuc2lvbmFsIHNwYWNlLgoKYGBge3J9ClYyIDwtIFZbLDE6Ml0KWjIgPC0gWlssMToyXQpYMiA8LSBaMiAlKiUgdChWMikKYGBgCgpCZWNhdXNlIG9mIHRoZSBvcnRob25vcm1hbGl0eSBvZiB0aGUgc2luZ3VsYXIgdmVjdG9ycywgd2UgYWxzbyBoYXZlClxiZWdpbntlcW5hcnJheSp9CiAgXG1hdGhiZntYfV9rXG1hdGhiZntWfV9rICY9JiBcbWF0aGJme1p9X2sgXG1hdGhiZntWfV9rXlRcbWF0aGJme1Z9X2sgXFwKICBcbWF0aGJme1h9X2tcbWF0aGJme1Z9X2sgJj0mIFxtYXRoYmZ7Wn1fay4KXGVuZHtlcW5hcnJheSp9CgpUaHVzIHRoZSBtYXRyaXggJFxtYXRoYmZ7Vn1fayQgaXMgYSAqKnRyYW5zZm9ybWF0aW9uIG1hdHJpeCoqIHRoYXQgbWF5IGJlIHVzZWQgdG8gdHJhbnNmb3JtICRcbWF0aGJme1h9X2skIGludG8gJFxtYXRoYmZ7Wn1fayQsIGFuZCAkXG1hdGhiZntafV9rJCBpbnRvICRcbWF0aGJme1h9X2skLgoKLS0tCgpNb3JlIGltcG9ydGFudGx5LCBpdCBjYW4gYmUgc2hvd24gdGhhdCAodGhhbmtzIHRvIG9ydGhvbm9ybWFsaXR5IG9mICRcbWF0aGJme1Z9JCkKXFsKXG1hdGhiZntYfVxtYXRoYmZ7Vn1fayA9IFxtYXRoYmZ7Wn1fay4KXF0KClRoaXMgZm9sbG93cyBmcm9tICh3LmwuZy4gcmFuaygkXG1hdGhiZntYfSQpPSRyJCkKXGJlZ2lue2VxbmFycmF5Kn0KXG1hdGhiZntYfVxtYXRoYmZ7Vn1fawomPSYgXG1hdGhiZntVRFZ9XlRcbWF0aGJme1Z9X2sgPSBcbWF0aGJme1VEfVxiZWdpbntwbWF0cml4fQpcbWF0aGJme3Z9XzFeVCBcXApcdmRvdHMgXFwKXG1hdGhiZnt2fV9yXlQKXGVuZHtwbWF0cml4fQpcYmVnaW57cG1hdHJpeH0KXG1hdGhiZnt2fV8xIFxsZG90cyBcbWF0aGJme3Z9X2sKXGVuZHtwbWF0cml4fSBcXAomPSYgXG1hdGhiZntVRFZ9XlRcbWF0aGJme1Z9X2sgPSBcbWF0aGJme1VEfVxiZWdpbntwbWF0cml4fQoxICYgMCAmIFxsZG90cyAmIDAgXFwKMCAmIDEgJiBcbGRvdHMgJiAwIFxcClx2ZG90cyAmIFx2ZG90cyAmIFxkZG90cyAmIDAgXFwKMCAmIDAgJiBcbGRvdHMgJiAxIFxcCjAgJiAwICYgXGxkb3RzICYgMCBcXApcdmRvdHMgJiBcdmRvdHMgJiBcdmRvdHMgJiBcdmRvdHMgXFwKMCAmIDAgJiBcbGRvdHMgJiAwClxlbmR7cG1hdHJpeH0gXAo9IFxtYXRoYmZ7VX1fa1xib2xkc3ltYm9se1xEZWx0YX1fayA9IFxtYXRoYmZ7Wn1fayBcZW5ke2VxbmFycmF5Kn0KClRoZSAkcCBcdGltZXMgayQgbWF0cml4ICRcbWF0aGJme1Z9X2skIGFjdHMgYXMgYSB0cmFuc2Zvcm1hdGlvbiBtYXRyaXg6IHRyYW5zZm9ybWluZyAkbiQgcG9pbnRzIGluIGEgJHAkIGRpbWVuc2lvbmFsIHNwYWNlIHRvICRuJCBwb2ludHMgaW4gYSAkayQgZGltZW5zaW9uYWwgc3BhY2UuCgpgYGB7cn0KWjJwcm9qIDwtIFggJSolIFYyCnJhbmdlKFoyIC0gWjJwcm9qKQpgYGAKCgojIyBQcm9qZWN0aW9uIG9mIGEgc2luZ2xlIGRhdGEgcG9pbnQKCi0gWm9vbSBpbiB0byBzZWUgcHJvamVjdGlvbi4KLSBUaGUgcHJvamVjdGlvbiBpcyBpbmRpY2F0ZWQgZm9yIHRoZSBibHVlIHBvaW50ICRYX3s0NH0kIHRvIHRoZSByZWQgcG9pbnQgJFhfezIsNDR9JCBpbiB0aGUgcGxhbmUgc3BhbmVkIGJ5IFYyLgoKYGBge3IgZWNobz1GQUxTRX0KaSA8LSA0NApjb2xuYW1lcyhYMikgPC0gY29sbmFtZXMoWCkKcDcgPC0gcDIgJT4lIGxheW91dCgKICBzY2VuZSA9IGxpc3QoCiAgICB4YXhpcyA9IGxpc3QocmFuZ2U9YygtMSwxKSptYXgoYWJzKFgpKSksCiAgICB5YXhpcyA9IGxpc3QocmFuZ2U9YygtMSwxKSptYXgoYWJzKFgpKSksCiAgICB6YXhpcyA9IGxpc3QocmFuZ2U9YygtMSwxKSptYXgoYWJzKFgpKSkpCiAgICApICU+JQogIGFkZF90cmFjZSgKICAgIHggPSBjKFhbaSwgMV0sIFpbaSwgMV0qVlsxLCAxXSksCiAgICB5ID0gYyhYW2ksIDJdLCBaW2ksIDFdKlZbMiwgMV0pLAogICAgeiA9IGMoWFtpLCAzXSwgWltpLCAxXSpWWzMsIDFdKSwKICAgIG1vZGUgPSAibGluZXMiLAogICAgbGluZSA9IGxpc3QoCiAgICAgIHdpZHRoID0gNSwKICAgICAgY29sb3IgPSAiYmxhY2siLAogICAgICBkYXNoID0gImRhc2giKSwKICAgIHR5cGUgPSAic2NhdHRlcjNkIikgJT4lCiAgYWRkX3RyYWNlKAogICAgeCA9IGMoWFtpLCAxXSwgWltpLCAyXSAqIFZbMSwgMl0pLAogICAgeSA9IGMoWFtpLCAyXSwgWltpLCAyXSAqIFZbMiwgMl0pLAogICAgeiA9IGMoWFtpLCAzXSwgWltpLCAyXSAqIFZbMywgMl0pLAogICAgbW9kZSA9ICJsaW5lcyIsCiAgICBsaW5lID0gbGlzdCgKICAgICAgd2lkdGggPSA1LAogICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgIGRhc2ggPSAiZGFzaCIpLAogICAgdHlwZT0ic2NhdHRlcjNkIikgJT4lCiAgYWRkX21hcmtlcnModHlwZT0ic2NhdHRlcjNkIixtb2RlPSJtYXJrZXJzIikgJT4lCiAgYWRkX3RyYWNlKAogICAgeCA9IGMoMCwgVlsxLCAxXSksCiAgICB5ID0gYygwLCBWWzIsIDFdKSwKICAgIHogPSBjKDAsIFZbMywgMV0pLAogICAgbW9kZSA9ICJsaW5lcyIsCiAgICBsaW5lID0gbGlzdCgKICAgICAgd2lkdGggPSA1LAogICAgICBjb2xvciA9ICJyZWQiKSwKICAgIHR5cGU9InNjYXR0ZXIzZCIpICU+JQogICAgYWRkX3RyYWNlKAogICAgICB4ID0gYygwLCBWWzEsIDJdKSwKICAgICAgeSA9IGMoMCwgVlsyLCAyXSksCiAgICAgIHogPSBjKDAsIFZbMywyXSksCiAgICAgIG1vZGUgPSAibGluZXMiLAogICAgICBsaW5lID0gbGlzdCgKICAgICAgICB3aWR0aCA9IDUsCiAgICAgICAgY29sb3IgPSAicmVkIiksCiAgICAgIHR5cGU9InNjYXR0ZXIzZCIpICU+JQogICAgYWRkX3RyYWNlKAogICAgICB4ID0gYygwLCBWWzEsIDNdKSwKICAgICAgeSA9IGMoMCwgVlsyLCAzXSksCiAgICAgIHogPSBjKDAsIFZbMywgM10pLAogICAgICBtb2RlID0gImxpbmVzIiwKICAgICAgbGluZSA9IGxpc3QoCiAgICAgICAgd2lkdGggPSA1LAogICAgICAgIGNvbG9yID0gInJlZCIsCiAgICAgICAgZGFzaCA9ICJkYXNoIiksCiAgICAgICAgdHlwZT0ic2NhdHRlcjNkIikgJT4lCiAgICBoaWRlX2xlZ2VuZCgpICU+JQogICAgbGF5b3V0KAogICAgICBzY2VuZSA9IGxpc3QoCiAgICAgICAgYXNwZWN0bW9kZT0iY3ViZSIsCiAgICAgICAgYW5ub3RhdGlvbnMgPSBsaXN0KGxpc3QoCiAgICAgICAgICB4ID0gVlsxLDFdLAogICAgICAgICAgeSA9IFZbMiwxXSwKICAgICAgICAgIHogPSBWWzMsMV0sCiAgICAgICAgICB0ZXh0ID0gIlYxIiwKICAgICAgICAgIHRleHRhbmdsZT0gMCwKICAgICAgICAgIGF4ID0gMCwKICAgICAgICAgIGF5ID0gMCwKICAgICAgICAgIGF6ID0gMCwKICAgICAgICAgIHhyZWYgPSAneCcsCiAgICAgICAgICBheHJlZiA9ICd4JywKICAgICAgICAgIHlyZWYgPSAneScsCiAgICAgICAgICBheXJlZiA9ICd5JywKICAgICAgICAgIHpyZWYgPSAneicsCiAgICAgICAgICBhenJlZj0neicsCiAgICAgICAgICBzaG93YXJyb3c9RkFMU0UKICAgICAgICAgICksCiAgICAgICAgbGlzdCgKICAgICAgICAgIHggPSBWWzEsMl0sCiAgICAgICAgICB5ID0gVlsyLDJdLAogICAgICAgICAgeiA9IFZbMywyXSwKICAgICAgICAgIHRleHQgPSAiVjIiLAogICAgICAgICAgdGV4dGFuZ2xlPSAwLAogICAgICAgICAgYXggPSAwLAogICAgICAgICAgYXkgPSAwLAogICAgICAgICAgYXogPSAwLAogICAgICAgICAgeHJlZiA9ICd4JywKICAgICAgICAgIGF4cmVmID0gJ3gnLAogICAgICAgICAgeXJlZiA9ICd5JywKICAgICAgICAgIGF5cmVmID0gJ3knLAogICAgICAgICAgenJlZiA9ICd6JywKICAgICAgICAgIGF6cmVmPSd6JywKICAgICAgICAgIHNob3dhcnJvdz1GQUxTRQogICAgICAgICAgKSwKICAgICAgICBsaXN0KAogICAgICAgICAgeCA9IFZbMSwzXSwKICAgICAgICAgIHkgPSBWWzIsM10sCiAgICAgICAgICB6ID0gVlszLDNdLAogICAgICAgICAgdGV4dCA9ICJWMyIsCiAgICAgICAgICB0ZXh0YW5nbGU9IDAsCiAgICAgICAgICBheCA9IDAsCiAgICAgICAgICBheSA9IDAsCiAgICAgICAgICBheiA9IDAsCiAgICAgICAgICB4cmVmID0gJ3gnLAogICAgICAgICAgYXhyZWYgPSAneCcsCiAgICAgICAgICB5cmVmID0gJ3knLAogICAgICAgICAgYXlyZWYgPSAneScsCiAgICAgICAgICB6cmVmID0gJ3onLAogICAgICAgICAgYXpyZWY9J3onLAogICAgICAgICAgc2hvd2Fycm93PUZBTFNFCiAgICAgICAgICApCiAgICAgICAgKQogICAgICApCiAgICApICU+JQogIGFkZF9tYXJrZXJzKHR5cGU9InNjYXR0ZXIzZCIsbW9kZT0ibWFya2VycyIsbWFya2VyPWxpc3QoY29sb3I9ImdyZXkiKSxob3ZlcmluZm89Im5vbmUiKSAlPiUKYWRkX3RyYWNlKAogIGRhdGEgPSAoWCU+JWFzLmRhdGEuZnJhbWUpW2ksXSwKICB4ID0gflNlcGFsLkxlbmd0aCwKICB5ID0gflNlcGFsLldpZHRoLAogIHogPSB+UGV0YWwuTGVuZ3RoLAogIHR5cGUgPSAic2NhdHRlcjNkIiwKICBtb2RlID0gIm1hcmtlcnMiLAogIG1hcmtlciA9IGxpc3QoY29sb3I9IiMxZjc3YjQiKQogICklPiUKYWRkX3RyYWNlKAogIGRhdGEgPSAoWDIgJT4lIGFzLmRhdGEuZnJhbWUpW2ksXSwKICB4ID0gflNlcGFsLkxlbmd0aCwKICB5ID0gflNlcGFsLldpZHRoLAogIHogPSB+UGV0YWwuTGVuZ3RoLAogIHR5cGUgPSAic2NhdHRlcjNkIiwKICBtb2RlID0gIm1hcmtlcnMiLAogIG1hcmtlciA9IGxpc3QoY29sb3I9InJlZCIpKSU+JQphZGRfdHJhY2UoCiAgeCA9IGMoWDJbaSwgMV0sIFpbaSwgMV0gKiBWWzEsIDFdKSwKICB5ID0gYyhYMltpLCAyXSwgWltpLCAxXSAqIFZbMiwgMV0pLAogIHogPSBjKFgyW2ksIDNdLCBaW2ksIDFdICogVlszLCAxXSksCiAgbW9kZSA9ICJsaW5lcyIsCiAgbGluZSA9IGxpc3QoCiAgICB3aWR0aCA9IDUsCiAgICBjb2xvciA9ICJyZWQiLAogICAgZGFzaCA9ICJkYXNoIiksCiAgdHlwZT0ic2NhdHRlcjNkIikgJT4lCmFkZF90cmFjZSgKICB4ID0gYyhYMltpLCAxXSwgWltpLCAyXSAqIFZbMSwgMl0pLAogIHkgPSBjKFgyW2ksIDJdLCBaW2ksIDJdICogVlsyLCAyXSksCiAgeiA9IGMoWDJbaSwgM10sIFpbaSwgMl0gKiBWWzMsMl0pLAogIG1vZGUgPSAibGluZXMiLAogIGxpbmUgPSBsaXN0KAogICAgd2lkdGggPSA1LAogICAgY29sb3IgPSAicmVkIiwKICAgIGRhc2ggPSAiZGFzaCIpLAogIHR5cGU9InNjYXR0ZXIzZCIpICU+JQphZGRfdHJhY2UoCiAgeCA9IGMoWDJbaSwgMV0sIFhbaSwgMV0pLAogIHkgPSBjKFgyW2ksIDJdLCBYW2ksIDJdKSwKICB6ID0gYyhYMltpLCAzXSwgWFtpLCAzXSksCiAgbW9kZSA9ICJsaW5lcyIsCiAgbGluZSA9IGxpc3QoCiAgICB3aWR0aCA9IDUsCiAgICBjb2xvciA9ICJvcmFuZ2UiLAogICAgZGFzaCA9ICJkYXNoIiksCiAgdHlwZT0ic2NhdHRlcjNkIikKcDcKYGBgCgojIyBQcm9qZWN0aW9uIG9mIGFsbCBkYXRhcG9pbnRzOiBwcm9qZWN0IGFsbCByb3dzIG9mIFggb24gVjIKCi0gWm9vbSBpbiBmaXJzdCBsb29rIG9ydGhvbmFsIHZpYSBkaXJlY3Rpb24gVjIgKHJvdGF0ZSB1bnRpbCB0ZXh0IFYyIGlzIHZpZXdlZCBpbiB0aGUgb3JpZ2luKQotIFpvb20gaW4gZmlyc3QgbG9vayBvcnRob25hbCB2aWEgZGlyZWN0aW9uIFYxIChyb3RhdGUgdW50aWwgdGV4dCBWMSBpcyB2aWV3ZWQgaW4gdGhlIG9yaWdpbikKLSBOb3RlLCB0aGF0CiAgLSBWMSBwb2ludHMgaW4gdGhlIGRpcmVjdGlvbiBvZiB0aGUgbGFyZ2VzdCB2YXJpYWJpbGl0eSBpbiB0aGUgZGF0YQogIC0gVjIgcG9pbnRzIGluIGEgZGlyZWN0aW9uIG9ydGhvZ2FsIG9uIFYxIHBvaW50aW5nIGluIHRoZSBkaXJlY3Rpb24gb2YgdGhlIHNlY29uZCBsYXJnZXN0IHZhcmlhYmlsaXR5IGluIHRoZSBkYXRhLgoKYGBge3IgZWNobz1GQUxTRX0KcDggPC0gcDIgJT4lIGxheW91dCgKICBzY2VuZSA9IGxpc3QoCiAgICB4YXhpcyA9IGxpc3QocmFuZ2U9YygtMSwxKSptYXgoYWJzKFgpKSksCiAgICB5YXhpcyA9IGxpc3QocmFuZ2U9YygtMSwxKSptYXgoYWJzKFgpKSksCiAgICB6YXhpcyA9IGxpc3QocmFuZ2U9YygtMSwxKSptYXgoYWJzKFgpKSkpCiAgICApICU+JQogIGFkZF90cmFjZSgKICAgIHggPSBjKDAsIFZbMSwgMV0pLAogICAgeSA9IGMoMCwgVlsyLCAxXSksCiAgICB6ID0gYygwLCBWWzMsIDFdKSwKICAgIG1vZGUgPSAibGluZXMiLAogICAgbGluZSA9IGxpc3QoCiAgICAgIHdpZHRoID0gNSwKICAgICAgY29sb3IgPSAicmVkIiksCiAgICB0eXBlPSJzY2F0dGVyM2QiKSAlPiUKICAgIGFkZF90cmFjZSgKICAgICAgeCA9IGMoMCwgVlsxLCAyXSksCiAgICAgIHkgPSBjKDAsIFZbMiwgMl0pLAogICAgICB6ID0gYygwLCBWWzMsMl0pLAogICAgICBtb2RlID0gImxpbmVzIiwKICAgICAgbGluZSA9IGxpc3QoCiAgICAgICAgd2lkdGggPSA1LAogICAgICAgIGNvbG9yID0gInJlZCIpLAogICAgICB0eXBlPSJzY2F0dGVyM2QiKSAlPiUKICAgIGFkZF90cmFjZSgKICAgICAgeCA9IGMoMCwgVlsxLCAzXSksCiAgICAgIHkgPSBjKDAsIFZbMiwgM10pLAogICAgICB6ID0gYygwLCBWWzMsIDNdKSwKICAgICAgbW9kZSA9ICJsaW5lcyIsCiAgICAgIGxpbmUgPSBsaXN0KAogICAgICAgIHdpZHRoID0gNSwKICAgICAgICBjb2xvciA9ICJyZWQiLAogICAgICAgIGRhc2ggPSAiZGFzaCIpLAogICAgICAgIHR5cGU9InNjYXR0ZXIzZCIpICU+JQogICAgaGlkZV9sZWdlbmQoKSAlPiUKICAgIGxheW91dCgKICAgICAgc2NlbmUgPSBsaXN0KAogICAgICAgIGFzcGVjdG1vZGU9ImN1YmUiLAogICAgICAgIGFubm90YXRpb25zID0gbGlzdChsaXN0KAogICAgICAgICAgeCA9IFZbMSwxXSwKICAgICAgICAgIHkgPSBWWzIsMV0sCiAgICAgICAgICB6ID0gVlszLDFdLAogICAgICAgICAgdGV4dCA9ICJWMSIsCiAgICAgICAgICB0ZXh0YW5nbGU9IDAsCiAgICAgICAgICBheCA9IDAsCiAgICAgICAgICBheSA9IDAsCiAgICAgICAgICBheiA9IDAsCiAgICAgICAgICB4cmVmID0gJ3gnLAogICAgICAgICAgYXhyZWYgPSAneCcsCiAgICAgICAgICB5cmVmID0gJ3knLAogICAgICAgICAgYXlyZWYgPSAneScsCiAgICAgICAgICB6cmVmID0gJ3onLAogICAgICAgICAgYXpyZWY9J3onLAogICAgICAgICAgc2hvd2Fycm93PUZBTFNFCiAgICAgICAgICApLAogICAgICAgIGxpc3QoCiAgICAgICAgICB4ID0gVlsxLDJdLAogICAgICAgICAgeSA9IFZbMiwyXSwKICAgICAgICAgIHogPSBWWzMsMl0sCiAgICAgICAgICB0ZXh0ID0gIlYyIiwKICAgICAgICAgIHRleHRhbmdsZT0gMCwKICAgICAgICAgIGF4ID0gMCwKICAgICAgICAgIGF5ID0gMCwKICAgICAgICAgIGF6ID0gMCwKICAgICAgICAgIHhyZWYgPSAneCcsCiAgICAgICAgICBheHJlZiA9ICd4JywKICAgICAgICAgIHlyZWYgPSAneScsCiAgICAgICAgICBheXJlZiA9ICd5JywKICAgICAgICAgIHpyZWYgPSAneicsCiAgICAgICAgICBhenJlZj0neicsCiAgICAgICAgICBzaG93YXJyb3c9RkFMU0UKICAgICAgICAgICksCiAgICAgICAgbGlzdCgKICAgICAgICAgIHggPSBWWzEsM10sCiAgICAgICAgICB5ID0gVlsyLDNdLAogICAgICAgICAgeiA9IFZbMywzXSwKICAgICAgICAgIHRleHQgPSAiVjMiLAogICAgICAgICAgdGV4dGFuZ2xlPSAwLAogICAgICAgICAgYXggPSAwLAogICAgICAgICAgYXkgPSAwLAogICAgICAgICAgYXogPSAwLAogICAgICAgICAgeHJlZiA9ICd4JywKICAgICAgICAgIGF4cmVmID0gJ3gnLAogICAgICAgICAgeXJlZiA9ICd5JywKICAgICAgICAgIGF5cmVmID0gJ3knLAogICAgICAgICAgenJlZiA9ICd6JywKICAgICAgICAgIGF6cmVmPSd6JywKICAgICAgICAgIHNob3dhcnJvdz1GQUxTRQogICAgICAgICAgKQogICAgICAgICkKICAgICAgKQogICAgKSAlPiUKICBhZGRfdHJhY2UoCiAgICBkYXRhID0gWDIgJT4lIGFzLmRhdGEuZnJhbWUsCiAgICB4ID0gflNlcGFsLkxlbmd0aCwKICAgIHkgPSB+U2VwYWwuV2lkdGgsCiAgICB6ID0gflBldGFsLkxlbmd0aCwKICAgIHR5cGUgPSAic2NhdHRlcjNkIiwKICAgIG1vZGUgPSAibWFya2VycyIsCiAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gInJlZCIpKQoKZm9yIChpIGluIDE6bnJvdyhYMikpCnA4IDwtIHA4ICU+JSAgYWRkX3RyYWNlKAogIHggPSBjKFgyW2ksIDFdLCBYW2ksIDFdKSwKICB5ID0gYyhYMltpLCAyXSwgWFtpLCAyXSksCiAgeiA9IGMoWDJbaSwgM10sIFhbaSwgM10pLAogIG1vZGUgPSAibGluZXMiLAogIGxpbmUgPSBsaXN0KAogICAgd2lkdGggPSA1LAogICAgY29sb3IgPSAib3JhbmdlIiwKICAgIGRhc2ggPSAiZGFzaCIpLAogIHR5cGU9InNjYXR0ZXIzZCIpCgpwOApgYGAKCi0gUHJvamVjdGlvbiBvbmx5LgotIFRoaXMgY2xlYXJseSBzaG93cyB0aGF0IHRoZSBwcm9qZWN0ZWQgcG9pbnRzIFgyIChYIHByb2plY3RlZCBvbiBWMikgbGl2ZSBpbiBhIHR3byBkaW1lbnNpb25hbCBzcGFjZQoKYGBge3IgZWNobyA9IEZBTFNFfQpwOSA8LSBwbG90X2x5KAogICAgWCAlPiUgYXMuZGF0YS5mcmFtZSwKICAgIHggPSB+U2VwYWwuTGVuZ3RoLAogICAgeSA9IH5TZXBhbC5XaWR0aCwKICAgIHo9IH5QZXRhbC5MZW5ndGgpICU+JQogIGFkZF90cmFjZSgKICAgIGRhdGEgPSBYMiAlPiUgYXMuZGF0YS5mcmFtZSwKICAgIHggPSB+U2VwYWwuTGVuZ3RoLAogICAgeSA9IH5TZXBhbC5XaWR0aCwKICAgIHogPSB+UGV0YWwuTGVuZ3RoLAogICAgdHlwZSA9ICJzY2F0dGVyM2QiLAogICAgbW9kZSA9ICJtYXJrZXJzIiwKICAgIG1hcmtlciA9IGxpc3QoY29sb3I9InJlZCIpKSAlPiUKICBhZGRfdHJhY2UoCiAgICB4ID0gYygwLCAxKSwKICAgIHkgPSBjKDAsIDApLAogICAgeiA9IGMoMCwgMCksCiAgICBtb2RlID0gImxpbmVzIiwKICAgIGxpbmUgPSBsaXN0KAogICAgICB3aWR0aCA9IDUsCiAgICAgIGNvbG9yID0gImdyZXkiLAogICAgICBkYXNoID0gImRhc2giKSwKICAgIHR5cGU9InNjYXR0ZXIzZCIpICU+JQogIGFkZF90cmFjZSgKICAgIHggPSBjKDAsIDApLAogICAgeSA9IGMoMCwgMSksCiAgICB6ID0gYygwLCAwKSwKICAgIG1vZGUgPSAibGluZXMiLAogICAgbGluZSA9IGxpc3QoCiAgICAgIHdpZHRoID0gNSwKICAgICAgY29sb3IgPSAiZ3JleSIsCiAgICAgIGRhc2ggPSAiZGFzaCIpLAogICAgdHlwZT0ic2NhdHRlcjNkIikgJT4lCiAgYWRkX3RyYWNlKAogICAgeCA9IGMoMCwgMCksCiAgICB5ID0gYygwLCAwKSwKICAgIHogPSBjKDAsIDEpLAogICAgbW9kZSA9ICJsaW5lcyIsCiAgICBsaW5lID0gbGlzdCgKICAgICAgd2lkdGggPSA1LAogICAgICBjb2xvciA9ICJncmV5IiwKICAgICAgZGFzaCA9ICJkYXNoIiksCiAgICB0eXBlPSJzY2F0dGVyM2QiKSAlPiUKICBhZGRfdHJhY2UoCiAgICB4ID0gYygwLCBWWzEsIDFdKSwKICAgIHkgPSBjKDAsIFZbMiwgMV0pLAogICAgeiA9IGMoMCwgVlszLCAxXSksCiAgICBtb2RlID0gImxpbmVzIiwKICAgIGxpbmUgPSBsaXN0KAogICAgICB3aWR0aCA9IDUsCiAgICAgIGNvbG9yID0gInJlZCIpLAogICAgdHlwZT0ic2NhdHRlcjNkIikgJT4lCiAgYWRkX3RyYWNlKAogICAgeCA9IGMoMCwgVlsxLCAyXSksCiAgICB5ID0gYygwLCBWWzIsIDJdKSwKICAgIHogPSBjKDAsIFZbMywgMl0pLAogICAgbW9kZSA9ICJsaW5lcyIsCiAgICBsaW5lID0gbGlzdCgKICAgICAgd2lkdGggPSA1LAogICAgICBjb2xvciA9ICJyZWQiKSwKICAgIHR5cGU9InNjYXR0ZXIzZCIpICU+JQogIGhpZGVfbGVnZW5kKCkgJT4lCiAgbGF5b3V0KAogICAgc2NlbmUgPSBsaXN0KAogICAgICBhc3BlY3Rtb2RlPSJjdWJlIiwKICAgICAgYW5ub3RhdGlvbnMgPSBsaXN0KGxpc3QoCiAgICAgICAgeCA9IFZbMSwxXSwKICAgICAgICB5ID0gVlsyLDFdLAogICAgICAgIHogPSBWWzMsMV0sCiAgICAgICAgdGV4dCA9ICJWMSIsCiAgICAgICAgdGV4dGFuZ2xlPSAwLAogICAgICAgIGF4ID0gMCwKICAgICAgICBheSA9IDAsCiAgICAgICAgYXogPSAwLAogICAgICAgIHhyZWYgPSAneCcsCiAgICAgICAgYXhyZWYgPSAneCcsCiAgICAgICAgeXJlZiA9ICd5JywKICAgICAgICBheXJlZiA9ICd5JywKICAgICAgICB6cmVmID0gJ3onLAogICAgICAgIGF6cmVmPSd6JywKICAgICAgICBzaG93YXJyb3c9RkFMU0UKICAgICAgKSwKICAgICAgbGlzdCgKICAgICAgICB4ID0gVlsxLDJdLAogICAgICAgIHkgPSBWWzIsMl0sCiAgICAgICAgeiA9IFZbMywyXSwKICAgICAgICB0ZXh0ID0gIlYyIiwKICAgICAgICB0ZXh0YW5nbGUgPSAwLAogICAgICAgIGF4ID0gMCwKICAgICAgICBheSA9IDAsCiAgICAgICAgYXogPSAwLAogICAgICAgIHhyZWYgPSAneCcsCiAgICAgICAgYXhyZWYgPSAneCcsCiAgICAgICAgeXJlZiA9ICd5JywKICAgICAgICBheXJlZiA9ICd5JywKICAgICAgICB6cmVmID0gJ3onLAogICAgICAgIGF6cmVmPSd6JywKICAgICAgICBzaG93YXJyb3c9RkFMU0UKICAgICAgICApCiAgICAgICkKICAgICkKICApICU+JQogIGxheW91dCgKICAgIHNjZW5lID0gbGlzdCgKICAgICAgYXNwZWN0bW9kZSA9ICJjdWJlIiwKICAgICAgeGF4aXMgPSBsaXN0KHJhbmdlID0gYygtMSwgMSkgKiBtYXgoYWJzKFgpKSksIHlheGlzID0gbGlzdChyYW5nZT1jKC0xLCAxKSAqIG1heChhYnMoWCkpKSwKICAgICAgemF4aXMgPSBsaXN0KHJhbmdlPWMoLTEsIDEpKm1heChhYnMoWCkpKSkKICAgICAgKQpwOQpgYGAK