Практическая работа №4

Метод наименьших квадратов в задаче линейной и нелинейной регрессии

Глушков Егор Александрович, гр. 20.М04-мм
Вариант 4


  1. Промоделировать нелинейную модель \(y = f(x, a, b) + \delta\) с несмещённой нормально распределенной ошибкой, дисперсия которой равна \(\varepsilon\), считая, \(x\) стандартно нормально распределённой случайной величиной.
  1. Оценить параметры нелинейной модели по методу наименьших квадратов (численно). Применить к модельным данным линейную модель и оценить параметры. Построить на двумерной диаграмме основную и линейную модель. Сравнить невязки для обеих моделей.

  2. Для линейной модели выполнить дисперсионный анализ, проверить значимость прогноза и коэффициентов регрессии. Сравнить непосредственные вычисления с результатами встроенной функции.

  3. Промоделировать данные для множественной регрессии. Применить функцию \(lm\). Ответить на вопросы о значимости коэффициента детерминации, частных коэффициентов регрессии, о коэффициенте корреляции между остатком и независимыми переменными.


Задание линейной и нелинейной моделей регрессии

Нелинейная модель \[y_i = a \sin x_i + bx_i^2 + \delta_i, \quad \delta_i \sim \mathcal{N}(0, \sigma)\] Модель одномерной линейной регрессии

\[y_i = \alpha + \beta x_i, \quad \delta_i \sim \mathcal{N}(0, \sigma)\]

Задаем нелинейную и линейную модели и их функции ошибки L

N <- 100
f <- function(x, ab) ab[1] * sin(x) + ab[2] * x^2
L <- function(X, Y, ab) sum((Y - f(X, ab))^2)

f_lin <- function(x, ab_lin) ab_lin[1] + ab_lin[2] * x
L_lin <- function(X, Y, ab_lin) sum((Y - f_lin(X, ab_lin))^2)

Моделируем данные нелинейной модели

ab <- c(2, 1)
eps <- 0.8

X <- rnorm(N)
Y <- f(X, ab) + rnorm(N, 0, eps^2)

Оценка параметров линейной модели и наилучший прогноз

\[ \hat{\beta} = \frac{\sum\nolimits_i x_i y_i - n \bar{x} \bar{y}}{{\sum\nolimits_i x_i^2 - n \bar{x}^2}}, \quad \hat{\alpha} = \bar{y} - \hat{\beta} \bar{x}, \quad \hat{y_i} = \hat{\alpha} - \hat{\beta} x_i\]

b. <- (sum(X * Y) - N * mean(X) * mean(Y)) / (sum(X * X) - N * mean(X)^2)
a. <- mean(Y) - b. * mean(X)
ab_lin_est <- c(a., b.)
Y. <- f_lin(X, ab_lin_est)
ab_lin_est
[1] 0.9219083 1.2337556

Дисперсионный анализ

Источники вариации: общий \(Q_T\), обусловленный регрессией \(Q_R\), невязка \(Q_E\). Коэффициент детерминации \(R^2\)

QT <- sum((Y - mean(Y))^2)
QR <- sum((Y. - mean(Y))^2)
QE <- sum((Y - Y.)^2)
R2 <- QR / QT

c(QT=QT, QR=QR, QE=QE, R2=R2)
         QT          QR          QE          R2 
348.7500256 135.4274537 213.3225718   0.3883224 

38.8% дисперсии объясняется данной моделью – линией регресии.
Проверим равенство источников вариации [посчитаны верно]:

print(paste("(QR + QE == QT):", QR + QE - QT < 1e-9))
[1] "(QR + QE == QT): TRUE"

Дисперсии общая и коэффициентов регрессии

xx <- sum((X - mean(X))^2)
S2 <- QE / (N - 2)
S2.a <- S2 * sum(X^2) / (xx * N)
S2.b <- S2 / xx

c(S2, S2.a, S2.b)
[1] 2.17676094 0.02176906 0.02446596

Статистики для проверки значимости прогноза и коэффициентов регрессии

F_stat <- QR / QE * (N - 2)

Pf <- 1 - pf(F_stat, 1, N - 2)
T.a <- ab_lin_est[1] / sqrt(S2.a)
T.b <- ab_lin_est[2] / sqrt(S2.b)

P.a <- 2*(1 - pt(abs(T.a), N - 2))
P.b <- 2*(1 - pt(abs(T.b), N - 2))

P.model <- 1 - pf(F_stat, 1, N - 2)

Выведем самостоятельно посчитанные величины:

show_stats_coef <- rbind(c(ab_lin_est[1], sqrt(S2.a), T.a, P.a), c(ab_lin_est[2], sqrt(S2.b), T.b, P.b))
colnames(show_stats_coef) <- c("Estimate", "Std.Error","t value", "Pr(>|t|)")
rownames(show_stats_coef) <- c("(Intercept)", "X"); show_stats_coef
             Estimate Std.Error  t value     Pr(>|t|)
(Intercept) 0.9219083 0.1475434 6.248386 1.075902e-08
X           1.2337556 0.1564160 7.887656 4.401812e-12
show_stats_model <- c(sd=sqrt(S2), R2=R2, F_stats=F_stat, p.value.F=P.model); show_stats_model
          sd           R2      F_stats    p.value.F 
1.475385e+00 3.883224e-01 6.221512e+01 4.401812e-12 

Проверим при помощи встроенной функции lm:

summary(lm(Y~X))

Call:
lm(formula = Y ~ X)

Residuals:
    Min      1Q  Median      3Q     Max 
-2.1924 -0.8860 -0.3422  0.5329  6.1879 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   0.9219     0.1475   6.248 1.08e-08 ***
X             1.2338     0.1564   7.888 4.40e-12 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.475 on 98 degrees of freedom
Multiple R-squared:  0.3883,    Adjusted R-squared:  0.3821 
F-statistic: 62.22 on 1 and 98 DF,  p-value: 4.402e-12

Как видно, все посчитанные величины совпадают. Вычисления были верны. Что касается самой модели, то итоговое p-value (близкое к нулю) говорит о значимости регрессии, также малые Pr говорят о том, что соответствующие этим уровням значимости коэффициенты отличны от нуля и вносят вклад в модель. \(R^2\) сообщает, что 38.8% дисперсии объясняется данной моделью – линией регресии.

Оценка параметров нелинейной модели по МНК

Параметры нелинейной модели оцениваем методом наименьших квадратов (МНК)

NLM <- nlm(function(ab) L(X, Y, ab), ab)
ab. <- NLM$estimate
rbind(ab=ab, ab.=ab.)
        [,1]      [,2]
ab  2.000000 1.0000000
ab. 1.864256 0.9972268
plot(X, Y)
f_ <- function(x) f(x, ab); curve(f_, -3, 3, add=TRUE, col=2)
f_ <- function(x) f(x, ab.); curve(f_, -3, 3, add=TRUE, col=3)
f_ <- function(x) f_lin(x, ab_lin_est); curve(f_, -3, 3, add=TRUE, col=4, lty=2)
legend('bottomright', c('hyp', 'mnk', 'linear'), pch=20, col=2:4)

Невязки

c(Q.linear=L_lin(X, Y, ab_lin_est), Q.hyp=L(X, Y, ab), Q.mnk=L(X, Y, ab.))
 Q.linear     Q.hyp     Q.mnk 
213.32257  42.52355  41.80144 

Заметим, что линейная модель оценивает достаточно грубо, тогда как нелинейная модель достаточно точно описывает данные. Конечно, меньшей невязкой как суммы квадратов отклонений точек от графика обладает модель, построенная по МНК.

Множественная регрессия

N <- 100
a <- c(2, -1, 5)
eps <- 3
X1 <- rnorm(N, 1, 1.5)
X2 <- rnorm(N, 2, 0.5)
Y <- a[1] * X1 + a[2] * X2 + a[3] + rnorm(N, 0, eps^2)

SLM <- summary(lm(Y ~ X1 + X2)); SLM

Call:
lm(formula = Y ~ X1 + X2)

Residuals:
     Min       1Q   Median       3Q      Max 
-16.1076  -6.0017  -0.6972   4.7822  21.5682 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)   
(Intercept)   6.9812     3.3939   2.057  0.04237 * 
X1            1.5445     0.5706   2.707  0.00802 **
X2           -1.3288     1.6065  -0.827  0.41018   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 8.294 on 97 degrees of freedom
Multiple R-squared:  0.08022,   Adjusted R-squared:  0.06125 
F-statistic:  4.23 on 2 and 97 DF,  p-value: 0.01733

Согласно p-value < 0.05 отвергаем гипотезу о том, что данная модель не зависит от предикторов (т.е. их коэффициенты равны нулю – отвергаем). Отвергается и незначимость коэффициента при X1, а вот X2, как следует, не вносит весомый вклад (\(p.value = 0.41 > 0.05\), то не отвергается факт, коэффициент незначим)

Проверим некоррелированность остатков [практически равны 0]

c(cor(X1, SLM$residuals), cor(X1, SLM$residuals))
[1] -5.386815e-17 -5.386815e-17
op <- par(mfrow = c(2, 2))

plot(X1, SLM$residuals)
title(sub=paste("r", round(cor(SLM$residuals, X1), 3), sep="="))
plot(X2, SLM$residuals)
title(sub=paste("r", round(cor(SLM$residuals, X2), 3), sep="="))

plot(X1, Y)
title(sub=paste("r", round(cor(X1, Y),3), sep="="))
plot(X2, Y)
title(sub=paste("r", round(cor(X2, Y), 3), sep="="))

Как видно на верхних двух рисунках, коэффициент корреляции остатков с независимыми переменными равен нулю, тогда как в целом некоторая зависимость (линейная) в данных наблюдается (см. нижние рисунки).

sh_t <- shapiro.test(SLM$residuals); sh_t

    Shapiro-Wilk normality test

data:  SLM$residuals
W = 0.97998, p-value = 0.1325

Согласно критерию Шапиро-Уилка, нормальность остатков не отвергается с \(p.value = 0.133\)

qqnorm(SLM$residuals)

LS0tDQp0aXRsZTogIiINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiMjIyMg0J/RgNCw0LrRgtC40YfQtdGB0LrQsNGPINGA0LDQsdC+0YLQsCDihJY0DQojIyMg0JzQtdGC0L7QtCDQvdCw0LjQvNC10L3RjNGI0LjRhSDQutCy0LDQtNGA0LDRgtC+0LIg0LIg0LfQsNC00LDRh9C1INC70LjQvdC10LnQvdC+0Lkg0Lgg0L3QtdC70LjQvdC10LnQvdC+0Lkg0YDQtdCz0YDQtdGB0YHQuNC4IA0KDQo+INCT0LvRg9GI0LrQvtCyINCV0LPQvtGAINCQ0LvQtdC60YHQsNC90LTRgNC+0LLQuNGHLCDQs9GALiAyMC7QnDA0LdC80LwgIA0KPiDQktCw0YDQuNCw0L3RgiA0DQoNCi0tLQ0KDQoxLiDQn9GA0L7QvNC+0LTQtdC70LjRgNC+0LLQsNGC0Ywg0L3QtdC70LjQvdC10LnQvdGD0Y4g0LzQvtC00LXQu9GMICR5ID0gZih4LCBhLCBiKSArIFxkZWx0YSQg0YEg0L3QtdGB0LzQtdGJ0ZHQvdC90L7QuSDQvdC+0YDQvNCw0LvRjNC90L4g0YDQsNGB0L/RgNC10LTQtdC70LXQvdC90L7QuSDQvtGI0LjQsdC60L7QuSwg0LTQuNGB0L/QtdGA0YHQuNGPINC60L7RgtC+0YDQvtC5INGA0LDQstC90LAgJFx2YXJlcHNpbG9uJCwg0YHRh9C40YLQsNGPLCAkeCQg0YHRgtCw0L3QtNCw0YDRgtC90L4g0L3QvtGA0LzQsNC70YzQvdC+INGA0LDRgdC/0YDQtdC00LXQu9GR0L3QvdC+0Lkg0YHQu9GD0YfQsNC50L3QvtC5INCy0LXQu9C40YfQuNC90L7QuS4NCg0KKiAkZih4LCBhLCBiKSA9IGEgXHNpbiB4ICsgYnheMiwgXDsgYT0yLCBiPTEsIFx2YXJlcHNpbG9uPTAuOCQNCg0KMi4g0J7RhtC10L3QuNGC0Ywg0L/QsNGA0LDQvNC10YLRgNGLINC90LXQu9C40L3QtdC50L3QvtC5INC80L7QtNC10LvQuCDQv9C+INC80LXRgtC+0LTRgyDQvdCw0LjQvNC10L3RjNGI0LjRhSDQutCy0LDQtNGA0LDRgtC+0LIgKNGH0LjRgdC70LXQvdC90L4pLiDQn9GA0LjQvNC10L3QuNGC0Ywg0Log0LzQvtC00LXQu9GM0L3Ri9C8INC00LDQvdC90YvQvCDQu9C40L3QtdC50L3Rg9GOINC80L7QtNC10LvRjCDQuCDQvtGG0LXQvdC40YLRjCDQv9Cw0YDQsNC80LXRgtGA0YsuINCf0L7RgdGC0YDQvtC40YLRjCDQvdCwINC00LLRg9C80LXRgNC90L7QuSDQtNC40LDQs9GA0LDQvNC80LUg0L7RgdC90L7QstC90YPRjiDQuCDQu9C40L3QtdC50L3Rg9GOINC80L7QtNC10LvRjC4g0KHRgNCw0LLQvdC40YLRjCDQvdC10LLRj9C30LrQuCDQtNC70Y8g0L7QsdC10LjRhSDQvNC+0LTQtdC70LXQuS4NCg0KMy4g0JTQu9GPINC70LjQvdC10LnQvdC+0Lkg0LzQvtC00LXQu9C4INCy0YvQv9C+0LvQvdC40YLRjCDQtNC40YHQv9C10YDRgdC40L7QvdC90YvQuSDQsNC90LDQu9C40LcsINC/0YDQvtCy0LXRgNC40YLRjCDQt9C90LDRh9C40LzQvtGB0YLRjCDQv9GA0L7Qs9C90L7Qt9CwINC4INC60L7RjdGE0YTQuNGG0LjQtdC90YLQvtCyINGA0LXQs9GA0LXRgdGB0LjQuC4g0KHRgNCw0LLQvdC40YLRjCDQvdC10L/QvtGB0YDQtdC00YHRgtCy0LXQvdC90YvQtSDQstGL0YfQuNGB0LvQtdC90LjRjyDRgSDRgNC10LfRg9C70YzRgtCw0YLQsNC80Lgg0LLRgdGC0YDQvtC10L3QvdC+0Lkg0YTRg9C90LrRhtC40LguDQoNCjQuINCf0YDQvtC80L7QtNC10LvQuNGA0L7QstCw0YLRjCDQtNCw0L3QvdGL0LUg0LTQu9GPINC80L3QvtC20LXRgdGC0LLQtdC90L3QvtC5INGA0LXQs9GA0LXRgdGB0LjQuC4g0J/RgNC40LzQtdC90LjRgtGMINGE0YPQvdC60YbQuNGOICRsbSQuINCe0YLQstC10YLQuNGC0Ywg0L3QsCDQstC+0L/RgNC+0YHRiyDQviDQt9C90LDRh9C40LzQvtGB0YLQuCDQutC+0Y3RhNGE0LjRhtC40LXQvdGC0LAg0LTQtdGC0LXRgNC80LjQvdCw0YbQuNC4LCDRh9Cw0YHRgtC90YvRhSDQutC+0Y3RhNGE0LjRhtC40LXQvdGC0L7QsiDRgNC10LPRgNC10YHRgdC40LgsINC+INC60L7RjdGE0YTQuNGG0LjQtdC90YLQtSDQutC+0YDRgNC10LvRj9GG0LjQuCDQvNC10LbQtNGDINC+0YHRgtCw0YLQutC+0Lwg0Lgg0L3QtdC30LDQstC40YHQuNC80YvQvNC4INC/0LXRgNC10LzQtdC90L3Ri9C80LguDQoNCi0tLQ0KDQo+INCX0LDQtNCw0L3QuNC1INC70LjQvdC10LnQvdC+0Lkg0Lgg0L3QtdC70LjQvdC10LnQvdC+0Lkg0LzQvtC00LXQu9C10Lkg0YDQtdCz0YDQtdGB0YHQuNC4IA0KDQrQndC10LvQuNC90LXQudC90LDRjyDQvNC+0LTQtdC70YwNCiQkeV9pID0gYSBcc2luIHhfaSArIGJ4X2leMiArIFxkZWx0YV9pLCBccXVhZCBcZGVsdGFfaSBcc2ltIFxtYXRoY2Fse059KDAsIFxzaWdtYSkkJA0K0JzQvtC00LXQu9GMINC+0LTQvdC+0LzQtdGA0L3QvtC5INC70LjQvdC10LnQvdC+0Lkg0YDQtdCz0YDQtdGB0YHQuNC4DQoNCiQkeV9pID0gXGFscGhhICsgXGJldGEgeF9pLCBccXVhZCBcZGVsdGFfaSBcc2ltIFxtYXRoY2Fse059KDAsIFxzaWdtYSkkJA0KDQrQl9Cw0LTQsNC10Lwg0L3QtdC70LjQvdC10LnQvdGD0Y4g0Lgg0LvQuNC90LXQudC90YPRjiDQvNC+0LTQtdC70Lgg0Lgg0LjRhSDRhNGD0L3QutGG0LjQuCDQvtGI0LjQsdC60LggKkwqDQpgYGB7cn0NCk4gPC0gMTAwDQpmIDwtIGZ1bmN0aW9uKHgsIGFiKSBhYlsxXSAqIHNpbih4KSArIGFiWzJdICogeF4yDQpMIDwtIGZ1bmN0aW9uKFgsIFksIGFiKSBzdW0oKFkgLSBmKFgsIGFiKSleMikNCg0KZl9saW4gPC0gZnVuY3Rpb24oeCwgYWJfbGluKSBhYl9saW5bMV0gKyBhYl9saW5bMl0gKiB4DQpMX2xpbiA8LSBmdW5jdGlvbihYLCBZLCBhYl9saW4pIHN1bSgoWSAtIGZfbGluKFgsIGFiX2xpbikpXjIpDQpgYGANCg0K0JzQvtC00LXQu9C40YDRg9C10Lwg0LTQsNC90L3Ri9C1INC90LXQu9C40L3QtdC50L3QvtC5INC80L7QtNC10LvQuA0KYGBge3J9DQphYiA8LSBjKDIsIDEpDQplcHMgPC0gMC44DQoNClggPC0gcm5vcm0oTikNClkgPC0gZihYLCBhYikgKyBybm9ybShOLCAwLCBlcHNeMikNCmBgYA0KDQo+INCe0YbQtdC90LrQsCDQv9Cw0YDQsNC80LXRgtGA0L7QsiDQu9C40L3QtdC50L3QvtC5INC80L7QtNC10LvQuCDQuCDQvdCw0LjQu9GD0YfRiNC40Lkg0L/RgNC+0LPQvdC+0LcNCg0KJCQgXGhhdHtcYmV0YX0gPSBcZnJhY3tcc3VtXG5vbGltaXRzX2kgeF9pIHlfaSAtIG4gXGJhcnt4fSBcYmFye3l9fXt7XHN1bVxub2xpbWl0c19pIHhfaV4yIC0gbiBcYmFye3h9XjJ9fSwgXHF1YWQgXGhhdHtcYWxwaGF9ID0gXGJhcnt5fSAtIFxoYXR7XGJldGF9IFxiYXJ7eH0sIFxxdWFkIFxoYXR7eV9pfSA9IFxoYXR7XGFscGhhfSAtIFxoYXR7XGJldGF9IHhfaSQkDQoNCmBgYHtyfQ0KYi4gPC0gKHN1bShYICogWSkgLSBOICogbWVhbihYKSAqIG1lYW4oWSkpIC8gKHN1bShYICogWCkgLSBOICogbWVhbihYKV4yKQ0KYS4gPC0gbWVhbihZKSAtIGIuICogbWVhbihYKQ0KYWJfbGluX2VzdCA8LSBjKGEuLCBiLikNClkuIDwtIGZfbGluKFgsIGFiX2xpbl9lc3QpDQphYl9saW5fZXN0DQpgYGANCg0KPiDQlNC40YHQv9C10YDRgdC40L7QvdC90YvQuSDQsNC90LDQu9C40LcNCg0K0JjRgdGC0L7Rh9C90LjQutC4INCy0LDRgNC40LDRhtC40Lg6INC+0LHRidC40LkgJFFfVCQsINC+0LHRg9GB0LvQvtCy0LvQtdC90L3Ri9C5INGA0LXQs9GA0LXRgdGB0LjQtdC5ICRRX1IkLCDQvdC10LLRj9C30LrQsCAkUV9FJC4g0JrQvtGN0YTRhNC40YbQuNC10L3RgiDQtNC10YLQtdGA0LzQuNC90LDRhtC40LggJFJeMiQNCmBgYHtyfQ0KUVQgPC0gc3VtKChZIC0gbWVhbihZKSleMikNClFSIDwtIHN1bSgoWS4gLSBtZWFuKFkpKV4yKQ0KUUUgPC0gc3VtKChZIC0gWS4pXjIpDQpSMiA8LSBRUiAvIFFUDQoNCmMoUVQ9UVQsIFFSPVFSLCBRRT1RRSwgUjI9UjIpDQpgYGANCmByIHJvdW5kKFIyLCAzKSoxMDBgJSDQtNC40YHQv9C10YDRgdC40Lgg0L7QsdGK0Y/RgdC90Y/QtdGC0YHRjyDQtNCw0L3QvdC+0Lkg0LzQvtC00LXQu9GM0Y4gLS0g0LvQuNC90LjQtdC5INGA0LXQs9GA0LXRgdC40LguICANCtCf0YDQvtCy0LXRgNC40Lwg0YDQsNCy0LXQvdGB0YLQstC+INC40YHRgtC+0YfQvdC40LrQvtCyINCy0LDRgNC40LDRhtC40LggW9C/0L7RgdGH0LjRgtCw0L3RiyDQstC10YDQvdC+XToNCg0KYGBge3J9DQpwcmludChwYXN0ZSgiKFFSICsgUUUgPT0gUVQpOiIsIFFSICsgUUUgLSBRVCA8IDFlLTkpKQ0KYGBgDQrQlNC40YHQv9C10YDRgdC40Lgg0L7QsdGJ0LDRjyDQuCDQutC+0Y3RhNGE0LjRhtC40LXQvdGC0L7QsiDRgNC10LPRgNC10YHRgdC40LgNCmBgYHtyfQ0KeHggPC0gc3VtKChYIC0gbWVhbihYKSleMikNClMyIDwtIFFFIC8gKE4gLSAyKQ0KUzIuYSA8LSBTMiAqIHN1bShYXjIpIC8gKHh4ICogTikNClMyLmIgPC0gUzIgLyB4eA0KDQpjKFMyLCBTMi5hLCBTMi5iKQ0KYGBgDQoNCtCh0YLQsNGC0LjRgdGC0LjQutC4INC00LvRjyDQv9GA0L7QstC10YDQutC4INC30L3QsNGH0LjQvNC+0YHRgtC4INC/0YDQvtCz0L3QvtC30LAg0Lgg0LrQvtGN0YTRhNC40YbQuNC10L3RgtC+0LIg0YDQtdCz0YDQtdGB0YHQuNC4DQpgYGB7cn0NCkZfc3RhdCA8LSBRUiAvIFFFICogKE4gLSAyKQ0KDQpQZiA8LSAxIC0gcGYoRl9zdGF0LCAxLCBOIC0gMikNClQuYSA8LSBhYl9saW5fZXN0WzFdIC8gc3FydChTMi5hKQ0KVC5iIDwtIGFiX2xpbl9lc3RbMl0gLyBzcXJ0KFMyLmIpDQoNClAuYSA8LSAyKigxIC0gcHQoYWJzKFQuYSksIE4gLSAyKSkNClAuYiA8LSAyKigxIC0gcHQoYWJzKFQuYiksIE4gLSAyKSkNCg0KUC5tb2RlbCA8LSAxIC0gcGYoRl9zdGF0LCAxLCBOIC0gMikNCmBgYA0KDQrQktGL0LLQtdC00LXQvCDRgdCw0LzQvtGB0YLQvtGP0YLQtdC70YzQvdC+INC/0L7RgdGH0LjRgtCw0L3QvdGL0LUg0LLQtdC70LjRh9C40L3RizoNCmBgYHtyfQ0Kc2hvd19zdGF0c19jb2VmIDwtIHJiaW5kKGMoYWJfbGluX2VzdFsxXSwgc3FydChTMi5hKSwgVC5hLCBQLmEpLCBjKGFiX2xpbl9lc3RbMl0sIHNxcnQoUzIuYiksIFQuYiwgUC5iKSkNCmNvbG5hbWVzKHNob3dfc3RhdHNfY29lZikgPC0gYygiRXN0aW1hdGUiLCAiU3RkLkVycm9yIiwidCB2YWx1ZSIsICJQcig+fHR8KSIpDQpyb3duYW1lcyhzaG93X3N0YXRzX2NvZWYpIDwtIGMoIihJbnRlcmNlcHQpIiwgIlgiKTsgc2hvd19zdGF0c19jb2VmDQoNCnNob3dfc3RhdHNfbW9kZWwgPC0gYyhzZD1zcXJ0KFMyKSwgUjI9UjIsIEZfc3RhdHM9Rl9zdGF0LCBwLnZhbHVlLkY9UC5tb2RlbCk7IHNob3dfc3RhdHNfbW9kZWwNCmBgYA0K0J/RgNC+0LLQtdGA0LjQvCDQv9GA0Lgg0L/QvtC80L7RidC4INCy0YHRgtGA0L7QtdC90L3QvtC5INGE0YPQvdC60YbQuNC4ICpsbSo6DQpgYGB7cn0NCnN1bW1hcnkobG0oWX5YKSkNCmBgYA0K0JrQsNC6INCy0LjQtNC90L4sINCy0YHQtSDQv9C+0YHRh9C40YLQsNC90L3Ri9C1INCy0LXQu9C40YfQuNC90Ysg0YHQvtCy0L/QsNC00LDRjtGCLiDQktGL0YfQuNGB0LvQtdC90LjRjyDQsdGL0LvQuCDQstC10YDQvdGLLg0K0KfRgtC+INC60LDRgdCw0LXRgtGB0Y8g0YHQsNC80L7QuSDQvNC+0LTQtdC70LgsINGC0L4g0LjRgtC+0LPQvtCy0L7QtSAqcC12YWx1ZSogKNCx0LvQuNC30LrQvtC1INC6INC90YPQu9GOKSDQs9C+0LLQvtGA0LjRgiDQviDQt9C90LDRh9C40LzQvtGB0YLQuCDRgNC10LPRgNC10YHRgdC40LgsINGC0LDQutC20LUg0LzQsNC70YvQtSAqUHIqINCz0L7QstC+0YDRj9GCINC+INGC0L7QvCwg0YfRgtC+INGB0L7QvtGC0LLQtdGC0YHRgtCy0YPRjtGJ0LjQtSDRjdGC0LjQvCDRg9GA0L7QstC90Y/QvCDQt9C90LDRh9C40LzQvtGB0YLQuCDQutC+0Y3RhNGE0LjRhtC40LXQvdGC0Ysg0L7RgtC70LjRh9C90Ysg0L7RgiDQvdGD0LvRjyDQuCDQstC90L7RgdGP0YIg0LLQutC70LDQtCDQsiDQvNC+0LTQtdC70YwuICRSXjIkINGB0L7QvtCx0YnQsNC10YIsINGH0YLQviBgciByb3VuZChSMiwgMykqMTAwYCUg0LTQuNGB0L/QtdGA0YHQuNC4INC+0LHRitGP0YHQvdGP0LXRgtGB0Y8g0LTQsNC90L3QvtC5INC80L7QtNC10LvRjNGOIC0tINC70LjQvdC40LXQuSDRgNC10LPRgNC10YHQuNC4LiANCg0KPiDQntGG0LXQvdC60LAg0L/QsNGA0LDQvNC10YLRgNC+0LIg0L3QtdC70LjQvdC10LnQvdC+0Lkg0LzQvtC00LXQu9C4INC/0L4g0JzQndCaDQoNCtCf0LDRgNCw0LzQtdGC0YDRiyDQvdC10LvQuNC90LXQudC90L7QuSDQvNC+0LTQtdC70Lgg0L7RhtC10L3QuNCy0LDQtdC8INC80LXRgtC+0LTQvtC8INC90LDQuNC80LXQvdGM0YjQuNGFINC60LLQsNC00YDQsNGC0L7QsiAo0JzQndCaKQ0KYGBge3J9DQpOTE0gPC0gbmxtKGZ1bmN0aW9uKGFiKSBMKFgsIFksIGFiKSwgYWIpDQphYi4gPC0gTkxNJGVzdGltYXRlDQpyYmluZChhYj1hYiwgYWIuPWFiLikNCmBgYA0KYGBge3J9DQpwbG90KFgsIFkpDQpmXyA8LSBmdW5jdGlvbih4KSBmKHgsIGFiKTsgY3VydmUoZl8sIC0zLCAzLCBhZGQ9VFJVRSwgY29sPTIpDQpmXyA8LSBmdW5jdGlvbih4KSBmKHgsIGFiLik7IGN1cnZlKGZfLCAtMywgMywgYWRkPVRSVUUsIGNvbD0zKQ0KZl8gPC0gZnVuY3Rpb24oeCkgZl9saW4oeCwgYWJfbGluX2VzdCk7IGN1cnZlKGZfLCAtMywgMywgYWRkPVRSVUUsIGNvbD00LCBsdHk9MikNCmxlZ2VuZCgnYm90dG9tcmlnaHQnLCBjKCdoeXAnLCAnbW5rJywgJ2xpbmVhcicpLCBwY2g9MjAsIGNvbD0yOjQpDQpgYGANCtCd0LXQstGP0LfQutC4DQpgYGB7cn0NCmMoUS5saW5lYXI9TF9saW4oWCwgWSwgYWJfbGluX2VzdCksIFEuaHlwPUwoWCwgWSwgYWIpLCBRLm1uaz1MKFgsIFksIGFiLikpDQpgYGANCtCX0LDQvNC10YLQuNC8LCDRh9GC0L4g0LvQuNC90LXQudC90LDRjyDQvNC+0LTQtdC70Ywg0L7RhtC10L3QuNCy0LDQtdGCINC00L7RgdGC0LDRgtC+0YfQvdC+INCz0YDRg9Cx0L4sINGC0L7Qs9C00LAg0LrQsNC6INC90LXQu9C40L3QtdC50L3QsNGPINC80L7QtNC10LvRjCDQtNC+0YHRgtCw0YLQvtGH0L3QviDRgtC+0YfQvdC+INC+0L/QuNGB0YvQstCw0LXRgiDQtNCw0L3QvdGL0LUuINCa0L7QvdC10YfQvdC+LCDQvNC10L3RjNGI0LXQuSAg0L3QtdCy0Y/Qt9C60L7QuSDQutCw0Log0YHRg9C80LzRiyDQutCy0LDQtNGA0LDRgtC+0LIg0L7RgtC60LvQvtC90LXQvdC40Lkg0YLQvtGH0LXQuiDQvtGCINCz0YDQsNGE0LjQutCwINC+0LHQu9Cw0LTQsNC10YIg0LzQvtC00LXQu9GMLCDQv9C+0YHRgtGA0L7QtdC90L3QsNGPINC/0L4g0JzQndCaLg0KDQo+INCc0L3QvtC20LXRgdGC0LLQtdC90L3QsNGPINGA0LXQs9GA0LXRgdGB0LjRjw0KDQpgYGB7cn0NCk4gPC0gMTAwDQphIDwtIGMoMiwgLTEsIDUpDQplcHMgPC0gMw0KWDEgPC0gcm5vcm0oTiwgMSwgMS41KQ0KWDIgPC0gcm5vcm0oTiwgMiwgMC41KQ0KWSA8LSBhWzFdICogWDEgKyBhWzJdICogWDIgKyBhWzNdICsgcm5vcm0oTiwgMCwgZXBzXjIpDQoNClNMTSA8LSBzdW1tYXJ5KGxtKFkgfiBYMSArIFgyKSk7IFNMTQ0KYGBgDQrQodC+0LPQu9Cw0YHQvdC+ICpwLXZhbHVlKiA8IDAuMDUg0L7RgtCy0LXRgNCz0LDQtdC8INCz0LjQv9C+0YLQtdC30YMg0L4g0YLQvtC8LCDRh9GC0L4g0LTQsNC90L3QsNGPINC80L7QtNC10LvRjCDQvdC1INC30LDQstC40YHQuNGCINC+0YIg0L/RgNC10LTQuNC60YLQvtGA0L7QsiAo0YIu0LUuINC40YUg0LrQvtGN0YTRhNC40YbQuNC10L3RgtGLINGA0LDQstC90Ysg0L3Rg9C70Y4gLS0g0L7RgtCy0LXRgNCz0LDQtdC8KS4g0J7RgtCy0LXRgNCz0LDQtdGC0YHRjyDQuCDQvdC10LfQvdCw0YfQuNC80L7RgdGC0Ywg0LrQvtGN0YTRhNC40YbQuNC10L3RgtCwINC/0YDQuCAqWDEqLCDQsCDQstC+0YIgKlgyKiwg0LrQsNC6INGB0LvQtdC00YPQtdGCLCDQvdC1INCy0L3QvtGB0LjRgiDQstC10YHQvtC80YvQuSDQstC60LvQsNC0ICgkcC52YWx1ZSA9IGByIHJvdW5kKFNMTSRjb2VmZmljaWVudHNbLDRdWzNdLCAzKWAgPiAwLjA1JCwg0YLQviDQvdC1INC+0YLQstC10YDQs9Cw0LXRgtGB0Y8g0YTQsNC60YIsINC60L7RjdGE0YTQuNGG0LjQtdC90YIg0L3QtdC30L3QsNGH0LjQvCkNCg0K0J/RgNC+0LLQtdGA0LjQvCDQvdC10LrQvtGA0YDQtdC70LjRgNC+0LLQsNC90L3QvtGB0YLRjCDQvtGB0YLQsNGC0LrQvtCyIFvQv9GA0LDQutGC0LjRh9C10YHQutC4INGA0LDQstC90YsgMF0NCmBgYHtyfQ0KYyhjb3IoWDEsIFNMTSRyZXNpZHVhbHMpLCBjb3IoWDEsIFNMTSRyZXNpZHVhbHMpKQ0KYGBgDQpgYGB7cn0NCm9wIDwtIHBhcihtZnJvdyA9IGMoMiwgMikpDQoNCnBsb3QoWDEsIFNMTSRyZXNpZHVhbHMpDQp0aXRsZShzdWI9cGFzdGUoInIiLCByb3VuZChjb3IoU0xNJHJlc2lkdWFscywgWDEpLCAzKSwgc2VwPSI9IikpDQpwbG90KFgyLCBTTE0kcmVzaWR1YWxzKQ0KdGl0bGUoc3ViPXBhc3RlKCJyIiwgcm91bmQoY29yKFNMTSRyZXNpZHVhbHMsIFgyKSwgMyksIHNlcD0iPSIpKQ0KcGxvdChYMSwgWSkNCnRpdGxlKHN1Yj1wYXN0ZSgiciIsIHJvdW5kKGNvcihYMSwgWSksMyksIHNlcD0iPSIpKQ0KcGxvdChYMiwgWSkNCnRpdGxlKHN1Yj1wYXN0ZSgiciIsIHJvdW5kKGNvcihYMiwgWSksIDMpLCBzZXA9Ij0iKSkNCmBgYA0K0JrQsNC6INCy0LjQtNC90L4g0L3QsCDQstC10YDRhdC90LjRhSDQtNCy0YPRhSDRgNC40YHRg9C90LrQsNGFLCDQutC+0Y3RhNGE0LjRhtC40LXQvdGCINC60L7RgNGA0LXQu9GP0YbQuNC4INC+0YHRgtCw0YLQutC+0LIg0YEg0L3QtdC30LDQstC40YHQuNC80YvQvNC4INC/0LXRgNC10LzQtdC90L3Ri9C80Lgg0YDQsNCy0LXQvSDQvdGD0LvRjiwg0YLQvtCz0LTQsCDQutCw0Log0LIg0YbQtdC70L7QvCDQvdC10LrQvtGC0L7RgNCw0Y8g0LfQsNCy0LjRgdC40LzQvtGB0YLRjCAo0LvQuNC90LXQudC90LDRjykg0LIg0LTQsNC90L3Ri9GFINC90LDQsdC70Y7QtNCw0LXRgtGB0Y8gKNGB0LwuINC90LjQttC90LjQtSDRgNC40YHRg9C90LrQuCkuDQoNCmBgYHtyfQ0Kc2hfdCA8LSBzaGFwaXJvLnRlc3QoU0xNJHJlc2lkdWFscyk7IHNoX3QNCmBgYA0K0KHQvtCz0LvQsNGB0L3QviDQutGA0LjRgtC10YDQuNGOINCo0LDQv9C40YDQvi3Qo9C40LvQutCwLCDQvdC+0YDQvNCw0LvRjNC90L7RgdGC0Ywg0L7RgdGC0LDRgtC60L7QsiDQvdC1INC+0YLQstC10YDQs9Cw0LXRgtGB0Y8g0YEgJHAudmFsdWUgPSBgciByb3VuZChzaF90JHAudmFsdWUsIDMpYCQNCg0KYGBge3J9DQpxcW5vcm0oU0xNJHJlc2lkdWFscykNCmBgYA0KDQo=