趣旨

個性や行動シンドローム、個性と適応度の関連を調べるうえで、統計解析の部分で勉強したことをまとめていきます。個性や行動シンドロームの概念的な部分は日本生態学会誌に総説 を書いていますのでそちらを参照ください。

自分で分析を始めたら、その時に詰まったところなどまとめていきます。

個体内で反復測定をしたデータ分析に共通の手法ですので、個性だけでなく、成長過程での形質相関の変化など色々応用できると思います。

Rコードは右上 “Code” ボタン → “Download Rmd” でダウンロードできます。


General settings

rm(list=ls())  # reset workspace
options(scipen=100)  # do not show numbers using exponential

# install & load packages
pacman::p_load(
  tidyverse
  # , openxlsx # open excel
  , magrittr   # extended pipe
  # , foreach    # Parallel processing
  , knitr  
  , kableExtra # nice tables
  , pander     # nice tables
  # , svglite    # Export SVG plots
  # , patchwork   # combine multiple plots
)

# Rmarkdown settings
knitr::opts_chunk$set(
  prompt  = FALSE,  # Do not add > or + in inline-code
  message = FALSE, 
  comment = "", 
  warning = FALSE,  # Mute warnings
  tidy    = TRUE
  ) 
options(knitr.kable.NA = '') # Hide NAs in kable table

MCMCglmm : Houslay & Wilson 2017 Behav Ecol

T.M. Houslay & A.J. Wilson, Behavioral Ecology 2017: Supplement のまとめ。

問題点であるBLUPとは

Best Linear Unbiased Predictors - 混合モデルで推定された、ランダム効果の各個体での推定値 - 当然大きな誤差が伴う

【問題となっている手法】
個体IDにランダム効果を当てた混合モデルにおいて、各個体のランダム効果値(BLUP, 各個体の行動性向を示す)を抽出し、それを用いてさらに分析を進める(行動シンドロームなど)

【問題点】
点推定であるBLUPには誤差が反映されないので、BLUPを使った分析では慌て者の過誤が起こりやすくなる(編集元のSupplementではBLUPによる分析もしているがここでは省略)

【解決策】
個性分析(行動Repeatability)と追加分析(行動シンドロームや個性ー適応度の関連)を一つの混合モデルで片付けてしまう


Install & load packages

pacman::p_load(
  MCMCglmm
  , lme4
  , broom.mixed # create tidy output of glmm result
  , nadiv
  , coda # Judge MCMC convergence
  )

# Supplementで用意されている仮想データ
df_syndrome <- read_csv("learn_Personality_stats_dat_syndrome.csv")

Data assumption

ここでは、複数の繰り返し計測した行動指標と、一回計測の適応度形質(mating success)データを想定。

今回の仮想データは全てオスのもので、以下の列を持つ

  • Individual ID
  • The repeat number for each behavioural test, assay_rep
  • boldness, measured 4 times per individual
  • exploration, measured 4 times per individual
  • fitness, a single value for each individual
  • Individual body_size, as measured on the day of testing.

単回帰モデル

  • 各行動形質での、個体差による表現型分散の割合を計算

  • lme4にて

  • 計測の反復IDは固定効果に

  • 個体IDがrandom effects

  • 計測可能な個体の状態(ここでは体サイズ)はScaling or Centringして固定効果に

  • 行動シンドロームを調べる全形質でこれを行う

lmer_b <- lmer(
  boldness ~ scale(assay_rep, scale=FALSE) + scale(body_size) + 
    # Don't forget scaling variables!
    (1|ID),
  data = df_syndrome
  )

plot(lmer_b)

qqnorm(residuals(lmer_b))

hist(residuals(lmer_b))

summary(lmer_b)
Linear mixed model fit by REML ['lmerMod']
Formula: boldness ~ scale(assay_rep, scale = FALSE) + scale(body_size) +  
    (1 | ID)
   Data: df_syndrome

REML criterion at convergence: 1061.4

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-2.3666 -0.6478 -0.1155  0.6445  2.6892 

Random effects:
 Groups   Name        Variance Std.Dev.
 ID       (Intercept) 0.6951   0.8337  
 Residual             1.1681   1.0808  
Number of obs: 320, groups:  ID, 80

Fixed effects:
                                Estimate Std. Error t value
(Intercept)                     20.09134    0.11108 180.871
scale(assay_rep, scale = FALSE) -0.04813    0.05404  -0.891
scale(body_size)                 0.14113    0.10893   1.296

Correlation of Fixed Effects:
            (Intr) s(_s=F
s(_,s=FALSE  0.000       
scl(bdy_sz)  0.000 -0.002
  • ここではrandom effectsのvariance componentに興味がある。

  • 動物の個性の証拠となるのは、repeatability (= intraclass correlation coefficient)

  • Repeatability:

    • \(\frac{個体差による分散}{固定効果を考慮したうえでの全分散} = \frac{V_{ID}}{V_{ID} + V_{residual}}\)
broom.mixed::tidy(lmer_b, effects = "ran_pars", scales = "vcov") %>%
  select(group, estimate) %>%
  spread(group, estimate) %>%
  mutate(Repeatability = ID/(ID + Residual)) %>% 
  kable("html", digits = 3) %>% 
  kable_styling("striped", position = "left")  
ID Residual Repeatability
0.695 1.168 0.373

この仮想データでは、ばらつきの37%が固定効果ではなく個体差によるもの。


行動シンドローム:Bivariate models

  • MCMCglmmでの、行動2形質を応答変数に置いたモデルを組む。

  • 各行動形質とそれらの共分散に対する、個体間分散を推定

事前分布の設定

解説は以下参照

固定効果にはNormal distribution、(co)variancesにはinverse Wishartを事前分布として使っている。


指定するもの

  • B: 固定効果の事前分布。Defaultは信仰の弱い正規分布

  • R: 残差

  • G: ランダム効果

  • ランダム効果の数だけ指定。例:

    G = list(
      G1 = list(V = 1, nu = 1, alpha.mu = 0, alpha.V = 1000),
      G2 = list(V = 1, nu = 1, alpha.mu = 0, alpha.V = 1000),
      )
    )
  • alpha.mu: Prior mean

  • alpha.V: 分散行列


inverse Wishart事前分布の変数

  • V: 事前分布のピークを決める。よく使われるのは1

  • nu: 信仰の強さ=分布の偏り を決める。よく使われるのは0.002

prior_E_B_1px = list(
  R = list(V = diag(2), nu = 0.002),
  G = list(
    G1 = list(
      V = diag(2), 
      nu = 2, 
      alpha.mu = rep(0,2), 
      alpha.V = diag(25^2,2,2))
    )
  )

MCMCglmmモデル

全体のコード

MCMCglmm(
  # Response variables. Combine after scaling
  cbind(scale(exploration), scale(boldness)) ~ 
    trait-1 +
    trait:scale(assay_rep, scale = FALSE) +
    trait:scale(body_size),
  random =~ us(trait):ID,
  rcov =~ us(trait):units,
  family = c("gaussian","gaussian"),
  prior = prior_E_B_1px,
  nitt = 150000,
  burnin = 10000,
  thin = 30,
  verbose = TRUE,
  data = as.data.frame(df_syndrome)
  )

項目ごとの解説

  • Response variable: cbind after scaling
  cbind(scale(exploration), scale(boldness)) ~ 
  • Predictor variable:

    • 各形質に対し切片を用意
    trait-1 +
  • trait keywordにより多変量モデルであることを明記
  • 固定効果による形質への影響を、それぞれの形質で推定
    trait:scale(assay_rep, scale = FALSE) +
    trait:scale(body_size),
  • Random effects structureを設定

    • ‘unstructured’ (us) 共分散行列を個体IDに適用
      以下を計算するため

      • 個体差による、それぞれの行動形質の分散
      • これらの分散の共分散
  random =~ us(trait):ID,
  • 残差分散の構造を設定

    • ‘within-individual variation’
    • 各個体で反復計測しているので、ここでもunstructured covariance matrixを設定
      • 各形質での残差分散と共分散を計算
    rcov =~ us(trait):units,
  • MCMCプロセスの設定
    収束が悪い時はこれらの値を大きく上げる
    • 反復試行数 (Iterations) nitt
      収束が悪ければ青天井
    • 不安定な初期のIterationを切り捨てる数burnin
      収束が悪ければ50000など
    • 使うIteration間隔 thin: Samplingでの自己相関を減らす
      収束が悪ければ200など
    nitt=420000,
    burnin=20000,
    thin=100,
  • データセット
    • MCMCglmmではtbl_dfを受け入れないのでas.data.frame
    data = as.data.frame(df_syndrome)

MCMCの収束

Traceは一定の傾向を持っていてはいけないー未収束を示す。ある値の上下で終始ギザギザしていると収束が示唆。

ランダム効果のMCMC連鎖

mcmc_E_B_us <- readRDS("learn_Personality_stats_mcmc_syndrome.obj")
plot(mcmc_E_B_us$VCV)

固定効果の収束過程

plot(mcmc_E_B_us$Sol)


geweke.diag

  • Markov連鎖の初期と後期での平均値が同じか調べる
    • 初期設定では、初期10%と後期50%
  • もし連鎖がstationary distributionに達していれば、
    • 二つの平均は同じ
    • Geweke統計量はasymptotically standard normal distribution
  • test statistic: Z-score
    • \(\frac{Sample\ meansの差}{推定standard\ error}\)
    • SEは、spectral density at zeroから推定
      • 自己相関が考慮に入っている
    • calculated under the assumption that the two parts of the chain are asymptotically independent, which requires that the sum of frac1 and frac2 be strictly less than 1
geweke.diag(mcmc_E_B_us$Sol, frac1=0.1, frac2=0.5)

Fraction in 1st window = 0.1
Fraction in 2nd window = 0.5 

                                traitexploration 
                                         1.60470 
                                   traitboldness 
                                         1.68896 
traitexploration:scale(assay_rep, scale = FALSE) 
                                        -0.95071 
   traitboldness:scale(assay_rep, scale = FALSE) 
                                        -0.83522 
               traitexploration:scale(body_size) 
                                         0.00896 
                  traitboldness:scale(body_size) 
                                        -0.26172 

Z値が0からほど遠いので、このMarchov連鎖は収束していないとみるべき


モデルが2つ以上あるときにはgelman.diagによる判定もできる

gelman.diag(mcmc.list(m1$Sol, m2$Sol))

Repeatability

反復性を計算するために、新たに ‘個体差で説明された行動形質ばらつきの割合’ の事後分布を作る

  • SummaryにあるVariance componentsの名前に基づいて計算

  • ここではExplorationが対象

mcmc_prop_E <- mcmc_E_B_us$VCV[,"traitexploration:traitexploration.ID"]/
  (mcmc_E_B_us$VCV[,"traitexploration:traitexploration.ID"] +
     mcmc_E_B_us$VCV[,"traitexploration:traitexploration.units"])

plot(mcmc_prop_E)

mean(mcmc_prop_E)
[1] 0.2887684
# 95% CIs
HPDinterval(mcmc_prop_E)
         lower     upper
var1 0.1691948 0.4039535
attr(,"Probability")
[1] 0.95

Bayesian 95%信頼区間が0を跨がないことが古典的(頻度主義的)な統計的有意を示すだと言われるが、ここで扱っているvariance componentsは、MCMCglmmでは必ず正の値をとる

  • 信頼区間が0を跨がない≠有意
  • 下限が0に近ければ、Repeatabilityが弱いと考えるべき

なお、Variance componentsの名前は以下で調べられる

mcmc_E_B_us$VCV %>% 
  as.tibble() %>% 
  colnames()
[1] "traitexploration:traitexploration.ID"   
[2] "traitboldness:traitexploration.ID"      
[3] "traitexploration:traitboldness.ID"      
[4] "traitboldness:traitboldness.ID"         
[5] "traitexploration:traitexploration.units"
[6] "traitboldness:traitexploration.units"   
[7] "traitexploration:traitboldness.units"   
[8] "traitboldness:traitboldness.units"      
  • 個体差による分散は
    trait{*trait name*}:trait{trait name}.ID
  • 残差分散は
    trait{trait name}:trait{trait name}.units

Covariance

Repeatabilityの計算プロセスを共分散に応用できる。

個体間での形質間相関の事後分布:

  • \(\frac{形質間の共分散}{各形質の分散の平方根を掛け合わせたもの}\)

    • 共分散を-1~1にスケーリング
mcmc_cor_EB <- mcmc_E_B_us$VCV[,"traitboldness:traitexploration.ID"]/
  (sqrt(mcmc_E_B_us$VCV[,"traitboldness:traitboldness.ID"])*
     sqrt(mcmc_E_B_us$VCV[,"traitexploration:traitexploration.ID"]))

plot(mcmc_cor_EB)

mean(mcmc_cor_EB)
[1] 0.238657
HPDinterval(mcmc_cor_EB)
           lower     upper
var1 -0.06996265 0.5195749
attr(,"Probability")
[1] 0.95

相関は正負どちらもとりうるので、95%信頼区間が0を跨ぐかは頻度主義的な統計的有意を示す。ここでは信頼区間が0を跨いでいるので、有意な行動シンドロームはないと結論付ける。


さらに形質を加える

仮想データセットでの、行動2形質(反復測定)と適応度(1回計測)の関係を調べる。

# 相対適応度を算出し、rel_fitnessに格納
df_syndrome %<>%
  mutate(rel_fitness = fitness/mean(fitness, na.rm=TRUE))

事前分布を設定

注意

  • 1回計測の形質(ここでは適応度)では、残差分散(個体内分散)は0
  • 1回計測の計測との間のすべての個体内形質相関も0
    • fixでVariance componentを特定の値に固定
      • 分散は正の値でないといけないので、個体内分散を小さな正の値で代入(ここでは0.0001)
      • 個体内分散=残差分散R
prior_E_B_fit_1px = list(
  R = list(
    # 反復測定形質が2つの後に1回計測形質の分散を指定するので、3つ目の要素に0.0001を代入
    V = diag(c(1,1,0.0001),3,3), 
    nu = 1.002, 
    # 3つ目のVariance component = 1回計測形質を固定
    fix = 3
    ),
  G = list(
    G1 = list(
      V = diag(3), nu = 3, alpha.mu = rep(0,3), alpha.V = diag(25^2,3,3)
      )
    )
  )

MCMCglmmモデル

全体のコード

mcmc_E_B_fit <- MCMCglmm(
  cbind(scale(exploration), scale(boldness), rel_fitness) ~ 
    trait-1 + 
    at.level(trait,1):scale(assay_rep, scale = FALSE) +
    at.level(trait,2):scale(assay_rep, scale = FALSE) +
    trait:scale(body_size),
  random =~ us(trait):ID,
  rcov =~ us(trait):units,
  family = c("gaussian","gaussian","gaussian"),
  prior = prior_E_B_fit_1px,
  nitt = 100000,
  burnin = 10000,
  thin = 100,
  verbose = TRUE,
  pr = TRUE,
  data = as.data.frame(df_syndrome)
  )
# saveRDS(mcmc_E_B_fit, "learn_Personality_stats_mcmc_fit.obj")

個別解説

    at.level(trait,1):scale(assay_rep, scale = FALSE) +
    at.level(trait,2):scale(assay_rep, scale = FALSE) +
  • at.level
    • specify that fixed effects are estimated only for certain traits
      • ここでは、反復計測assay_repの影響を反復計測された形質に対してだけ調べている
      • 一方、繰り返し測った体サイズの影響は全ての形質に対して調べている
  pr = TRUE,
  • 各個体でのランダム効果(ID)の事後分布を保存
    • REMLでのBLUPに相当
    • 後で可視化
    • めっちゃファイルサイズデカくなる (もともと<1Mbのモデルでも、>8Mbになる)

結果

mcmc_E_B_fit <- readRDS("learn_Personality_stats_mcmc_fit.obj")

summary(mcmc_E_B_fit)

 Iterations = 10001:99901
 Thinning interval  = 100
 Sample size  = 900 

 DIC: 795.0887 

 G-structure:  ~us(trait):ID

                                     post.mean  l-95% CI u-95% CI eff.samp
traitexploration:traitexploration.ID   0.29540  0.148747  0.45910    900.0
traitboldness:traitexploration.ID      0.08595 -0.027963  0.20552    900.0
traitrel_fitness:traitexploration.ID   0.02778 -0.008056  0.06991    900.0
traitexploration:traitboldness.ID      0.08595 -0.027963  0.20552    900.0
traitboldness:traitboldness.ID         0.38911  0.231034  0.56482    900.0
traitrel_fitness:traitboldness.ID      0.09359  0.051660  0.13954   1009.0
traitexploration:traitrel_fitness.ID   0.02778 -0.008056  0.06991    900.0
traitboldness:traitrel_fitness.ID      0.09359  0.051660  0.13954   1009.0
traitrel_fitness:traitrel_fitness.ID   0.06048  0.042892  0.08079    289.6

 R-structure:  ~us(trait):units

                                        post.mean  l-95% CI u-95% CI eff.samp
traitexploration:traitexploration.units 0.7323518  0.604013 0.869493   900.00
traitboldness:traitexploration.units    0.3298602  0.226774 0.423178   900.00
traitrel_fitness:traitexploration.units 0.0005896 -0.006883 0.007051    81.69
traitexploration:traitboldness.units    0.3298602  0.226774 0.423178   900.00
traitboldness:traitboldness.units       0.6397129  0.529047 0.757717   900.00
traitrel_fitness:traitboldness.units    0.0014744 -0.005383 0.006489    66.25
traitexploration:traitrel_fitness.units 0.0005896 -0.006883 0.007051    81.69
traitboldness:traitrel_fitness.units    0.0014744 -0.005383 0.006489    66.25
traitrel_fitness:traitrel_fitness.units 0.0001000  0.000100 0.000100     0.00

 Location effects: cbind(scale(exploration), scale(boldness), rel_fitness) ~ trait - 1 + at.level(trait, 1):scale(assay_rep, scale = FALSE) + at.level(trait, 2):scale(assay_rep, scale = FALSE) + trait:scale(body_size) 

                                                    post.mean   l-95% CI
traitexploration                                    0.0001755 -0.1626782
traitboldness                                      -0.0051980 -0.1871777
traitrel_fitness                                    0.9976330  0.9396981
at.level(trait, 1):scale(assay_rep, scale = FALSE) -0.0203557 -0.0949575
scale(assay_rep, scale = FALSE):at.level(trait, 2) -0.0326581 -0.1050051
traitexploration:scale(body_size)                   0.0686491 -0.0822292
traitboldness:scale(body_size)                      0.0959950 -0.0546117
traitrel_fitness:scale(body_size)                   0.0092247 -0.0497545
                                                     u-95% CI eff.samp  pMCMC
traitexploration                                    0.1602554   900.00  0.973
traitboldness                                       0.1421898   900.00  0.936
traitrel_fitness                                    1.0548906   900.00 <0.001
at.level(trait, 1):scale(assay_rep, scale = FALSE)  0.0651687   767.60  0.642
scale(assay_rep, scale = FALSE):at.level(trait, 2)  0.0493624   900.00  0.451
traitexploration:scale(body_size)                   0.2049156   900.00  0.356
traitboldness:scale(body_size)                      0.2448215   414.66  0.236
traitrel_fitness:scale(body_size)                   0.0579210    98.24  0.760
                                                     
traitexploration                                     
traitboldness                                        
traitrel_fitness                                   **
at.level(trait, 1):scale(assay_rep, scale = FALSE)   
scale(assay_rep, scale = FALSE):at.level(trait, 2)   
traitexploration:scale(body_size)                    
traitboldness:scale(body_size)                       
traitrel_fitness:scale(body_size)                    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
  • 個体内分散(~~.units)において、適応度(1回計測)が関わっているもの(rel_fitness:rel_fitness.units)は指定通り0.0001に固定され、effective sample sizeは0。

  • 適応度(1回計測)が関わっている個体内の共分散はとても小さく、effective sample sizeも小さくなっているはず

行動シンドロームが以前のモデルと近い値になっているか確認

mcmc_E_B_fit_cor_EB <- mcmc_E_B_fit$VCV[,"traitboldness:traitexploration.ID"]/
  (sqrt(mcmc_E_B_fit$VCV[,"traitboldness:traitboldness.ID"])*
     sqrt(mcmc_E_B_fit$VCV[,"traitexploration:traitexploration.ID"]))

mean(mcmc_E_B_fit_cor_EB)
[1] 0.2455875
HPDinterval(mcmc_E_B_fit_cor_EB)
           lower     upper
var1 -0.06393585 0.5372623
attr(,"Probability")
[1] 0.95

適応度と行動形質の相関を抽出

mcmc_E_B_fit_cor_Efit <- mcmc_E_B_fit$VCV[,"traitrel_fitness:traitexploration.ID"]/
  (sqrt(mcmc_E_B_fit$VCV[,"traitrel_fitness:traitrel_fitness.ID"])*
     sqrt(mcmc_E_B_fit$VCV[,"traitexploration:traitexploration.ID"]))

mcmc_E_B_fit_cor_Bfit <- mcmc_E_B_fit$VCV[,"traitrel_fitness:traitboldness.ID"]/
  (sqrt(mcmc_E_B_fit$VCV[,"traitrel_fitness:traitrel_fitness.ID"])*
     sqrt(mcmc_E_B_fit$VCV[,"traitboldness:traitboldness.ID"]))

形質相関を図示

df_mcmc_cors <- data_frame(
  Traits = c(
    "Exploration, Boldness", "Exploration, Fitness", "Boldness, Fitness"
    ),
  Estimate = c(
    mean(mcmc_E_B_fit_cor_EB),
    mean(mcmc_E_B_fit_cor_Efit),
    mean(mcmc_E_B_fit_cor_Bfit)
    ),
  Lower = c(
    HPDinterval(mcmc_E_B_fit_cor_EB)[,"lower"],
    HPDinterval(mcmc_E_B_fit_cor_Efit)[,"lower"],
    HPDinterval(mcmc_E_B_fit_cor_Bfit)[,"lower"]
    ),
  Upper = c(
    HPDinterval(mcmc_E_B_fit_cor_EB)[,"upper"],
    HPDinterval(mcmc_E_B_fit_cor_Efit)[,"upper"],
    HPDinterval(mcmc_E_B_fit_cor_Bfit)[,"upper"]
    )
  )

ggplot(df_mcmc_cors, aes(x = Traits, y = Estimate)) +
  geom_pointrange(aes(ymin = Lower, ymax = Upper)) +
  geom_hline(yintercept = 0, linetype = "dotted") +
  scale_x_discrete(
    limits = c("Boldness, Fitness", "Exploration, Fitness", 
               "Exploration, Boldness")
    ) +
  labs(x = "Trait combinations",
       y = "Correlation (Estimate ±95% CIs)") +
  ylim(-1,1) +
  coord_flip()


BLUPで散布図

ランダム効果のposterior modes (BLUPs from the MCMCglmm model) をFull-modelから抽出し、個性形質と適応度の関係を図示。図示のためにBLUPを使うのはOK

個性と適応度の個体毎の点推定を取り出す

ここではBoldnessー適応度の関連を調べる

df_bf_coefs <- data_frame(
  # Same as writing as: names(colMeans(mcmc_E_B_fit$Sol))
  Trait = attr(colMeans(mcmc_E_B_fit$Sol), "names"),
  # $Solには1属性当たり4つの値が格納されている。なんだこれは?
  # ここではcoMeansで4つの値の平均を取って今後の分析に使う
  Value = colMeans(mcmc_E_B_fit$Sol)
  ) %>%
  # この時点では全ての項目の推定値がまぜこぜに1列に並んでいる
  # BLUPは例えば以下のように格納されている: traitexploration.ID.S_1
  # これを"."で分割
  separate(Trait, c("Trait","Type","ID"), sep = "\\.", fill = "right") %>%
  filter(
    # ID列に値があるのは個体毎の推定値だけ。これを取り出す
    Type == "ID",
    # ここではboldnessと、相対適応度を取り出す
    Trait %in% c("traitboldness", "traitrel_fitness")
    ) %>%
  select(-Type) %>%
  pivot_wider(names_from = Trait, values_from = Value)

回帰直線を得る

  • Boldnessに対する相対適応度を傾き
    • \(\frac{boldnessと相対適応度の共分散}{boldnessの分散}\)
B_fit_slope <- mcmc_E_B_fit$VCV[,"traitrel_fitness:traitboldness.ID"]/
  mcmc_E_B_fit$VCV[,"traitboldness:traitboldness.ID"]

図示

ggplot(df_bf_coefs, aes(x = traitboldness, y = traitrel_fitness, group = ID)) +
  geom_point(alpha = 0.7) +
  geom_abline(intercept = 0, slope = mean(B_fit_slope)) +
  labs(
    x = "Boldness (BLUP)",
    y = "Relative fitness (BLUP)"
    )


brms : Mitchell et al

David Mitchell, Christa Beckmann, Peter A Biro: Supplement

brmsとは

概要: Bürkner 2017

  • Bayesian multilevel modelを扱う
  • Stan, C++を経由

MCMCglmmとの比較

  1. 〇複数のマルコフ連鎖を走らせれる
  2. 〇共分散の事前分布が柔軟に指定できる
  3. 〇Link関数が柔軟
  4. 〇Robust linear modelsができる

など。利点はそれなりに多いが(特に①)、問題はそれを扱えるか…。

まあMCMCglmmでいいか。


ASReml-R

Avoid this because it’s not free

LS0tDQp0aXRsZTogIuWAi+aAp+OBqOihjOWLleOCt+ODs+ODieODreODvOODoOOBrue1seioiOino+aekCINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0aGVtZTogZGFya2x5ICMgZmxhdGx5IA0KICAgIGhpZ2hsaWdodDogdGV4dG1hdGUNCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDogeWVzDQogICAgZGZfcHJpbnQ6ICJrYWJsZSINCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgIyBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBudW1iZXJfc2VjdGlvbjogZmFsc2UNCi0tLQ0KDQo8ZGl2IHN0eWxlPSJtYXJnaW4tYm90dG9tOjYwcHg7Ij4NCjwvZGl2Pg0KDQojIOi2o+aXqA0KDQrlgIvmgKfjgoTooYzli5Xjgrfjg7Pjg4njg63jg7zjg6DjgIHlgIvmgKfjgajpganlv5zluqbjga7plqLpgKPjgpLoqr/jgbnjgovjgYbjgYjjgafjgIHntbHoqIjop6PmnpDjga7pg6jliIbjgafli4nlvLfjgZfjgZ/jgZPjgajjgpLjgb7jgajjgoHjgabjgYTjgY3jgb7jgZnjgILlgIvmgKfjgoTooYzli5Xjgrfjg7Pjg4njg63jg7zjg6Djga7mpoLlv7XnmoTjgarpg6jliIbjga/ml6XmnKznlJ/mhYvlrabkvJroqozjgatb57eP6KqsXShodHRwczovL3d3dy5yZXNlYXJjaGdhdGUubmV0L3B1YmxpY2F0aW9uLzM1MDQ4NTA1MF9kb25nd3Vub2dleGluZ3lhbmppdXdvZnVrYW5zdXJ1KQ0K44KS5pu444GE44Gm44GE44G+44GZ44Gu44Gn44Gd44Gh44KJ44KS5Y+C54Wn44GP44Gg44GV44GE44CCDQoNCuiHquWIhuOBp+WIhuaekOOCkuWni+OCgeOBn+OCieOAgeOBneOBruaZguOBq+ipsOOBvuOBo+OBn+OBqOOBk+OCjeOBquOBqeOBvuOBqOOCgeOBpuOBhOOBjeOBvuOBmeOAgg0KDQrlgIvkvZPlhoXjgaflj43lvqnmuKzlrprjgpLjgZfjgZ/jg4fjg7zjgr/liIbmnpDjgavlhbHpgJrjga7miYvms5XjgafjgZnjga7jgafjgIHlgIvmgKfjgaDjgZHjgafjgarjgY/jgIHmiJDplbfpgY7nqIvjgafjga7lvaLos6rnm7jplqLjga7lpInljJbjgarjganoibLjgIXlv5znlKjjgafjgY3jgovjgajmgJ3jgYTjgb7jgZnjgIINCg0KUuOCs+ODvOODieOBr+WPs+S4iiAiQ29kZSIg44Oc44K/44OzIOKGkiAiRG93bmxvYWQgUm1kIiDjgafjg4Djgqbjg7Pjg63jg7zjg4njgafjgY3jgb7jgZnjgIINCg0KLS0tDQo8ZGl2IHN0eWxlPSJtYXJnaW4tYm90dG9tOjkwcHg7Ij4NCjwvZGl2Pg0KDQojIEdlbmVyYWwgc2V0dGluZ3MNCg0KYGBge3J9DQoNCnJtKGxpc3Q9bHMoKSkgICMgcmVzZXQgd29ya3NwYWNlDQpvcHRpb25zKHNjaXBlbj0xMDApICAjIGRvIG5vdCBzaG93IG51bWJlcnMgdXNpbmcgZXhwb25lbnRpYWwNCg0KIyBpbnN0YWxsICYgbG9hZCBwYWNrYWdlcw0KcGFjbWFuOjpwX2xvYWQoDQogIHRpZHl2ZXJzZQ0KICAjICwgb3Blbnhsc3ggIyBvcGVuIGV4Y2VsDQogICwgbWFncml0dHIgICAjIGV4dGVuZGVkIHBpcGUNCiAgIyAsIGZvcmVhY2ggICAgIyBQYXJhbGxlbCBwcm9jZXNzaW5nDQogICwga25pdHIgIA0KICAsIGthYmxlRXh0cmEgIyBuaWNlIHRhYmxlcw0KICAsIHBhbmRlciAgICAgIyBuaWNlIHRhYmxlcw0KICAjICwgc3ZnbGl0ZSAgICAjIEV4cG9ydCBTVkcgcGxvdHMNCiAgIyAsIHBhdGNod29yayAgICMgY29tYmluZSBtdWx0aXBsZSBwbG90cw0KKQ0KDQojIFJtYXJrZG93biBzZXR0aW5ncw0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KA0KICBwcm9tcHQgID0gRkFMU0UsICAjIERvIG5vdCBhZGQgPiBvciArIGluIGlubGluZS1jb2RlDQogIG1lc3NhZ2UgPSBGQUxTRSwgDQogIGNvbW1lbnQgPSAiIiwgDQogIHdhcm5pbmcgPSBGQUxTRSwgICMgTXV0ZSB3YXJuaW5ncw0KICB0aWR5ICAgID0gVFJVRQ0KICApIA0Kb3B0aW9ucyhrbml0ci5rYWJsZS5OQSA9ICcnKSAjIEhpZGUgTkFzIGluIGthYmxlIHRhYmxlDQoNCmBgYA0KDQo8ZGl2IHN0eWxlPSJtYXJnaW4tYm90dG9tOjkwcHg7Ij4NCjwvZGl2Pg0KDQotLS0NCg0KIyBgTUNNQ2dsbW1gIDogSG91c2xheSAmIFdpbHNvbiAyMDE3ICpCZWhhdiBFY29sKg0KDQpbVC5NLiBIb3VzbGF5ICYgQS5KLiBXaWxzb24sIEJlaGF2aW9yYWwgRWNvbG9neSAyMDE3OiBTdXBwbGVtZW50XShodHRwczovL3RvbWhvdXNsYXkuZmlsZXMud29yZHByZXNzLmNvbS8yMDE3LzAyL2luZGl2dmFyX212X3R1dG9yaWFsX21jbWNnbG1tLnBkZikg44Gu44G+44Go44KB44CCDQoNCiMjIOWVj+mhjOeCueOBp+OBguOCi0JMVVDjgajjga8NCg0KQmVzdCBMaW5lYXIgVW5iaWFzZWQgUHJlZGljdG9ycw0KLSDmt7flkIjjg6Ljg4fjg6vjgafmjqjlrprjgZXjgozjgZ/jgIHjg6njg7Pjg4Djg6Dlirnmnpzjga7lkITlgIvkvZPjgafjga7mjqjlrprlgKQNCi0g5b2T54S25aSn44GN44Gq6Kqk5beu44GM5Ly044GGDQoNCuOAkOWVj+mhjOOBqOOBquOBo+OBpuOBhOOCi+aJi+azleOAkTxicj4NCuWAi+S9k0lE44Gr44Op44Oz44OA44Og5Yq55p6c44KS5b2T44Gm44Gf5re35ZCI44Oi44OH44Or44Gr44GK44GE44Gm44CB5ZCE5YCL5L2T44Gu44Op44Oz44OA44Og5Yq55p6c5YCk77yIQkxVUCwg5ZCE5YCL5L2T44Gu6KGM5YuV5oCn5ZCR44KS56S644GZ77yJ44KS5oq95Ye644GX44CB44Gd44KM44KS55So44GE44Gm44GV44KJ44Gr5YiG5p6Q44KS6YCy44KB44KL77yI6KGM5YuV44K344Oz44OJ44Ot44O844Og44Gq44Gp77yJDQoNCuOAkOWVj+mhjOeCueOAkTxicj4NCueCueaOqOWumuOBp+OBguOCi0JMVVDjgavjga/oqqTlt67jgYzlj43mmKDjgZXjgozjgarjgYTjga7jgafjgIFCTFVQ44KS5L2/44Gj44Gf5YiG5p6Q44Gn44Gv5oWM44Gm6ICF44Gu6YGO6Kqk44GM6LW344GT44KK44KE44GZ44GP44Gq44KL77yI57eo6ZuG5YWD44GuU3VwcGxlbWVudOOBp+OBr0JMVVDjgavjgojjgovliIbmnpDjgoLjgZfjgabjgYTjgovjgYzjgZPjgZPjgafjga/nnIHnlaXvvIkNCg0K44CQ6Kej5rG6562W44CRPGJyPg0K5YCL5oCn5YiG5p6Q77yI6KGM5YuVUmVwZWF0YWJpbGl0ee+8ieOBqOi/veWKoOWIhuaekO+8iOihjOWLleOCt+ODs+ODieODreODvOODoOOChOWAi+aAp+ODvOmBqeW/nOW6puOBrumWoumAo++8ieOCkuS4gOOBpOOBrua3t+WQiOODouODh+ODq+OBp+eJh+S7mOOBkeOBpuOBl+OBvuOBhg0KDQotLS0NCjxkaXYgc3R5bGU9Im1hcmdpbi1ib3R0b206OTBweDsiPg0KPC9kaXY+DQoNCiMjIEluc3RhbGwgJiBsb2FkIHBhY2thZ2VzDQoNCmBgYHtyfQ0KDQpwYWNtYW46OnBfbG9hZCgNCiAgTUNNQ2dsbW0NCiAgLCBsbWU0DQogICwgYnJvb20ubWl4ZWQgIyBjcmVhdGUgdGlkeSBvdXRwdXQgb2YgZ2xtbSByZXN1bHQNCiAgLCBuYWRpdg0KICAsIGNvZGEgIyBKdWRnZSBNQ01DIGNvbnZlcmdlbmNlDQogICkNCg0KIyBTdXBwbGVtZW5044Gn55So5oSP44GV44KM44Gm44GE44KL5Luu5oOz44OH44O844K/DQpkZl9zeW5kcm9tZSA8LSByZWFkX2NzdigibGVhcm5fUGVyc29uYWxpdHlfc3RhdHNfZGF0X3N5bmRyb21lLmNzdiIpDQoNCmBgYA0KDQotLS0NCg0KPGRpdiBzdHlsZT0ibWFyZ2luLWJvdHRvbTo2MHB4OyI+DQo8L2Rpdj4NCg0KIyMgRGF0YSBhc3N1bXB0aW9uDQoNCuOBk+OBk+OBp+OBr+OAgeikh+aVsOOBrue5sOOCiui/lOOBl+ioiOa4rOOBl+OBn+ihjOWLleaMh+aomeOBqOOAgeS4gOWbnuioiOa4rOOBrumBqeW/nOW6puW9ouizqu+8iG1hdGluZyBzdWNjZXNz77yJ44OH44O844K/44KS5oOz5a6a44CCDQoNCuS7iuWbnuOBruS7ruaDs+ODh+ODvOOCv+OBr+WFqOOBpuOCquOCueOBruOCguOBruOBp+OAgeS7peS4i+OBruWIl+OCkuaMgeOBpA0KDQotIEluZGl2aWR1YWwgKipJRCoqDQotIFRoZSByZXBlYXQgbnVtYmVyIGZvciBlYWNoIGJlaGF2aW91cmFsIHRlc3QsICoqYXNzYXlfcmVwKioNCi0gKipib2xkbmVzcyoqLCBtZWFzdXJlZCA0IHRpbWVzIHBlciBpbmRpdmlkdWFsDQotICoqZXhwbG9yYXRpb24qKiwgbWVhc3VyZWQgNCB0aW1lcyBwZXIgaW5kaXZpZHVhbA0KLSAqKmZpdG5lc3MqKiwgYSBzaW5nbGUgdmFsdWUgZm9yIGVhY2ggaW5kaXZpZHVhbA0KLSBJbmRpdmlkdWFsICoqYm9keV9zaXplKiosIGFzIG1lYXN1cmVkIG9uIHRoZSBkYXkgb2YgdGVzdGluZy4NCg0KLS0tDQoNCjxkaXYgc3R5bGU9Im1hcmdpbi1ib3R0b206OTBweDsiPg0KPC9kaXY+DQoNCiMjIOWNmOWbnuW4sOODouODh+ODqw0KDQotIOWQhOihjOWLleW9ouizquOBp+OBruOAgeWAi+S9k+W3ruOBq+OCiOOCi+ihqOePvuWei+WIhuaVo+OBruWJsuWQiOOCkuioiOeulw0KDQotIGBsbWU0YOOBq+OBpg0KDQotIOioiOa4rOOBruWPjeW+qUlE44Gv5Zu65a6a5Yq55p6c44GrDQoNCi0g5YCL5L2TSUTjgYxyYW5kb20gZWZmZWN0cw0KDQotIOioiOa4rOWPr+iDveOBquWAi+S9k+OBrueKtuaFi++8iOOBk+OBk+OBp+OBr+S9k+OCteOCpOOCuu+8ieOBr1NjYWxpbmcgb3IgQ2VudHJpbmfjgZfjgablm7rlrprlirnmnpzjgasNCg0KLSDooYzli5Xjgrfjg7Pjg4njg63jg7zjg6DjgpLoqr/jgbnjgovlhajlvaLos6rjgafjgZPjgozjgpLooYzjgYYNCg0KYGBge3IsIGZpZy53aWR0aCA9IDUsIGZpZy5oZWlnaHQgPSAzfQ0KDQpsbWVyX2IgPC0gbG1lcigNCiAgYm9sZG5lc3MgfiBzY2FsZShhc3NheV9yZXAsIHNjYWxlPUZBTFNFKSArIHNjYWxlKGJvZHlfc2l6ZSkgKyANCiAgICAjIERvbid0IGZvcmdldCBzY2FsaW5nIHZhcmlhYmxlcyENCiAgICAoMXxJRCksDQogIGRhdGEgPSBkZl9zeW5kcm9tZQ0KICApDQoNCnBsb3QobG1lcl9iKQ0KcXFub3JtKHJlc2lkdWFscyhsbWVyX2IpKQ0KaGlzdChyZXNpZHVhbHMobG1lcl9iKSkNCnN1bW1hcnkobG1lcl9iKQ0KDQpgYGANCg0KLSDjgZPjgZPjgafjga9yYW5kb20gZWZmZWN0c+OBrnZhcmlhbmNlIGNvbXBvbmVudOOBq+iIiOWRs+OBjOOBguOCi+OAgg0KDQotIOWLleeJqeOBruWAi+aAp+OBruiovOaLoOOBqOOBquOCi+OBruOBr+OAgXJlcGVhdGFiaWxpdHkgKD0gaW50cmFjbGFzcyBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCkNCg0KLSBSZXBlYXRhYmlsaXR5Og0KDQogIC0gJFxmcmFje+WAi+S9k+W3ruOBq+OCiOOCi+WIhuaVo3175Zu65a6a5Yq55p6c44KS6ICD5oWu44GX44Gf44GG44GI44Gn44Gu5YWo5YiG5pWjfSA9IFxmcmFje1Zfe0lEfX17Vl97SUR9ICsgVl97cmVzaWR1YWx9fSQNCg0KYGBge3J9DQoNCmJyb29tLm1peGVkOjp0aWR5KGxtZXJfYiwgZWZmZWN0cyA9ICJyYW5fcGFycyIsIHNjYWxlcyA9ICJ2Y292IikgJT4lDQogIHNlbGVjdChncm91cCwgZXN0aW1hdGUpICU+JQ0KICBzcHJlYWQoZ3JvdXAsIGVzdGltYXRlKSAlPiUNCiAgbXV0YXRlKFJlcGVhdGFiaWxpdHkgPSBJRC8oSUQgKyBSZXNpZHVhbCkpICU+JSANCiAga2FibGUoImh0bWwiLCBkaWdpdHMgPSAzKSAlPiUgDQogIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikgIA0KDQpgYGANCg0K44GT44Gu5Luu5oOz44OH44O844K/44Gn44Gv44CB44Gw44KJ44Gk44GN44GuMzcl44GM5Zu65a6a5Yq55p6c44Gn44Gv44Gq44GP5YCL5L2T5beu44Gr44KI44KL44KC44Gu44CCDQoNCi0tLQ0KDQo8ZGl2IHN0eWxlPSJtYXJnaW4tYm90dG9tOjkwcHg7Ij4NCjwvZGl2Pg0KDQojIyDooYzli5Xjgrfjg7Pjg4njg63jg7zjg6DvvJpCaXZhcmlhdGUgbW9kZWxzDQoNCi0gYE1DTUNnbG1tYOOBp+OBruOAgeihjOWLlTLlvaLos6rjgpLlv5znrZTlpInmlbDjgavnva7jgYTjgZ/jg6Ljg4fjg6vjgpLntYTjgoDjgIINCg0KLSDlkITooYzli5XlvaLos6rjgajjgZ3jgozjgonjga7lhbHliIbmlaPjgavlr77jgZnjgovjgIHlgIvkvZPplpPliIbmlaPjgpLmjqjlrpoNCg0KDQojIyMg5LqL5YmN5YiG5biD44Gu6Kit5a6aDQoNCuino+iqrOOBr+S7peS4i+WPgueFpw0KDQotIFtDb2RpbmcgaHViXShodHRwczovL291cmNvZGluZ2NsdWIuZ2l0aHViLmlvL3R1dG9yaWFscy9tY21jZ2xtbS8pDQoNCi0gW0NvdXJzZSBub3Rlc10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL01DTUNnbG1tL3ZpZ25ldHRlcy9Db3Vyc2VOb3Rlcy5wZGYpDQoNCi0g44Kr44OG44K044Oq44Kr44Or5aSJ5pWw44Gr44GvW0dlbG1hbiBwcmlvcl0oaHR0cHM6Ly9yZHJyLmlvL2NyYW4vTUNNQ2dsbW0vbWFuL2dlbG1hbi5wcmlvci5odG1sKeOCkuW9k+OBpuOBr+OCgeOCiw0KDQotIOikh+aVsOOBruS6i+WJjeWIhuW4g+OBq+WvvuOBl+e1kOaenOOBjOmgkeWBpeOBi+imi+OBpuOBiuOBj+OBqOiJr+OBhA0KDQoNCuWbuuWumuWKueaenOOBq+OBr05vcm1hbCBkaXN0cmlidXRpb27jgIEoY28pdmFyaWFuY2Vz44Gr44GvaW52ZXJzZSBXaXNoYXJ044KS5LqL5YmN5YiG5biD44Go44GX44Gm5L2/44Gj44Gm44GE44KL44CCDQoNCi0tLQ0KDQrmjIflrprjgZnjgovjgoLjga4NCg0KLSAqKkIqKjog5Zu65a6a5Yq55p6c44Gu5LqL5YmN5YiG5biD44CCRGVmYXVsdOOBr+S/oeS7sOOBruW8seOBhOato+imj+WIhuW4gw0KDQotICoqUioqOiDmrovlt64NCg0KLSAqKkcqKjog44Op44Oz44OA44Og5Yq55p6cIA0KDQotIOODqeODs+ODgOODoOWKueaenOOBruaVsOOBoOOBkeaMh+WumuOAguS+i++8mg0KDQpgYGBSDQogICAgRyA9IGxpc3QoDQogICAgICBHMSA9IGxpc3QoViA9IDEsIG51ID0gMSwgYWxwaGEubXUgPSAwLCBhbHBoYS5WID0gMTAwMCksDQogICAgICBHMiA9IGxpc3QoViA9IDEsIG51ID0gMSwgYWxwaGEubXUgPSAwLCBhbHBoYS5WID0gMTAwMCksDQogICAgICApDQogICAgKQ0KYGBgDQoNCi0gKiphbHBoYS5tdSoqOiBQcmlvciBtZWFuDQoNCi0gKiphbHBoYS5WKio6IOWIhuaVo+ihjOWIlw0KDQoNCi0tLQ0KDQppbnZlcnNlIFdpc2hhcnTkuovliY3liIbluIPjga7lpInmlbANCg0KLSAqKlYqKjog5LqL5YmN5YiG5biD44Gu44OU44O844Kv44KS5rG644KB44KL44CC44KI44GP5L2/44KP44KM44KL44Gu44GvMQ0KDQotICoqbnUqKjog5L+h5Luw44Gu5by344GV77yd5YiG5biD44Gu5YGP44KKIOOCkuaxuuOCgeOCi+OAguOCiOOBj+S9v+OCj+OCjOOCi+OBruOBrzAuMDAyDQoNCmBgYHtyfQ0KDQpwcmlvcl9FX0JfMXB4ID0gbGlzdCgNCiAgUiA9IGxpc3QoViA9IGRpYWcoMiksIG51ID0gMC4wMDIpLA0KICBHID0gbGlzdCgNCiAgICBHMSA9IGxpc3QoDQogICAgICBWID0gZGlhZygyKSwgDQogICAgICBudSA9IDIsIA0KICAgICAgYWxwaGEubXUgPSByZXAoMCwyKSwgDQogICAgICBhbHBoYS5WID0gZGlhZygyNV4yLDIsMikpDQogICAgKQ0KICApDQoNCmBgYA0KDQotLS0NCg0KPGRpdiBzdHlsZT0ibWFyZ2luLWJvdHRvbTo2MHB4OyI+DQo8L2Rpdj4NCg0KIyMjIE1DTUNnbG1t44Oi44OH44OrDQoNCuWFqOS9k+OBruOCs+ODvOODiQ0KDQpgYGBSDQpNQ01DZ2xtbSgNCiAgIyBSZXNwb25zZSB2YXJpYWJsZXMuIENvbWJpbmUgYWZ0ZXIgc2NhbGluZw0KICBjYmluZChzY2FsZShleHBsb3JhdGlvbiksIHNjYWxlKGJvbGRuZXNzKSkgfiANCiAgICB0cmFpdC0xICsNCiAgICB0cmFpdDpzY2FsZShhc3NheV9yZXAsIHNjYWxlID0gRkFMU0UpICsNCiAgICB0cmFpdDpzY2FsZShib2R5X3NpemUpLA0KICByYW5kb20gPX4gdXModHJhaXQpOklELA0KICByY292ID1+IHVzKHRyYWl0KTp1bml0cywNCiAgZmFtaWx5ID0gYygiZ2F1c3NpYW4iLCJnYXVzc2lhbiIpLA0KICBwcmlvciA9IHByaW9yX0VfQl8xcHgsDQogIG5pdHQgPSAxNTAwMDAsDQogIGJ1cm5pbiA9IDEwMDAwLA0KICB0aGluID0gMzAsDQogIHZlcmJvc2UgPSBUUlVFLA0KICBkYXRhID0gYXMuZGF0YS5mcmFtZShkZl9zeW5kcm9tZSkNCiAgKQ0KYGBgDQoNCumgheebruOBlOOBqOOBruino+iqrA0KDQotIFJlc3BvbnNlIHZhcmlhYmxlOiBgY2JpbmRgIGFmdGVyIHNjYWxpbmcNCg0KYGBgUg0KICBjYmluZChzY2FsZShleHBsb3JhdGlvbiksIHNjYWxlKGJvbGRuZXNzKSkgfiANCmBgYA0KDQotIFByZWRpY3RvciB2YXJpYWJsZToNCg0KICAtIOWQhOW9ouizquOBq+WvvuOBl+WIh+eJh+OCkueUqOaEjw0KDQpgYGBSDQogICAgdHJhaXQtMSArDQpgYGANCiAgLSAqKnRyYWl0Kioga2V5d29yZOOBq+OCiOOCiuWkmuWkiemHj+ODouODh+ODq+OBp+OBguOCi+OBk+OBqOOCkuaYjuiomA0KICAtICDlm7rlrprlirnmnpzjgavjgojjgovlvaLos6rjgbjjga7lvbHpn7/jgpLjgIHjgZ3jgozjgZ7jgozjga7lvaLos6rjgafmjqjlrpoNCg0KYGBgUg0KICAgIHRyYWl0OnNjYWxlKGFzc2F5X3JlcCwgc2NhbGUgPSBGQUxTRSkgKw0KICAgIHRyYWl0OnNjYWxlKGJvZHlfc2l6ZSksDQpgYGANCg0KLSBSYW5kb20gZWZmZWN0cyBzdHJ1Y3R1cmXjgpLoqK3lrpo8YnI+DQoNCiAgLSDigJh1bnN0cnVjdHVyZWTigJkgKHVzKSDlhbHliIbmlaPooYzliJfjgpLlgIvkvZNJROOBq+mBqeeUqDxicj4NCiAg5Lul5LiL44KS6KiI566X44GZ44KL44Gf44KBDQoNCiAgICAgIC0g5YCL5L2T5beu44Gr44KI44KL44CB44Gd44KM44Ge44KM44Gu6KGM5YuV5b2i6LOq44Gu5YiG5pWjDQogICAgICAtIOOBk+OCjOOCieOBruWIhuaVo+OBruWFseWIhuaVow0KDQpgYGBSDQogIHJhbmRvbSA9fiB1cyh0cmFpdCk6SUQsDQpgYGANCg0KLSDmrovlt67liIbmlaPjga7mp4vpgKDjgpLoqK3lrpoNCg0KICAtIOKAmHdpdGhpbi1pbmRpdmlkdWFsIHZhcmlhdGlvbuKAmQ0KICAtIOWQhOWAi+S9k+OBp+WPjeW+qeioiOa4rOOBl+OBpuOBhOOCi+OBruOBp+OAgeOBk+OBk+OBp+OCgnVuc3RydWN0dXJlZCBjb3ZhcmlhbmNlIG1hdHJpeOOCkuioreWumg0KICAgIC0g5ZCE5b2i6LOq44Gn44Gu5q6L5beu5YiG5pWj44Go5YWx5YiG5pWj44KS6KiI566XDQoNCmBgYFINCiAgICByY292ID1+IHVzKHRyYWl0KTp1bml0cywNCmBgYA0KDQotIE1DTUPjg5fjg63jgrvjgrnjga7oqK3lrpo8YnI+DQrlj47mnZ/jgYzmgqrjgYTmmYLjga/jgZPjgozjgonjga7lgKTjgpLlpKfjgY3jgY/kuIrjgZLjgosNCiAgLSDlj43lvqnoqabooYzmlbAgKEl0ZXJhdGlvbnMpICoqbml0dCoqPGJyPg0KICAgIOWPjuadn+OBjOaCquOBkeOCjOOBsOmdkuWkqeS6lQ0KICAtIOS4jeWuieWumuOBquWIneacn+OBrkl0ZXJhdGlvbuOCkuWIh+OCiuaNqOOBpuOCi+aVsCoqYnVybmluKio8YnI+DQogICAg5Y+O5p2f44GM5oKq44GR44KM44GwNTAwMDDjgarjgakNCiAgLSDkvb/jgYZJdGVyYXRpb27plpPpmpQgKip0aGluKio6IFNhbXBsaW5n44Gn44Gu6Ieq5bex55u46Zai44KS5rib44KJ44GZPGJyPg0KICAgIOWPjuadn+OBjOaCquOBkeOCjOOBsDIwMOOBquOBqQ0KICANCmBgYFINCiAgICBuaXR0PTQyMDAwMCwNCiAgICBidXJuaW49MjAwMDAsDQogICAgdGhpbj0xMDAsDQpgYGANCg0KLSDjg4fjg7zjgr/jgrvjg4Pjg4gNCiAgLSBgTUNNQ2dsbW1g44Gn44GvdGJsX2Rm44KS5Y+X44GR5YWl44KM44Gq44GE44Gu44GnYGFzLmRhdGEuZnJhbWVgDQoNCmBgYFINCiAgICBkYXRhID0gYXMuZGF0YS5mcmFtZShkZl9zeW5kcm9tZSkNCmBgYA0KDQotLS0NCg0KPGRpdiBzdHlsZT0ibWFyZ2luLWJvdHRvbTo2MHB4OyI+DQo8L2Rpdj4NCg0KIyMjIE1DTUPjga7lj47mnZ8NCg0KVHJhY2Xjga/kuIDlrprjga7lgr7lkJHjgpLmjIHjgaPjgabjgYTjgabjga/jgYTjgZHjgarjgYTjg7zmnKrlj47mnZ/jgpLnpLrjgZnjgILjgYLjgovlgKTjga7kuIrkuIvjgafntYLlp4vjgq7jgrbjgq7jgrbjgZfjgabjgYTjgovjgajlj47mnZ/jgYznpLrllIbjgIIgICAgDQoNCuODqeODs+ODgOODoOWKueaenOOBrk1DTUPpgKPpjpYNCg0KYGBge3IsIGZpZy5oZWlnaHQ9MTB9DQptY21jX0VfQl91cyA8LSByZWFkUkRTKCJsZWFybl9QZXJzb25hbGl0eV9zdGF0c19tY21jX3N5bmRyb21lLm9iaiIpDQpwbG90KG1jbWNfRV9CX3VzJFZDVikNCmBgYA0KDQrlm7rlrprlirnmnpzjga7lj47mnZ/pgY7nqIsNCg0KYGBge3J9DQoNCnBsb3QobWNtY19FX0JfdXMkU29sKQ0KDQpgYGANCg0KLS0tDQoNCltgZ2V3ZWtlLmRpYWdgXShodHRwczovL3d3dy5yZG9jdW1lbnRhdGlvbi5vcmcvcGFja2FnZXMvY29kYS92ZXJzaW9ucy8wLjE5LTQvdG9waWNzL2dld2VrZS5kaWFnKQ0KDQotIE1hcmtvdumAo+mOluOBruWIneacn+OBqOW+jOacn+OBp+OBruW5s+Wdh+WApOOBjOWQjOOBmOOBi+iqv+OBueOCiw0KICAtIOWIneacn+ioreWumuOBp+OBr+OAgeWIneacnzEwJeOBqOW+jOacnzUwJQ0KLSDjgoLjgZfpgKPpjpbjgYxzdGF0aW9uYXJ5IGRpc3RyaWJ1dGlvbuOBq+mBlOOBl+OBpuOBhOOCjOOBsOOAgQ0KICAtIOS6jOOBpOOBruW5s+Wdh+OBr+WQjOOBmA0KICAtIEdld2VrZee1seioiOmHj+OBr2FzeW1wdG90aWNhbGx5IHN0YW5kYXJkIG5vcm1hbCBkaXN0cmlidXRpb24NCg0KLSB0ZXN0IHN0YXRpc3RpYzogWi1zY29yZQ0KICAtICRcZnJhY3tTYW1wbGVcIG1lYW5z44Gu5beufXvmjqjlrppzdGFuZGFyZFwgZXJyb3J9JA0KICAtIFNF44Gv44CBc3BlY3RyYWwgZGVuc2l0eSBhdCB6ZXJv44GL44KJ5o6o5a6aDQogICAgLSDoh6rlt7Hnm7jplqLjgYzogIPmha7jgavlhaXjgaPjgabjgYTjgosNCiAgLSBjYWxjdWxhdGVkIHVuZGVyIHRoZSBhc3N1bXB0aW9uIHRoYXQgdGhlIHR3byBwYXJ0cyBvZiB0aGUgY2hhaW4gYXJlIGFzeW1wdG90aWNhbGx5IGluZGVwZW5kZW50LCB3aGljaCByZXF1aXJlcyB0aGF0IHRoZSBzdW0gb2YgZnJhYzEgYW5kIGZyYWMyIGJlIHN0cmljdGx5IGxlc3MgdGhhbiAxDQoNCmBgYHtyfQ0KZ2V3ZWtlLmRpYWcobWNtY19FX0JfdXMkU29sLCBmcmFjMT0wLjEsIGZyYWMyPTAuNSkNCmBgYA0KWuWApOOBjO+8kOOBi+OCieOBu+OBqemBoOOBhOOBruOBp+OAgeOBk+OBrk1hcmNob3bpgKPpjpbjga/lj47mnZ/jgZfjgabjgYTjgarjgYTjgajjgb/jgovjgbnjgY0NCg0KLS0tDQoNCuODouODh+ODq+OBjDLjgaTku6XkuIrjgYLjgovjgajjgY3jgavjga9bYGdlbG1hbi5kaWFnYF0oaHR0cHM6Ly93d3cucmRvY3VtZW50YXRpb24ub3JnL3BhY2thZ2VzL2NvZGEvdmVyc2lvbnMvMC4xOS00L3RvcGljcy9nZWxtYW4uZGlhZynjgavjgojjgovliKTlrprjgoLjgafjgY3jgosNCg0KYGBgUg0KZ2VsbWFuLmRpYWcobWNtYy5saXN0KG0xJFNvbCwgbTIkU29sKSkNCmBgYA0KDQoNCjxkaXYgc3R5bGU9Im1hcmdpbi1ib3R0b206NjBweDsiPg0KPC9kaXY+DQoNCiMjIyBSZXBlYXRhYmlsaXR5DQoNCuWPjeW+qeaAp+OCkuioiOeul+OBmeOCi+OBn+OCgeOBq+OAgeaWsOOBn+OBqyDigJjlgIvkvZPlt67jgafoqqzmmI7jgZXjgozjgZ/ooYzli5XlvaLos6rjgbDjgonjgaTjgY3jga7libLlkIjigJkg44Gu5LqL5b6M5YiG5biD44KS5L2c44KLDQoNCi0gU3VtbWFyeeOBq+OBguOCi1ZhcmlhbmNlIGNvbXBvbmVudHPjga7lkI3liY3jgavln7rjgaXjgYTjgaboqIjnrpcNCg0KLSDjgZPjgZPjgafjga9FeHBsb3JhdGlvbuOBjOWvvuixoQ0KDQpgYGB7ciwgZmlnLmhlaWdodCA9IDN9DQoNCm1jbWNfcHJvcF9FIDwtIG1jbWNfRV9CX3VzJFZDVlssInRyYWl0ZXhwbG9yYXRpb246dHJhaXRleHBsb3JhdGlvbi5JRCJdLw0KICAobWNtY19FX0JfdXMkVkNWWywidHJhaXRleHBsb3JhdGlvbjp0cmFpdGV4cGxvcmF0aW9uLklEIl0gKw0KICAgICBtY21jX0VfQl91cyRWQ1ZbLCJ0cmFpdGV4cGxvcmF0aW9uOnRyYWl0ZXhwbG9yYXRpb24udW5pdHMiXSkNCg0KcGxvdChtY21jX3Byb3BfRSkNCg0KbWVhbihtY21jX3Byb3BfRSkNCg0KIyA5NSUgQ0lzDQpIUERpbnRlcnZhbChtY21jX3Byb3BfRSkNCg0KYGBgDQoNCkJheWVzaWFuIDk1JeS/oemgvOWMuumWk+OBjO+8kOOCkui3qOOBjOOBquOBhOOBk+OBqOOBjOWPpOWFuOeahO+8iOmgu+W6puS4u+e+qeeahO+8ieOBque1seioiOeahOacieaEj+OCkuekuuOBmeOBoOOBqOiogOOCj+OCjOOCi+OBjOOAgeOBk+OBk+OBp+aJseOBo+OBpuOBhOOCiyoqdmFyaWFuY2UgY29tcG9uZW50c+OBr+OAgU1DTUNnbG1t44Gn44Gv5b+F44Ga5q2j44Gu5YCk44KS44Go44KLKioNCg0KLSAqKuS/oemgvOWMuumWk+OBjO+8kOOCkui3qOOBjOOBquOBhOKJoOacieaEjyoqDQotIOS4i+mZkOOBjO+8kOOBq+i/keOBkeOCjOOBsOOAgVJlcGVhdGFiaWxpdHnjgYzlvLHjgYTjgajogIPjgYjjgovjgbnjgY0NCg0KDQrjgarjgYrjgIFWYXJpYW5jZSBjb21wb25lbnRz44Gu5ZCN5YmN44Gv5Lul5LiL44Gn6Kq/44G544KJ44KM44KLDQoNCmBgYHtyfQ0KbWNtY19FX0JfdXMkVkNWICU+JSANCiAgYXMudGliYmxlKCkgJT4lIA0KICBjb2xuYW1lcygpDQpgYGANCi0g5YCL5L2T5beu44Gr44KI44KL5YiG5pWj44GvPGJyPnRyYWl0e1wqdHJhaXQgbmFtZVwqfTp0cmFpdHsqdHJhaXQgbmFtZSp9LioqSUQqKg0KLSDmrovlt67liIbmlaPjga88YnI+dHJhaXR7KnRyYWl0IG5hbWUqfTp0cmFpdHsqdHJhaXQgbmFtZSp9LioqdW5pdHMqKg0KDQoNCi0tLQ0KPGRpdiBzdHlsZT0ibWFyZ2luLWJvdHRvbTo2MHB4OyI+DQo8L2Rpdj4NCg0KIyMjIENvdmFyaWFuY2UNCg0KUmVwZWF0YWJpbGl0eeOBruioiOeul+ODl+ODreOCu+OCueOCkuWFseWIhuaVo+OBq+W/nOeUqOOBp+OBjeOCi+OAgg0KDQrlgIvkvZPplpPjgafjga7lvaLos6rplpPnm7jplqLjga7kuovlvozliIbluIPvvJoNCg0KLSAkXGZyYWN75b2i6LOq6ZaT44Gu5YWx5YiG5pWjfXvlkITlvaLos6rjga7liIbmlaPjga7lubPmlrnmoLnjgpLmjpvjgZHlkIjjgo/jgZvjgZ/jgoLjga59JA0KDQogIC0g5YWx5YiG5pWj44KSLTF+MeOBq+OCueOCseODvOODquODs+OCsA0KDQoNCmBgYHtyLCBmaWcuaGVpZ2h0ID0gM30NCg0KbWNtY19jb3JfRUIgPC0gbWNtY19FX0JfdXMkVkNWWywidHJhaXRib2xkbmVzczp0cmFpdGV4cGxvcmF0aW9uLklEIl0vDQogIChzcXJ0KG1jbWNfRV9CX3VzJFZDVlssInRyYWl0Ym9sZG5lc3M6dHJhaXRib2xkbmVzcy5JRCJdKSoNCiAgICAgc3FydChtY21jX0VfQl91cyRWQ1ZbLCJ0cmFpdGV4cGxvcmF0aW9uOnRyYWl0ZXhwbG9yYXRpb24uSUQiXSkpDQoNCnBsb3QobWNtY19jb3JfRUIpDQoNCm1lYW4obWNtY19jb3JfRUIpDQoNCkhQRGludGVydmFsKG1jbWNfY29yX0VCKQ0KDQpgYGANCg0K55u46Zai44Gv5q2j6LKg44Gp44Gh44KJ44KC44Go44KK44GG44KL44Gu44Gn44CBOTUl5L+h6aC85Yy66ZaT44GM77yQ44KS6Leo44GQ44GL44Gv6aC75bqm5Li7576p55qE44Gq57Wx6KiI55qE5pyJ5oSP44KS56S644GZ44CC44GT44GT44Gn44Gv5L+h6aC85Yy66ZaT44GM77yQ44KS6Leo44GE44Gn44GE44KL44Gu44Gn44CB5pyJ5oSP44Gq6KGM5YuV44K344Oz44OJ44Ot44O844Og44Gv44Gq44GE44Go57WQ6KuW5LuY44GR44KL44CCDQoNCi0tLQ0KPGRpdiBzdHlsZT0ibWFyZ2luLWJvdHRvbTo2MHB4OyI+DQo8L2Rpdj4NCg0KIyMg44GV44KJ44Gr5b2i6LOq44KS5Yqg44GI44KLDQoNCuS7ruaDs+ODh+ODvOOCv+OCu+ODg+ODiOOBp+OBruOAgeihjOWLle+8kuW9ouizqu+8iOWPjeW+qea4rOWumu+8ieOBqOmBqeW/nOW6pu+8iDHlm57oqIjmuKzvvInjga7plqLkv4LjgpLoqr/jgbnjgovjgIINCg0KYGBge3J9DQojIOebuOWvvumBqeW/nOW6puOCkueul+WHuuOBl+OAgXJlbF9maXRuZXNz44Gr5qC857SNDQpkZl9zeW5kcm9tZSAlPD4lDQogIG11dGF0ZShyZWxfZml0bmVzcyA9IGZpdG5lc3MvbWVhbihmaXRuZXNzLCBuYS5ybT1UUlVFKSkNCmBgYA0KDQotLS0NCg0KIyMjIOS6i+WJjeWIhuW4g+OCkuioreWumg0KDQrms6jmhI8NCg0KLSAqKjHlm57oqIjmuKzjga7lvaLos6rvvIjjgZPjgZPjgafjga/pganlv5zluqbvvInjgafjga/jgIHmrovlt67liIbmlaPvvIjlgIvkvZPlhoXliIbmlaPvvInjga/vvJAqKg0KLSAqKjHlm57oqIjmuKzjga7oqIjmuKzjgajjga7plpPjga7jgZnjgbnjgabjga7lgIvkvZPlhoXlvaLos6rnm7jplqLjgoLvvJAqKg0KICAtIGBmaXhg44GnVmFyaWFuY2UgY29tcG9uZW5044KS54m55a6a44Gu5YCk44Gr5Zu65a6aDQogICAgLSDliIbmlaPjga/mraPjga7lgKTjgafjgarjgYTjgajjgYTjgZHjgarjgYTjga7jgafjgIHlgIvkvZPlhoXliIbmlaPjgpLlsI/jgZXjgarmraPjga7lgKTjgafku6PlhaXvvIjjgZPjgZPjgafjga8wLjAwMDHvvIkNCiAgICAtIOWAi+S9k+WGheWIhuaVo++8neaui+W3ruWIhuaVoyoqUioqDQoNCmBgYHtyfQ0KcHJpb3JfRV9CX2ZpdF8xcHggPSBsaXN0KA0KICBSID0gbGlzdCgNCiAgICAjIOWPjeW+qea4rOWumuW9ouizquOBjDLjgaTjga7lvozjgasx5Zue6KiI5ris5b2i6LOq44Gu5YiG5pWj44KS5oyH5a6a44GZ44KL44Gu44Gn44CBM+OBpOebruOBruimgee0oOOBqzAuMDAwMeOCkuS7o+WFpQ0KICAgIFYgPSBkaWFnKGMoMSwxLDAuMDAwMSksMywzKSwgDQogICAgbnUgPSAxLjAwMiwgDQogICAgIyAz44Gk55uu44GuVmFyaWFuY2UgY29tcG9uZW50ID0gMeWbnuioiOa4rOW9ouizquOCkuWbuuWumg0KICAgIGZpeCA9IDMNCiAgICApLA0KICBHID0gbGlzdCgNCiAgICBHMSA9IGxpc3QoDQogICAgICBWID0gZGlhZygzKSwgbnUgPSAzLCBhbHBoYS5tdSA9IHJlcCgwLDMpLCBhbHBoYS5WID0gZGlhZygyNV4yLDMsMykNCiAgICAgICkNCiAgICApDQogICkNCmBgYA0KDQotLS0NCg0KIyMjIE1DTUNnbG1t44Oi44OH44OrDQoNCuWFqOS9k+OBruOCs+ODvOODiQ0KDQpgYGBSDQptY21jX0VfQl9maXQgPC0gTUNNQ2dsbW0oDQogIGNiaW5kKHNjYWxlKGV4cGxvcmF0aW9uKSwgc2NhbGUoYm9sZG5lc3MpLCByZWxfZml0bmVzcykgfiANCiAgICB0cmFpdC0xICsgDQogICAgYXQubGV2ZWwodHJhaXQsMSk6c2NhbGUoYXNzYXlfcmVwLCBzY2FsZSA9IEZBTFNFKSArDQogICAgYXQubGV2ZWwodHJhaXQsMik6c2NhbGUoYXNzYXlfcmVwLCBzY2FsZSA9IEZBTFNFKSArDQogICAgdHJhaXQ6c2NhbGUoYm9keV9zaXplKSwNCiAgcmFuZG9tID1+IHVzKHRyYWl0KTpJRCwNCiAgcmNvdiA9fiB1cyh0cmFpdCk6dW5pdHMsDQogIGZhbWlseSA9IGMoImdhdXNzaWFuIiwiZ2F1c3NpYW4iLCJnYXVzc2lhbiIpLA0KICBwcmlvciA9IHByaW9yX0VfQl9maXRfMXB4LA0KICBuaXR0ID0gMTAwMDAwLA0KICBidXJuaW4gPSAxMDAwMCwNCiAgdGhpbiA9IDEwMCwNCiAgdmVyYm9zZSA9IFRSVUUsDQogIHByID0gVFJVRSwNCiAgZGF0YSA9IGFzLmRhdGEuZnJhbWUoZGZfc3luZHJvbWUpDQogICkNCiMgc2F2ZVJEUyhtY21jX0VfQl9maXQsICJsZWFybl9QZXJzb25hbGl0eV9zdGF0c19tY21jX2ZpdC5vYmoiKQ0KYGBgDQoNCuWAi+WIpeino+iqrA0KDQpgYGANCiAgICBhdC5sZXZlbCh0cmFpdCwxKTpzY2FsZShhc3NheV9yZXAsIHNjYWxlID0gRkFMU0UpICsNCiAgICBhdC5sZXZlbCh0cmFpdCwyKTpzY2FsZShhc3NheV9yZXAsIHNjYWxlID0gRkFMU0UpICsNCmBgYA0KLSBgYXQubGV2ZWxgDQogIC0gc3BlY2lmeSB0aGF0IGZpeGVkIGVmZmVjdHMgYXJlIGVzdGltYXRlZCBvbmx5IGZvciBjZXJ0YWluIHRyYWl0cw0KICAgIC0g44GT44GT44Gn44Gv44CB5Y+N5b6p6KiI5risYGFzc2F5X3JlcGDjga7lvbHpn7/jgpLlj43lvqnoqIjmuKzjgZXjgozjgZ/lvaLos6rjgavlr77jgZfjgabjgaDjgZHoqr/jgbnjgabjgYTjgosNCiAgICAtIOS4gOaWueOAgee5sOOCiui/lOOBl+a4rOOBo+OBn+S9k+OCteOCpOOCuuOBruW9semfv+OBr+WFqOOBpuOBruW9ouizquOBq+WvvuOBl+OBpuiqv+OBueOBpuOBhOOCiw0KDQpgYGANCiAgcHIgPSBUUlVFLA0KYGBgDQotIOWQhOWAi+S9k+OBp+OBruODqeODs+ODgOODoOWKueaenO+8iElE77yJ44Gu5LqL5b6M5YiG5biD44KS5L+d5a2YDQogIC0gUkVNTOOBp+OBrkJMVVDjgavnm7jlvZMNCiAgLSBb5b6M44Gn5Y+v6KaW5YyWXSgjIyMgQkxVUOOBp+aVo+W4g+WbsykNCiAgLSDjgoHjgaPjgaHjgoPjg5XjgqHjgqTjg6vjgrXjgqTjgrrjg4fjgqvjgY/jgarjgosgKOOCguOBqOOCguOBqDwxTWLjga7jg6Ljg4fjg6vjgafjgoLjgIE+OE1i44Gr44Gq44KLKQ0KDQotLS0NCg0KIyMjIOe1kOaenA0KDQpgYGB7cn0NCm1jbWNfRV9CX2ZpdCA8LSByZWFkUkRTKCJsZWFybl9QZXJzb25hbGl0eV9zdGF0c19tY21jX2ZpdC5vYmoiKQ0KDQpzdW1tYXJ5KG1jbWNfRV9CX2ZpdCkNCmBgYA0KDQotIOWAi+S9k+WGheWIhuaVo++8iGB+fi51bml0c2DvvInjgavjgYrjgYTjgabjgIHpganlv5zluqbvvIgx5Zue6KiI5ris77yJ44GM6Zai44KP44Gj44Gm44GE44KL44KC44Gu77yIYHJlbF9maXRuZXNzOnJlbF9maXRuZXNzLnVuaXRzYO+8ieOBr+aMh+WumumAmuOCijAuMDAwMeOBq+WbuuWumuOBleOCjOOAgWVmZmVjdGl2ZSBzYW1wbGUgc2l6ZeOBrzDjgIINCg0KLSDpganlv5zluqbvvIgx5Zue6KiI5ris77yJ44GM6Zai44KP44Gj44Gm44GE44KL5YCL5L2T5YaF44Gu5YWx5YiG5pWj44Gv44Go44Gm44KC5bCP44GV44GP44CBZWZmZWN0aXZlIHNhbXBsZSBzaXpl44KC5bCP44GV44GP44Gq44Gj44Gm44GE44KL44Gv44GaDQoNCg0K6KGM5YuV44K344Oz44OJ44Ot44O844Og44GM5Lul5YmN44Gu44Oi44OH44Or44Go6L+R44GE5YCk44Gr44Gq44Gj44Gm44GE44KL44GL56K66KqNDQoNCmBgYHtyfQ0KbWNtY19FX0JfZml0X2Nvcl9FQiA8LSBtY21jX0VfQl9maXQkVkNWWywidHJhaXRib2xkbmVzczp0cmFpdGV4cGxvcmF0aW9uLklEIl0vDQogIChzcXJ0KG1jbWNfRV9CX2ZpdCRWQ1ZbLCJ0cmFpdGJvbGRuZXNzOnRyYWl0Ym9sZG5lc3MuSUQiXSkqDQogICAgIHNxcnQobWNtY19FX0JfZml0JFZDVlssInRyYWl0ZXhwbG9yYXRpb246dHJhaXRleHBsb3JhdGlvbi5JRCJdKSkNCg0KbWVhbihtY21jX0VfQl9maXRfY29yX0VCKQ0KSFBEaW50ZXJ2YWwobWNtY19FX0JfZml0X2Nvcl9FQikNCmBgYA0KDQrpganlv5zluqbjgajooYzli5XlvaLos6rjga7nm7jplqLjgpLmir3lh7oNCg0KYGBge3J9DQptY21jX0VfQl9maXRfY29yX0VmaXQgPC0gbWNtY19FX0JfZml0JFZDVlssInRyYWl0cmVsX2ZpdG5lc3M6dHJhaXRleHBsb3JhdGlvbi5JRCJdLw0KICAoc3FydChtY21jX0VfQl9maXQkVkNWWywidHJhaXRyZWxfZml0bmVzczp0cmFpdHJlbF9maXRuZXNzLklEIl0pKg0KICAgICBzcXJ0KG1jbWNfRV9CX2ZpdCRWQ1ZbLCJ0cmFpdGV4cGxvcmF0aW9uOnRyYWl0ZXhwbG9yYXRpb24uSUQiXSkpDQoNCm1jbWNfRV9CX2ZpdF9jb3JfQmZpdCA8LSBtY21jX0VfQl9maXQkVkNWWywidHJhaXRyZWxfZml0bmVzczp0cmFpdGJvbGRuZXNzLklEIl0vDQogIChzcXJ0KG1jbWNfRV9CX2ZpdCRWQ1ZbLCJ0cmFpdHJlbF9maXRuZXNzOnRyYWl0cmVsX2ZpdG5lc3MuSUQiXSkqDQogICAgIHNxcnQobWNtY19FX0JfZml0JFZDVlssInRyYWl0Ym9sZG5lc3M6dHJhaXRib2xkbmVzcy5JRCJdKSkNCmBgYA0KDQrlvaLos6rnm7jplqLjgpLlm7PnpLoNCg0KYGBge3IsIGZpZy5oZWlnaHQgPSAzfQ0KDQpkZl9tY21jX2NvcnMgPC0gZGF0YV9mcmFtZSgNCiAgVHJhaXRzID0gYygNCiAgICAiRXhwbG9yYXRpb24sIEJvbGRuZXNzIiwgIkV4cGxvcmF0aW9uLCBGaXRuZXNzIiwgIkJvbGRuZXNzLCBGaXRuZXNzIg0KICAgICksDQogIEVzdGltYXRlID0gYygNCiAgICBtZWFuKG1jbWNfRV9CX2ZpdF9jb3JfRUIpLA0KICAgIG1lYW4obWNtY19FX0JfZml0X2Nvcl9FZml0KSwNCiAgICBtZWFuKG1jbWNfRV9CX2ZpdF9jb3JfQmZpdCkNCiAgICApLA0KICBMb3dlciA9IGMoDQogICAgSFBEaW50ZXJ2YWwobWNtY19FX0JfZml0X2Nvcl9FQilbLCJsb3dlciJdLA0KICAgIEhQRGludGVydmFsKG1jbWNfRV9CX2ZpdF9jb3JfRWZpdClbLCJsb3dlciJdLA0KICAgIEhQRGludGVydmFsKG1jbWNfRV9CX2ZpdF9jb3JfQmZpdClbLCJsb3dlciJdDQogICAgKSwNCiAgVXBwZXIgPSBjKA0KICAgIEhQRGludGVydmFsKG1jbWNfRV9CX2ZpdF9jb3JfRUIpWywidXBwZXIiXSwNCiAgICBIUERpbnRlcnZhbChtY21jX0VfQl9maXRfY29yX0VmaXQpWywidXBwZXIiXSwNCiAgICBIUERpbnRlcnZhbChtY21jX0VfQl9maXRfY29yX0JmaXQpWywidXBwZXIiXQ0KICAgICkNCiAgKQ0KDQpnZ3Bsb3QoZGZfbWNtY19jb3JzLCBhZXMoeCA9IFRyYWl0cywgeSA9IEVzdGltYXRlKSkgKw0KICBnZW9tX3BvaW50cmFuZ2UoYWVzKHltaW4gPSBMb3dlciwgeW1heCA9IFVwcGVyKSkgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkb3R0ZWQiKSArDQogIHNjYWxlX3hfZGlzY3JldGUoDQogICAgbGltaXRzID0gYygiQm9sZG5lc3MsIEZpdG5lc3MiLCAiRXhwbG9yYXRpb24sIEZpdG5lc3MiLCANCiAgICAgICAgICAgICAgICJFeHBsb3JhdGlvbiwgQm9sZG5lc3MiKQ0KICAgICkgKw0KICBsYWJzKHggPSAiVHJhaXQgY29tYmluYXRpb25zIiwNCiAgICAgICB5ID0gIkNvcnJlbGF0aW9uIChFc3RpbWF0ZSDCsTk1JSBDSXMpIikgKw0KICB5bGltKC0xLDEpICsNCiAgY29vcmRfZmxpcCgpDQoNCmBgYA0KDQotLS0NCjxkaXYgc3R5bGU9Im1hcmdpbi1ib3R0b206NjBweDsiPg0KPC9kaXY+DQoNCiMjIyBCTFVQ44Gn5pWj5biD5ZuzDQoNCuODqeODs+ODgOODoOWKueaenOOBrnBvc3RlcmlvciBtb2RlcyAoQkxVUHMgZnJvbSB0aGUgTUNNQ2dsbW0gbW9kZWwpIOOCkkZ1bGwtbW9kZWzjgYvjgonmir3lh7rjgZfjgIHlgIvmgKflvaLos6rjgajpganlv5zluqbjga7plqLkv4LjgpLlm7PnpLrjgILlm7PnpLrjga7jgZ/jgoHjgatCTFVQ44KS5L2/44GG44Gu44GvT0sNCg0KDQojIyMjIOWAi+aAp+OBqOmBqeW/nOW6puOBruWAi+S9k+avjuOBrueCueaOqOWumuOCkuWPluOCiuWHuuOBmQ0KDQrjgZPjgZPjgafjga9Cb2xkbmVzc+ODvOmBqeW/nOW6puOBrumWoumAo+OCkuiqv+OBueOCiw0KDQpgYGB7cn0NCmRmX2JmX2NvZWZzIDwtIGRhdGFfZnJhbWUoDQogICMgU2FtZSBhcyB3cml0aW5nIGFzOiBuYW1lcyhjb2xNZWFucyhtY21jX0VfQl9maXQkU29sKSkNCiAgVHJhaXQgPSBhdHRyKGNvbE1lYW5zKG1jbWNfRV9CX2ZpdCRTb2wpLCAibmFtZXMiKSwNCiAgIyAkU29s44Gr44Gv77yR5bGe5oCn5b2T44Gf44KK77yU44Gk44Gu5YCk44GM5qC857SN44GV44KM44Gm44GE44KL44CC44Gq44KT44Gg44GT44KM44Gv77yfDQogICMg44GT44GT44Gn44GvY29NZWFuc+OBpzTjgaTjga7lgKTjga7lubPlnYfjgpLlj5bjgaPjgabku4rlvozjga7liIbmnpDjgavkvb/jgYYNCiAgVmFsdWUgPSBjb2xNZWFucyhtY21jX0VfQl9maXQkU29sKQ0KICApICU+JQ0KICAjIOOBk+OBruaZgueCueOBp+OBr+WFqOOBpuOBrumgheebruOBruaOqOWumuWApOOBjOOBvuOBnOOBk+OBnOOBqzHliJfjgavkuKbjgpPjgafjgYTjgosNCiAgIyBCTFVQ44Gv5L6L44GI44Gw5Lul5LiL44Gu44KI44GG44Gr5qC857SN44GV44KM44Gm44GE44KL77ya44CAdHJhaXRleHBsb3JhdGlvbi5JRC5TXzENCiAgIyDjgZPjgozjgpIiLiLjgafliIblibINCiAgc2VwYXJhdGUoVHJhaXQsIGMoIlRyYWl0IiwiVHlwZSIsIklEIiksIHNlcCA9ICJcXC4iLCBmaWxsID0gInJpZ2h0IikgJT4lDQogIGZpbHRlcigNCiAgICAjIElE5YiX44Gr5YCk44GM44GC44KL44Gu44Gv5YCL5L2T5q+O44Gu5o6o5a6a5YCk44Gg44GR44CC44GT44KM44KS5Y+W44KK5Ye644GZDQogICAgVHlwZSA9PSAiSUQiLA0KICAgICMg44GT44GT44Gn44GvYm9sZG5lc3PjgajjgIHnm7jlr77pganlv5zluqbjgpLlj5bjgorlh7rjgZkNCiAgICBUcmFpdCAlaW4lIGMoInRyYWl0Ym9sZG5lc3MiLCAidHJhaXRyZWxfZml0bmVzcyIpDQogICAgKSAlPiUNCiAgc2VsZWN0KC1UeXBlKSAlPiUNCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IFRyYWl0LCB2YWx1ZXNfZnJvbSA9IFZhbHVlKQ0KYGBgDQoNCiMjIyMg5Zue5biw55u057ea44KS5b6X44KLDQoNCi0gQm9sZG5lc3Pjgavlr77jgZnjgovnm7jlr77pganlv5zluqbjgpLlgr7jgY0NCiAgLSAkXGZyYWN7Ym9sZG5lc3Pjgajnm7jlr77pganlv5zluqbjga7lhbHliIbmlaN9e2JvbGRuZXNz44Gu5YiG5pWjfSQNCg0KYGBge3J9DQpCX2ZpdF9zbG9wZSA8LSBtY21jX0VfQl9maXQkVkNWWywidHJhaXRyZWxfZml0bmVzczp0cmFpdGJvbGRuZXNzLklEIl0vDQogIG1jbWNfRV9CX2ZpdCRWQ1ZbLCJ0cmFpdGJvbGRuZXNzOnRyYWl0Ym9sZG5lc3MuSUQiXQ0KYGBgDQoNCuWbs+ekug0KDQpgYGB7cn0NCg0KZ2dwbG90KGRmX2JmX2NvZWZzLCBhZXMoeCA9IHRyYWl0Ym9sZG5lc3MsIHkgPSB0cmFpdHJlbF9maXRuZXNzLCBncm91cCA9IElEKSkgKw0KICBnZW9tX3BvaW50KGFscGhhID0gMC43KSArDQogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gbWVhbihCX2ZpdF9zbG9wZSkpICsNCiAgbGFicygNCiAgICB4ID0gIkJvbGRuZXNzIChCTFVQKSIsDQogICAgeSA9ICJSZWxhdGl2ZSBmaXRuZXNzIChCTFVQKSINCiAgICApDQoNCmBgYA0KDQotLS0NCg0KPGRpdiBzdHlsZT0ibWFyZ2luLWJvdHRvbTo5MHB4OyI+DQo8L2Rpdj4NCg0KIyBgYnJtc2AgOiBNaXRjaGVsbCBldCBhbCANCg0KW0RhdmlkIE1pdGNoZWxsLCBDaHJpc3RhIEJlY2ttYW5uLCBQZXRlciBBIEJpcm86IFN1cHBsZW1lbnRdKGh0dHBzOi8vb3NmLmlvL2o3dmJyLykNCg0KIyMgYGJybXNg44Go44GvDQoNClvmpoLopoE6IELDvHJrbmVyIDIwMTddKGh0dHBzOi8vd3d3LnJlc2VhcmNoZ2F0ZS5uZXQvcHVibGljYXRpb24vMzE5MzM3MjIzX2JybXNfQW5fUl9QYWNrYWdlX2Zvcl9CYXllc2lhbl9NdWx0aWxldmVsX01vZGVsc19Vc2luZ19TdGFuKQ0KDQotIEJheWVzaWFuIG11bHRpbGV2ZWwgbW9kZWzjgpLmibHjgYYNCi0gU3RhbiwgQysr44KS57WM55SxDQoNCmBNQ01DZ2xtbWDjgajjga7mr5TovIMNCg0KMS4g44CH6KSH5pWw44Gu44Oe44Or44Kz44OV6YCj6Y6W44KS6LWw44KJ44Gb44KM44KLDQoxLiDjgIflhbHliIbmlaPjga7kuovliY3liIbluIPjgYzmn5Tou5/jgavmjIflrprjgafjgY3jgosNCjEuIOOAh0xpbmvplqLmlbDjgYzmn5Tou58NCjEuIOOAh1JvYnVzdCBsaW5lYXIgbW9kZWxz44GM44Gn44GN44KLDQoNCuOBquOBqeOAguWIqeeCueOBr+OBneOCjOOBquOCiuOBq+WkmuOBhOOBjO+8iOeJueOBq+KRoO+8ieOAgeWVj+mhjOOBr+OBneOCjOOCkuaJseOBiOOCi+OBiy4uLuOAgg0KDQrjgb7jgYJgTUNNQ2dsbW1g44Gn44GE44GE44GL44CCDQoNCi0tLQ0KDQo8ZGl2IHN0eWxlPSJtYXJnaW4tYm90dG9tOjYwcHg7Ij4NCjwvZGl2Pg0KDQojIH5+QVNSZW1sLVJ+fg0KDQpBdm9pZCB0aGlzIGJlY2F1c2UgaXQncyBbbm90IGZyZWVdKGh0dHBzOi8vd3d3LmlldS51emguY2gvZW4vc3RhZmYvbWVtYmVyL25pa2xhdXNfcGFzY2FsL0FTUmVtbC5odG1sKQ==