General

Statistical Learning (Data mining) methods can be classified as supervised or unsupervised.

\(X\) -> predictors, independent variables, features, variables.
\(Y\) -> response, dependent variable.
\(X = (X_1,X_2,...,X_p)\) and \(Y\) -> \(Y = f(X) + \epsilon\), \(\epsilon\) is a random error term and has mean zero. Data mining refers to a set of approaches to estimate \(f\).

We estimate \(f\) to :
1. prediction. \(\hat Y = \hat f(X)\)
2. inference. ( learn the relationship )

The accuracy of \(\hat Y\) as a prediction for \(Y\) depends on:
1. reducible error
2. irreducible error

overfitting -> It is an undesirable situation because the fit obtained will not yield accurate estimates of the response on new observations that were not part of the original training data set.

Trade-Off between Prediction Accuracy and Model Interpretability

DT is good for interpreting.
Bagging, Boosting, RF has higher Accuracy, hard to interpret.

Supervised vs Unsupervised

  • supervised - for each observation of the predictor measurement(s) \(x_i, i=1,...n\) there is an associated response measurement \(y_i\) -> predict \(Y\) or learn relationship between \(X\) and \(Y\) .
  • unsupervised - for each observations \(x_i, i=1,...n\) we observe a vector of measurements \(x_i\) but no associated response \(y_i\) -> understand relationship between the \(X_i\)s or observations.

Regression vs Classification

regression -> quantitative response, numerical response
classification -> qualitative response, categorical response

Model Accuracy

Regression

\[ MSE = \frac{1}{n} \sum_{i=1}^n {(y_i - \hat f(x_i))^2} \] where \(\hat f(x_i) -> \hat y_i\) (the prediction).

we are interested in the accuracy of the predictions that we obtain when we apply our method to previously unseen test data. there is no guarantee that the method with the lowest training MSE will also have the lowest test MSE.

When a given method yields a small training MSE but a large test MSE, we are said to be overfitting the data.

Cross-Validation (CV) can be used to estimate the test MSE on the training data.

Classification

Error rate: \[ error rate = \frac{1}{n} \sum_{i=1}^n {y_i \ne \hat y_i} \] Bayes Classifier: \[ Pr(Y=k|X=x) \\ Pr(Y=1|X=x) > 0.5 \ \therefore k=1 \] KNN \[ Pr(Y=j|X=x_0) = \frac{1}{K} \sum_{i\in N_0}{I(y_i=j)} \] \(N_0\) -> K points in the training data that are closet to \(x_0\)

The Bias-Variance Trande-Off

Expected test MSE for a given value \(x_0\) can be given as:

In order to minimize the expected test error, we need to select a statistical learning method that simultaneously achieves low variance and low bias.
- Variance -> Variance refers to the amount by which \(\hat f\) would change if we estimated it using a different training data set. (due to randomness on data) - Bias -> bias refers to the error that is introduced by approximating a real-life problem, which may be extremely complicated, by a much simpler model. (due to simplification)

model is too simple -> high bias (just use several \(X_i\))
model is too complex -> low bias (use too much \(X_i\), overfitting)

Classification

Response variable is qualitative.
simple:
- Naive Bayes
- KNN

computer intensive:
- DT
- Begging
- RF
- Boosting

Confusion Matrix

  • Accuracy: ratio of correct predictions over all actual obs. \(\frac{TP+TN}{A0+A1}\) = \(\frac{TP+TN}{P0+P1}\)
  • Sensitivity=Recall=True Positive Rate: # of correct ‘1’ s over all actual ’1’s. \(\frac{TP}{A1}\) = \(\frac{TP}{TP+FN}\).
  • Specificity : # of correct ‘0’ s over all actual ‘0’ s. \(\frac{TN}{A0}\) = \(\frac{TN}{TN+FP}\)
  • Precision: # of correct ‘1’ s over all predicted ‘1’ s. \(\frac{TP}{P1}\) = \(\frac{TP}{TP+FP}\)
  • F-score: \(\frac{2\times precision \ \times\ recall }{precision + recall}\)

Naive Bayes Classifier

\(X: X_1,X_2,...X_p\)
Predicted label is \(Y\)

Bayes theory: \[ P(Y|X) = \frac{P(X|Y)P(Y)}{P(X)} \]

Naive Bayes: (ignore the dependence)
\[ P(X_1,X_2,...X_p|Y) = P(X_1|Y)P(X_2|Y)...P(X_P|Y) \\ \] \[ P(Y=1|X_1,X_2,..X_p) = \frac{P(X_1,X_2,...X_p|Y=1) P(Y=1)}{P(X_1)P(X_2)...P(X_p)} \\ P(Y=0|X_1,X_2,..X_p) = \frac{P(X_1,X_2,...X_p|Y=0) P(Y=0)}{P(X_1)P(X_2)...P(X_p)} \] and \(P(Y=1|X)P(X) + P(Y=0|X)P(X) = 1\)

if the Variable is numerical, we use PDF.

\[ PDF= f(x|\mu,\sigma^2) = \frac{1}{\sqrt{2\pi\sigma^2}}e^{-\frac{(x-\mu)^2}{2\sigma^2}} \] \[ Pr(X|Y=1)= \frac{1}{\sqrt{2\pi\sigma_{y=1}^2}}e^{-\frac{(X-\mu_{y=1})^2}{2\sigma_{y=1}^2}} \\ Pr(X|Y=0)= \frac{1}{\sqrt{2\pi\sigma_{y=0}^2}}e^{-\frac{(X-\mu_{y=0})^2}{2\sigma_{y=0}^2}} \\ \]

KNN

KNN dose not require training. All of the methods that needs to calculate the distance, requires normalization.

Estimates conditional distribution of y given x and then classifies a given observation to the class with highest probability.

Step 1: Pick integer K.
Step 2: for \(x_0\) (test observation), identify K points in the data that are closet to the \(x_0\) (\(N_0\)).
Step3: Estimate the conditional probability for each class j, as the fraction of points, in \(N_0\), whose response values equal to j. \[ Pr(y=j|X=x_0) = \frac{1}{K} \sum_{i\in N_0} (I(y_i=j)) \] Step4: Apply bayes rule, classifiy to the class with larger probability.

Resampling Methods

Resampling methods: Draw samples from a training set, to fit the same statistical method multiple times using different subset of the training data.

Resampling Methods:
1. Validation Set Approach
2. Cross Validation
3. Bootstrap
- Evaluating models performance -> model assessment
- Selecting the proper level of complexity -> model selection

Validation Set Approach

We explore the use of the validation set approach in order to estimate the test error rates that result from fitting various linear models on the Auto data set.

  • test error rate can be highly variable
  • only a subset of the observations are used to fit the model

Leave-One-Out Cross-Validation (LOOCV)

LOOCV has a couple of major advantages:

  • First, it has far less bias.
  • Second,there is no randomness in the training/validation set splits.

drawbacks:

  • expensive to implement
  • very time consuming
  • uses too much computational power

LOOCV is a very general method, and can be used with any kind of predictive modeling.

K-Fold Cross-Validation

k-fold CV. This approach involves randomly dividing the set of observations into k groups, or folds, of approximately equal size.

LOOCV is a special case of k-fold CV in which k is set to equal n. 

advantages:

  • The most obvious advantage is computational.

there is some variability in the CV, But this variability is typically much lower than the variability in the test error estimates that results from the validation set approach

CV can be used for model selection : find the location of the minimum point in the estimated test MSE curve.

\[ CV_{k} = \frac{1}{k} \sum_{i=1}^k {MSE_k} \] \[ CV_{k} = \frac{1}{k} \sum_{i=1}^k {Err_k} \] where \(Err_k = I(Y_i \ne \hat Y)\).

Bootstrap

Randomly select, with replacement, n obs from training dataset. invest in \(X,Y\) (there is some variability). We want: \[ minimize \ Var(\alpha X+(1-\alpha)Y) \\ minimize \ \hat \alpha = \frac{\hat \sigma_Y^2 - \hat \sigma_{XY}}{\hat \sigma_X^2+\hat \sigma_Y^2-2\hat \sigma_{XY}} \] where: \(\hat \sigma_Y^2 = Var(Y), \hat \sigma_X^2 = Var(X),\hat \sigma_{XY} = Cov(X,Y)\) we estimate \(\alpha\) using historical data (train data).

the bootstrap approach allows us to use a computer to emulate the process of obtaining new sample sets, so that we can estimate the variability of ˆα without generating additional samples.

Rather than repeatedly obtaining independent data sets from the population, we instead obtain distinct data sets by repeatedly sampling observations from the original data set.

Tree Based Methods

Decision Tree: Classification Tree + Regression Tree
Logic: Segment the predictor space into a number of Simple Rectangle Regions.

Regression Tree

The goal is to find rectangles (boxes) \(R_1,R_2,...R_J\) that minimizes the RSS given by:

\[ RSS = \sum_{j=1}^J \sum_{i \in R_J} (y_i - \hat y_{Rj})^2 \] \(R_1,R_2,R_3...\) - terminal nodes, leaf nodes.
\(\hat y_{Rj}\) mean response for the training observations within \(j\)th Rectangle (terminal node).

Recursive Binary Splitting (Greedy):
Pick \(X_j\) and the cut pint \(s\), so that it will devide the area to : \(R_1 = \{X|X_j <s\}\) and \(R_2 = \{X|X_j \ge s \}\) . \[ RSS_{R_1} = \sum_{i \in R_1} (y_i - \hat y_{i})^2 \\ RSS_{R_2} = \sum_{i \in R_2} (y_i - \hat y_{i})^2 \\ \text{total RSS from this split}\ RSS = RSS_{R_1} + RSS_{R_2} \]

and we seek the value of \(X_j\) and \(s\) that minimize the total RSS.

We use RSS a method to pick \(X_j\) when split.

Classification Tree

Instead of RSS, in classification tree we use impurety measure to pick the \(X_j\) that minimizes the impurity.

impurity measures are: \[ \text{error rate} \ E=1-\underset{k}{max} (\hat p_k) \\ \text{Gini index} \ G=1-\sum_{k=1}^mp_k^2 \\ \text{Entropy} \ E=-\sum_{k=1}^m p_k log_2(p_k)\\ \text{Deviance} \ D=-2\sum_{k=1}^m n_k ln(p_k)\\ \] \(p_k\) -> propertion of the training obs belong to class m.
\(n_k\) -> number of training obs belong to class m.

When the values are smaller, much better (much pure)

Tree Pruning

The trees might overfit, this is because the resulting tree might be too complex. Smaller tree with fewer splits ( fewer regions) might led to:
- lower variance
- better interpretation ( at the cost of a little bit bias)

Build a Large Tree \(T_0\) -> Prune -> Sub Tree \(T\).

How do we determind the best way to prune the tree? Intuitivly our goal is to select a sub tree that leads to the lowest test error rate (with cv let’s say).

A sequence of Trees indexed by a non negative tuning parameter \(\alpha\), for each value of \(\alpha\) corresponds a sub tree \(T \in T_o\) such that: \[ \sum_{m=1}^{|T|} \sum_{i:i\in R_m} (y_i-\hat y_{R_m})2 + \alpha |T| \]

\(|T|\) # of terminal nodes of the tree T. \(R_m\) is the rectangle corresponding to the \(m\)th terminal node. \(\hat y_{R_m}\) is the predicted response associated with R_m.

when \(\alpha\) increases there is a price to pay for having a tree with many terminal nodes.

we can select a value of \(\alpha\) using a validation set or using CV approach then return to the full data set and obtain the subtree with corresponding \(\alpha\) or tree size.

Ansemble methods : Begging, RF, Boosting

An enseble method is an approach that combines many simple “building block” models in order to obtain a single and potentially very powerful model.

for Beg,RF,Boost those building block is the “regression or classification tree”.

Begging

Bootstrap Aggregation or Begging is a general purpose procedure for reducing the variance of a statistical learning method.

Averaging a set of observation, reduces variance.

Begging: We use Bootstrap, take repeated samples from the single training data set so that we generate B different Bootstrapped training dataset, and we do aggregation (build a separate prediction model using each training set and average the resulting predictions) \[ \hat f_{bag(x)} = \frac{1}{B} \sum_{b=1}^B \hat f_b(x) \] begging can improve predictions.

  1. Split Data: \(D\) -> \(D_T\), \(D_V\), \(len(D_T)=B\)
  2. Bootstrap: \(DT\) -> \(B_1,B_2,B_3,...B_B\)
  3. Train: \(B_1 -> \hat f_1\),…,\(B_B -> \hat f_B\)
  4. Predict(CV/OOB): \(\hat f_1 -> \hat y_1\),…,\(\hat f_B -> \hat y_B\)
  5. Aggregate: \(\hat y = \frac{1}{B}\sum_b^B\hat y_b\) or \(\hat y =\text{Majority Vote}\)

Begging = Bootstrapping + Aggregation

ADV: - averaging reduces variance. - test error rate is lower than test error rate of single tree

OOB-Error

It turns out that there is a very strightforward way to estimate the test error of a begged model, without the need to perform CV.

Each bagged tree \(B_b\) makes use of around 2/3 of the observations. Remaining 1/3 of the observations not used to fit a given bagged tree are referred to as the out-of-bag observations.

So we can use OOB observations for testing, when number of B is sufficiently large, OOB error is visually equivelent to LOOCV error.

OOB error testing is better because is uses observations that model has not seen to test the model.

Variable Importance

Bagging: - ADV: Improve accuracy than single tree - DAV: Difficult to interpret.

VarIMP: - On regression: For each bag, we record the amount of RSS decrease due to split over a given predictor, then we take average on all B trees. - On classification: For each bag, we record the amount of Impurity decrease due to split over a given predictor, then we take average on all B trees.

Random Forest

Random Forest provides an improvment over bagged tree by a way of a small teak – that decorrelates the tree.

In RF, a fresh sample of m predictors is taken randomly on each split. typically \(m=\sqrt{p}\). RF eliminates the affects of very strong predictors by randomly picking inoput predictors.

If there is strong predictors, then almost in all B trees , will use this predictor to split the tree, resulting tees are very much correlated.

averaging many highly correlated quantities dose not lead to as large of reduction in variance.

RF: adds a step tp decorrelates the tree. RF: reduction in both test error and OOB-error over bagging. Bagging,RF: will not overfit if we increase number of B.

  1. Split Data: \(D\) -> \(D_T\), \(D_V\), \(len(D_T)=B\)
  2. Bootstrap: \(DT\) -> \(B_1,B_2,B_3,...B_B\)
  3. Decorrelate X: rnd from \(\{X_1,X_2,...X_p\}\) pick \(\{X_1,X_2,...X_m\}\).
  4. Train: \(B_1 -> \hat f_1\),…,\(B_B -> \hat f_B\)
  5. Predict(CV/OOB): \(\hat f_1 -> \hat y_1\),…,\(\hat f_B -> \hat y_B\)
  6. Aggregate: \(\hat y = \frac{1}{B}\sum_b^B\hat y_b\) or \(\hat y =\text{Majority Vote}\)

Boosting

Yet another approach for improving the predictions resuylting from a decision tree.

bagging involves creating multiple copies of the original training data set using the bootstrap, fitting a separate decision tree to each copy, and then combining all of the trees in order to create a single predictive model.

trees are grown sequentially : each tree is grown using information from previously grown trees. Boosting does not involve bootstrap sampling; instead each tree is fit on a modified version of the original data set.

Boosting: - learns slow, with stumps (weak learner) - fit a tree using the current residuals rather than the outcome Y, we then add this new decision tree into fitted function in order to update the residuals.
\[ \hat f(x) = \hat f(x) + \lambda \hat f_b(x) \\ r_i <- r_i - \lambda \hat f_b (x_i) \\ \hat f(x)=\sum_{b-1}^B(\lambda \hat f_b(x)) \] 1. Unlike bagging and random forest, Boosting can overfit if B is too large. 2. Shrinkage controlls the learning rate (lamda) 3. Often we split the each tree to stumps ( each involves onlya single variable)

Using stumps leads to additive model.

LS0tCnRpdGxlOiAiTVQtUmV2aWV3IEdlbmVyaWMiCm91dHB1dDogaHRtbF9ub3RlYm9vawpkYXRlOiAyMDIzLTA1LTA4CmF1dGhvcjogQXphdAotLS0KCiMjIEdlbmVyYWwgCgpTdGF0aXN0aWNhbCBMZWFybmluZyAoRGF0YSBtaW5pbmcpIG1ldGhvZHMgY2FuIGJlIGNsYXNzaWZpZWQgYXMgYHN1cGVydmlzZWRgIG9yIGB1bnN1cGVydmlzZWQuYCAgICAgCgokWCQgLT4gcHJlZGljdG9ycywgaW5kZXBlbmRlbnQgdmFyaWFibGVzLCBmZWF0dXJlcywgdmFyaWFibGVzLiAgCiRZJCAtPiByZXNwb25zZSwgZGVwZW5kZW50IHZhcmlhYmxlLiAgICAKJFggPSAoWF8xLFhfMiwuLi4sWF9wKSQgYW5kICRZJCAtPiAkWSA9IGYoWCkgKyBcZXBzaWxvbiQsCiRcZXBzaWxvbiQgaXMgYSByYW5kb20gZXJyb3IgdGVybSBhbmQgaGFzIG1lYW4gemVyby4gRGF0YSBtaW5pbmcgcmVmZXJzIHRvIGEgc2V0IG9mIGFwcHJvYWNoZXMgdG8gZXN0aW1hdGUgJGYkLiAgICAKCldlIGVzdGltYXRlICRmJCB0byA6ICAgICAgICAgCjEuIHByZWRpY3Rpb24uICRcaGF0IFkgPSBcaGF0IGYoWCkkICAgCjIuIGluZmVyZW5jZS4gKCBsZWFybiB0aGUgcmVsYXRpb25zaGlwICkgICAgCgpUaGUgYWNjdXJhY3kgb2YgJFxoYXQgWSQgYXMgYSBwcmVkaWN0aW9uIGZvciAkWSQgZGVwZW5kcyBvbjogICAgCjEuIHJlZHVjaWJsZSBlcnJvciAgICAKMi4gaXJyZWR1Y2libGUgZXJyb3IgICAgCiFbXShhc3NldHMvZXJyb3ItcmVkLWlyci5wbmcpICAgICAKCmBvdmVyZml0dGluZ2AgLT4gSXQgaXMgYW4gdW5kZXNpcmFibGUgc2l0dWF0aW9uIGJlY2F1c2UKdGhlIGZpdCBvYnRhaW5lZCB3aWxsIG5vdCB5aWVsZCBhY2N1cmF0ZSBlc3RpbWF0ZXMgb2YgdGhlIHJlc3BvbnNlIG9uIG5ldyBvYnNlcnZhdGlvbnMgdGhhdCB3ZXJlIG5vdCBwYXJ0IG9mIHRoZSBvcmlnaW5hbCB0cmFpbmluZyBkYXRhIHNldC4KCiMjIyBUcmFkZS1PZmYgYmV0d2VlbiBQcmVkaWN0aW9uIEFjY3VyYWN5IGFuZCBNb2RlbCBJbnRlcnByZXRhYmlsaXR5IAoKYERUYCBpcyBnb29kIGZvciBpbnRlcnByZXRpbmcuICAgIApgQmFnZ2luZ2AsIGBCb29zdGluZ2AsIGBSRmAgaGFzIGhpZ2hlciBBY2N1cmFjeSwgaGFyZCB0byBpbnRlcnByZXQuCgojIyMgU3VwZXJ2aXNlZCB2cyBVbnN1cGVydmlzZWQKLSBgc3VwZXJ2aXNlZGAgLSBmb3IgZWFjaCBvYnNlcnZhdGlvbiBvZiB0aGUgcHJlZGljdG9yIG1lYXN1cmVtZW50KHMpICR4X2ksIGk9MSwuLi5uJCB0aGVyZSBpcyBhbiBhc3NvY2lhdGVkIHJlc3BvbnNlIG1lYXN1cmVtZW50ICR5X2kkIC0+IHByZWRpY3QgJFkkIG9yIGxlYXJuIHJlbGF0aW9uc2hpcCBiZXR3ZWVuICRYJCBhbmQgJFkkIC4KLSBgdW5zdXBlcnZpc2VkYCAtIGZvciBlYWNoIG9ic2VydmF0aW9ucyAkeF9pLCBpPTEsLi4ubiQgd2Ugb2JzZXJ2ZSBhIHZlY3RvciBvZiBtZWFzdXJlbWVudHMgJHhfaSQgYnV0ICoqbm8qKiBhc3NvY2lhdGVkIHJlc3BvbnNlICR5X2kkIC0+IHVuZGVyc3RhbmQgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlICRYX2kkcyBvciBvYnNlcnZhdGlvbnMuICAgICAKCiMjIyBSZWdyZXNzaW9uIHZzIENsYXNzaWZpY2F0aW9uICAgIApgcmVncmVzc2lvbmAgLT4gcXVhbnRpdGF0aXZlIHJlc3BvbnNlLCBudW1lcmljYWwgcmVzcG9uc2UgICAKYGNsYXNzaWZpY2F0aW9uYCAtPiBxdWFsaXRhdGl2ZSByZXNwb25zZSwgY2F0ZWdvcmljYWwgcmVzcG9uc2UgIAoKIyMjIE1vZGVsIEFjY3VyYWN5CgojIyMjIFJlZ3Jlc3Npb24KCiQkCk1TRSA9IFxmcmFjezF9e259IFxzdW1fe2k9MX1ebiB7KHlfaSAtIFxoYXQgZih4X2kpKV4yfQokJAp3aGVyZSAkXGhhdCBmKHhfaSkgLT4gXGhhdCB5X2kkICh0aGUgcHJlZGljdGlvbikuCgp3ZSBhcmUgaW50ZXJlc3RlZCBpbiB0aGUgYWNjdXJhY3kgb2YgdGhlIHByZWRpY3Rpb25zIHRoYXQgd2Ugb2J0YWluIHdoZW4gd2UgYXBwbHkgb3VyIG1ldGhvZCB0byBwcmV2aW91c2x5IHVuc2VlbiB0ZXN0IGRhdGEuIHRoZXJlIGlzIG5vIGd1YXJhbnRlZSB0aGF0IHRoZSBtZXRob2Qgd2l0aCB0aGUgbG93ZXN0IHRyYWluaW5nIE1TRSB3aWxsIGFsc28gaGF2ZSB0aGUgbG93ZXN0IHRlc3QgTVNFLiAgIAoKV2hlbiBhIGdpdmVuIG1ldGhvZCB5aWVsZHMgYSBzbWFsbCB0cmFpbmluZyBNU0UgYnV0IGEgbGFyZ2UgdGVzdCBNU0UsIHdlIGFyZSBzYWlkIHRvIGJlIGBvdmVyZml0dGluZyB0aGUgZGF0YWAuICAgIAoKQ3Jvc3MtVmFsaWRhdGlvbiAoQ1YpIGNhbiBiZSB1c2VkIHRvICoqZXN0aW1hdGUqKiB0aGUgdGVzdCBNU0Ugb24gdGhlIHRyYWluaW5nIGRhdGEuCgojIyMjIENsYXNzaWZpY2F0aW9uCgpFcnJvciByYXRlOgokJAplcnJvciByYXRlID0gXGZyYWN7MX17bn0gXHN1bV97aT0xfV5uIHt5X2kgXG5lIFxoYXQgeV9pfQokJApCYXllcyBDbGFzc2lmaWVyOiAKJCQKUHIoWT1rfFg9eCkgXFwKUHIoWT0xfFg9eCkgPiAwLjUgXCBcdGhlcmVmb3JlIGs9MQokJApLTk4gCiQkClByKFk9anxYPXhfMCkgPSBcZnJhY3sxfXtLfSBcc3VtX3tpXGluIE5fMH17SSh5X2k9ail9CiQkCiROXzAkIC0+IEsgcG9pbnRzIGluIHRoZSB0cmFpbmluZyBkYXRhIHRoYXQgYXJlIGNsb3NldCB0byAkeF8wJCAKCiMjIyBUaGUgQmlhcy1WYXJpYW5jZSBUcmFuZGUtT2ZmIAoKRXhwZWN0ZWQgdGVzdCBNU0UgZm9yIGEgZ2l2ZW4gdmFsdWUgJHhfMCQgY2FuIGJlIGdpdmVuIGFzOgohW10oYXNzZXRzL2V4cC1lcnIucG5nKSAgIAoKSW4gb3JkZXIgdG8gbWluaW1pemUgdGhlIGV4cGVjdGVkIHRlc3QgZXJyb3IsCndlIG5lZWQgdG8gc2VsZWN0IGEgc3RhdGlzdGljYWwgbGVhcm5pbmcgbWV0aG9kIHRoYXQgc2ltdWx0YW5lb3VzbHkgYWNoaWV2ZXMgYGxvdyB2YXJpYW5jZWAgYW5kIGBsb3cgYmlhc2AuICAgIAotIGBWYXJpYW5jZWAgLT4gVmFyaWFuY2UgcmVmZXJzIHRvIHRoZSBhbW91bnQgYnkgd2hpY2ggJFxoYXQgZiQgd291bGQgY2hhbmdlIGlmIHdlIGVzdGltYXRlZCBpdCB1c2luZyBhIGRpZmZlcmVudCB0cmFpbmluZyBkYXRhIHNldC4gKGR1ZSB0byByYW5kb21uZXNzIG9uIGRhdGEpIAotIGBCaWFzYCAtPiBiaWFzIHJlZmVycyB0byB0aGUgZXJyb3IgdGhhdCBpcyBpbnRyb2R1Y2VkIGJ5IGFwcHJveGltYXRpbmcgYSByZWFsLWxpZmUgcHJvYmxlbSwgd2hpY2ggbWF5IGJlIGV4dHJlbWVseSBjb21wbGljYXRlZCwgYnkgYSBtdWNoIHNpbXBsZXIgbW9kZWwuIChkdWUgdG8gc2ltcGxpZmljYXRpb24pIAoKbW9kZWwgaXMgdG9vIHNpbXBsZSAtPiBoaWdoIGJpYXMgKGp1c3QgdXNlIHNldmVyYWwgJFhfaSQpICAgCm1vZGVsIGlzIHRvbyBjb21wbGV4IC0+IGxvdyBiaWFzICh1c2UgdG9vIG11Y2ggJFhfaSQsIG92ZXJmaXR0aW5nKSAgICAKCiMjIENsYXNzaWZpY2F0aW9uIAoKUmVzcG9uc2UgdmFyaWFibGUgaXMgcXVhbGl0YXRpdmUuICAgCnNpbXBsZTogICAgCi0gTmFpdmUgQmF5ZXMgICAKLSBLTk4KCmNvbXB1dGVyIGludGVuc2l2ZTogICAKICAtIERUICAgIAogIC0gQmVnZ2luZyAgIAogIC0gUkYgICAgCiAgLSBCb29zdGluZyAgICAKCiMjIyBDb25mdXNpb24gTWF0cml4ICAgIAohW10oYXNzZXRzL2NtLnBuZykKCi0gQWNjdXJhY3k6IHJhdGlvIG9mIGNvcnJlY3QgcHJlZGljdGlvbnMgb3ZlciBhbGwgYWN0dWFsIG9icy4gJFxmcmFje1RQK1ROfXtBMCtBMX0kID0gJFxmcmFje1RQK1ROfXtQMCtQMX0kIAotIFNlbnNpdGl2aXR5PVJlY2FsbD1UcnVlIFBvc2l0aXZlIFJhdGU6ICMgb2YgY29ycmVjdCAnMScgcyBvdmVyIGFsbCBhY3R1YWwgJzEncy4gJFxmcmFje1RQfXtBMX0kID0gJFxmcmFje1RQfXtUUCtGTn0kLiAgIAotIFNwZWNpZmljaXR5IDogIyBvZiBjb3JyZWN0ICcwJyBzIG92ZXIgYWxsIGFjdHVhbCAnMCcgcy4gJFxmcmFje1ROfXtBMH0kID0gJFxmcmFje1ROfXtUTitGUH0kICAKLSBQcmVjaXNpb246ICMgb2YgY29ycmVjdCAnMScgcyBvdmVyIGFsbCBwcmVkaWN0ZWQgJzEnIHMuICRcZnJhY3tUUH17UDF9JCA9ICRcZnJhY3tUUH17VFArRlB9JCAKLSBGLXNjb3JlOiAkXGZyYWN7Mlx0aW1lcyBwcmVjaXNpb24gXCBcdGltZXNcICByZWNhbGwgfXtwcmVjaXNpb24gKyByZWNhbGx9JCAgCgojIyMgTmFpdmUgQmF5ZXMgQ2xhc3NpZmllciAKJFg6IFhfMSxYXzIsLi4uWF9wJCAgClByZWRpY3RlZCBsYWJlbCBpcyAkWSQgIAoKQmF5ZXMgdGhlb3J5OiAKJCQKUChZfFgpID0gXGZyYWN7UChYfFkpUChZKX17UChYKX0KJCQKCmBOYWl2ZWAgQmF5ZXM6IChpZ25vcmUgdGhlIGRlcGVuZGVuY2UpICAgIAokJApQKFhfMSxYXzIsLi4uWF9wfFkpID0gUChYXzF8WSlQKFhfMnxZKS4uLlAoWF9QfFkpIFxcCiQkCiQkClAoWT0xfFhfMSxYXzIsLi5YX3ApID0gXGZyYWN7UChYXzEsWF8yLC4uLlhfcHxZPTEpIFAoWT0xKX17UChYXzEpUChYXzIpLi4uUChYX3ApfSBcXApQKFk9MHxYXzEsWF8yLC4uWF9wKSA9IFxmcmFje1AoWF8xLFhfMiwuLi5YX3B8WT0wKSBQKFk9MCl9e1AoWF8xKVAoWF8yKS4uLlAoWF9wKX0gCiQkCmFuZCAkUChZPTF8WClQKFgpICsgUChZPTB8WClQKFgpID0gMSQgCgppZiB0aGUgVmFyaWFibGUgaXMgbnVtZXJpY2FsLCB3ZSB1c2UgUERGLiAKCiQkClBERj0gZih4fFxtdSxcc2lnbWFeMikgPSBcZnJhY3sxfXtcc3FydHsyXHBpXHNpZ21hXjJ9fWVeey1cZnJhY3soeC1cbXUpXjJ9ezJcc2lnbWFeMn19CiQkCiQkClByKFh8WT0xKT0gXGZyYWN7MX17XHNxcnR7MlxwaVxzaWdtYV97eT0xfV4yfX1lXnstXGZyYWN7KFgtXG11X3t5PTF9KV4yfXsyXHNpZ21hX3t5PTF9XjJ9fSBcXApQcihYfFk9MCk9IFxmcmFjezF9e1xzcXJ0ezJccGlcc2lnbWFfe3k9MH1eMn19ZV57LVxmcmFjeyhYLVxtdV97eT0wfSleMn17MlxzaWdtYV97eT0wfV4yfX0gXFwKJCQKCiMjIyBLTk4KCktOTiBkb3NlIG5vdCByZXF1aXJlIHRyYWluaW5nLiAKQWxsIG9mIHRoZSBtZXRob2RzIHRoYXQgbmVlZHMgdG8gY2FsY3VsYXRlIHRoZSBkaXN0YW5jZSwgcmVxdWlyZXMgbm9ybWFsaXphdGlvbi4KCkVzdGltYXRlcyBjb25kaXRpb25hbCBkaXN0cmlidXRpb24gb2YgeSBnaXZlbiB4IGFuZCB0aGVuIGNsYXNzaWZpZXMgYSBnaXZlbiBvYnNlcnZhdGlvbiB0byB0aGUgY2xhc3Mgd2l0aCBoaWdoZXN0IHByb2JhYmlsaXR5LgoKU3RlcCAxOiBQaWNrIGludGVnZXIgSy4gIApTdGVwIDI6IGZvciAkeF8wJCAodGVzdCBvYnNlcnZhdGlvbiksIGlkZW50aWZ5IEsgcG9pbnRzIGluIHRoZSBkYXRhIHRoYXQgYXJlIGNsb3NldCB0byB0aGUgJHhfMCQgKCROXzAkKS4gICAgClN0ZXAzOiBFc3RpbWF0ZSB0aGUgY29uZGl0aW9uYWwgcHJvYmFiaWxpdHkgZm9yIGVhY2ggY2xhc3MgaiwgYXMgdGhlIGZyYWN0aW9uIG9mIHBvaW50cywgaW4gJE5fMCQsIHdob3NlIHJlc3BvbnNlIHZhbHVlcyBlcXVhbCB0byBqLgokJApQcih5PWp8WD14XzApID0gXGZyYWN7MX17S30gXHN1bV97aVxpbiBOXzB9IChJKHlfaT1qKSkKJCQKU3RlcDQ6IEFwcGx5IGJheWVzIHJ1bGUsIGNsYXNzaWZpeSB0byB0aGUgY2xhc3Mgd2l0aCBsYXJnZXIgcHJvYmFiaWxpdHkuCgohW10oYXNzZXRzL2tubi5wbmcpCgojIyBSZXNhbXBsaW5nIE1ldGhvZHMgICAKClJlc2FtcGxpbmcgbWV0aG9kczogRHJhdyBzYW1wbGVzIGZyb20gYSB0cmFpbmluZyBzZXQsIHRvIGZpdCB0aGUgc2FtZSBzdGF0aXN0aWNhbCBtZXRob2QgbXVsdGlwbGUgdGltZXMgdXNpbmcgZGlmZmVyZW50IHN1YnNldCBvZiB0aGUgdHJhaW5pbmcgZGF0YS4KClJlc2FtcGxpbmcgTWV0aG9kczogICAKMS4gVmFsaWRhdGlvbiBTZXQgQXBwcm9hY2ggICAgCjIuIENyb3NzIFZhbGlkYXRpb24gICAgICAgICAKMy4gQm9vdHN0cmFwICAgICAgICAgICAKLSBFdmFsdWF0aW5nIG1vZGVscyBwZXJmb3JtYW5jZSAtPiBtb2RlbCBhc3Nlc3NtZW50ICAgIAotIFNlbGVjdGluZyB0aGUgcHJvcGVyIGxldmVsIG9mIGNvbXBsZXhpdHkgLT4gbW9kZWwgc2VsZWN0aW9uIAoKIyMjIFZhbGlkYXRpb24gU2V0IEFwcHJvYWNoCgpXZSBleHBsb3JlIHRoZSB1c2Ugb2YgdGhlIHZhbGlkYXRpb24gc2V0IGFwcHJvYWNoIGluIG9yZGVyIHRvIGVzdGltYXRlIHRoZQp0ZXN0IGVycm9yIHJhdGVzIHRoYXQgcmVzdWx0IGZyb20gZml0dGluZyB2YXJpb3VzIGxpbmVhciBtb2RlbHMgb24gdGhlIEF1dG8KZGF0YSBzZXQuCgohW10oYXNzZXRzL3ZhbC1zZXQucG5nKSAgICAgICAgIAoKLSB0ZXN0IGVycm9yIHJhdGUgY2FuIGJlIGhpZ2hseSB2YXJpYWJsZQotIG9ubHkgYSBzdWJzZXQgb2YgdGhlIG9ic2VydmF0aW9ucyBhcmUgdXNlZCB0byBmaXQgdGhlIG1vZGVsCgojIyMgTGVhdmUtT25lLU91dCBDcm9zcy1WYWxpZGF0aW9uIChMT09DVikgICAgCgpMT09DViBoYXMgYSBjb3VwbGUgb2YgbWFqb3IgKiphZHZhbnRhZ2VzKio6CgogLSBGaXJzdCwgaXQgaGFzIGZhciBsZXNzIGJpYXMuICAgCiAtIFNlY29uZCx0aGVyZSBpcyBubyByYW5kb21uZXNzIGluIHRoZSB0cmFpbmluZy92YWxpZGF0aW9uCnNldCBzcGxpdHMuICAgICAKCioqZHJhd2JhY2tzKio6CgotIGV4cGVuc2l2ZSB0byBpbXBsZW1lbnQKLSB2ZXJ5IHRpbWUgY29uc3VtaW5nCi0gdXNlcyB0b28gbXVjaCBjb21wdXRhdGlvbmFsIHBvd2VyCgpMT09DViBpcyBhIHZlcnkgZ2VuZXJhbCBtZXRob2QsIGFuZCBjYW4gYmUgdXNlZCB3aXRoIGFueSBraW5kIG9mCnByZWRpY3RpdmUgbW9kZWxpbmcuCgohW10oYXNzZXRzL2xvb2N2LnBuZykgIAoKIyMjIEstRm9sZCBDcm9zcy1WYWxpZGF0aW9uICAgCgprLWZvbGQgQ1YuIFRoaXMgYXBwcm9hY2ggaW52b2x2ZXMgcmFuZG9tbHkgZGl2aWRpbmcgdGhlIHNldCBvZiBvYnNlcnZhdGlvbnMgaW50byBrIGdyb3Vwcywgb3IgZm9sZHMsIG9mIGFwcHJveGltYXRlbHkgZXF1YWwgc2l6ZS4gCgpMT09DViBpcyBhIHNwZWNpYWwgY2FzZSBvZiBrLWZvbGQgQ1YgaW4gd2hpY2ggayBpcyBzZXQgdG8gZXF1YWwgbi4gCgoqKmFkdmFudGFnZXM6KiogCgotIFRoZSBtb3N0IG9idmlvdXMgYWR2YW50YWdlIGlzIGNvbXB1dGF0aW9uYWwuCgoKdGhlcmUgaXMgc29tZSB2YXJpYWJpbGl0eSBpbiB0aGUgQ1YsIEJ1dCB0aGlzIHZhcmlhYmlsaXR5IGlzIHR5cGljYWxseQptdWNoIGxvd2VyIHRoYW4gdGhlIHZhcmlhYmlsaXR5IGluIHRoZSB0ZXN0IGVycm9yIGVzdGltYXRlcyB0aGF0IHJlc3VsdHMgZnJvbQp0aGUgdmFsaWRhdGlvbiBzZXQgYXBwcm9hY2ggCgoKQ1YgY2FuIGJlIHVzZWQgZm9yIG1vZGVsIHNlbGVjdGlvbiA6IGZpbmQgdGhlIGxvY2F0aW9uIG9mIHRoZSBtaW5pbXVtIHBvaW50IGluIHRoZSBlc3RpbWF0ZWQgdGVzdCBNU0UgY3VydmUuCgoKJCQKQ1Zfe2t9ID0gXGZyYWN7MX17a30gXHN1bV97aT0xfV5rIHtNU0Vfa30KJCQKJCQKQ1Zfe2t9ID0gXGZyYWN7MX17a30gXHN1bV97aT0xfV5rIHtFcnJfa30gCiQkCndoZXJlICRFcnJfayA9IEkoWV9pIFxuZSBcaGF0IFkpJC4gICAgCgojIyMgQm9vdHN0cmFwICAgCgpSYW5kb21seSBzZWxlY3QsIHdpdGggcmVwbGFjZW1lbnQsIG4gb2JzIGZyb20gdHJhaW5pbmcgZGF0YXNldC4gCmludmVzdCBpbiAkWCxZJCAodGhlcmUgaXMgc29tZSB2YXJpYWJpbGl0eSkuIFdlIHdhbnQ6IAokJAptaW5pbWl6ZSBcIFZhcihcYWxwaGEgWCsoMS1cYWxwaGEpWSkgXFwKbWluaW1pemUgXCBcaGF0IFxhbHBoYSA9IFxmcmFje1xoYXQgXHNpZ21hX1leMiAtIFxoYXQgXHNpZ21hX3tYWX19e1xoYXQgXHNpZ21hX1heMitcaGF0IFxzaWdtYV9ZXjItMlxoYXQgXHNpZ21hX3tYWX19CiQkCndoZXJlOiAkXGhhdCBcc2lnbWFfWV4yID0gVmFyKFkpLCBcaGF0IFxzaWdtYV9YXjIgPSBWYXIoWCksXGhhdCBcc2lnbWFfe1hZfSA9IENvdihYLFkpJCAKd2UgZXN0aW1hdGUgJFxhbHBoYSQgdXNpbmcgaGlzdG9yaWNhbCBkYXRhICh0cmFpbiBkYXRhKS4gCiFbXShhc3NldHMvYm9vdHN0cmFwLnBuZykKCnRoZSBib290c3RyYXAgYXBwcm9hY2ggYWxsb3dzIHVzCnRvIHVzZSBhIGNvbXB1dGVyIHRvIGVtdWxhdGUgdGhlIHByb2Nlc3Mgb2Ygb2J0YWluaW5nIG5ldyBzYW1wbGUgc2V0cywKc28gdGhhdCB3ZSBjYW4gZXN0aW1hdGUgdGhlIHZhcmlhYmlsaXR5IG9mIMuGzrEgd2l0aG91dCBnZW5lcmF0aW5nIGFkZGl0aW9uYWwKc2FtcGxlcy4KClJhdGhlciB0aGFuIHJlcGVhdGVkbHkgb2J0YWluaW5nIGluZGVwZW5kZW50IGRhdGEgc2V0cyBmcm9tIHRoZQpwb3B1bGF0aW9uLCB3ZSBpbnN0ZWFkIG9idGFpbiBkaXN0aW5jdCBkYXRhIHNldHMgYnkgcmVwZWF0ZWRseSBzYW1wbGluZwpvYnNlcnZhdGlvbnMgZnJvbSB0aGUgb3JpZ2luYWwgZGF0YSBzZXQuCgojIyBUcmVlIEJhc2VkIE1ldGhvZHMgCgpEZWNpc2lvbiBUcmVlOiBDbGFzc2lmaWNhdGlvbiBUcmVlICsgUmVncmVzc2lvbiBUcmVlICAgIApMb2dpYzogU2VnbWVudCB0aGUgcHJlZGljdG9yIHNwYWNlIGludG8gYSBudW1iZXIgb2YgU2ltcGxlIFJlY3RhbmdsZSBSZWdpb25zLgoKLSBEZWNpc2lvbiBUcmVlIEJhc2VkIG1ldGhvZHMgYXJlIHNpbXBsZSBhbmQgdXNlZnVsIGZvciBpbnRlcnByZXRhdGlvbi4gCi0gQmVnZ2luZywgUmFuZG9tIEZvcmVzdCwgQm9vc3RpbmcgcHJvZHVjZXMgbXVsdGlwbGUgdHJlZSB0aGVuIGNvbWJpbmUgdGhlbSB0byB5aWVsZCBhIHNpbmdsZSBjb25zZW5zdXMgcHJlZGljdGlvbi4gICAgCgojIyMgUmVncmVzc2lvbiBUcmVlIAoKVGhlIGdvYWwgaXMgdG8gZmluZCByZWN0YW5nbGVzIChib3hlcykgJFJfMSxSXzIsLi4uUl9KJCB0aGF0IG1pbmltaXplcyB0aGUgUlNTIGdpdmVuIGJ5OgoKJCQKUlNTID0gXHN1bV97aj0xfV5KIFxzdW1fe2kgXGluIFJfSn0gKHlfaSAtIFxoYXQgeV97Ump9KV4yCiQkCiRSXzEsUl8yLFJfMy4uLiQgLSB0ZXJtaW5hbCBub2RlcywgbGVhZiBub2Rlcy4gICAgCiRcaGF0IHlfe1JqfSQgbWVhbiByZXNwb25zZSBmb3IgdGhlIHRyYWluaW5nIG9ic2VydmF0aW9ucyB3aXRoaW4gJGokdGggUmVjdGFuZ2xlICh0ZXJtaW5hbCBub2RlKS4gICAKClJlY3Vyc2l2ZSBCaW5hcnkgU3BsaXR0aW5nIChHcmVlZHkpOiAgICAKUGljayAkWF9qJCBhbmQgdGhlIGN1dCBwaW50ICRzJCwgc28gdGhhdCBpdCB3aWxsIGRldmlkZSB0aGUgYXJlYSB0byA6ICAgJFJfMSA9IFx7WHxYX2ogPHNcfSQgIGFuZCAkUl8yID0gXHtYfFhfaiBcZ2UgcyBcfSQgLgokJApSU1Nfe1JfMX0gPSBcc3VtX3tpIFxpbiBSXzF9ICh5X2kgLSBcaGF0IHlfe2l9KV4yIFxcClJTU197Ul8yfSA9IFxzdW1fe2kgXGluIFJfMn0gKHlfaSAtIFxoYXQgeV97aX0pXjIgXFwKXHRleHR7dG90YWwgUlNTIGZyb20gdGhpcyBzcGxpdH1cIFJTUyA9IFJTU197Ul8xfSArIFJTU197Ul8yfQokJAoKYW5kIHdlIHNlZWsgdGhlIHZhbHVlIG9mICRYX2okIGFuZCAkcyQgdGhhdCBgbWluaW1pemVgIHRoZSB0b3RhbCBSU1MuICAgIAoKV2UgdXNlIFJTUyBhIG1ldGhvZCB0byBwaWNrICRYX2okIHdoZW4gc3BsaXQuCgojIyMgQ2xhc3NpZmljYXRpb24gVHJlZSAKCkluc3RlYWQgb2YgUlNTLCBpbiBjbGFzc2lmaWNhdGlvbiB0cmVlIHdlIHVzZSBpbXB1cmV0eSBtZWFzdXJlIHRvIHBpY2sgdGhlICRYX2okIHRoYXQgbWluaW1pemVzIHRoZSBpbXB1cml0eS4KCmltcHVyaXR5IG1lYXN1cmVzIGFyZTogCiQkClx0ZXh0e2Vycm9yIHJhdGV9IFwgRT0xLVx1bmRlcnNldHtrfXttYXh9IChcaGF0IHBfaykgXFwKXHRleHR7R2luaSBpbmRleH0gXCBHPTEtXHN1bV97az0xfV5tcF9rXjIgXFwKXHRleHR7RW50cm9weX0gXCBFPS1cc3VtX3trPTF9Xm0gcF9rIGxvZ18yKHBfaylcXApcdGV4dHtEZXZpYW5jZX0gXCBEPS0yXHN1bV97az0xfV5tIG5fayBsbihwX2spXFwKJCQKJHBfayQgLT4gcHJvcGVydGlvbiBvZiB0aGUgdHJhaW5pbmcgb2JzIGJlbG9uZyB0byBjbGFzcyBtLiAgICAKJG5fayQgLT4gbnVtYmVyIG9mIHRyYWluaW5nIG9icyBiZWxvbmcgdG8gY2xhc3MgbS4KCldoZW4gdGhlIHZhbHVlcyBhcmUgc21hbGxlciwgbXVjaCBiZXR0ZXIgKG11Y2ggcHVyZSkKCiMjIyBUcmVlIFBydW5pbmcgICAgCgpUaGUgdHJlZXMgbWlnaHQgb3ZlcmZpdCwgdGhpcyBpcyBiZWNhdXNlIHRoZSByZXN1bHRpbmcgdHJlZSBtaWdodCBiZSB0b28gY29tcGxleC4gClNtYWxsZXIgdHJlZSB3aXRoIGZld2VyIHNwbGl0cyAoIGZld2VyIHJlZ2lvbnMpIG1pZ2h0IGxlZCB0bzogICAgCi0gbG93ZXIgdmFyaWFuY2UgIAotIGJldHRlciBpbnRlcnByZXRhdGlvbiAoIGF0IHRoZSBjb3N0IG9mIGEgbGl0dGxlIGJpdCBiaWFzKQoKQnVpbGQgYSBMYXJnZSBUcmVlICRUXzAkIC0+IFBydW5lIC0+IFN1YiBUcmVlICRUJC4gCgpIb3cgZG8gd2UgZGV0ZXJtaW5kIHRoZSBiZXN0IHdheSB0byBwcnVuZSB0aGUgdHJlZT8gSW50dWl0aXZseSBvdXIgZ29hbCBpcyB0byBzZWxlY3QgYSBzdWIgdHJlZSB0aGF0IGxlYWRzIHRvIHRoZSBsb3dlc3QgdGVzdCBlcnJvciByYXRlICh3aXRoIGN2IGxldCdzIHNheSkuIAoKQSBzZXF1ZW5jZSBvZiBUcmVlcyBpbmRleGVkIGJ5IGEgbm9uIG5lZ2F0aXZlIHR1bmluZyBwYXJhbWV0ZXIgJFxhbHBoYSQsIGZvciBlYWNoIHZhbHVlIG9mICRcYWxwaGEkIGNvcnJlc3BvbmRzIGEgc3ViIHRyZWUgJFQgXGluIFRfbyQgIHN1Y2ggdGhhdDogCiQkClxzdW1fe209MX1ee3xUfH0gXHN1bV97aTppXGluIFJfbX0gKHlfaS1caGF0IHlfe1JfbX0pMiArIFxhbHBoYSB8VHwKJCQKCiR8VHwkICMgb2YgdGVybWluYWwgbm9kZXMgb2YgdGhlIHRyZWUgVC4KJFJfbSQgaXMgdGhlIHJlY3RhbmdsZSBjb3JyZXNwb25kaW5nIHRvIHRoZSAkbSR0aCB0ZXJtaW5hbCBub2RlLgokXGhhdCB5X3tSX219JCBpcyB0aGUgcHJlZGljdGVkIHJlc3BvbnNlIGFzc29jaWF0ZWQgd2l0aCBSX20uCgp3aGVuICRcYWxwaGEkIGluY3JlYXNlcyB0aGVyZSBpcyBhIHByaWNlIHRvIHBheSBmb3IgaGF2aW5nIGEgdHJlZSB3aXRoIG1hbnkgdGVybWluYWwgbm9kZXMuCgp3ZSBjYW4gc2VsZWN0IGEgdmFsdWUgb2YgJFxhbHBoYSQgdXNpbmcgYSB2YWxpZGF0aW9uIHNldCBvciB1c2luZyBDViBhcHByb2FjaCB0aGVuIHJldHVybiB0byB0aGUgZnVsbCBkYXRhIHNldCBhbmQgb2J0YWluIHRoZSBzdWJ0cmVlIHdpdGggY29ycmVzcG9uZGluZyAkXGFscGhhJCBvciB0cmVlIHNpemUuCgojIyMgQW5zZW1ibGUgbWV0aG9kcyA6IEJlZ2dpbmcsIFJGLCBCb29zdGluZyAKQW4gZW5zZWJsZSBtZXRob2QgaXMgYW4gYXBwcm9hY2ggdGhhdCBjb21iaW5lcyBtYW55IHNpbXBsZSAiYnVpbGRpbmcgYmxvY2siIG1vZGVscyBpbiBvcmRlciB0byBvYnRhaW4gYSBzaW5nbGUgYW5kIHBvdGVudGlhbGx5IHZlcnkgcG93ZXJmdWwgbW9kZWwuCgpmb3IgQmVnLFJGLEJvb3N0IHRob3NlIGJ1aWxkaW5nIGJsb2NrIGlzIHRoZSAicmVncmVzc2lvbiBvciBjbGFzc2lmaWNhdGlvbiB0cmVlIi4gCgojIyMgQmVnZ2luZyAKCkJvb3RzdHJhcCBBZ2dyZWdhdGlvbiBvciBCZWdnaW5nIGlzIGEgZ2VuZXJhbCBwdXJwb3NlIHByb2NlZHVyZSBmb3IgcmVkdWNpbmcgdGhlIHZhcmlhbmNlIG9mIGEgc3RhdGlzdGljYWwgbGVhcm5pbmcgbWV0aG9kLgoKQXZlcmFnaW5nIGEgc2V0IG9mIG9ic2VydmF0aW9uLCByZWR1Y2VzIHZhcmlhbmNlLgoKQmVnZ2luZzogV2UgdXNlIEJvb3RzdHJhcCwgdGFrZSByZXBlYXRlZCBzYW1wbGVzIGZyb20gdGhlIHNpbmdsZSB0cmFpbmluZyBkYXRhIHNldCBzbyB0aGF0IHdlIGdlbmVyYXRlIEIgZGlmZmVyZW50IEJvb3RzdHJhcHBlZCB0cmFpbmluZyBkYXRhc2V0LCBhbmQgd2UgZG8gYWdncmVnYXRpb24gKGJ1aWxkIGEgc2VwYXJhdGUgcHJlZGljdGlvbiBtb2RlbCB1c2luZyBlYWNoIHRyYWluaW5nIHNldCBhbmQgYXZlcmFnZSB0aGUgcmVzdWx0aW5nIHByZWRpY3Rpb25zKQokJApcaGF0IGZfe2JhZyh4KX0gPSBcZnJhY3sxfXtCfSBcc3VtX3tiPTF9XkIgXGhhdCBmX2IoeCkgCiQkCmJlZ2dpbmcgY2FuIGltcHJvdmUgcHJlZGljdGlvbnMuCgoxLiBTcGxpdCBEYXRhOiAkRCQgLT4gJERfVCQsICREX1YkLCAkbGVuKERfVCk9QiQKMi4gQm9vdHN0cmFwOiAkRFQkIC0+ICRCXzEsQl8yLEJfMywuLi5CX0IkCjMuIFRyYWluOiAkQl8xIC0+IFxoYXQgZl8xJCwuLi4sJEJfQiAtPiBcaGF0IGZfQiQKNC4gUHJlZGljdChDVi9PT0IpOiAkXGhhdCBmXzEgLT4gXGhhdCB5XzEkLC4uLiwkXGhhdCBmX0IgLT4gXGhhdCB5X0IkCjUuIEFnZ3JlZ2F0ZTogJFxoYXQgeSA9IFxmcmFjezF9e0J9XHN1bV9iXkJcaGF0IHlfYiQgb3IgJFxoYXQgeSA9XHRleHR7TWFqb3JpdHkgVm90ZX0kCgpCZWdnaW5nID0gQm9vdHN0cmFwcGluZyArIEFnZ3JlZ2F0aW9uIAoKQURWOiAKLSBhdmVyYWdpbmcgcmVkdWNlcyB2YXJpYW5jZS4gCi0gdGVzdCBlcnJvciByYXRlIGlzIGxvd2VyIHRoYW4gdGVzdCBlcnJvciByYXRlIG9mIHNpbmdsZSB0cmVlCgojIyMjIE9PQi1FcnJvcgpJdCB0dXJucyBvdXQgdGhhdCB0aGVyZSBpcyBhIHZlcnkgc3RyaWdodGZvcndhcmQgd2F5IHRvIGVzdGltYXRlIHRoZSB0ZXN0IGVycm9yIG9mIGEgYmVnZ2VkIG1vZGVsLCB3aXRob3V0IHRoZSBuZWVkIHRvIHBlcmZvcm0gQ1YuCgpFYWNoIGJhZ2dlZCB0cmVlICRCX2IkIG1ha2VzIHVzZSBvZiBhcm91bmQgMi8zIG9mIHRoZSBvYnNlcnZhdGlvbnMuIFJlbWFpbmluZyAxLzMgb2YgdGhlIG9ic2VydmF0aW9ucyBub3QgdXNlZCB0byBmaXQgYSBnaXZlbiBiYWdnZWQgdHJlZSBhcmUgcmVmZXJyZWQgdG8gYXMgdGhlIG91dC1vZi1iYWcgb2JzZXJ2YXRpb25zLgoKU28gd2UgY2FuIHVzZSBPT0Igb2JzZXJ2YXRpb25zIGZvciB0ZXN0aW5nLCB3aGVuIG51bWJlciBvZiBCIGlzIHN1ZmZpY2llbnRseSBsYXJnZSwgT09CIGVycm9yIGlzIHZpc3VhbGx5IGVxdWl2ZWxlbnQgdG8gTE9PQ1YgZXJyb3IuCgpPT0IgZXJyb3IgdGVzdGluZyBpcyBiZXR0ZXIgYmVjYXVzZSBpcyB1c2VzIG9ic2VydmF0aW9ucyB0aGF0IG1vZGVsIGhhcyBub3Qgc2VlbiB0byB0ZXN0IHRoZSBtb2RlbC4KCiMjIyMgVmFyaWFibGUgSW1wb3J0YW5jZSAKCkJhZ2dpbmc6IAotIEFEVjogSW1wcm92ZSBhY2N1cmFjeSB0aGFuIHNpbmdsZSB0cmVlCi0gREFWOiBEaWZmaWN1bHQgdG8gaW50ZXJwcmV0LiAKClZhcklNUDoKLSBPbiByZWdyZXNzaW9uOiBGb3IgZWFjaCBiYWcsIHdlIHJlY29yZCB0aGUgYW1vdW50IG9mIFJTUyBkZWNyZWFzZSBkdWUgdG8gc3BsaXQgb3ZlciBhIGdpdmVuIHByZWRpY3RvciwgdGhlbiB3ZSB0YWtlIGF2ZXJhZ2Ugb24gYWxsIEIgdHJlZXMuCi0gT24gY2xhc3NpZmljYXRpb246IEZvciBlYWNoIGJhZywgd2UgcmVjb3JkIHRoZSBhbW91bnQgb2YgSW1wdXJpdHkgZGVjcmVhc2UgZHVlIHRvIHNwbGl0IG92ZXIgYSBnaXZlbiBwcmVkaWN0b3IsIHRoZW4gd2UgdGFrZSBhdmVyYWdlIG9uIGFsbCBCIHRyZWVzLgoKIyMjIFJhbmRvbSBGb3Jlc3QKClJhbmRvbSBGb3Jlc3QgcHJvdmlkZXMgYW4gaW1wcm92bWVudCBvdmVyIGJhZ2dlZCB0cmVlIGJ5IGEgd2F5IG9mIGEgc21hbGwgdGVhayAtLSB0aGF0IGRlY29ycmVsYXRlcyB0aGUgdHJlZS4KCkluIFJGLCBhIGZyZXNoIHNhbXBsZSBvZiBtIHByZWRpY3RvcnMgaXMgdGFrZW4gcmFuZG9tbHkgb24gZWFjaCBzcGxpdC4gdHlwaWNhbGx5ICRtPVxzcXJ0e3B9JC4KUkYgZWxpbWluYXRlcyB0aGUgYWZmZWN0cyBvZiB2ZXJ5IHN0cm9uZyBwcmVkaWN0b3JzIGJ5IHJhbmRvbWx5IHBpY2tpbmcgaW5vcHV0IHByZWRpY3RvcnMuICAgCgpJZiB0aGVyZSBpcyBzdHJvbmcgcHJlZGljdG9ycywgdGhlbiBhbG1vc3QgaW4gYWxsIEIgdHJlZXMgLCB3aWxsIHVzZSB0aGlzIHByZWRpY3RvciB0byBzcGxpdCB0aGUgdHJlZSwgcmVzdWx0aW5nIHRlZXMgYXJlIHZlcnkgbXVjaCBjb3JyZWxhdGVkLgoKYXZlcmFnaW5nIG1hbnkgaGlnaGx5IGNvcnJlbGF0ZWQgcXVhbnRpdGllcyBkb3NlIG5vdCBsZWFkIHRvIGFzIGxhcmdlIG9mIHJlZHVjdGlvbiBpbiB2YXJpYW5jZS4KClJGOiBhZGRzIGEgc3RlcCB0cCBkZWNvcnJlbGF0ZXMgdGhlIHRyZWUuClJGOiByZWR1Y3Rpb24gaW4gYm90aCB0ZXN0IGVycm9yIGFuZCBPT0ItZXJyb3Igb3ZlciBiYWdnaW5nLiAKQmFnZ2luZyxSRjogd2lsbCBub3Qgb3ZlcmZpdCBpZiB3ZSBpbmNyZWFzZSBudW1iZXIgb2YgQi4KCjEuIFNwbGl0IERhdGE6ICREJCAtPiAkRF9UJCwgJERfViQsICRsZW4oRF9UKT1CJAoyLiBCb290c3RyYXA6ICREVCQgLT4gJEJfMSxCXzIsQl8zLC4uLkJfQiQKMy4gRGVjb3JyZWxhdGUgWDogcm5kIGZyb20gJFx7WF8xLFhfMiwuLi5YX3BcfSQgcGljayAkXHtYXzEsWF8yLC4uLlhfbVx9JC4KMy4gVHJhaW46ICRCXzEgLT4gXGhhdCBmXzEkLC4uLiwkQl9CIC0+IFxoYXQgZl9CJAo0LiBQcmVkaWN0KENWL09PQik6ICRcaGF0IGZfMSAtPiBcaGF0IHlfMSQsLi4uLCRcaGF0IGZfQiAtPiBcaGF0IHlfQiQKNS4gQWdncmVnYXRlOiAkXGhhdCB5ID0gXGZyYWN7MX17Qn1cc3VtX2JeQlxoYXQgeV9iJCBvciAkXGhhdCB5ID1cdGV4dHtNYWpvcml0eSBWb3RlfSQKCiMjIyBCb29zdGluZyAKCllldCBhbm90aGVyIGFwcHJvYWNoIGZvciBpbXByb3ZpbmcgdGhlIHByZWRpY3Rpb25zIHJlc3V5bHRpbmcgZnJvbSBhIGRlY2lzaW9uIHRyZWUuCgpiYWdnaW5nIGludm9sdmVzIGNyZWF0aW5nIG11bHRpcGxlIGNvcGllcyBvZiB0aGUgb3JpZ2luYWwgdHJhaW5pbmcKZGF0YSBzZXQgdXNpbmcgdGhlIGJvb3RzdHJhcCwgZml0dGluZyBhIHNlcGFyYXRlIGRlY2lzaW9uIHRyZWUgdG8gZWFjaApjb3B5LCBhbmQgdGhlbiBjb21iaW5pbmcgYWxsIG9mIHRoZSB0cmVlcyBpbiBvcmRlciB0byBjcmVhdGUgYSBzaW5nbGUgcHJlZGljdGl2ZQptb2RlbC4KCnRyZWVzIGFyZQpncm93biBzZXF1ZW50aWFsbHkgOiBlYWNoIHRyZWUgaXMgZ3Jvd24gdXNpbmcgaW5mb3JtYXRpb24gZnJvbSBwcmV2aW91c2x5Cmdyb3duIHRyZWVzLiBCb29zdGluZyBkb2VzIG5vdCBpbnZvbHZlIGJvb3RzdHJhcCBzYW1wbGluZzsgaW5zdGVhZCBlYWNoCnRyZWUgaXMgZml0IG9uIGEgbW9kaWZpZWQgdmVyc2lvbiBvZiB0aGUgb3JpZ2luYWwgZGF0YSBzZXQuCgpCb29zdGluZzoKLSBsZWFybnMgc2xvdywgd2l0aCBzdHVtcHMgKHdlYWsgbGVhcm5lcikKLSBmaXQgYSB0cmVlIHVzaW5nIHRoZSBjdXJyZW50IHJlc2lkdWFscyByYXRoZXIgdGhhbiB0aGUgb3V0Y29tZSBZLCB3ZSB0aGVuIGFkZCB0aGlzIG5ldyBkZWNpc2lvbiB0cmVlIGludG8gZml0dGVkIGZ1bmN0aW9uIGluIG9yZGVyIHRvIHVwZGF0ZSB0aGUgcmVzaWR1YWxzLiAgICAKJCQKXGhhdCBmKHgpID0gXGhhdCBmKHgpICsgXGxhbWJkYSBcaGF0IGZfYih4KSBcXApyX2kgPC0gcl9pIC0gXGxhbWJkYSBcaGF0IGZfYiAoeF9pKSBcXApcaGF0IGYoeCk9XHN1bV97Yi0xfV5CKFxsYW1iZGEgXGhhdCBmX2IoeCkpCiQkCjEuIFVubGlrZSBiYWdnaW5nIGFuZCByYW5kb20gZm9yZXN0LCBCb29zdGluZyBjYW4gb3ZlcmZpdCBpZiBCIGlzIHRvbyBsYXJnZS4KMi4gU2hyaW5rYWdlIGNvbnRyb2xscyB0aGUgbGVhcm5pbmcgcmF0ZSAobGFtZGEpCjMuIE9mdGVuIHdlIHNwbGl0IHRoZSBlYWNoIHRyZWUgdG8gc3R1bXBzICggZWFjaCBpbnZvbHZlcyBvbmx5YSBzaW5nbGUgdmFyaWFibGUpCgpVc2luZyBzdHVtcHMgbGVhZHMgdG8gYWRkaXRpdmUgbW9kZWwuCgoK