モデル推定
ベータ回帰モデル
事例①
betareg
パッケージのGasolineYield
データを用いた分析を行います。
- データの概要はこちらを参照してください。
- データを読み込みます。
data("GasolineYield", package = "betareg")
- 可視化します。ここでは、非説明変数を
yeild
(蒸留分別後に原油からガソリンに転換された割合)、説明変数をtemp
(ガソリンが帰化する温度)としています。
ggplot(GasolineYield) + geom_point(aes(x = temp, y = yield, col = 2)) +
guides(colour = "none")
betareg()
関数を用いて、ベータ回帰モデルを推定します。説明変数には、batch
とtemp
を用います。
gs.beta <- betareg(yield ~ batch + temp, data = GasolineYield)
summary(gs.beta)
Call:
betareg(formula = yield ~ batch + temp, data = GasolineYield)
Standardized weighted residuals 2:
Min 1Q Median 3Q Max
-2.8750 -0.8149 0.1601 0.8384 2.0483
Coefficients (mean model with logit link):
Estimate Std. Error z value Pr(>|z|)
(Intercept) -6.1595710 0.1823247 -33.784 < 2e-16 ***
batch1 1.7277289 0.1012294 17.067 < 2e-16 ***
batch2 1.3225969 0.1179020 11.218 < 2e-16 ***
batch3 1.5723099 0.1161045 13.542 < 2e-16 ***
batch4 1.0597141 0.1023598 10.353 < 2e-16 ***
batch5 1.1337518 0.1035232 10.952 < 2e-16 ***
batch6 1.0401618 0.1060365 9.809 < 2e-16 ***
batch7 0.5436922 0.1091275 4.982 6.29e-07 ***
batch8 0.4959007 0.1089257 4.553 5.30e-06 ***
batch9 0.3857930 0.1185933 3.253 0.00114 **
temp 0.0109669 0.0004126 26.577 < 2e-16 ***
Phi coefficients (precision model with identity link):
Estimate Std. Error z value Pr(>|z|)
(phi) 440.3 110.0 4.002 6.29e-05 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Type of estimator: ML (maximum likelihood)
Log-likelihood: 84.8 on 12 Df
Pseudo R-squared: 0.9617
Number of iterations: 51 (BFGS) + 3 (Fisher scoring)
gs.beta.prd <-
cbind(
Y=GasolineYield$yield,
X=GasolineYield$temp,
response=predict(gs.beta, type = "response"),
link=predict(gs.beta, type = "link"),
precision=predict(gs.beta, type = "precision"),
variance=predict(gs.beta, type = "variance"),
predict(gs.beta, type = "quantile", at = c(0.25, 0.5, 0.75))
)
colnames(gs.beta.prd)<-c("Y","X","response", "link", "precision", "variance",
"q_0.25", "q_0.5", "q_0.75")
gs.beta.prd <- as.data.frame(gs.beta.prd)
ggplot(gs.beta.prd, aes(x = Y, y = response, col = 2)) + geom_point() +
geom_line(aes(x=Y, y=response), col="darkblue", lwd=1) +
geom_ribbon(aes(ymin = q_0.25, ymax = q_0.75), col="darkblue", alpha = .2, lwd=0) +
guides(colour = "none")
ガンマ回帰モデル
- 分析には、
Zelig
パッケージのcoalition
データを用います。
- 参考文献1, 参考文献2を参考にしています。
data(coalition, package = "Zelig")
summary(coalition)
duration ciep12 invest fract polar
Min. : 0.50 Min. :0.0000 Min. :0.0000 Min. :349.0 Min. : 0.00
1st Qu.: 6.00 1st Qu.:1.0000 1st Qu.:0.0000 1st Qu.:677.0 1st Qu.: 3.00
Median :14.00 Median :1.0000 Median :0.0000 Median :719.0 Median :14.50
Mean :18.44 Mean :0.8631 Mean :0.4522 Mean :718.8 Mean :15.29
3rd Qu.:28.00 3rd Qu.:1.0000 3rd Qu.:1.0000 3rd Qu.:788.0 3rd Qu.:25.00
Max. :59.00 Max. :1.0000 Max. :1.0000 Max. :868.0 Max. :43.00
numst2 crisis
Min. :0.0000 Min. : 0.00
1st Qu.:0.0000 1st Qu.: 0.00
Median :1.0000 Median : 10.00
Mean :0.6306 Mean : 22.38
3rd Qu.:1.0000 3rd Qu.: 29.75
Max. :1.0000 Max. :274.00
ggplot(coalition, aes(x=duration)) +
geom_density(color="darkblue", fill="lightblue") +
geom_vline(aes(xintercept=mean(duration)),
color="blue", linetype="dashed")
- 変数
fract
とduration
との関係を可視化します。
ggplot(coalition) + geom_point(aes(x = fract, y = duration, col = 2)) +
guides(colour = "none")
coa.gam <- glm(duration ~ fract + numst2, data=coalition,
family=Gamma)
summary(coa.gam)
Call:
glm(formula = duration ~ fract + numst2, family = Gamma, data = coalition)
Deviance Residuals:
Min 1Q Median 3Q Max
-2.2510 -0.9112 -0.2278 0.4132 1.5360
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -1.296e-02 1.329e-02 -0.975 0.33016
fract 1.149e-04 1.723e-05 6.668 1.19e-10 ***
numst2 -1.739e-02 5.881e-03 -2.957 0.00335 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for Gamma family taken to be 0.6291004)
Null deviance: 300.74 on 313 degrees of freedom
Residual deviance: 272.19 on 311 degrees of freedom
AIC: 2428.1
Number of Fisher Scoring iterations: 6
exp(coef(coa.gam))
(Intercept) fract numst2
0.9871239 1.0001149 0.9827628
zellig()
関数を用いてモデル推定を行うこともできます。
z.out <- zelig(duration ~ fract + numst2, model = "gamma", data = coalition)
How to cite this model in Zelig:
R Core Team. 2007.
gamma: Gamma Regression for Continuous, Positive Dependent Variables
in Christine Choirat, Christopher Gandrud, James Honaker, Kosuke Imai, Gary King, and Olivia Lau,
"Zelig: Everyone's Statistical Software," http://zeligproject.org/
x.low <- setx(z.out, numst2 = 0)
x.high <- setx(z.out, numst2 = 1)
s.out <- sim(z.out, x = x.low, x1 = x.high)
summary(s.out)
sim x :
-----
ev
mean sd 50% 2.5% 97.5%
[1,] 14.42859 1.059792 14.38851 12.61026 16.58989
pv
mean sd 50% 2.5% 97.5%
[1,] 14.64059 12.75808 10.76264 0.7475632 46.15597
sim x1 :
-----
ev
mean sd 50% 2.5% 97.5%
[1,] 19.25073 1.109373 19.1745 17.29701 21.62251
pv
mean sd 50% 2.5% 97.5%
[1,] 19.24491 16.58495 15.00363 1.028835 59.09073
fd
mean sd 50% 2.5% 97.5%
[1,] 4.822135 1.518249 4.851093 1.766683 7.658619
plot(s.out)
指数-ガウス回帰モデル
- まず、指数-ガウス分布データを作成してみましょう。MrUnadonさんのコードを使わせていただいています。
rnorm()
関数で正規分布(ガウス分布)の乱数を、rexp()
関数で指数分布の乱数を生成します。
df_norm<-data.frame(norm = rnorm(1000, mean = 10, sd =1), exp = rexp(1000,rate = 0.5))
- 次に、
gamlss.dist
パッケージのrexGAUS()
関数を使って、指数-ガウス分布の乱数を生成します。
df_exGauss<-data.frame(exGauss = rexGAUS(2000,mu=10,sigma=1,nu=1/0.5)) #nu=1/rate
- 2つのデータフレームを結合します。
- パイプ
%>%
を有効化するには、needs::prioritize(magrittr)
と入力してください。
df_bind<-cbind(df_norm,df_exGauss)%>%
dplyr::mutate(norm_exp = norm + exp)%>%
tidyr::gather()
df_bind2<-transform(df_bind,key = factor(key,levels = c("norm","exp","norm_exp","exGauss")))
ggplot(df_bind2,aes(x=value,colour=key,fill=key))+#ggplot2で描画
geom_histogram(alpha=0.5)+
geom_vline(xintercept = 0,linetype=2)+
theme_bw()+facet_wrap(~key)
- 指数-ガウス回帰モデルの推定例として、
lme4
パッケージのsleepstudy
データを用います。データの概要はここを参考にしてください。
data(sleepstudy)
summary(sleepstudy)
Reaction Days Subject
Min. :194.3 Min. :0.0 308 : 10
1st Qu.:255.4 1st Qu.:2.0 309 : 10
Median :288.7 Median :4.5 310 : 10
Mean :298.5 Mean :4.5 330 : 10
3rd Qu.:336.8 3rd Qu.:7.0 331 : 10
Max. :466.4 Max. :9.0 332 : 10
(Other):120
- 変数
Days
とReaction
との関係を可視化します。
base.plot <- ggplot(sleepstudy) + geom_point(aes(x = Days, y = Reaction, col = 2)) +
guides(colour = "none")
base.plot
hist.plot <- ggplot(sleepstudy, aes(x = Reaction, fill=2))+
geom_histogram(alpha=0.5)+
geom_vline(xintercept = 0,linetype=2, col="darkblue")+
guides(colour = "none")
hist.plot
- ここでは、①
glmss
パッケージのglmss()
関数を用いる方法と、②brms
パッケージを用いてベイズ推定する方法の2つを紹介します。
- ①
glmss
パッケージのglmss()
関数を用いる方法
sleep.model<-gamlss(Reaction~Days,
data=sleepstudy,
family=exGAUS,
mu.fix=FALSE,
sigma.fix = FALSE,
nu.fix = FALSE)
GAMLSS-RS iteration 1: Global Deviance = 1900.86
GAMLSS-RS iteration 2: Global Deviance = 1900.163
GAMLSS-RS iteration 3: Global Deviance = 1900.13
GAMLSS-RS iteration 4: Global Deviance = 1900.105
GAMLSS-RS iteration 5: Global Deviance = 1900.086
GAMLSS-RS iteration 6: Global Deviance = 1900.075
GAMLSS-RS iteration 7: Global Deviance = 1900.067
GAMLSS-RS iteration 8: Global Deviance = 1900.061
GAMLSS-RS iteration 9: Global Deviance = 1900.055
GAMLSS-RS iteration 10: Global Deviance = 1900.051
GAMLSS-RS iteration 11: Global Deviance = 1900.046
GAMLSS-RS iteration 12: Global Deviance = 1900.043
GAMLSS-RS iteration 13: Global Deviance = 1900.04
GAMLSS-RS iteration 14: Global Deviance = 1900.037
GAMLSS-RS iteration 15: Global Deviance = 1900.034
GAMLSS-RS iteration 16: Global Deviance = 1900.032
GAMLSS-RS iteration 17: Global Deviance = 1900.029
GAMLSS-RS iteration 18: Global Deviance = 1900.026
GAMLSS-RS iteration 19: Global Deviance = 1900.024
GAMLSS-RS iteration 20: Global Deviance = 1900.023
Algorithm RS has not yet converged
summary(sleep.model)
******************************************************************
Family: c("exGAUS", "ex-Gaussian")
Call: gamlss(formula = Reaction ~ Days, family = exGAUS,
data = sleepstudy, mu.fix = FALSE, sigma.fix = FALSE, nu.fix = FALSE)
Fitting method: RS()
------------------------------------------------------------------
Mu link function: identity
Mu Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 233.888 10.175 22.987 < 2e-16 ***
Days 10.013 1.365 7.333 7.87e-12 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
------------------------------------------------------------------
Sigma link function: log
Sigma Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 3.7680 0.1136 33.17 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
------------------------------------------------------------------
Nu link function: log
Nu Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 2.970 0.548 5.42 1.94e-07 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
------------------------------------------------------------------
No. of observations in the fit: 180
Degrees of Freedom for the fit: 4
Residual Deg. of Freedom: 176
at cycle: 20
Global Deviance: 1900.022
AIC: 1908.022
SBC: 1920.794
******************************************************************
plot(sleep.model)
******************************************************************
Summary of the Quantile Residuals
mean = 0.001632282
variance = 1.006378
coef. of skewness = -0.09752817
coef. of kurtosis = 3.193978
Filliben correlation coefficient = 0.9929095
******************************************************************
set.seed(1234)
sleep.exGauss.brms <- brm(Reaction ~ Days, data = sleepstudy,
family = exgaussian(),
prior = c(prior('normal(1, 1)', class = 'Intercept'),
prior('normal(1, 1)', class = 'sigma'),
prior('normal(1, 1)', class = 'beta')),
seed = 1, chains = 1)
Compiling the C++ model
Start sampling
SAMPLING FOR MODEL '64e67dadfe14ae649762403a4b205f37' NOW (CHAIN 1).
Chain 1:
Chain 1: Gradient evaluation took 5.7e-05 seconds
Chain 1: 1000 transitions using 10 leapfrog steps per transition would take 0.57 seconds.
Chain 1: Adjust your expectations accordingly!
Chain 1:
Chain 1:
Chain 1: Iteration: 1 / 2000 [ 0%] (Warmup)
Chain 1: Iteration: 200 / 2000 [ 10%] (Warmup)
Chain 1: Iteration: 400 / 2000 [ 20%] (Warmup)
Chain 1: Iteration: 600 / 2000 [ 30%] (Warmup)
Chain 1: Iteration: 800 / 2000 [ 40%] (Warmup)
Chain 1: Iteration: 1000 / 2000 [ 50%] (Warmup)
Chain 1: Iteration: 1001 / 2000 [ 50%] (Sampling)
Chain 1: Iteration: 1200 / 2000 [ 60%] (Sampling)
Chain 1: Iteration: 1400 / 2000 [ 70%] (Sampling)
Chain 1: Iteration: 1600 / 2000 [ 80%] (Sampling)
Chain 1: Iteration: 1800 / 2000 [ 90%] (Sampling)
Chain 1: Iteration: 2000 / 2000 [100%] (Sampling)
Chain 1:
Chain 1: Elapsed Time: 0.656754 seconds (Warm-up)
Chain 1: 0.177539 seconds (Sampling)
Chain 1: 0.834293 seconds (Total)
Chain 1:
There were 525 divergent transitions after warmup. Increasing adapt_delta above 0.8 may help. See
http://mc-stan.org/misc/warnings.html#divergent-transitions-after-warmupExamine the pairs() plot to diagnose sampling problems
summary(sleep.exGauss.brms)
There were 525 divergent transitions after warmup. Increasing adapt_delta above 0.8 may help.
See http://mc-stan.org/misc/warnings.html#divergent-transitions-after-warmup
Family: exgaussian
Links: mu = identity; sigma = identity; beta = identity
Formula: Reaction ~ Days
Data: sleepstudy (Number of observations: 180)
Samples: 1 chains, each with iter = 2000; warmup = 1000; thin = 1;
total post-warmup samples = 1000
Population-Level Effects:
Estimate Est.Error l-95% CI u-95% CI Eff.Sample Rhat
Intercept -18.65 137.48 -246.51 214.72 168 1.00
Days 5.47 30.56 -46.55 56.24 168 1.00
Family Specific Parameters:
Estimate Est.Error l-95% CI u-95% CI Eff.Sample Rhat
sigma 1.49 0.81 0.24 3.33 231 1.00
beta 36.26 0.57 35.06 37.41 380 1.00
Samples were drawn using sampling(NUTS). For each parameter, Eff.Sample
is a crude measure of effective sample size, and Rhat is the potential
scale reduction factor on split chains (at convergence, Rhat = 1).
LS0tCnRpdGxlOiAi57Wx6KiI6Kej5p6QUua8lOe/kjgiCiNhdXRob3I6ICJUb21veXVraSBGdXJ1dGFuaSIKI2RhdGU6ICIyMDE5LzgvMTQiCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdAotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmtuaXRyOjpvcHRzX2NodW5rJHNldChjYWNoZSA9IFRSVUUpCmtuaXRyOjpvcHRzX2NodW5rJHNldChlcnJvciA9IFRSVUUpCmBgYAoKIyMg5ryU57+S44Gu5qaC6KaBCi0gQmV0YeWbnuW4sOODouODh+ODq+OAgeOCrOODs+ODnuWbnuW4sOODouODh+ODq+OAgeaMh+aVsC3jgqzjgqbjgrnlm57luLDjg6Ljg4fjg6sKCiMjIyDms6jmhI/kuovpoIUKLSDmhbbmh4nnvqnlob7lpKflraZTRkPjgafplovorJvjgZfjgabjgYTjgovjgIzntbHoqIjop6PmnpDjgI3jga7mjojmpa3lsaXkv67ogIXlkJHjgZHjga7mvJTnv5LnlKjjg5rjg7zjgrjjgafjgZnjgIIKLSDlv4XjgZrjgZfjgoLlhajjgabjga7jg5Djg7zjgrjjg6fjg7Pjga5S44KET1Pjgafli5XkvZznorroqo3jgpLooYzjgaPjgabjgYTjgb7jgZvjgpPjgILjgZPjga7mvJTnv5LnlKjjg5rjg7zjgrjjgpLkvZzmiJDjgZfjgabjgYTjgovmrrXpmo7jgafjga/jgIFSMy42LjDjgpLkvb/jgaPjgabjgYTjgb7jgZnjgIIKLSBS44Gu5pu05paw44Gq44Gp44Gr44KI44KK44CBUuOCs+ODvOODieOBquOBqeOCkuS6iOWRiueEoeOBl+OBq+WkieabtOOBmeOCi+WgtOWQiOOBjOOBguOCiuOBvuOBmeOAgiAKCiMjIOODh+ODvOOCv+WIhuaekOOBrua6luWCmQojIyMg44OR44OD44Kx44O844K444Gu44Kk44Oz44K544OI44O844OrCi0g5LuK5Zue44Gu5ryU57+S44Gn44Gv44CB5Lul5LiL44Gu44OR44OD44Kx44O844K444KS5L2/44GE44G+44GZ44CCCmBgYHtyIGluc3RhbGwucGFja2FnZXMsIGV2YWw9RkFMU0V9Cmluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQppbnN0YWxsLnBhY2thZ2VzKCJiZXRhcmVnIikKaW5zdGFsbC5wYWNrYWdlcygiWmVsaWciKQppbnN0YWxsLnBhY2thZ2VzKCJsbWU0IikKaW5zdGFsbC5wYWNrYWdlcygiZ2FtbHNzLmRpc3QiKQppbnN0YWxsLnBhY2thZ2VzKCJnYW1sc3MiKQppbnN0YWxsLnBhY2thZ2VzKCJnYW1sc3MudXRpbCIpCmluc3RhbGwucGFja2FnZXMoImJybXMiKQpgYGAKCmBgYHtyIGxpYnJhcnksIGV2YWw9RkFMU0V9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShiZXRhcmVnKQpsaWJyYXJ5KFplbGlnKQpsaWJyYXJ5KGxtZTQpCmxpYnJhcnkoZ2FtbHNzLmRpc3QpCmxpYnJhcnkoZ2FtbHNzKQpsaWJyYXJ5KGdhbWxzcy51dGlsKQpsaWJyYXJ5KGJybXMpCmBgYAoKIyMg44Oi44OH44Or5o6o5a6aCiMjIyDjg5njg7zjgr/lm57luLDjg6Ljg4fjg6sKIyMjIOS6i+S+i+KRoAotIGBiZXRhcmVnYOODkeODg+OCseODvOOCuOOBrmBHYXNvbGluZVlpZWxkYOODh+ODvOOCv+OCkueUqOOBhOOBn+WIhuaekOOCkuihjOOBhOOBvuOBmeOAggotIOODh+ODvOOCv+OBruamguimgeOBr1vjgZPjgaHjgoldKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9iZXRhcmVnL2JldGFyZWcucGRmKeOCkuWPgueFp+OBl+OBpuOBj+OBoOOBleOBhOOAggotIOODh+ODvOOCv+OCkuiqreOBv+i+vOOBv+OBvuOBmeOAggpgYGB7ciBiZXRhcmVnLmRhdGExfQpkYXRhKCJHYXNvbGluZVlpZWxkIiwgcGFja2FnZSA9ICJiZXRhcmVnIikKYGBgCi0g5Y+v6KaW5YyW44GX44G+44GZ44CC44GT44GT44Gn44Gv44CB6Z2e6Kqs5piO5aSJ5pWw44KSYHllaWxkYO+8iOiSuOeVmeWIhuWIpeW+jOOBq+WOn+ayueOBi+OCieOCrOOCveODquODs+OBq+i7ouaPm+OBleOCjOOBn+WJsuWQiO+8ieOAgeiqrOaYjuWkieaVsOOCkmB0ZW1wYO+8iOOCrOOCveODquODs+OBjOW4sOWMluOBmeOCi+a4qeW6pu+8ieOBqOOBl+OBpuOBhOOBvuOBmeOAggpgYGB7ciBiZXRhcmVnLmdncGxvdDF9CmdncGxvdChHYXNvbGluZVlpZWxkKSArIGdlb21fcG9pbnQoYWVzKHggPSB0ZW1wLCB5ID0geWllbGQsIGNvbCA9IDIpKSArIAogIGd1aWRlcyhjb2xvdXIgPSAibm9uZSIpCmBgYAoKLSBgYmV0YXJlZygpYOmWouaVsOOCkueUqOOBhOOBpuOAgeODmeODvOOCv+WbnuW4sOODouODh+ODq+OCkuaOqOWumuOBl+OBvuOBmeOAguiqrOaYjuWkieaVsOOBq+OBr+OAgWBiYXRjaGDjgahgdGVtcGDjgpLnlKjjgYTjgb7jgZnjgIIKYGBge3IgYmV0YXJlZy5tb2RlbDF9CmdzLmJldGEgPC0gYmV0YXJlZyh5aWVsZCB+IGJhdGNoICsgdGVtcCwgZGF0YSA9IEdhc29saW5lWWllbGQpCnN1bW1hcnkoZ3MuYmV0YSkKYGBgCgotIOmdnuiqrOaYjuWkieaVsOOBruS6iOa4rOeyvuW6puOCkuOAgeioiOeul+OBl+OBvuOBmeOAggpgYGB7ciBiZXRhLnByZWR9CmdzLmJldGEucHJkIDwtIAogIGNiaW5kKAogICAgWT1HYXNvbGluZVlpZWxkJHlpZWxkLAogICAgWD1HYXNvbGluZVlpZWxkJHRlbXAsCiAgICByZXNwb25zZT1wcmVkaWN0KGdzLmJldGEsIHR5cGUgPSAicmVzcG9uc2UiKSwKICAgIGxpbms9cHJlZGljdChncy5iZXRhLCB0eXBlID0gImxpbmsiKSwKICAgIHByZWNpc2lvbj1wcmVkaWN0KGdzLmJldGEsIHR5cGUgPSAicHJlY2lzaW9uIiksCiAgICB2YXJpYW5jZT1wcmVkaWN0KGdzLmJldGEsIHR5cGUgPSAidmFyaWFuY2UiKSwKICAgIHByZWRpY3QoZ3MuYmV0YSwgdHlwZSA9ICJxdWFudGlsZSIsIGF0ID0gYygwLjI1LCAwLjUsIDAuNzUpKQogICkKY29sbmFtZXMoZ3MuYmV0YS5wcmQpPC1jKCJZIiwiWCIsInJlc3BvbnNlIiwgImxpbmsiLCAicHJlY2lzaW9uIiwgInZhcmlhbmNlIiwKICAgICAgICAgICAgICAgICAgICAgICJxXzAuMjUiLCAicV8wLjUiLCAicV8wLjc1IikKZ3MuYmV0YS5wcmQgPC0gYXMuZGF0YS5mcmFtZShncy5iZXRhLnByZCkKYGBgCi0g5LqI5ris57K+5bqm44KS5Y+v6KaW5YyW44GZ44KL44CCCmBgYHtyIHIuYmV0YS5wQHJlZDJ9CmdncGxvdChncy5iZXRhLnByZCwgYWVzKHggPSBZLCB5ID0gcmVzcG9uc2UsIGNvbCA9IDIpKSArIGdlb21fcG9pbnQoKSArIAogIGdlb21fbGluZShhZXMoeD1ZLCB5PXJlc3BvbnNlKSwgY29sPSJkYXJrYmx1ZSIsIGx3ZD0xKSArCiAgZ2VvbV9yaWJib24oYWVzKHltaW4gPSBxXzAuMjUsIHltYXggPSBxXzAuNzUpLCBjb2w9ImRhcmtibHVlIiwgYWxwaGEgPSAuMiwgbHdkPTApICsKICBndWlkZXMoY29sb3VyID0gIm5vbmUiKQpgYGAKCiMjIyDjgqzjg7Pjg57lm57luLDjg6Ljg4fjg6sKLSDliIbmnpDjgavjga/jgIFgWmVsaWdg44OR44OD44Kx44O844K444GuYGNvYWxpdGlvbmDjg4fjg7zjgr/jgpLnlKjjgYTjgb7jgZnjgIIKLSBb5Y+C6ICD5paH54yuMV0oaHR0cDovL2Z0cC51bmktYmF5cmV1dGguZGUvbWF0aC9zdGF0bGliL1IvQ1JBTi9kb2MvdmlnbmV0dGVzL1plbGlnL2dhbW1hLnBkZiksIFvlj4LogIPmlofnjK4yXShodHRwczovL3JwdWJzLmNvbS9rYXpfeW9zL2dsbS1HYW1tYSnjgpLlj4LogIPjgavjgZfjgabjgYTjgb7jgZnjgIIKCmBgYHtyIGdhbW1hLmRhdGF9CmRhdGEoY29hbGl0aW9uLCBwYWNrYWdlID0gIlplbGlnIikKc3VtbWFyeShjb2FsaXRpb24pCmBgYAoKLSDlpInmlbBgZGVuc2l0eWDjga7liIbluIPjgpLlj6/oppbljJbjgZfjgb7jgZnjgIIKYGBge3IgZ2FtbWEucGxvdDF9CmdncGxvdChjb2FsaXRpb24sIGFlcyh4PWR1cmF0aW9uKSkgKyAKICBnZW9tX2RlbnNpdHkoY29sb3I9ImRhcmtibHVlIiwgZmlsbD0ibGlnaHRibHVlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQ9bWVhbihkdXJhdGlvbikpLAogICAgICAgICAgICAgICBjb2xvcj0iYmx1ZSIsIGxpbmV0eXBlPSJkYXNoZWQiKQpgYGAKCi0g5aSJ5pWwYGZyYWN0YOOBqGBkdXJhdGlvbmDjgajjga7plqLkv4LjgpLlj6/oppbljJbjgZfjgb7jgZnjgIIKYGBge3IgZ2FtbWEucGxvdDJ9CmdncGxvdChjb2FsaXRpb24pICsgZ2VvbV9wb2ludChhZXMoeCA9IGZyYWN0LCB5ID0gZHVyYXRpb24sIGNvbCA9IDIpKSArIAogIGd1aWRlcyhjb2xvdXIgPSAibm9uZSIpCmBgYAotIOOCrOODs+ODnuWbnuW4sOODouODh+ODq+OCkuaOqOWumuOBl+OBvuOBmeOAggpgYGB7ciBnYW0ubW9kZWwxfQpjb2EuZ2FtIDwtIGdsbShkdXJhdGlvbiB+IGZyYWN0ICsgbnVtc3QyLCBkYXRhPWNvYWxpdGlvbiwKICAgICAgICAgICAgICAgIGZhbWlseT1HYW1tYSkKc3VtbWFyeShjb2EuZ2FtKQpgYGAKLSDlm57luLDkv4LmlbDjga7mjIfmlbDjgpLjgajjgaPjgZ/lgKTjgpLnpLrjgZfjgb7jgZnjgIIKYGBge3IgZ2FtbWEuZXhwfQpleHAoY29lZihjb2EuZ2FtKSkKYGBgCgotIGB6ZWxsaWcoKWDplqLmlbDjgpLnlKjjgYTjgabjg6Ljg4fjg6vmjqjlrprjgpLooYzjgYbjgZPjgajjgoLjgafjgY3jgb7jgZnjgIIKYGBge3IgZ2FtLm1vZGVsMn0Kei5vdXQgPC0gemVsaWcoZHVyYXRpb24gfiBmcmFjdCArIG51bXN0MiwgbW9kZWwgPSAiZ2FtbWEiLCBkYXRhID0gY29hbGl0aW9uKQp4LmxvdyA8LSBzZXR4KHoub3V0LCBudW1zdDIgPSAwKQp4LmhpZ2ggPC0gc2V0eCh6Lm91dCwgbnVtc3QyID0gMSkKcy5vdXQgPC0gc2ltKHoub3V0LCB4ID0geC5sb3csIHgxID0geC5oaWdoKQpzdW1tYXJ5KHMub3V0KQpgYGAKLSDmjqjlrprntZDmnpzjgpLlj6/oppbljJbjgZfjgb7jgZnjgIIKYGBge3IgZ2FtLm1vZGVsMi5wbG90fQpwbG90KHMub3V0KQpgYGAKCiMjIyDmjIfmlbAt44Ks44Km44K55Zue5biw44Oi44OH44OrCi0g44G+44Ga44CB5oyH5pWwLeOCrOOCpuOCueWIhuW4g+ODh+ODvOOCv+OCkuS9nOaIkOOBl+OBpuOBv+OBvuOBl+OCh+OBhuOAgltNclVuYWRvbl0oaHR0cHM6Ly9tcnVuYWRvbi5naXRodWIuaW8vRXhHYXVzc2lhblJlZ3Jlc3Npb24vKeOBleOCk+OBruOCs+ODvOODieOCkuS9v+OCj+OBm+OBpuOBhOOBn+OBoOOBhOOBpuOBhOOBvuOBmeOAggotIGBybm9ybSgpYOmWouaVsOOBp+ato+imj+WIhuW4g++8iOOCrOOCpuOCueWIhuW4g++8ieOBruS5seaVsOOCkuOAgWByZXhwKClg6Zai5pWw44Gn5oyH5pWw5YiG5biD44Gu5Lmx5pWw44KS55Sf5oiQ44GX44G+44GZ44CCCmBgYHtyIGRmLm5vcm19CmRmX25vcm08LWRhdGEuZnJhbWUobm9ybSA9IHJub3JtKDEwMDAsIG1lYW4gPSAxMCwgc2QgPTEpLCBleHAgPSByZXhwKDEwMDAscmF0ZSA9IDAuNSkpCmBgYAoKLSDmrKHjgavjgIFgZ2FtbHNzLmRpc3Rg44OR44OD44Kx44O844K444GuYHJleEdBVVMoKWDplqLmlbDjgpLkvb/jgaPjgabjgIHmjIfmlbAt44Ks44Km44K55YiG5biD44Gu5Lmx5pWw44KS55Sf5oiQ44GX44G+44GZ44CCCmBgYHtyIHJ4R0FVU30KZGZfZXhHYXVzczwtZGF0YS5mcmFtZShleEdhdXNzID0gcmV4R0FVUygyMDAwLG11PTEwLHNpZ21hPTEsbnU9MS8wLjUpKSAjbnU9MS9yYXRlCmBgYAoKLSDvvJLjgaTjga7jg4fjg7zjgr/jg5Xjg6zjg7zjg6DjgpLntZDlkIjjgZfjgb7jgZnjgIIKLSDjg5HjgqTjg5dgJT4lYOOCkuacieWKueWMluOBmeOCi+OBq+OBr+OAgWBuZWVkczo6cHJpb3JpdGl6ZShtYWdyaXR0cikgYOOBqOWFpeWKm+OBl+OBpuOBj+OBoOOBleOBhOOAggpgYGB7ciBkZi5iaW5kfQpkZl9iaW5kPC1jYmluZChkZl9ub3JtLGRmX2V4R2F1c3MpJT4lCiAgZHBseXI6Om11dGF0ZShub3JtX2V4cCA9IG5vcm0gKyBleHApJT4lCiAgdGlkeXI6OmdhdGhlcigpCmBgYAoKLSDkvZzmiJDjgZfjgZ/kubHmlbDjg4fjg7zjgr/jgpLlj6/oppbljJbjgZfjgb7jgZnjgIIKYGBge3IgZGYuYmluZC5wbG90fQpkZl9iaW5kMjwtdHJhbnNmb3JtKGRmX2JpbmQsa2V5ID0gZmFjdG9yKGtleSxsZXZlbHMgPSBjKCJub3JtIiwiZXhwIiwibm9ybV9leHAiLCJleEdhdXNzIikpKQpnZ3Bsb3QoZGZfYmluZDIsYWVzKHg9dmFsdWUsY29sb3VyPWtleSxmaWxsPWtleSkpKyNnZ3Bsb3Qy44Gn5o+P55S7CiAgZ2VvbV9oaXN0b2dyYW0oYWxwaGE9MC41KSsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLGxpbmV0eXBlPTIpKwogIHRoZW1lX2J3KCkrZmFjZXRfd3JhcCh+a2V5KQpgYGAKCi0g5oyH5pWwLeOCrOOCpuOCueWbnuW4sOODouODh+ODq+OBruaOqOWumuS+i+OBqOOBl+OBpuOAgWBsbWU0YOODkeODg+OCseODvOOCuOOBrmBzbGVlcHN0dWR5YOODh+ODvOOCv+OCkueUqOOBhOOBvuOBmeOAguODh+ODvOOCv+OBruamguimgeOBr1vjgZPjgZNdKGh0dHBzOi8vcmRyci5pby9jcmFuL2xtZTQvbWFuL3NsZWVwc3R1ZHkuaHRtbCnjgpLlj4LogIPjgavjgZfjgabjgY/jgaDjgZXjgYTjgIIKCmBgYHtyIHNsZWVwc3R1ZHl9CmRhdGEoc2xlZXBzdHVkeSkKc3VtbWFyeShzbGVlcHN0dWR5KQpgYGAKCi0g5aSJ5pWwYERheXNg44GoYFJlYWN0aW9uYOOBqOOBrumWouS/guOCkuWPr+imluWMluOBl+OBvuOBmeOAggpgYGB7ciBzbGVlcHN0dWR5LnBsb3QxfQpiYXNlLnBsb3QgPC0gZ2dwbG90KHNsZWVwc3R1ZHkpICsgZ2VvbV9wb2ludChhZXMoeCA9IERheXMsIHkgPSBSZWFjdGlvbiwgY29sID0gMikpICsgCiAgZ3VpZGVzKGNvbG91ciA9ICJub25lIikKYmFzZS5wbG90CmBgYAoKLSDlpInmlbBgUmVhY3Rpb25g44Gu44OS44K544OI44Kw44Op44Og44KS5L2c5oiQ44GX44G+44GZ44CCCmBgYHtyIHNsZWVwc3R1ZHkucGxvdDJ9Cmhpc3QucGxvdCA8LSBnZ3Bsb3Qoc2xlZXBzdHVkeSwgYWVzKHggPSBSZWFjdGlvbiwgZmlsbD0yKSkrCiAgZ2VvbV9oaXN0b2dyYW0oYWxwaGE9MC41KSsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLGxpbmV0eXBlPTIsIGNvbD0iZGFya2JsdWUiKSsgCiAgZ3VpZGVzKGNvbG91ciA9ICJub25lIikKaGlzdC5wbG90CmBgYAoKLSDjgZPjgZPjgafjga/jgIHikaBgZ2xtc3Ng44OR44OD44Kx44O844K444GuYGdsbXNzKClg6Zai5pWw44KS55So44GE44KL5pa55rOV44Go44CB4pGhYGJybXNg44OR44OD44Kx44O844K444KS55So44GE44Gm44OZ44Kk44K65o6o5a6a44GZ44KL5pa55rOV44Gu77yS44Gk44KS57S55LuL44GX44G+44GZ44CCCi0g4pGgYGdsbXNzYOODkeODg+OCseODvOOCuOOBrmBnbG1zcygpYOmWouaVsOOCkueUqOOBhOOCi+aWueazlQpgYGB7ciBzbGVlcHN0dWR5Lm1vZGVsMX0Kc2xlZXAubW9kZWw8LWdhbWxzcyhSZWFjdGlvbn5EYXlzLAogICAgICAgICAgICBkYXRhPXNsZWVwc3R1ZHksCiAgICAgICAgICAgIGZhbWlseT1leEdBVVMsIAogICAgICAgICAgICBtdS5maXg9RkFMU0UsCiAgICAgICAgICAgIHNpZ21hLmZpeCA9IEZBTFNFLAogICAgICAgICAgICBudS5maXggPSBGQUxTRSkKc3VtbWFyeShzbGVlcC5tb2RlbCkKYGBgCgotIOe1kOaenOOCkuWPr+imluWMluOBl+OBvuOBmeOAggpgYGB7ciBzbGVlcHN0eWR5Lm1vZGVsMS5wbG90fQpwbG90KHNsZWVwLm1vZGVsKQpgYGAKCi0g4pGhYGJybXNg44OR44OD44Kx44O844K444KS55So44GE44Gm44OZ44Kk44K65o6o5a6a44GZ44KL5pa55rOVCmBgYHtyIHNsZWVwc3R1ZHkubW9kZWwyfQpzZXQuc2VlZCgxMjM0KQpzbGVlcC5leEdhdXNzLmJybXMgPC0gYnJtKFJlYWN0aW9uIH4gRGF5cywgZGF0YSA9IHNsZWVwc3R1ZHksCiAgICAgICAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBleGdhdXNzaWFuKCksCiAgICAgICAgICAgICAgICAgICAgICAgICBwcmlvciA9IGMocHJpb3IoJ25vcm1hbCgxLCAxKScsIGNsYXNzID0gJ0ludGVyY2VwdCcpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yKCdub3JtYWwoMSwgMSknLCBjbGFzcyA9ICdzaWdtYScpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yKCdub3JtYWwoMSwgMSknLCBjbGFzcyA9ICdiZXRhJykpLAogICAgICAgICAgICAgICAgICAgICAgICAgc2VlZCA9IDEsIGNoYWlucyA9IDEpCnN1bW1hcnkoc2xlZXAuZXhHYXVzcy5icm1zKQpgYGAK