Метод наименьших квадратов в задаче линейной и нелинейной регрессии
Глушков Егор Александрович, гр. 20.М04-мм
Вариант 4
- Промоделировать нелинейную модель \(y = f(x, a, b) + \delta\) с несмещённой нормально распределенной ошибкой, дисперсия которой равна \(\varepsilon\), считая, \(x\) стандартно нормально распределённой случайной величиной.
- \(f(x, a, b) = a \sin x + bx^2, \; a=2, b=1, \varepsilon=0.8\)
Оценить параметры нелинейной модели по методу наименьших квадратов (численно). Применить к модельным данным линейную модель и оценить параметры. Построить на двумерной диаграмме основную и линейную модель. Сравнить невязки для обеих моделей.
Для линейной модели выполнить дисперсионный анализ, проверить значимость прогноза и коэффициентов регрессии. Сравнить непосредственные вычисления с результатами встроенной функции.
Промоделировать данные для множественной регрессии. Применить функцию \(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=