library(MASS)
library(latex2exp)
library(ggplot2)
library(tibble)
library(dplyr)
library(ggpubr)
library(QuantPsyc)
En el modelo habitual de regresión partimos del supuesto que hay una
relación lineal entre la variable \(y\)
y los regresores. Sin embargo en algunos casos esta suposición es
inadecuada, puesto que por ejemplo si observamos los gráficos de
dispersión esta suposición puede no estarse cumpliendo de manera
evidente. Para poder solucionar este problema de no linealidad, en
algunos casos a estos modelos podemos hacerlos lineales, usando una
transformación adecuada.
Quizás nos preguntemos que comportamiento deberÃamos observar para
poder encontrar una transformación que pueda linealizar el modelo. Antes
de mostrar algunos casos comunes en los que podemos transformar, veamos
un ejemplo de que va transformar un modelo que a primera vista no es
lineal, pero si podemos hacerlo lineal.
Consideremos la función \[y=\beta_0
e^{\beta_1 x}\varepsilon\] Esta función como podemos ver no es
linear, pero la podemos transformar en una lineal si aplicamos un
logaritmo, con lo que obtenemos \[\ln{y}=\ln{\beta_0 e^{\beta_1
x}\varepsilon}=\ln{\beta_0}+\beta_1 x+\ln{\varepsilon}\] Haciendo
\(y'=\ln{y}\), \(\ln{\beta_0}=\beta_0'\), \(\ln{\beta_1}=\beta_1'\) y \(\ln{\varepsilon}=\varepsilon'\),
tenemos el modelo \[y'=\beta_0'+\beta_1'
x+\varepsilon'.\] Como podemos observar en esta
transformación estamos tomando el logaritmo del error, de modo que si
queremos que haya normalidad en los errores de la transformación es
decir \(\ln{\varepsilon}\) sea normal
distribuido con media \(0\) y varianza
\(\sigma^2\), lo que implica que el
error multiplicativo en el modelo original \(\varepsilon\), debe tener distribución log
normal.
Comentario: De igual forma que en el modelo
de regresión simple, cuando linealizamos un modelo es necesario realizar
la validación de supuestos.
Otro ejemplo de modelos que podemos linealizar, son el caso de
transformaciones reciprocas, es decir algo de la forma
\[\dfrac{1}{y}=\beta_0+\beta_1
x+\varepsilon\] y \[y=\dfrac{x}{\beta_0 x-\beta_1}+\epsilon\]
Comentario: Cuando las transformaciones como
las anteriores son empleadas el estimador de mÃnimos cuadrados tiene
propiedades de mÃnimos cuadrados con respecto a los datos transformados,
no a los originales.
Ejemplo (Molino de Viento)
tabla1 <- data.frame(stringsAsFactors=FALSE,
Velocidad_Viento = c(5.00, 6.00, 3.40, 2.70,
10.00, 9.70, 9.55, 3.05, 8.15, 6.20, 2.90, 6.35, 4.60, 5.80, 7.40, 3.60,
7.85, 8.80, 7.00, 5.45, 9.10, 10.20, 4.10, 3.95, 2.45),
Salida_DC = c(1.582, 1.822, 1.057, 0.500, 2.236, 2.386, 2.294, 0.558, 2.166, 1.866,
0.653, 1.930, 1.562, 1.737, 2.088, 1.137, 2.179, 2.112, 1.800, 1.501, 2.303,
2.310, 1.194, 1.144, 0.123)
)
names(tabla1)<-c("Velocidad del Viento (Mph)","Salida DC")
tabla1
Un ingeniero, está investigando el uso de un molino de viento para
generar electricidad. Ha recopilado datos sobre la salida de DC de su
molino de viento y la velocidad del viento correspondiente. La
inspección del diagrama de dispersión indica que la relación entre la
salida de DC \((y)\) y la velocidad del
viento \((x)\) puede ser no lineal como
veremos a continuación del gráfico de dispersión.
plot(tabla1$`Velocidad del Viento (Mph)`,tabla1$`Salida DC`,xlab=TeX(r'(Velocidad del Viento $x$ )'),ylab=TeX(r'(Salida DC $y$)'),pch=20,cex=2)

mult.norm(tabla1)$test
NULL
Como se puede observar del gráfico de dispersión, pareciera que la
relación entre la salida del voltaje en función de la velocidad del
viento es no lineal. Lo cual podemos contrastar con el trafico de
residuales.
Para ellos,a justando un modelo lineal obtenemos
modelo1<-lm(tabla1$`Salida DC`~tabla1$`Velocidad del Viento (Mph)`)
summary(modelo1)
Call:
lm(formula = tabla1$`Salida DC` ~ tabla1$`Velocidad del Viento (Mph)`)
Residuals:
Min 1Q Median 3Q Max
-0.59869 -0.14099 0.06059 0.17262 0.32184
Coefficients:
Estimate Std. Error
(Intercept) 0.13088 0.12599
tabla1$`Velocidad del Viento (Mph)` 0.24115 0.01905
t value Pr(>|t|)
(Intercept) 1.039 0.31
tabla1$`Velocidad del Viento (Mph)` 12.659 7.55e-12 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.2361 on 23 degrees of freedom
Multiple R-squared: 0.8745, Adjusted R-squared: 0.869
F-statistic: 160.3 on 1 and 23 DF, p-value: 7.546e-12
shapiro.test(modelo1$residuals)
Shapiro-Wilk normality test
data: modelo1$residuals
W = 0.93587, p-value = 0.1188
plot(modelo1$fitted.values,modelo1$residuals,pch=19,xlab="Ajustado",ylab="Residuales")

qqnorm(y=modelo1$residuals)
qqline(modelo1$residuals)

Este comportamiento observado, hace pensar que en efecto el modelo
lineal no es el adecuado y quizás un modelo cuadrático del tipo \[y=\beta_0+\beta_1 x+\beta_2
x^2+\varepsilon\] resulte mejor para explicar la curvatura
aparente. Sin embargo podemos observar del diagrama de dispersión que a
medida que la velocidad del viento aumenta, la salida de voltaje se
acerca un punto extremo de 2.5 , lo cual es consistente con el
funcionamiento de un molino de viento. Dado que el modelo cuadrático
eventualmente se doblará, esto indicarÃa que a velocidades mas altas de
este punto máximo observado la salida de voltaje disminuirÃa lo cual,
con lo cual nuevamente el modelo cuadrático tampoco seria adecuado para
los datos.
Como mencionamos a medida que la velocidad aumenta, la salida de
voltaje pareciera alcanzar un punto extremo, de manera que tiende como a
estabilizarse, lo que sugiere que una transformación de tipo reciproca
sea lo mas adecuada, pues en ellas incorporamos asÃntotas, y en este
caso buscamos que haya una asÃntota superior que se acerque a este valor
extremo. Transformando el modelo como \[y=\beta_0+\beta_1
\left(\dfrac{1}{x}\right)+\varepsilon.\] Usando esta
transformación veamos su relación mediante el gráfico de dispersión
plot(1/tabla1$`Velocidad del Viento (Mph)`,tabla1$`Salida DC`,xlab=TeX(r'(Velocidad del Viento $x$ )'),ylab=TeX(r'(Salida DC $y$)'),pch=20,cex=2)

ynuevos<-(tabla1$`Salida DC`)^2
#plot(tabla1$`Velocidad del Viento (Mph)`,ynuevos)
#modelo22<-lm(ynuevos~tabla1$`Velocidad del Viento (Mph)`)
#plot(modelo22)
xnuevos<-log(tabla1$`Velocidad del Viento (Mph)`)
modelo222<-lm(tabla1$`Salida DC`~xnuevos)
plot(modelo222)




Ajustando el modelo, tenemos como resultado
tabla2 <- data.frame(stringsAsFactors=FALSE,
Velocidad_Viento = 1/c(5.00, 6.00, 3.40, 2.70,
10.00, 9.70, 9.55, 3.05, 8.15, 6.20, 2.90, 6.35, 4.60, 5.80, 7.40, 3.60,
7.85, 8.80, 7.00, 5.45, 9.10, 10.20, 4.10, 3.95, 2.45),
Salida_DC = c(1.582, 1.822, 1.057, 0.500, 2.236, 2.386, 2.294, 0.558, 2.166, 1.866,
0.653, 1.930, 1.562, 1.737, 2.088, 1.137, 2.179, 2.112, 1.800, 1.501, 2.303,
2.310, 1.194, 1.144, 0.123)
)
names(tabla2)<-c("Velocidad del Viento (Mph)","Salida DC")
tabla2
modelo2<-lm(tabla2$`Salida DC`~tabla2$`Velocidad del Viento (Mph)`)
summary(modelo2)
Call:
lm(formula = tabla2$`Salida DC` ~ tabla2$`Velocidad del Viento (Mph)`)
Residuals:
Min 1Q Median 3Q Max
-0.20547 -0.04940 0.01100 0.08352 0.12204
Coefficients:
Estimate Std. Error
(Intercept) 2.9789 0.0449
tabla2$`Velocidad del Viento (Mph)` -6.9345 0.2064
t value Pr(>|t|)
(Intercept) 66.34 <2e-16 ***
tabla2$`Velocidad del Viento (Mph)` -33.59 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.09417 on 23 degrees of freedom
Multiple R-squared: 0.98, Adjusted R-squared: 0.9792
F-statistic: 1128 on 1 and 23 DF, p-value: < 2.2e-16
plot(modelo2$fitted.values,rstudent(modelo2),pch=19,xlab="Ajustado",ylab="Residuales")
abline(h=0,lty=2,col="red")

plot(modelo2)




ggqqplot(modelo2$residuals)

#mult.norm(tabla1)$mult.test
Ejemplo Datos MariaJuana
Veamos ahora si podemos aplicar alguna transformación al conjunto de
datos de Mariajuana. Recordemos que en este conjunto de datos tenÃamos
en esencia tres subconjuntos a causa de los tres cantidades que se
tenÃan para la dosis. De esta manera es conveniente trabajar con estos
tres subconjuntos. Recordemos que las transformaciones que vimos
previamente por ahora están limitadas a la regresión lineal simple, con
lo cual consideraremos la altura como función de precipitación o como
función de la temperatura.
## Carga del conjunto de datos
maria<-read.table("/Users/danimathud/Documents/GitHub/R_projects/ModelosEstadisticos1/Datas/Mariajuana.txt")
maria
NA
## Filtrado
maria_dosis0<-maria %>% filter(Dosis.en.kg==0)
maria_dosis0
maria_dosis1<-maria %>% filter(Dosis.en.kg==1)
maria_dosis1
maria_dosis15<-maria %>% filter(Dosis.en.kg==1.5)
maria_dosis15
par(mfrow=c(1,3))
plot(maria_dosis0[,1:3],lower.panel=NULL,main="Dosis 0")
par(mfrow=c(1,3))

plot(maria_dosis1[,1:3],lower.panel=NULL,main="Dosis 1")
par(mfrow=c(1,3))

plot(maria_dosis15[,1:3],lower.panel=NULL,main="Dosis 1.5")

#plot(maria[,1:3],lower.panel=NULL)
#plot3d(maria[,1:3])
Para este ejemplo consideremos el subconjunto para dosis de 1.5, y
veamos para cual resulta mas conveniente una transformación, si para
altura en función de temperatura o altura en función de
precipitación.
Altura en función de la temperatura
modelo3<-lm(maria_dosis15$Altura.en.cm~maria_dosis15$Temperatura.en.C)
plot(modelo3,pch=19)




shapiro.test(modelo3$residuals)
Shapiro-Wilk normality test
data: modelo3$residuals
W = 0.96296, p-value = 0.7156
plot(maria_dosis15$Temperatura.en.C,maria_dosis15$Altura.en.cm,xlab="Temperatura",ylab="Altura",pch=19)
abline(modelo3,col="red")

Como podemos considerando altura en función de temperatura, aunque
del gráfico de residuales y QQ pareciera que se cumplen todos los
supuestos de regresión lineal y normalidad en los errores, sin embargo
podemos ver también, que la recta no se ajusta lo suficientemente bien.
Por lo cual podrÃamos intentar transformar los datos esperando conseguir
un mejor resultado en el ajuste del modelo.
Notemos de los datos que la recta que ajustemos tiene parámetro \(\beta_1<0\) y la temperatura que
consideramos es positiva, con lo cual podemos observar que nuestros
datos, tienen mas parecido con los gráficos b) y d) de la figura
mostrada en un inició, asà podrÃamos intentar considerar como
transformaciones
\[\log{y}=\log{\beta_0
x^{\beta_1}}=\log{\beta_0}+\beta_1\log{x}\] o \[\log{y}=\log{\beta_0 e^{\beta_1
x}}=\log{\beta_0}+\beta_1 x.\] Veamos cual de estas nos da buenos
resultados
y1_tran<-log(maria_dosis15$Altura.en.cm)
x1_tran<-log(maria_dosis15$Temperatura.en.C)
plot(x1_tran,y1_tran,pch=19,main=TeX(r'("Transformando con $y'=\log{(y)}$ y $x'=\log{(x)}$)'),xlab="log(Temperatura)",ylab="log(Altura)")
modelo3_tran1<-lm(y1_tran~x1_tran)
abline(modelo3_tran1,col="blue")

plot(modelo3_tran1,pch=19)




shapiro.test(modelo3_tran1$residuals)
Shapiro-Wilk normality test
data: modelo3_tran1$residuals
W = 0.96199, p-value = 0.6981
plot(maria_dosis15$Temperatura.en.C,y1_tran,pch=19,main=TeX(r'("Transformando con $y'=\log{(y)}$)'),ylab="log(Altura)",xlab="Temperatura")
modelo3_tran2<-lm(y1_tran~maria_dosis15$Temperatura.en.C)
abline(modelo3_tran2,col="red")

plot(modelo3_tran2,pch=19)




shapiro.test(modelo3_tran2$residuals)
Shapiro-Wilk normality test
data: modelo3_tran2$residuals
W = 0.95863, p-value = 0.637
LS0tCnRpdGxlOiAiU2VjY2lvbiA1LjMgVHJhbnNmb3JtYWNpb25lcyBQYXJhIExpbmVhbGl6YXIgTW9kZWxvcyIKYXV0aG9yOiAiRGFuaWVsIE1hcnRpbmV6IgpvdXRwdXQ6CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAplZGl0b3Jfb3B0aW9uczoKICBtYXJrZG93bjoKICAgIHdyYXA6IDcyCi0tLQoKYGBge3J9CmxpYnJhcnkoTUFTUykKbGlicmFyeShsYXRleDJleHApCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeSh0aWJibGUpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwdWJyKQpsaWJyYXJ5KFF1YW50UHN5YykKYGBgCgoKCkVuIGVsIG1vZGVsbyBoYWJpdHVhbCBkZSByZWdyZXNpw7NuIHBhcnRpbW9zIGRlbCBzdXB1ZXN0byBxdWUgaGF5IHVuYSByZWxhY2nDs24gbGluZWFsIGVudHJlIGxhIHZhcmlhYmxlICR5JCB5IGxvcyByZWdyZXNvcmVzLiBTaW4gZW1iYXJnbyBlbiBhbGd1bm9zIGNhc29zIGVzdGEgc3Vwb3NpY2nDs24gZXMgaW5hZGVjdWFkYSwgcHVlc3RvIHF1ZSBwb3IgZWplbXBsbyBzaSBvYnNlcnZhbW9zIGxvcyBncsOhZmljb3MgZGUgZGlzcGVyc2nDs24gZXN0YSBzdXBvc2ljacOzbiBwdWVkZSBubyBlc3RhcnNlIGN1bXBsaWVuZG8gZGUgbWFuZXJhIGV2aWRlbnRlLiBQYXJhIHBvZGVyIHNvbHVjaW9uYXIgZXN0ZSBwcm9ibGVtYSBkZSBubyBsaW5lYWxpZGFkLCBlbiBhbGd1bm9zIGNhc29zIGEgZXN0b3MgbW9kZWxvcyBwb2RlbW9zIGhhY2VybG9zIGxpbmVhbGVzLCB1c2FuZG8gdW5hIHRyYW5zZm9ybWFjacOzbiBhZGVjdWFkYS4KClF1aXrDoXMgbm9zIHByZWd1bnRlbW9zIHF1ZSBjb21wb3J0YW1pZW50byBkZWJlcsOtYW1vcyBvYnNlcnZhciBwYXJhIHBvZGVyCmVuY29udHJhciB1bmEgdHJhbnNmb3JtYWNpw7NuIHF1ZSBwdWVkYSBsaW5lYWxpemFyIGVsIG1vZGVsby4gQW50ZXMgZGUKbW9zdHJhciBhbGd1bm9zIGNhc29zIGNvbXVuZXMgZW4gbG9zIHF1ZSBwb2RlbW9zIHRyYW5zZm9ybWFyLCB2ZWFtb3MgdW4KZWplbXBsbyBkZSBxdWUgdmEgdHJhbnNmb3JtYXIgdW4gbW9kZWxvIHF1ZSBhIHByaW1lcmEgdmlzdGEgbm8gZXMKbGluZWFsLCBwZXJvIHNpIHBvZGVtb3MgaGFjZXJsbyBsaW5lYWwuCgpDb25zaWRlcmVtb3MgbGEgZnVuY2nDs24gJCR5PVxiZXRhXzAgZV57XGJldGFfMSB4fVx2YXJlcHNpbG9uJCQgRXN0YQpmdW5jacOzbiBjb21vIHBvZGVtb3MgdmVyIG5vIGVzIGxpbmVhciwgcGVybyBsYSBwb2RlbW9zIHRyYW5zZm9ybWFyIGVuCnVuYSBsaW5lYWwgc2kgYXBsaWNhbW9zIHVuIGxvZ2FyaXRtbywgY29uIGxvIHF1ZSBvYnRlbmVtb3MKJCRcbG57eX09XGxue1xiZXRhXzAgZV57XGJldGFfMSB4fVx2YXJlcHNpbG9ufT1cbG57XGJldGFfMH0rXGJldGFfMSB4K1xsbntcdmFyZXBzaWxvbn0kJApIYWNpZW5kbyAkeSc9XGxue3l9JCwgJFxsbntcYmV0YV8wfT1cYmV0YV8wJyQsICRcbG57XGJldGFfMX09XGJldGFfMSckIHkKJFxsbntcdmFyZXBzaWxvbn09XHZhcmVwc2lsb24nJCwgdGVuZW1vcyBlbCBtb2RlbG8KJCR5Jz1cYmV0YV8wJytcYmV0YV8xJyB4K1x2YXJlcHNpbG9uJy4kJCBDb21vIHBvZGVtb3Mgb2JzZXJ2YXIgZW4gZXN0YQp0cmFuc2Zvcm1hY2nDs24gZXN0YW1vcyB0b21hbmRvIGVsIGxvZ2FyaXRtbyBkZWwgZXJyb3IsIGRlIG1vZG8gcXVlIHNpCnF1ZXJlbW9zIHF1ZSBoYXlhIG5vcm1hbGlkYWQgZW4gbG9zIGVycm9yZXMgZGUgbGEgdHJhbnNmb3JtYWNpw7NuIGVzCmRlY2lyICRcbG57XHZhcmVwc2lsb259JCBzZWEgbm9ybWFsIGRpc3RyaWJ1aWRvIGNvbiBtZWRpYSAkMCQgeSB2YXJpYW56YQokXHNpZ21hXjIkLCBsbyBxdWUgaW1wbGljYSBxdWUgZWwgZXJyb3IgbXVsdGlwbGljYXRpdm8gZW4gZWwgbW9kZWxvCm9yaWdpbmFsICRcdmFyZXBzaWxvbiQsIGRlYmUgdGVuZXIgZGlzdHJpYnVjacOzbiBsb2cgbm9ybWFsLgoKKioqQ29tZW50YXJpbzoqKiogRGUgaWd1YWwgZm9ybWEgcXVlIGVuIGVsIG1vZGVsbyBkZSByZWdyZXNpw7NuIHNpbXBsZSwKY3VhbmRvIGxpbmVhbGl6YW1vcyB1biBtb2RlbG8gZXMgbmVjZXNhcmlvIHJlYWxpemFyIGxhIHZhbGlkYWNpw7NuIGRlCnN1cHVlc3Rvcy4KCiFbRnVuY2lvbmVzIExpbmVhbGl6YWJsZXNdKGltYWdlcy9MaW5lYWxpemFibGVzLTAxLnBuZykKCk90cm8gZWplbXBsbyBkZSBtb2RlbG9zIHF1ZSBwb2RlbW9zIGxpbmVhbGl6YXIsIHNvbiBlbCBjYXNvIGRlCnRyYW5zZm9ybWFjaW9uZXMgcmVjaXByb2NhcywgZXMgZGVjaXIgYWxnbyBkZSBsYSBmb3JtYQoKJCRcZGZyYWN7MX17eX09XGJldGFfMCtcYmV0YV8xIHgrXHZhcmVwc2lsb24kJCB5CiQkeT1cZGZyYWN7eH17XGJldGFfMCB4LVxiZXRhXzF9K1xlcHNpbG9uJCQgKioqQ29tZW50YXJpbzoqKiogQ3VhbmRvIGxhcwp0cmFuc2Zvcm1hY2lvbmVzIGNvbW8gbGFzIGFudGVyaW9yZXMgc29uIGVtcGxlYWRhcyBlbCBlc3RpbWFkb3IgZGUKbcOtbmltb3MgY3VhZHJhZG9zIHRpZW5lIHByb3BpZWRhZGVzIGRlIG3DrW5pbW9zIGN1YWRyYWRvcyBjb24gcmVzcGVjdG8gYSBsb3MgZGF0b3MgdHJhbnNmb3JtYWRvcywgKioqbm8gYSBsb3Mgb3JpZ2luYWxlcyoqKi4KCioqRWplbXBsbyAoTW9saW5vIGRlIFZpZW50bykqKgoKYGBge3J9CnRhYmxhMSA8LSBkYXRhLmZyYW1lKHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UsClZlbG9jaWRhZF9WaWVudG8gPSBjKDUuMDAsIDYuMDAsIDMuNDAsIDIuNzAsCiAgICAgIDEwLjAwLCA5LjcwLCA5LjU1LCAzLjA1LCA4LjE1LCA2LjIwLCAyLjkwLCA2LjM1LCA0LjYwLCA1LjgwLCA3LjQwLCAzLjYwLAogICAgICA3Ljg1LCA4LjgwLCA3LjAwLCA1LjQ1LCA5LjEwLCAxMC4yMCwgNC4xMCwgMy45NSwgMi40NSksClNhbGlkYV9EQyA9IGMoMS41ODIsIDEuODIyLCAxLjA1NywgMC41MDAsIDIuMjM2LCAyLjM4NiwgMi4yOTQsIDAuNTU4LCAyLjE2NiwgMS44NjYsCiAgICAgMC42NTMsIDEuOTMwLCAxLjU2MiwgMS43MzcsIDIuMDg4LCAxLjEzNywgMi4xNzksIDIuMTEyLCAxLjgwMCwgMS41MDEsIDIuMzAzLAogICAgIDIuMzEwLCAxLjE5NCwgMS4xNDQsIDAuMTIzKQopCm5hbWVzKHRhYmxhMSk8LWMoIlZlbG9jaWRhZCBkZWwgVmllbnRvIChNcGgpIiwiU2FsaWRhIERDIikKdGFibGExCmBgYAoKVW4gaW5nZW5pZXJvLCBlc3TDoSBpbnZlc3RpZ2FuZG8gZWwgdXNvIGRlIHVuIG1vbGlubyBkZSB2aWVudG8gcGFyYQpnZW5lcmFyIGVsZWN0cmljaWRhZC4gSGEgcmVjb3BpbGFkbyBkYXRvcyBzb2JyZSBsYSBzYWxpZGEgZGUgREMgZGUgc3UKbW9saW5vIGRlIHZpZW50byB5IGxhIHZlbG9jaWRhZCBkZWwgdmllbnRvIGNvcnJlc3BvbmRpZW50ZS4gTGEKaW5zcGVjY2nDs24gZGVsIGRpYWdyYW1hIGRlIGRpc3BlcnNpw7NuIGluZGljYSBxdWUgbGEgcmVsYWNpw7NuIGVudHJlIGxhCnNhbGlkYSBkZSBEQyAkKHkpJCB5IGxhIHZlbG9jaWRhZCBkZWwgdmllbnRvICQoeCkkIHB1ZWRlIHNlciBubyBsaW5lYWwKY29tbyB2ZXJlbW9zIGEgY29udGludWFjacOzbiBkZWwgZ3LDoWZpY28gZGUgZGlzcGVyc2nDs24uCgpgYGB7cn0KcGxvdCh0YWJsYTEkYFZlbG9jaWRhZCBkZWwgVmllbnRvIChNcGgpYCx0YWJsYTEkYFNhbGlkYSBEQ2AseGxhYj1UZVgocicoVmVsb2NpZGFkIGRlbCBWaWVudG8gJHgkICknKSx5bGFiPVRlWChyJyhTYWxpZGEgREMgJHkkKScpLHBjaD0yMCxjZXg9MikKbXVsdC5ub3JtKHRhYmxhMSkkdGVzdApgYGAKCkNvbW8gc2UgcHVlZGUgb2JzZXJ2YXIgZGVsIGdyw6FmaWNvIGRlIGRpc3BlcnNpw7NuLCBwYXJlY2llcmEgcXVlIGxhCnJlbGFjacOzbiBlbnRyZSBsYSBzYWxpZGEgZGVsIHZvbHRhamUgZW4gZnVuY2nDs24gZGUgbGEgdmVsb2NpZGFkIGRlbAp2aWVudG8gZXMgbm8gbGluZWFsLiBMbyBjdWFsIHBvZGVtb3MgY29udHJhc3RhciBjb24gZWwgdHJhZmljbyBkZQpyZXNpZHVhbGVzLgoKUGFyYSBlbGxvcyxhIGp1c3RhbmRvIHVuIG1vZGVsbyBsaW5lYWwgb2J0ZW5lbW9zCgpgYGB7cn0KbW9kZWxvMTwtbG0odGFibGExJGBTYWxpZGEgRENgfnRhYmxhMSRgVmVsb2NpZGFkIGRlbCBWaWVudG8gKE1waClgKQpzdW1tYXJ5KG1vZGVsbzEpCnNoYXBpcm8udGVzdChtb2RlbG8xJHJlc2lkdWFscykKYGBgCgpgYGB7cn0KcGxvdChtb2RlbG8xJGZpdHRlZC52YWx1ZXMsbW9kZWxvMSRyZXNpZHVhbHMscGNoPTE5LHhsYWI9IkFqdXN0YWRvIix5bGFiPSJSZXNpZHVhbGVzIikKCnFxbm9ybSh5PW1vZGVsbzEkcmVzaWR1YWxzKQpxcWxpbmUobW9kZWxvMSRyZXNpZHVhbHMpCmBgYAoKRXN0ZSBjb21wb3J0YW1pZW50byBvYnNlcnZhZG8sIGhhY2UgcGVuc2FyIHF1ZSBlbiBlZmVjdG8gZWwgbW9kZWxvIGxpbmVhbCBubyBlcyBlbCBhZGVjdWFkbyB5IHF1aXrDoXMgdW4gbW9kZWxvIGN1YWRyw6F0aWNvIGRlbCB0aXBvICQkeT1cYmV0YV8wK1xiZXRhXzEgeCtcYmV0YV8yIHheMitcdmFyZXBzaWxvbiQkCnJlc3VsdGUgbWVqb3IgcGFyYSBleHBsaWNhciBsYSBjdXJ2YXR1cmEgYXBhcmVudGUuIFNpbiBlbWJhcmdvIHBvZGVtb3Mgb2JzZXJ2YXIgZGVsIGRpYWdyYW1hIGRlIGRpc3BlcnNpw7NuIHF1ZSBhIG1lZGlkYSBxdWUgbGEgdmVsb2NpZGFkIGRlbCB2aWVudG8gYXVtZW50YSwgbGEgc2FsaWRhIGRlIHZvbHRhamUgc2UgYWNlcmNhIHVuIHB1bnRvIGV4dHJlbW8gZGUgMi41ICwgbG8gY3VhbCBlcyBjb25zaXN0ZW50ZSBjb24gZWwgZnVuY2lvbmFtaWVudG8gZGUgdW4gbW9saW5vIGRlIHZpZW50by4gRGFkbyBxdWUgZWwgbW9kZWxvIGN1YWRyw6F0aWNvIGV2ZW50dWFsbWVudGUgc2UgZG9ibGFyw6EsIGVzdG8gaW5kaWNhcsOtYSBxdWUgYSB2ZWxvY2lkYWRlcyBtYXMgYWx0YXMgZGUgZXN0ZSBwdW50byBtw6F4aW1vIG9ic2VydmFkbyBsYSBzYWxpZGEgZGUgdm9sdGFqZSBkaXNtaW51aXLDrWEgbG8gY3VhbCwgY29uIGxvIGN1YWwgbnVldmFtZW50ZSBlbCBtb2RlbG8gY3VhZHLDoXRpY28gdGFtcG9jbyBzZXJpYSBhZGVjdWFkbyBwYXJhIGxvcyBkYXRvcy4KCkNvbW8gbWVuY2lvbmFtb3MgYSBtZWRpZGEgcXVlIGxhIHZlbG9jaWRhZCBhdW1lbnRhLCBsYSBzYWxpZGEgZGUgdm9sdGFqZSBwYXJlY2llcmEgYWxjYW56YXIgdW4gcHVudG8gZXh0cmVtbywgZGUgbWFuZXJhIHF1ZSB0aWVuZGUgY29tbyBhIGVzdGFiaWxpemFyc2UsIGxvIHF1ZSBzdWdpZXJlIHF1ZSB1bmEgdHJhbnNmb3JtYWNpw7NuIGRlIHRpcG8gcmVjaXByb2NhIHNlYSBsbyBtYXMgYWRlY3VhZGEsIHB1ZXMgZW4gZWxsYXMgaW5jb3Jwb3JhbW9zIGFzw61udG90YXMsIHkgZW4gZXN0ZSBjYXNvIGJ1c2NhbW9zIHF1ZSBoYXlhIHVuYSBhc8OtbnRvdGEgc3VwZXJpb3IgcXVlIHNlIGFjZXJxdWUgYSBlc3RlIHZhbG9yIGV4dHJlbW8uIFRyYW5zZm9ybWFuZG8gZWwgbW9kZWxvIGNvbW8KJCR5PVxiZXRhXzArXGJldGFfMSBcbGVmdChcZGZyYWN7MX17eH1ccmlnaHQpK1x2YXJlcHNpbG9uLiQkClVzYW5kbyBlc3RhIHRyYW5zZm9ybWFjacOzbiB2ZWFtb3Mgc3UgcmVsYWNpw7NuIG1lZGlhbnRlIGVsIGdyw6FmaWNvIGRlIGRpc3BlcnNpw7NuCgpgYGB7cn0KcGxvdCgxL3RhYmxhMSRgVmVsb2NpZGFkIGRlbCBWaWVudG8gKE1waClgLHRhYmxhMSRgU2FsaWRhIERDYCx4bGFiPVRlWChyJyhWZWxvY2lkYWQgZGVsIFZpZW50byAkeCQgKScpLHlsYWI9VGVYKHInKFNhbGlkYSBEQyAkeSQpJykscGNoPTIwLGNleD0yKQoKeW51ZXZvczwtKHRhYmxhMSRgU2FsaWRhIERDYCleMgojcGxvdCh0YWJsYTEkYFZlbG9jaWRhZCBkZWwgVmllbnRvIChNcGgpYCx5bnVldm9zKQojbW9kZWxvMjI8LWxtKHludWV2b3N+dGFibGExJGBWZWxvY2lkYWQgZGVsIFZpZW50byAoTXBoKWApCiNwbG90KG1vZGVsbzIyKQoKeG51ZXZvczwtbG9nKHRhYmxhMSRgVmVsb2NpZGFkIGRlbCBWaWVudG8gKE1waClgKQptb2RlbG8yMjI8LWxtKHRhYmxhMSRgU2FsaWRhIERDYH54bnVldm9zKQpwbG90KG1vZGVsbzIyMikKYGBgCkFqdXN0YW5kbyBlbCBtb2RlbG8sIHRlbmVtb3MgY29tbyByZXN1bHRhZG8KYGBge3J9CnRhYmxhMiA8LSBkYXRhLmZyYW1lKHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UsClZlbG9jaWRhZF9WaWVudG8gPSAxL2MoNS4wMCwgNi4wMCwgMy40MCwgMi43MCwKICAgICAgMTAuMDAsIDkuNzAsIDkuNTUsIDMuMDUsIDguMTUsIDYuMjAsIDIuOTAsIDYuMzUsIDQuNjAsIDUuODAsIDcuNDAsIDMuNjAsCiAgICAgIDcuODUsIDguODAsIDcuMDAsIDUuNDUsIDkuMTAsIDEwLjIwLCA0LjEwLCAzLjk1LCAyLjQ1KSwKU2FsaWRhX0RDID0gYygxLjU4MiwgMS44MjIsIDEuMDU3LCAwLjUwMCwgMi4yMzYsIDIuMzg2LCAyLjI5NCwgMC41NTgsIDIuMTY2LCAxLjg2NiwKICAgICAwLjY1MywgMS45MzAsIDEuNTYyLCAxLjczNywgMi4wODgsIDEuMTM3LCAyLjE3OSwgMi4xMTIsIDEuODAwLCAxLjUwMSwgMi4zMDMsCiAgICAgMi4zMTAsIDEuMTk0LCAxLjE0NCwgMC4xMjMpCikKbmFtZXModGFibGEyKTwtYygiVmVsb2NpZGFkIGRlbCBWaWVudG8gKE1waCkiLCJTYWxpZGEgREMiKQp0YWJsYTIKYGBgCgoKYGBge3J9Cm1vZGVsbzI8LWxtKHRhYmxhMiRgU2FsaWRhIERDYH50YWJsYTIkYFZlbG9jaWRhZCBkZWwgVmllbnRvIChNcGgpYCkKc3VtbWFyeShtb2RlbG8yKQpgYGAKYGBge3J9CnBsb3QobW9kZWxvMiRmaXR0ZWQudmFsdWVzLHJzdHVkZW50KG1vZGVsbzIpLHBjaD0xOSx4bGFiPSJBanVzdGFkbyIseWxhYj0iUmVzaWR1YWxlcyIpCmFibGluZShoPTAsbHR5PTIsY29sPSJyZWQiKQpwbG90KG1vZGVsbzIpCmdncXFwbG90KG1vZGVsbzIkcmVzaWR1YWxzKQojbXVsdC5ub3JtKHRhYmxhMSkkbXVsdC50ZXN0CmBgYAojIyMjIyAqKkVqZW1wbG8gRGF0b3MgTWFyaWFKdWFuYSoqCgpWZWFtb3MgYWhvcmEgc2kgcG9kZW1vcyBhcGxpY2FyIGFsZ3VuYSB0cmFuc2Zvcm1hY2nDs24gYWwgY29uanVudG8gZGUgZGF0b3MgZGUgTWFyaWFqdWFuYS4gUmVjb3JkZW1vcyBxdWUgZW4gZXN0ZSBjb25qdW50byBkZSBkYXRvcyB0ZW7DrWFtb3MgZW4gZXNlbmNpYSB0cmVzIHN1YmNvbmp1bnRvcyBhIGNhdXNhIGRlIGxvcyB0cmVzIGNhbnRpZGFkZXMgcXVlIHNlIHRlbsOtYW4gcGFyYSBsYSBkb3Npcy4gRGUgZXN0YSBtYW5lcmEgZXMgY29udmVuaWVudGUgdHJhYmFqYXIgY29uIGVzdG9zIHRyZXMgc3ViY29uanVudG9zLiAKUmVjb3JkZW1vcyBxdWUgbGFzIHRyYW5zZm9ybWFjaW9uZXMgcXVlIHZpbW9zIHByZXZpYW1lbnRlIHBvciBhaG9yYSBlc3TDoW4gbGltaXRhZGFzIGEgbGEgcmVncmVzacOzbiBsaW5lYWwgc2ltcGxlLCBjb24gbG8gY3VhbCBjb25zaWRlcmFyZW1vcyBsYSBhbHR1cmEgY29tbyBmdW5jacOzbiBkZSBwcmVjaXBpdGFjacOzbiBvIGNvbW8gZnVuY2nDs24gZGUgbGEgdGVtcGVyYXR1cmEuCgoKYGBge3J9CiMjIENhcmdhIGRlbCBjb25qdW50byBkZSBkYXRvcwptYXJpYTwtcmVhZC50YWJsZSgiL1VzZXJzL2RhbmltYXRodWQvRG9jdW1lbnRzL0dpdEh1Yi9SX3Byb2plY3RzL01vZGVsb3NFc3RhZGlzdGljb3MxL0RhdGFzL01hcmlhanVhbmEudHh0IikKbWFyaWEKCmBgYAoKYGBge3J9CiMjIEZpbHRyYWRvCm1hcmlhX2Rvc2lzMDwtbWFyaWEgJT4lIGZpbHRlcihEb3Npcy5lbi5rZz09MCkKbWFyaWFfZG9zaXMwCgptYXJpYV9kb3NpczE8LW1hcmlhICU+JSBmaWx0ZXIoRG9zaXMuZW4ua2c9PTEpCm1hcmlhX2Rvc2lzMQoKbWFyaWFfZG9zaXMxNTwtbWFyaWEgJT4lIGZpbHRlcihEb3Npcy5lbi5rZz09MS41KQptYXJpYV9kb3NpczE1CmBgYAoKCmBgYHtyfQpwYXIobWZyb3c9YygxLDMpKQpwbG90KG1hcmlhX2Rvc2lzMFssMTozXSxsb3dlci5wYW5lbD1OVUxMLG1haW49IkRvc2lzIDAiKQpwYXIobWZyb3c9YygxLDMpKQpwbG90KG1hcmlhX2Rvc2lzMVssMTozXSxsb3dlci5wYW5lbD1OVUxMLG1haW49IkRvc2lzIDEiKQpwYXIobWZyb3c9YygxLDMpKQpwbG90KG1hcmlhX2Rvc2lzMTVbLDE6M10sbG93ZXIucGFuZWw9TlVMTCxtYWluPSJEb3NpcyAxLjUiKQojcGxvdChtYXJpYVssMTozXSxsb3dlci5wYW5lbD1OVUxMKQojcGxvdDNkKG1hcmlhWywxOjNdKQpgYGAKClBhcmEgZXN0ZSBlamVtcGxvIGNvbnNpZGVyZW1vcyBlbCBzdWJjb25qdW50byBwYXJhIGRvc2lzIGRlIDEuNSwgeSB2ZWFtb3MgcGFyYSBjdWFsIHJlc3VsdGEgbWFzIGNvbnZlbmllbnRlIHVuYSB0cmFuc2Zvcm1hY2nDs24sIHNpIHBhcmEgYWx0dXJhIGVuIGZ1bmNpw7NuIGRlIHRlbXBlcmF0dXJhIG8gYWx0dXJhIGVuIGZ1bmNpw7NuIGRlIHByZWNpcGl0YWNpw7NuLgoKCioqQWx0dXJhIGVuIGZ1bmNpw7NuIGRlIGxhIHRlbXBlcmF0dXJhKioKYGBge3J9Cm1vZGVsbzM8LWxtKG1hcmlhX2Rvc2lzMTUkQWx0dXJhLmVuLmNtfm1hcmlhX2Rvc2lzMTUkVGVtcGVyYXR1cmEuZW4uQykKcGxvdChtb2RlbG8zLHBjaD0xOSkKc2hhcGlyby50ZXN0KG1vZGVsbzMkcmVzaWR1YWxzKQpwbG90KG1hcmlhX2Rvc2lzMTUkVGVtcGVyYXR1cmEuZW4uQyxtYXJpYV9kb3NpczE1JEFsdHVyYS5lbi5jbSx4bGFiPSJUZW1wZXJhdHVyYSIseWxhYj0iQWx0dXJhIixwY2g9MTkpCmFibGluZShtb2RlbG8zLGNvbD0icmVkIikKYGBgCiAKQ29tbyBwb2RlbW9zIGNvbnNpZGVyYW5kbyBhbHR1cmEgZW4gZnVuY2nDs24gZGUgdGVtcGVyYXR1cmEsIGF1bnF1ZSBkZWwgZ3LDoWZpY28gZGUgcmVzaWR1YWxlcyB5IFFRIHBhcmVjaWVyYSBxdWUgc2UgY3VtcGxlbiB0b2RvcyBsb3Mgc3VwdWVzdG9zIGRlIHJlZ3Jlc2nDs24gbGluZWFsIHkgbm9ybWFsaWRhZCBlbiBsb3MgZXJyb3Jlcywgc2luIGVtYmFyZ28gcG9kZW1vcyB2ZXIgdGFtYmnDqW4sIHF1ZSBsYSByZWN0YSBubyBzZSBhanVzdGEgbG8gc3VmaWNpZW50ZW1lbnRlIGJpZW4uIFBvciBsbyBjdWFsIHBvZHLDrWFtb3MgaW50ZW50YXIgdHJhbnNmb3JtYXIgbG9zIGRhdG9zIGVzcGVyYW5kbyBjb25zZWd1aXIgdW4gbWVqb3IgcmVzdWx0YWRvIGVuIGVsIGFqdXN0ZSBkZWwgbW9kZWxvLgoKTm90ZW1vcyBkZSBsb3MgZGF0b3MgcXVlIGxhIHJlY3RhIHF1ZSBhanVzdGVtb3MgdGllbmUgcGFyw6FtZXRybyAkXGJldGFfMTwwJCB5IGxhIHRlbXBlcmF0dXJhIHF1ZSBjb25zaWRlcmFtb3MgZXMgcG9zaXRpdmEsIGNvbiBsbyBjdWFsIHBvZGVtb3Mgb2JzZXJ2YXIgcXVlIG51ZXN0cm9zIGRhdG9zLCB0aWVuZW4gbWFzIHBhcmVjaWRvIGNvbiBsb3MgZ3LDoWZpY29zIGIpIHkgZCkgZGUgbGEgZmlndXJhIG1vc3RyYWRhIGVuIHVuIGluaWNpw7MsIGFzw60gcG9kcsOtYW1vcyBpbnRlbnRhciBjb25zaWRlcmFyIGNvbW8gdHJhbnNmb3JtYWNpb25lcyAKCiQkXGxvZ3t5fT1cbG9ne1xiZXRhXzAgeF57XGJldGFfMX19PVxsb2d7XGJldGFfMH0rXGJldGFfMVxsb2d7eH0kJApvIAogJCRcbG9ne3l9PVxsb2d7XGJldGFfMCBlXntcYmV0YV8xIHh9fT1cbG9ne1xiZXRhXzB9K1xiZXRhXzEgeC4kJApWZWFtb3MgIGN1YWwgZGUgZXN0YXMgbm9zIGRhIGJ1ZW5vcyByZXN1bHRhZG9zIAoKYGBge3J9CnkxX3RyYW48LWxvZyhtYXJpYV9kb3NpczE1JEFsdHVyYS5lbi5jbSkKeDFfdHJhbjwtbG9nKG1hcmlhX2Rvc2lzMTUkVGVtcGVyYXR1cmEuZW4uQykKcGxvdCh4MV90cmFuLHkxX3RyYW4scGNoPTE5LG1haW49VGVYKHInKCJUcmFuc2Zvcm1hbmRvIGNvbiAkeSc9XGxvZ3soeSl9JCB5ICR4Jz1cbG9neyh4KX0kKScpLHhsYWI9ImxvZyhUZW1wZXJhdHVyYSkiLHlsYWI9ImxvZyhBbHR1cmEpIikKbW9kZWxvM190cmFuMTwtbG0oeTFfdHJhbn54MV90cmFuKQphYmxpbmUobW9kZWxvM190cmFuMSxjb2w9ImJsdWUiKQpwbG90KG1vZGVsbzNfdHJhbjEscGNoPTE5KQpzaGFwaXJvLnRlc3QobW9kZWxvM190cmFuMSRyZXNpZHVhbHMpCmBgYApgYGB7cn0KCnBsb3QobWFyaWFfZG9zaXMxNSRUZW1wZXJhdHVyYS5lbi5DLHkxX3RyYW4scGNoPTE5LG1haW49VGVYKHInKCJUcmFuc2Zvcm1hbmRvIGNvbiAkeSc9XGxvZ3soeSl9JCknKSx5bGFiPSJsb2coQWx0dXJhKSIseGxhYj0iVGVtcGVyYXR1cmEiKQptb2RlbG8zX3RyYW4yPC1sbSh5MV90cmFufm1hcmlhX2Rvc2lzMTUkVGVtcGVyYXR1cmEuZW4uQykKYWJsaW5lKG1vZGVsbzNfdHJhbjIsY29sPSJyZWQiKQpwbG90KG1vZGVsbzNfdHJhbjIscGNoPTE5KQpzaGFwaXJvLnRlc3QobW9kZWxvM190cmFuMiRyZXNpZHVhbHMpCmBgYAogCgo=