Los datos
Los datos del fichero EdadPesoGrasas.txt corresponden a tres
variables medidas en 25 individuos: edad, peso y cantidad de grasas en
sangre. Para leer el fichero de datos y saber los nombres de las
variables:
grasas <- read.table('http://verso.mat.uam.es/~joser.berrendero/datos/EdadPesoGrasas.txt', header = TRUE)
names(grasas)
[1] "peso" "edad" "grasas"
Con el fin de conocer las relaciones existentes entre cada par de
variables podemos representar una matriz de diagramas de dispersión. Al
parecer existe una relación lineal bastante clara entre la edad y las
grasas, pero no entre los otros dos pares de variables. Por otra parte
el fichero contiene un dato atípico.

Para cuantificar el grado de relación lineal, calculamos la matriz de
coeficientes de correlación:
cor(grasas)
peso edad grasas
peso 1.0000000 0.2400133 0.2652935
edad 0.2400133 1.0000000 0.8373534
grasas 0.2652935 0.8373534 1.0000000
Cálculo y representacion de la recta de mínimos cuadrados
El comando básico es lm (linear models). El primer argumento de este
comando es una fórmula \(y\)~\(x\) en la que se especifica cuál es la
variable respuesta o dependiente (\(y\)) y cuál es la variable regresora o
independiente (\(x\)). El segundo
argumento, llamado data especifica cuál es el fichero en el que se
encuentran las variables. El resultado lo guardamos en un objeto llamado
regresion. Este objeto es una lista que contiene toda la información
relevante sobre el análisis. Mediante el comando summary
obtenemos un resumen de los principales resultados:
regresion <- lm(grasas ~ edad, data = grasas)
summary(regresion)
Call:
lm(formula = grasas ~ edad, data = grasas)
Residuals:
Min 1Q Median 3Q Max
-63.478 -26.816 -3.854 28.315 90.881
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 102.5751 29.6376 3.461 0.00212 **
edad 5.3207 0.7243 7.346 1.79e-07 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 43.46 on 23 degrees of freedom
Multiple R-squared: 0.7012, Adjusted R-squared: 0.6882
F-statistic: 53.96 on 1 and 23 DF, p-value: 1.794e-07
Los parámetros de la ecuación de la recta de mínimos cuadrados que
relaciona la cantidad de grasas en la sangre en función del peso vienen
dados por la columna Estimate de la tabla
Coefficients de la salida anterior. Por lo tanto, en este
ejemplo la ecuación de la recta de mínimos cuadrados es:
\(y=102.575+5.321x\)
Los siguientes comandos representan la nube de puntos (comando plot)
y añaden la representación gráfica de la recta de mínimos cuadrados
(comando abline aplicado al objeto generado por lm):

El coeficiente de determinación (es decir, el coeficiente de
correlación al cuadrado) mide la bondad del ajuste de la recta a los
datos. A partir de la salida anterior, vemos que su valor en este caso
es Multiple R-squared: 0.701.
Cálculo de predicciones
Supongamos que queremos utilizar la recta de mínimos cuadrados para
predecir la cantidad de grasas para individuos de edades \(31,31,32,…,50\). Basta crear un fichero de
datos que contenga las nuevas variables regresoras y usar el comando
predict:
nuevas.edades <- data.frame(edad = seq(30, 50))
predict(regresion, nuevas.edades)
1 2 3 4 5 6 7 8 9
262.1954 267.5161 272.8368 278.1575 283.4781 288.7988 294.1195 299.4402 304.7608
10 11 12 13 14 15 16 17 18
310.0815 315.4022 320.7229 326.0435 331.3642 336.6849 342.0056 347.3263 352.6469
19 20 21
357.9676 363.2883 368.6090
Por ejemplo, para un individuo de 30 años, predecimos una cantidad de
grasas de 262.2
Inferencia en el modelo de regresión simple
Suponemos ahora que los datos proceden de un modelo de regresión
simple de la forma:
\(yi=β0+β1xi+ϵi, i=1,…,n,\)
donde los errores aleatorios \(ϵi\)
son independientes con distribución normal de media 0 y varianza \(σ^2\).
Bajo este modelo,
Los errores típicos de los estimadores
de los parámetros β0 y β1 se encuentran en la columna Std Error de la
salida anterior. En el ejemplo, sus valores son 29.638 y 0.724
respectivamente.
La columna t value contiene el estadístico
t, es decir, cociente entre cada estimador y su error típico.
Estos cocientes son la base para llevar a cabo los contrastes \(H_{0}:β_{0}=0\) y \(H_0:β_1=0\).
Los correspondientes p-valores aparecen en la columna
Pr(>|t|). En este caso son muy pequeños por lo que se
rechazan ambas hipótesis para los niveles de significación
habituales.
El estimador de la desviación típica de los
errores \(σ\) aparece como
Residual standard error y su valor en el ejemplo es 43.5
Los intervalos de confianza para los parámetros
se obtienen con el comando confint. El parámetro
level permite elegir el nivel de confianza (por defecto es
0.95):
confint(regresion)
2.5 % 97.5 %
(Intercept) 41.265155 163.885130
edad 3.822367 6.818986
confint(regresion, level = 0.90)
5 % 95 %
(Intercept) 51.780153 153.370132
edad 4.079335 6.562018
- Los intervalos de confianza para la respuesta media y los intervalos
de predicción para la respuesta se pueden obtener usando el comando
predict. Por ejemplo, el siguiente código calcula y
representa los dos tipos de intervalos para el rango de edades que va de
20 a 60 años (los de predicción en rojo):
nuevas.edades <- data.frame(edad = seq(20, 60))
# Grafico de dispersion y recta
plot(grasas$edad, grasas$grasas, xlab='Edad', ylab='Grasas')
abline(regresion)
# Intervalos de confianza de la respuesta media:
# ic es una matriz con tres columnas: la primera es la prediccion, las otras dos son los extremos del intervalo
ic <- predict(regresion, nuevas.edades, interval = 'confidence')
lines(nuevas.edades$edad, ic[, 2], lty = 2)
lines(nuevas.edades$edad, ic[, 3], lty = 2)
# Intervalos de prediccion
ic <- predict(regresion, nuevas.edades, interval = 'prediction')
lines(nuevas.edades$edad, ic[, 2], lty = 2, col = 'red')
lines(nuevas.edades$edad, ic[, 3], lty = 2, col = 'red')

- La tabla de análisis de la varianza de los errores
se obtiene con el comando
anova:
anova(regresion)
Analysis of Variance Table
Response: grasas
Df Sum Sq Mean Sq F value Pr(>F)
edad 1 101933 101933 53.964 1.794e-07 ***
Residuals 23 43444 1889
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Diagnóstico del modelo
Los valores ajustados \(\hat{y}_i\) y los residuos
\(e_i=\hat{y}_i−y_i\) se pueden obtener
con los comandos fitted y residuals
respectivamente. Los residuos estandarizados se obtienen con
rstandard. Por ejemplo, el siguiente código obtiene una
representación de los residuos estandarizados frente a los valores
ajustados, que resulta útil al llevar a cabo el diagnóstico del
modelo:

No se observa ningún patrón especial, por lo que tanto la
homocedasticidad como la linealidad resultan hipótesis razonables.
La hipótesis de normalidad se suele comprobar mediante un
QQ plot de los residuos. El siguiente código
sirve para obtenerlo:

Dado que los puntos están bastante alineados, la normalidad también
parece aceptable.
# Variable regresora (dieño fijo) y parámetros
x = seq(1,10)
beta0 <- 0
beta1 <- 1
sigma <- 0.3
# Genera la variable respuesta
y <- beta0 + beta1*x + rnorm(length(x), sd=sigma)
# Ajusta el modelo
reg <- lm(y~x)
# Extrae el valor de la pendiente estimada
coefficients(reg)[2]
x
1.031375
# Resume el ajuste
summary(reg)
Call:
lm(formula = y ~ x)
Residuals:
Min 1Q Median 3Q Max
-0.54850 -0.30062 -0.00401 0.17426 0.70650
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.06301 0.27941 -0.226 0.827
x 1.03138 0.04503 22.904 1.4e-08 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.409 on 8 degrees of freedom
Multiple R-squared: 0.985, Adjusted R-squared: 0.9831
F-statistic: 524.6 on 1 and 8 DF, p-value: 1.4e-08
LS0tDQp0aXRsZTogIlJlZ3Jlc2nDs24gTGluZWFsIHNpbXBsZSBjb24gUiINCmF1dGhvcjogIkRhbmllbCBCZW5hdmlkZXMiDQpkYXRlOiAiMTAgZGUganVsaW8gZGUgMjAyNCINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBEYW5pZWwgQmVuYXZpZGVzOiBkZWZhdWx0DQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0KLS0tDQoNCiMjIExvcyBkYXRvcw0KDQpMb3MgZGF0b3MgZGVsIGZpY2hlcm8gRWRhZFBlc29HcmFzYXMudHh0IGNvcnJlc3BvbmRlbiBhIHRyZXMgdmFyaWFibGVzIG1lZGlkYXMgZW4gMjUgaW5kaXZpZHVvczogZWRhZCwgcGVzbyB5IGNhbnRpZGFkIGRlIGdyYXNhcyBlbiBzYW5ncmUuIFBhcmEgbGVlciBlbCBmaWNoZXJvIGRlIGRhdG9zIHkgc2FiZXIgbG9zIG5vbWJyZXMgZGUgbGFzIHZhcmlhYmxlczoNCg0KYGBge3J9DQpncmFzYXMgPC0gcmVhZC50YWJsZSgnaHR0cDovL3ZlcnNvLm1hdC51YW0uZXMvfmpvc2VyLmJlcnJlbmRlcm8vZGF0b3MvRWRhZFBlc29HcmFzYXMudHh0JywgaGVhZGVyID0gVFJVRSkNCm5hbWVzKGdyYXNhcykNCmBgYA0KQ29uIGVsIGZpbiBkZSBjb25vY2VyIGxhcyByZWxhY2lvbmVzIGV4aXN0ZW50ZXMgZW50cmUgY2FkYSBwYXIgZGUgdmFyaWFibGVzIHBvZGVtb3MgcmVwcmVzZW50YXIgdW5hIG1hdHJpeiBkZSBkaWFncmFtYXMgZGUgZGlzcGVyc2nDs24uIEFsIHBhcmVjZXIgZXhpc3RlIHVuYSByZWxhY2nDs24gbGluZWFsIGJhc3RhbnRlIGNsYXJhIGVudHJlIGxhIGVkYWQgeSBsYXMgZ3Jhc2FzLCBwZXJvIG5vIGVudHJlIGxvcyBvdHJvcyBkb3MgcGFyZXMgZGUgdmFyaWFibGVzLiBQb3Igb3RyYSBwYXJ0ZSBlbCBmaWNoZXJvIGNvbnRpZW5lIHVuIGRhdG8gYXTDrXBpY28uDQoNCmBgYHtyfQ0KcGFpcnMoZ3Jhc2FzKQ0KYGBgDQpQYXJhIGN1YW50aWZpY2FyIGVsIGdyYWRvIGRlIHJlbGFjacOzbiBsaW5lYWwsIGNhbGN1bGFtb3MgbGEgbWF0cml6IGRlIGNvZWZpY2llbnRlcyBkZSBjb3JyZWxhY2nDs246DQoNCmBgYHtyfQ0KY29yKGdyYXNhcykNCmBgYA0KIyMgQ8OhbGN1bG8geSByZXByZXNlbnRhY2lvbiBkZSBsYSByZWN0YSBkZSBtw61uaW1vcyBjdWFkcmFkb3MNCg0KRWwgY29tYW5kbyBiw6FzaWNvIGVzIGxtIChsaW5lYXIgbW9kZWxzKS4gRWwgcHJpbWVyIGFyZ3VtZW50byBkZSBlc3RlIGNvbWFuZG8gZXMgdW5hIGbDs3JtdWxhICR5JH4keCQgZW4gbGEgcXVlIHNlIGVzcGVjaWZpY2EgY3XDoWwgZXMgbGEgdmFyaWFibGUgcmVzcHVlc3RhIG8gZGVwZW5kaWVudGUgKCR5JCkgeSBjdcOhbCBlcyBsYSB2YXJpYWJsZSByZWdyZXNvcmEgbyBpbmRlcGVuZGllbnRlICgkeCQpLiBFbCBzZWd1bmRvIGFyZ3VtZW50bywgbGxhbWFkbyBkYXRhIGVzcGVjaWZpY2EgY3XDoWwgZXMgZWwgZmljaGVybyBlbiBlbCBxdWUgc2UgZW5jdWVudHJhbiBsYXMgdmFyaWFibGVzLiBFbCByZXN1bHRhZG8gbG8gZ3VhcmRhbW9zIGVuIHVuIG9iamV0byBsbGFtYWRvIHJlZ3Jlc2lvbi4gRXN0ZSBvYmpldG8gZXMgdW5hIGxpc3RhIHF1ZSBjb250aWVuZSB0b2RhIGxhIGluZm9ybWFjacOzbiByZWxldmFudGUgc29icmUgZWwgYW7DoWxpc2lzLiBNZWRpYW50ZSBlbCBjb21hbmRvIGBzdW1tYXJ5YCBvYnRlbmVtb3MgdW4gcmVzdW1lbiBkZSBsb3MgcHJpbmNpcGFsZXMgcmVzdWx0YWRvczoNCg0KYGBge3J9DQpyZWdyZXNpb24gPC0gbG0oZ3Jhc2FzIH4gZWRhZCwgZGF0YSA9IGdyYXNhcykNCnN1bW1hcnkocmVncmVzaW9uKQ0KYGBgDQpMb3MgcGFyw6FtZXRyb3MgZGUgbGEgZWN1YWNpw7NuIGRlIGxhIHJlY3RhIGRlIG3DrW5pbW9zIGN1YWRyYWRvcyBxdWUgcmVsYWNpb25hIGxhIGNhbnRpZGFkIGRlIGdyYXNhcyBlbiBsYSBzYW5ncmUgZW4gZnVuY2nDs24gZGVsIHBlc28gdmllbmVuIGRhZG9zIHBvciBsYSBjb2x1bW5hIGBFc3RpbWF0ZWAgZGUgbGEgdGFibGEgYENvZWZmaWNpZW50c2AgZGUgbGEgc2FsaWRhIGFudGVyaW9yLiBQb3IgbG8gdGFudG8sIGVuIGVzdGUgZWplbXBsbyBsYSBlY3VhY2nDs24gZGUgbGEgcmVjdGEgZGUgbcOtbmltb3MgY3VhZHJhZG9zIGVzOg0KDQo8Y2VudGVyPiR5PTEwMi41NzUrNS4zMjF4JDwvY2VudGVyPg0KDQoNCkxvcyBzaWd1aWVudGVzIGNvbWFuZG9zIHJlcHJlc2VudGFuIGxhIG51YmUgZGUgcHVudG9zIChjb21hbmRvIHBsb3QpIHkgYcOxYWRlbiBsYSByZXByZXNlbnRhY2nDs24gZ3LDoWZpY2EgZGUgbGEgcmVjdGEgZGUgbcOtbmltb3MgY3VhZHJhZG9zIChjb21hbmRvIGFibGluZSBhcGxpY2FkbyBhbCBvYmpldG8gZ2VuZXJhZG8gcG9yIGBsbWApOg0KDQpgYGB7cn0NCnBsb3QoZ3Jhc2FzJGVkYWQsIGdyYXNhcyRncmFzYXMsIHhsYWI9J0VkYWQnLCB5bGFiPSdHcmFzYXMnKQ0KYWJsaW5lKHJlZ3Jlc2lvbikNCmBgYA0KRWwgY29lZmljaWVudGUgZGUgZGV0ZXJtaW5hY2nDs24gKGVzIGRlY2lyLCBlbCBjb2VmaWNpZW50ZSBkZSBjb3JyZWxhY2nDs24gYWwgY3VhZHJhZG8pIG1pZGUgbGEgYm9uZGFkIGRlbCBhanVzdGUgZGUgbGEgcmVjdGEgYSBsb3MgZGF0b3MuIEEgcGFydGlyIGRlIGxhIHNhbGlkYSBhbnRlcmlvciwgdmVtb3MgcXVlIHN1IHZhbG9yIGVuIGVzdGUgY2FzbyBlcyBgTXVsdGlwbGUgUi1zcXVhcmVkOiAwLjcwMWAuDQoNCiMjIEPDoWxjdWxvIGRlIHByZWRpY2Npb25lcw0KDQpTdXBvbmdhbW9zIHF1ZSBxdWVyZW1vcyB1dGlsaXphciBsYSByZWN0YSBkZSBtw61uaW1vcyBjdWFkcmFkb3MgcGFyYSBwcmVkZWNpciBsYSBjYW50aWRhZCBkZSBncmFzYXMgcGFyYSBpbmRpdmlkdW9zIGRlIGVkYWRlcyAkMzEsMzEsMzIs4oCmLDUwJC4gQmFzdGEgY3JlYXIgdW4gZmljaGVybyBkZSBkYXRvcyBxdWUgY29udGVuZ2EgbGFzIG51ZXZhcyB2YXJpYWJsZXMgcmVncmVzb3JhcyB5IHVzYXIgZWwgY29tYW5kbyBgcHJlZGljdGA6DQoNCmBgYHtyfQ0KbnVldmFzLmVkYWRlcyA8LSBkYXRhLmZyYW1lKGVkYWQgPSBzZXEoMzAsIDUwKSkNCnByZWRpY3QocmVncmVzaW9uLCBudWV2YXMuZWRhZGVzKQ0KYGBgDQpQb3IgZWplbXBsbywgcGFyYSB1biBpbmRpdmlkdW8gZGUgMzAgYcOxb3MsIHByZWRlY2ltb3MgdW5hIGNhbnRpZGFkIGRlIGdyYXNhcyBkZSAyNjIuMg0KDQojIyBJbmZlcmVuY2lhIGVuIGVsIG1vZGVsbyBkZSByZWdyZXNpw7NuIHNpbXBsZQ0KDQpTdXBvbmVtb3MgYWhvcmEgcXVlIGxvcyBkYXRvcyBwcm9jZWRlbiBkZSB1biBtb2RlbG8gZGUgcmVncmVzacOzbiBzaW1wbGUgZGUgbGEgZm9ybWE6DQoNCjxjZW50ZXI+JHlpPc6yMCvOsjF4aSvPtWksIGk9MSzigKYsbiwkPC9jZW50ZXI+ICANCg0KZG9uZGUgbG9zIGVycm9yZXMgYWxlYXRvcmlvcyAkz7VpJCBzb24gaW5kZXBlbmRpZW50ZXMgY29uIGRpc3RyaWJ1Y2nDs24gbm9ybWFsIGRlIG1lZGlhIDAgeSB2YXJpYW56YSAkz4NeMiQuDQoNCkJham8gZXN0ZSBtb2RlbG8sDQoNCi0gTG9zIF9fX2Vycm9yZXMgdMOtcGljb3NfX18gZGUgbG9zIGVzdGltYWRvcmVzIGRlIGxvcyBwYXLDoW1ldHJvcyDOsjAgeSDOsjEgc2UgZW5jdWVudHJhbiBlbiBsYSBjb2x1bW5hIFN0ZCBFcnJvciBkZSBsYSBzYWxpZGEgYW50ZXJpb3IuIEVuIGVsIGVqZW1wbG8sIHN1cyB2YWxvcmVzIHNvbiAyOS42MzggeSAwLjcyNCByZXNwZWN0aXZhbWVudGUuDQoNCi0gTGEgY29sdW1uYSBgdCB2YWx1ZWAgY29udGllbmUgZWwgX19lc3RhZMOtc3RpY28gdF9fLCBlcyBkZWNpciwgY29jaWVudGUgZW50cmUgY2FkYSBlc3RpbWFkb3IgeSBzdSBlcnJvciB0w61waWNvLiBFc3RvcyBjb2NpZW50ZXMgc29uIGxhIGJhc2UgcGFyYSBsbGV2YXIgYSBjYWJvIGxvcyBjb250cmFzdGVzICRIX3swfTrOsl97MH09MCQgeSAkSF8wOs6yXzE9MCQuDQogDQotIExvcyBjb3JyZXNwb25kaWVudGVzIHAtdmFsb3JlcyBhcGFyZWNlbiBlbiBsYSBjb2x1bW5hIGBQcig+fHR8KWAuIEVuIGVzdGUgY2FzbyBzb24gbXV5IHBlcXVlw7FvcyBwb3IgbG8gcXVlIHNlIHJlY2hhemFuIGFtYmFzIGhpcMOzdGVzaXMgcGFyYSBsb3Mgbml2ZWxlcyBkZSBzaWduaWZpY2FjacOzbiBoYWJpdHVhbGVzLg0KDQotIEVsIGVzdGltYWRvciBkZSBsYSBfX2Rlc3ZpYWNpw7NuIHTDrXBpY2EgZGUgbG9zIGVycm9yZXNfXyAkz4MkIGFwYXJlY2UgY29tbyBSZXNpZHVhbCBzdGFuZGFyZCBlcnJvciB5IHN1IHZhbG9yIGVuIGVsIGVqZW1wbG8gZXMgNDMuNQ0KDQotIExvcyBfX2ludGVydmFsb3MgZGUgY29uZmlhbnphIHBhcmEgbG9zIHBhcsOhbWV0cm9zX18gc2Ugb2J0aWVuZW4gY29uIGVsIGNvbWFuZG8gYGNvbmZpbnRgLiBFbCBwYXLDoW1ldHJvIGBsZXZlbGAgcGVybWl0ZSBlbGVnaXIgZWwgbml2ZWwgZGUgY29uZmlhbnphIChwb3IgZGVmZWN0byBlcyAwLjk1KToNCg0KYGBge3J9DQpjb25maW50KHJlZ3Jlc2lvbikNCmBgYA0KYGBge3J9DQpjb25maW50KHJlZ3Jlc2lvbiwgbGV2ZWwgPSAwLjkwKQ0KYGBgDQotIExvcyBpbnRlcnZhbG9zIGRlIGNvbmZpYW56YSBwYXJhIGxhIHJlc3B1ZXN0YSBtZWRpYSB5IGxvcyBpbnRlcnZhbG9zIGRlIHByZWRpY2Npw7NuIHBhcmEgbGEgcmVzcHVlc3RhIHNlIHB1ZWRlbiBvYnRlbmVyIHVzYW5kbyBlbCBjb21hbmRvIGBwcmVkaWN0YC4gUG9yIGVqZW1wbG8sIGVsIHNpZ3VpZW50ZSBjw7NkaWdvIGNhbGN1bGEgeSByZXByZXNlbnRhIGxvcyBkb3MgdGlwb3MgZGUgaW50ZXJ2YWxvcyBwYXJhIGVsIHJhbmdvIGRlIGVkYWRlcyBxdWUgdmEgZGUgMjAgYSA2MCBhw7FvcyAobG9zIGRlIHByZWRpY2Npw7NuIGVuIHJvam8pOg0KDQpgYGB7cn0NCm51ZXZhcy5lZGFkZXMgPC0gZGF0YS5mcmFtZShlZGFkID0gc2VxKDIwLCA2MCkpDQojIEdyYWZpY28gZGUgZGlzcGVyc2lvbiB5IHJlY3RhDQpwbG90KGdyYXNhcyRlZGFkLCBncmFzYXMkZ3Jhc2FzLCB4bGFiPSdFZGFkJywgeWxhYj0nR3Jhc2FzJykNCmFibGluZShyZWdyZXNpb24pDQoNCiMgSW50ZXJ2YWxvcyBkZSBjb25maWFuemEgZGUgbGEgcmVzcHVlc3RhIG1lZGlhOg0KIyBpYyBlcyB1bmEgbWF0cml6IGNvbiB0cmVzIGNvbHVtbmFzOiBsYSBwcmltZXJhIGVzIGxhIHByZWRpY2Npb24sIGxhcyBvdHJhcyBkb3Mgc29uIGxvcyBleHRyZW1vcyBkZWwgaW50ZXJ2YWxvDQppYyA8LSBwcmVkaWN0KHJlZ3Jlc2lvbiwgbnVldmFzLmVkYWRlcywgaW50ZXJ2YWwgPSAnY29uZmlkZW5jZScpDQpsaW5lcyhudWV2YXMuZWRhZGVzJGVkYWQsIGljWywgMl0sIGx0eSA9IDIpDQpsaW5lcyhudWV2YXMuZWRhZGVzJGVkYWQsIGljWywgM10sIGx0eSA9IDIpDQoNCiMgSW50ZXJ2YWxvcyBkZSBwcmVkaWNjaW9uDQppYyA8LSBwcmVkaWN0KHJlZ3Jlc2lvbiwgbnVldmFzLmVkYWRlcywgaW50ZXJ2YWwgPSAncHJlZGljdGlvbicpDQpsaW5lcyhudWV2YXMuZWRhZGVzJGVkYWQsIGljWywgMl0sIGx0eSA9IDIsIGNvbCA9ICdyZWQnKQ0KbGluZXMobnVldmFzLmVkYWRlcyRlZGFkLCBpY1ssIDNdLCBsdHkgPSAyLCBjb2wgPSAncmVkJykNCmBgYA0KLSBMYSBfX3RhYmxhIGRlIGFuw6FsaXNpcyBkZSBsYSB2YXJpYW56YV9fIGRlIGxvcyBlcnJvcmVzIHNlIG9idGllbmUgY29uIGVsIGNvbWFuZG8gYGFub3ZhYDoNCg0KYGBge3J9DQphbm92YShyZWdyZXNpb24pDQpgYGANCiMjIERpYWduw7NzdGljbyBkZWwgbW9kZWxvDQoNCkxvcyBfX3ZhbG9yZXMgYWp1c3RhZG9zX18gJFxoYXR7eX1faSQgeSBsb3MgX19yZXNpZHVvc19fICRlX2k9XGhhdHt5fV9p4oiSeV9pJCBzZSBwdWVkZW4gb2J0ZW5lciBjb24gbG9zIGNvbWFuZG9zICBgZml0dGVkYCB5IGByZXNpZHVhbHNgIHJlc3BlY3RpdmFtZW50ZS4gTG9zIHJlc2lkdW9zIGVzdGFuZGFyaXphZG9zIHNlIG9idGllbmVuIGNvbiBgcnN0YW5kYXJkYC4gUG9yIGVqZW1wbG8sIGVsIHNpZ3VpZW50ZSBjw7NkaWdvIG9idGllbmUgdW5hIHJlcHJlc2VudGFjacOzbiBkZSBsb3MgcmVzaWR1b3MgZXN0YW5kYXJpemFkb3MgZnJlbnRlIGEgbG9zIHZhbG9yZXMgYWp1c3RhZG9zLCBxdWUgcmVzdWx0YSDDunRpbCBhbCBsbGV2YXIgYSBjYWJvIGVsIGRpYWduw7NzdGljbyBkZWwgbW9kZWxvOg0KDQpgYGB7cn0NCnJlc2lkdW9zIDwtIHJzdGFuZGFyZChyZWdyZXNpb24pDQp2YWxvcmVzLmFqdXN0YWRvcyA8LSBmaXR0ZWQocmVncmVzaW9uKQ0KcGxvdCh2YWxvcmVzLmFqdXN0YWRvcywgcmVzaWR1b3MpDQpgYGANCk5vIHNlIG9ic2VydmEgbmluZ8O6biBwYXRyw7NuIGVzcGVjaWFsLCBwb3IgbG8gcXVlIHRhbnRvIGxhIGhvbW9jZWRhc3RpY2lkYWQgY29tbyBsYSBsaW5lYWxpZGFkIHJlc3VsdGFuIGhpcMOzdGVzaXMgcmF6b25hYmxlcy4NCg0KTGEgaGlww7N0ZXNpcyBkZSBub3JtYWxpZGFkIHNlIHN1ZWxlIGNvbXByb2JhciBtZWRpYW50ZSB1biBfX19RUV9fXyBwbG90IGRlIGxvcyByZXNpZHVvcy4gRWwgc2lndWllbnRlIGPDs2RpZ28gc2lydmUgcGFyYSBvYnRlbmVybG86DQoNCmBgYHtyfQ0KcXFub3JtKHJlc2lkdW9zKQ0KcXFsaW5lKHJlc2lkdW9zKQ0KYGBgDQpEYWRvIHF1ZSBsb3MgcHVudG9zIGVzdMOhbiBiYXN0YW50ZSBhbGluZWFkb3MsIGxhIG5vcm1hbGlkYWQgdGFtYmnDqW4gcGFyZWNlIGFjZXB0YWJsZS4NCg0KYGBge3J9DQojIFZhcmlhYmxlIHJlZ3Jlc29yYSAoZGllw7FvIGZpam8pIHkgcGFyw6FtZXRyb3MNCnggPSBzZXEoMSwxMCkNCmJldGEwIDwtIDANCmJldGExIDwtIDENCnNpZ21hIDwtIDAuMw0KDQojIEdlbmVyYSBsYSB2YXJpYWJsZSByZXNwdWVzdGENCnkgPC0gYmV0YTAgKyBiZXRhMSp4ICsgcm5vcm0obGVuZ3RoKHgpLCBzZD1zaWdtYSkNCg0KIyBBanVzdGEgZWwgbW9kZWxvDQpyZWcgPC0gbG0oeX54KQ0KDQojIEV4dHJhZSBlbCB2YWxvciBkZSBsYSBwZW5kaWVudGUgZXN0aW1hZGENCmNvZWZmaWNpZW50cyhyZWcpWzJdDQoNCiMgUmVzdW1lIGVsIGFqdXN0ZQ0Kc3VtbWFyeShyZWcpDQpgYGANCg0K