Aufgabe

Wir haben keine Normalverteilung oder wir kennen die Verteilung nicht. Wir müssen einen Wert (Mittelwert, Median,SD oder ein Perzentil) der Grundgesamtheit und sein Konfidenzintervall schätzen. Wie können wir das tun?

Beschreibung der Methode Bootstrap

Das Bootstrapping-Verfahren ist in der Statistik eine Methode des Resampling, das heißt aus den gegebenen Daten werden wiederholt Stichproben gezogen. Der Vorteil von Bootstrapping ist, dass diese Methode keine Verteilungsannahme trifft. Es handelt sich also um ein non-parametrisches Verfahren und kann auch angewandt werden, wenn Normalverteilungsannahmen des Modells nicht oder nur zweifelhaft erfüllt sind. Des Weiteren ist es ein robuster, einfacher Computer-Algorithmus.

Es gibt viele Bootstrap-Verfahren, unter anderem Bayesian Bootstrap, Smooth Bootstrap, Parametric Bootstrap, Residual Bootstrap, Gaussian process regression Bootstrap, Wild Bootstrap, Block Bootstrap.

Der grundlegende Prozess für das Bootstrapping ist wie folgt:

Nehmen Sie k wiederholte Proben mit Ersatz aus einem bestimmten Datensatz. Berechnen Sie für jede Stichprobe die Statistik, an der Sie interessiert sind. Dies führt zu k verschiedenen Schätzungen für eine bestimmte Statistik, mit denen Sie dann den Standardfehler der Statistik berechnen und ein Konfidenzintervall für die Statistik erstellen können.

Voraussetzungen

Variable “residual.sugar” - metrisch

Histogramm

hist_plot(wine_all,'residual.sugar', bins=100)

Es ist offensichtlich, dass es in diesem Fall keine Normalverteilung gibt.

Deskriptive Statistiken

Ohne Gruppirung

describe(wine_all$residual.sugar)

Für residual.sugar der Mittelwert liegt bei 5.44, SD=4.76, n=6497

Basic Bootstrap

Erstellen wir eine Funktion, die eine Zufallsstichprobe aus unserer Stichprobe zieht und deren Mittelwert und sein 95% KI berechnet.

mean_generator <- function(population, n){
  sample <- sample(population, #unsere ursprüngliche Stichprobe
                   n,# die Größe einer Zufallsstichprobe
                   replace = T) # mit Zurücklegen 
  mean(sample, na.rm = T)
  }

Wiederholung der Zufallsstichprobe aus der Stichprobe und Speicherung der Mittelwerte dieser Zufallsstichprobe.

means_distribution <- numeric(0)
x <- wine_all$residual.sugar

for (i in 1:2000) {
  mean_basic <- mean(x)
  mean_sample <- mean_generator(x, floor(length(x)*0.6))
  means_distribution <- c(means_distribution, mean_sample)
}
bounds <- quantile(means_distribution, probs=c(0.025,0.975))
sprintf("Die Mittelwert der Stichprobe = %.4f ", mean_basic)
[1] "Die Mittelwert der Stichprobe = 5.4432 "
print("Das KI befindet sich im folgenden Wertebereich zu 95% der wahre Mittelwert der Grundgesamtheit:")
[1] "Das KI befindet sich im folgenden Wertebereich zu 95% der wahre Mittelwert der Grundgesamtheit:"
bounds
    2.5%    97.5% 
5.297316 5.592838 

Visualisieren der Berechnung von Mittelwerten für unsere Stichproben:

means_distribution <- data.frame(means_distribution)
hist_plot(means_distribution, 'means_distribution')

Es ist zu erkennen, dass die Mittelwerte der Stichproben normal verteilt sind.

Mit Hilfe boot-Bibliothek

library(boot)
# Bootstrapping mit  Replikationen durchführen
samplemean <- function(x, d) {
  return(mean(x[d], na.rm = T))
}

reps <- boot(x, statistic= samplemean, R=2000)
# Ergebnisse des Boostrappings anzeigen
boot_means <- data.frame('boot_means'= reps$t)
hist_plot(boot_means,'boot_means')

Es ist zu erkennen, dass die Mittelwerte der Stichproben normal verteilt sind.

#95% KI  berechnen
print("Das KI befindet sich im folgenden Wertebereich zu 95% der wahre Mittelwert der Grundgesamtheit:")
[1] "Das KI befindet sich im folgenden Wertebereich zu 95% der wahre Mittelwert der Grundgesamtheit:"
quantile(reps$t, c(0.025, 0.975))
    2.5%    97.5% 
5.323493 5.557901 

Eine Aussage

Es gibt einen Unterschied in den Intervallgrenzen zwischen der selbst geschriebenen Funktion ( 95% KI : [5.298173 ,5.590283] ) und der Bibliothek (95% KI:[5.328805, 5.557393]), da die Bibliothek einen fortgeschrittenen mathematischen Algorithmus verwendet, der es ermöglicht, die Intervallgrenzen im Allgemeinen zu verengen.

Aufgabe 2

Unterscheiden sich die Mittelwerte des “residual.sugar” zwischen Weiß- und Rotwein signifikant?

Hypothesen

  • H0: Es gibt keinen Unterscheid in den Mittelwerten des “residual.sugar” zwischen Weiß- und Rotwein.

  • H1: Es gibt einen Unterscheid in den Mittelwerten des “residual.sugar” zwischen Weiß- und Rotwein.

Wie werden Hypothesen mit einem Bootstrap getestet?

    1. Bootstrap-Verteilungen der Parameter in A und B werden erstellt
    1. Dann wird deren Differenz (Matrixsubtraktion) berechnet
    1. Das Konfidenzintervall Intervall wird dann berechnet
    1. Es muss geprüft werden, ob das Konfidenzintervall auf 0 fällt, und wenn ja, dann die Nullhypothese wird bei einem bestimmten Signifikanzniveau beibehalten.

Histogramm

g1 <-hist_plot(wine_all[wine_all$color=='white',],'residual.sugar', 
               fill = '#eda1ba')+
    xlab('White')
g2 <- hist_plot(wine_all[wine_all$color=='red',],'residual.sugar')+
    xlab('Red')
grid.arrange(arrangeGrob(g1, g2, ncol=2),nrow = 1) 

Es ist offensichtlich, dass es in diesem Fall keine Normalverteilung gibt.

Deskriptive Statistiken

table <- describeBy(wine_all$residual.sugar, group = wine_all$color, mat = T, digits = 4)
table[1:6]

Im Mittel liegt die Variable residual.sugar :

Rotwein: M = 2.5388, SD = 1.4099, n = 1599 Weißwein: M = 6.3914, SD = 5.0721, n = 4898

Basic Bootstrap

# Erstellung der Subsets
red_subset <- wine_all[wine_all$color=='red',]
white_subset <- wine_all[wine_all$color=='white',]
#View(white_subset)

samplemean <- function(x, d) {
  return(mean(x[d], na.rm = T))
}

reps_red <- boot(red_subset$residual.sugar, statistic= samplemean, R=2000)
reps_white <-boot(white_subset$residual.sugar, statistic= samplemean, R=2000)

Ergebnisse des Boostrappings anzeigen mittels Histogramms


boot_means_red <- data.frame('boot_means_red'= reps_red$t)
boot_means_white <- data.frame('boot_means_white'= reps_white$t)

g1 <- hist_plot(boot_means_red,'boot_means_red')
g2 <- hist_plot(boot_means_white,'boot_means_white')

grid.arrange(arrangeGrob(g1,g2, ncol=2), nrow=1)

Offensichtlich eine Normalverteilung

diff_means <- boot_means_red$boot_means - boot_means_white$boot_means
print('95% KI')
[1] "95% KI"
quantile(diff_means, c(0.025, 0.975))
     2.5%     97.5% 
-4.011194 -3.699677 

Eine Aussage

Es gibt einen deutlichen Unterschied in den Mittelwerten von Zucker zwischen Rot ( M = 2.5388, SD = 1.4099, n = 1599)- und Weißweinen (M = 6.3914, SD = 5.0721, n = 4898)
Das 95% Konfidenzintervall vom Differenz der Mittelwerten ([-4.166267; -3.626046 ])auf 0 nicht fällt, deswegen kann H0 verworfen werden.

LS0tDQp0aXRsZTogIkJvb3RzdHJhcHBpbmctVmVyZmFocmVuIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCmBgYHtyIHdhcm5pbmc9IEZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlY2hvPUZBTFNFfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoY2FyKQ0KbGlicmFyeShwc3ljaCkNCmBgYA0KDQpgYGB7ciB3YXJuaW5nPSBGQUxTRSwgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0NCndpbmVfYWxsIDwtIHJlYWQuY3N2KCd3aW5lX2FsbC5jc3YnKQ0KYGBgDQoNCiMjIEF1ZmdhYmUNCg0KV2lyIGhhYmVuIGtlaW5lIE5vcm1hbHZlcnRlaWx1bmcgb2RlciB3aXIga2VubmVuIGRpZSBWZXJ0ZWlsdW5nIG5pY2h0LiBXaXIgbcO8c3NlbiBlaW5lbiBXZXJ0IChNaXR0ZWx3ZXJ0LCBNZWRpYW4sU0Qgb2RlciBlaW4gUGVyemVudGlsKSBkZXIgR3J1bmRnZXNhbXRoZWl0IHVuZCBzZWluIEtvbmZpZGVuemludGVydmFsbCBzY2jDpHR6ZW4uICBXaWUga8O2bm5lbiB3aXIgZGFzIHR1bj8NCg0KIyMgQmVzY2hyZWlidW5nIGRlciBNZXRob2RlIEJvb3RzdHJhcA0KDQpEYXMgQm9vdHN0cmFwcGluZy1WZXJmYWhyZW4gaXN0IGluIGRlciBTdGF0aXN0aWsgZWluZSBNZXRob2RlIGRlcyBSZXNhbXBsaW5nLA0KZGFzIGhlacOfdCBhdXMgZGVuIGdlZ2ViZW5lbiBEYXRlbiB3ZXJkZW4gd2llZGVyaG9sdCBTdGljaHByb2JlbiBnZXpvZ2VuLg0KRGVyIFZvcnRlaWwgdm9uIEJvb3RzdHJhcHBpbmcgaXN0LCBkYXNzIGRpZXNlIE1ldGhvZGUga2VpbmUgVmVydGVpbHVuZ3Nhbm5haG1lIHRyaWZmdC4gRXMgaGFuZGVsdCBzaWNoIGFsc28gdW0gZWluIG5vbi1wYXJhbWV0cmlzY2hlcyBWZXJmYWhyZW4gdW5kIGthbm4gYXVjaCBhbmdld2FuZHQgd2VyZGVuLCB3ZW5uIE5vcm1hbHZlcnRlaWx1bmdzYW5uYWhtZW4gZGVzIE1vZGVsbHMgbmljaHQgb2RlciBudXIgendlaWZlbGhhZnQgZXJmw7xsbHQgc2luZC4gRGVzIFdlaXRlcmVuIGlzdCBlcyBlaW4gcm9idXN0ZXIsIGVpbmZhY2hlciBDb21wdXRlci1BbGdvcml0aG11cy4NCg0KRXMgZ2lidCB2aWVsZSBCb290c3RyYXAtVmVyZmFocmVuLCB1bnRlciBhbmRlcmVtIEJheWVzaWFuIEJvb3RzdHJhcCwgU21vb3RoIEJvb3RzdHJhcCwgUGFyYW1ldHJpYyBCb290c3RyYXAsIFJlc2lkdWFsIEJvb3RzdHJhcCwgR2F1c3NpYW4gcHJvY2VzcyByZWdyZXNzaW9uIEJvb3RzdHJhcCwgV2lsZCBCb290c3RyYXAsIEJsb2NrIEJvb3RzdHJhcC4NCg0KRGVyIGdydW5kbGVnZW5kZSBQcm96ZXNzIGbDvHIgZGFzIEJvb3RzdHJhcHBpbmcgaXN0IHdpZSBmb2xndDoNCg0KTmVobWVuIFNpZSBrIHdpZWRlcmhvbHRlIFByb2JlbiBtaXQgRXJzYXR6IGF1cyBlaW5lbSBiZXN0aW1tdGVuIERhdGVuc2F0ei4NCkJlcmVjaG5lbiBTaWUgZsO8ciBqZWRlIFN0aWNocHJvYmUgZGllIFN0YXRpc3RpaywgYW4gZGVyIFNpZSBpbnRlcmVzc2llcnQgc2luZC4NCkRpZXMgZsO8aHJ0IHp1IGsgdmVyc2NoaWVkZW5lbiBTY2jDpHR6dW5nZW4gZsO8ciBlaW5lIGJlc3RpbW10ZSBTdGF0aXN0aWssIG1pdCBkZW5lbiBTaWUgZGFubiBkZW4gU3RhbmRhcmRmZWhsZXIgZGVyIFN0YXRpc3RpayBiZXJlY2huZW4gdW5kIGVpbiBLb25maWRlbnppbnRlcnZhbGwgZsO8ciBkaWUgU3RhdGlzdGlrIGVyc3RlbGxlbiBrw7ZubmVuLg0KDQojIyBWb3JhdXNzZXR6dW5nZW4NCg0KKyBkaWUgU3RpY2hwcm9iZSBpc3QgcmVwcsOkc2VudGF0aXYgZsO8ciBkaWUgR3J1bmRnZXNhbXRoZWl0Lg0KKyBnZW7DvGdlbmRlIFN0aWNocHJvYmVuZ3LDtsOfZSAtPiBlcyBtw7xzc2VuIHZpZWxlIFRlaWxzdGljaHByb2JlbiBnZXpvZ2VuIHdlcmRlbiAoaW4gZGVyIFJlZ2VsIG1pbmRlc3RlbnMgMTAwMCBtYWwpDQoNCioqVmFyaWFibGUqKg0KInJlc2lkdWFsLnN1Z2FyIiAtIG1ldHJpc2NoDQoNCioqSGlzdG9ncmFtbSoqDQoNCmBgYHtyIHdhcm5pbmc9IEZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlY2hvPUZBTFNFfQ0KIyBlaW5lIEZ1bmt0aW9uIGZ1ZXIgSGlzdG9ncmFtbQ0KaGlzdF9wbG90IDwtIGZ1bmN0aW9uKGRhdGEsIGNvbHVtbiwgYmlucz0xMDAsIGZpbGw9IiM2OWIzYTIiKXsNCiAgICAgIGdncGxvdChkYXRhLGFlcyh4PWRhdGFbLGNvbHVtbl0pKSArDQogICAgICAgIGdlb21faGlzdG9ncmFtKGJpbnM9YmlucywNCiAgICAgICAgICAgICAgICAgICAgIGFlcyh5PS4uZGVuc2l0eS4uKSwNCiAgICAgICAgICAgICAgICAgICAgIGZpbGw9ZmlsbCwNCiAgICAgICAgICAgICAgICAgICAgICNjb2xvcj0iI2U5ZWNlZiIsIA0KICAgICAgICAgICAgICAgICAgICAgYWxwaGE9MC45KSArDQogICAgICBnZW9tX2RlbnNpdHkoY29sb3I9InJlZCIpKw0KICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikrDQogICAgICB4bGFiKGNvbHVtbikrDQogICAgICBzdGF0X2Z1bmN0aW9uKGZ1biA9IGRub3JtLCANCiAgICAgICAgICAgICAgICAgICAgYXJncyA9IGxpc3QobWVhbiA9IG1lYW4oZGF0YVssY29sdW1uXSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZCA9IHNkKGRhdGFbLGNvbHVtbl0pKSkNCiAgfQ0KDQpgYGANCg0KYGBge3J9DQpoaXN0X3Bsb3Qod2luZV9hbGwsJ3Jlc2lkdWFsLnN1Z2FyJywgYmlucz0xMDApDQpgYGANCkVzIGlzdCBvZmZlbnNpY2h0bGljaCwgZGFzcyBlcyBpbiBkaWVzZW0gRmFsbCBrZWluZSBOb3JtYWx2ZXJ0ZWlsdW5nIGdpYnQuDQoNCiMjIyBEZXNrcmlwdGl2ZSBTdGF0aXN0aWtlbiANCg0KKipPaG5lIEdydXBwaXJ1bmcqKg0KDQpgYGB7cn0NCmRlc2NyaWJlKHdpbmVfYWxsJHJlc2lkdWFsLnN1Z2FyKQ0KYGBgDQpGw7xyICoqcmVzaWR1YWwuc3VnYXIqKiBkZXIgTWl0dGVsd2VydCBsaWVndCBiZWkgNS40NCwgU0Q9NC43Niwgbj02NDk3DQoNCg0KIyMjIEJhc2ljIEJvb3RzdHJhcA0KDQpFcnN0ZWxsZW4gd2lyIGVpbmUgRnVua3Rpb24sIGRpZSBlaW5lIFp1ZmFsbHNzdGljaHByb2JlIGF1cyB1bnNlcmVyIFN0aWNocHJvYmUgemllaHQgdW5kIGRlcmVuIE1pdHRlbHdlcnQgdW5kIHNlaW4gOTUlIEtJIGJlcmVjaG5ldC4NCg0KYGBge3J9DQptZWFuX2dlbmVyYXRvciA8LSBmdW5jdGlvbihwb3B1bGF0aW9uLCBuKXsNCiAgc2FtcGxlIDwtIHNhbXBsZShwb3B1bGF0aW9uLCAjdW5zZXJlIHVyc3Byw7xuZ2xpY2hlIFN0aWNocHJvYmUNCiAgICAgICAgICAgICAgICAgICBuLCMgZGllIEdyw7bDn2UgZWluZXIgWnVmYWxsc3N0aWNocHJvYmUNCiAgICAgICAgICAgICAgICAgICByZXBsYWNlID0gVCkgIyBtaXQgWnVyw7xja2xlZ2VuIA0KICBtZWFuKHNhbXBsZSwgbmEucm0gPSBUKQ0KICB9DQpgYGANCg0KV2llZGVyaG9sdW5nIGRlciBadWZhbGxzc3RpY2hwcm9iZSBhdXMgZGVyIFN0aWNocHJvYmUgdW5kIFNwZWljaGVydW5nIGRlciBNaXR0ZWx3ZXJ0ZSBkaWVzZXIgWnVmYWxsc3N0aWNocHJvYmUuDQpgYGB7cn0NCm1lYW5zX2Rpc3RyaWJ1dGlvbiA8LSBudW1lcmljKDApDQp4IDwtIHdpbmVfYWxsJHJlc2lkdWFsLnN1Z2FyDQoNCmZvciAoaSBpbiAxOjIwMDApIHsNCiAgbWVhbl9iYXNpYyA8LSBtZWFuKHgpDQogIG1lYW5fc2FtcGxlIDwtIG1lYW5fZ2VuZXJhdG9yKHgsIGZsb29yKGxlbmd0aCh4KSowLjYpKQ0KICBtZWFuc19kaXN0cmlidXRpb24gPC0gYyhtZWFuc19kaXN0cmlidXRpb24sIG1lYW5fc2FtcGxlKQ0KfQ0KYGBgDQoNCmBgYHtyfQ0KYm91bmRzIDwtIHF1YW50aWxlKG1lYW5zX2Rpc3RyaWJ1dGlvbiwgcHJvYnM9YygwLjAyNSwwLjk3NSkpDQpzcHJpbnRmKCJEaWUgTWl0dGVsd2VydCBkZXIgU3RpY2hwcm9iZSA9ICUuNGYgIiwgbWVhbl9iYXNpYykNCnByaW50KCJEYXMgS0kgYmVmaW5kZXQgc2ljaCBpbSBmb2xnZW5kZW4gV2VydGViZXJlaWNoIHp1IDk1JSBkZXIgd2FocmUgTWl0dGVsd2VydCBkZXIgR3J1bmRnZXNhbXRoZWl0OiIpDQpib3VuZHMNCmBgYA0KVmlzdWFsaXNpZXJlbiAgZGVyIEJlcmVjaG51bmcgdm9uIE1pdHRlbHdlcnRlbiBmw7xyIHVuc2VyZSBTdGljaHByb2JlbjoNCmBgYHtyfQ0KbWVhbnNfZGlzdHJpYnV0aW9uIDwtIGRhdGEuZnJhbWUobWVhbnNfZGlzdHJpYnV0aW9uKQ0KaGlzdF9wbG90KG1lYW5zX2Rpc3RyaWJ1dGlvbiwgJ21lYW5zX2Rpc3RyaWJ1dGlvbicpDQpgYGANCkVzIGlzdCB6dSBlcmtlbm5lbiwgZGFzcyBkaWUgTWl0dGVsd2VydGUgZGVyIFN0aWNocHJvYmVuIG5vcm1hbCB2ZXJ0ZWlsdCBzaW5kLg0KDQojIyMgTWl0IEhpbGZlIGJvb3QtQmlibGlvdGhlaw0KYGBge3J9DQpsaWJyYXJ5KGJvb3QpDQpgYGANCg0KYGBge3J9DQojIEJvb3RzdHJhcHBpbmcgbWl0ICBSZXBsaWthdGlvbmVuIGR1cmNoZsO8aHJlbg0Kc2FtcGxlbWVhbiA8LSBmdW5jdGlvbih4LCBkKSB7DQogIHJldHVybihtZWFuKHhbZF0sIG5hLnJtID0gVCkpDQp9DQoNCnJlcHMgPC0gYm9vdCh4LCBzdGF0aXN0aWM9IHNhbXBsZW1lYW4sIFI9MjAwMCkNCg0KYGBgDQpgYGB7cn0NCiMgRXJnZWJuaXNzZSBkZXMgQm9vc3RyYXBwaW5ncyBhbnplaWdlbg0KYm9vdF9tZWFucyA8LSBkYXRhLmZyYW1lKCdib290X21lYW5zJz0gcmVwcyR0KQ0KaGlzdF9wbG90KGJvb3RfbWVhbnMsJ2Jvb3RfbWVhbnMnKQ0KYGBgDQpFcyBpc3QgenUgZXJrZW5uZW4sIGRhc3MgZGllIE1pdHRlbHdlcnRlIGRlciBTdGljaHByb2JlbiBub3JtYWwgdmVydGVpbHQgc2luZC4NCg0KYGBge3J9DQojOTUlIEtJICBiZXJlY2huZW4NCnByaW50KCJEYXMgS0kgYmVmaW5kZXQgc2ljaCBpbSBmb2xnZW5kZW4gV2VydGViZXJlaWNoIHp1IDk1JSBkZXIgd2FocmUgTWl0dGVsd2VydCBkZXIgR3J1bmRnZXNhbXRoZWl0OiIpDQpxdWFudGlsZShyZXBzJHQsIGMoMC4wMjUsIDAuOTc1KSkNCmBgYA0KIyMjIEVpbmUgQXVzc2FnZQ0KDQpFcyBnaWJ0IGVpbmVuIFVudGVyc2NoaWVkIGluIGRlbiBJbnRlcnZhbGxncmVuemVuIHp3aXNjaGVuIGRlciBzZWxic3QgZ2VzY2hyaWViZW5lbiBGdW5rdGlvbiAoIDk1JSBLSSA6IFs1LjI5ODE3MyAsNS41OTAyODNdICkgdW5kIGRlciBCaWJsaW90aGVrICg5NSUgS0k6WzUuMzI4ODA1LCA1LjU1NzM5M10pLCBkYSBkaWUgQmlibGlvdGhlayBlaW5lbiBmb3J0Z2VzY2hyaXR0ZW5lbiBtYXRoZW1hdGlzY2hlbiBBbGdvcml0aG11cyB2ZXJ3ZW5kZXQsIGRlciBlcyBlcm3DtmdsaWNodCwgZGllIEludGVydmFsbGdyZW56ZW4gaW0gQWxsZ2VtZWluZW4genUgdmVyZW5nZW4uDQoNCiMjIyBBdWZnYWJlIDINCg0KVW50ZXJzY2hlaWRlbiBzaWNoIGRpZSBNaXR0ZWx3ZXJ0ZSBkZXMgInJlc2lkdWFsLnN1Z2FyIiB6d2lzY2hlbiBXZWnDny0gdW5kIFJvdHdlaW4gc2lnbmlmaWthbnQ/DQoNCiMjIyBIeXBvdGhlc2VuDQoNCisgSDA6IEVzIGdpYnQga2VpbmVuIFVudGVyc2NoZWlkIGluIGRlbiBNaXR0ZWx3ZXJ0ZW4gZGVzICJyZXNpZHVhbC5zdWdhciIgendpc2NoZW4gV2Vpw58tIHVuZCBSb3R3ZWluLg0KDQorIEgxOiBFcyBnaWJ0IGVpbmVuIFVudGVyc2NoZWlkIGluIGRlbiBNaXR0ZWx3ZXJ0ZW4gZGVzICJyZXNpZHVhbC5zdWdhciIgendpc2NoZW4gV2Vpw58tIHVuZCBSb3R3ZWluLg0KDQoNCiMjIyBXaWUgd2VyZGVuIEh5cG90aGVzZW4gbWl0IGVpbmVtIEJvb3RzdHJhcCBnZXRlc3RldD8NCiANCisgMSkgQm9vdHN0cmFwLVZlcnRlaWx1bmdlbiBkZXIgUGFyYW1ldGVyIGluIEEgdW5kIEIgd2VyZGVuIGVyc3RlbGx0DQorIDIpIERhbm4gd2lyZCBkZXJlbiBEaWZmZXJlbnogKE1hdHJpeHN1YnRyYWt0aW9uKSBiZXJlY2huZXQNCisgMykgRGFzIEtvbmZpZGVuemludGVydmFsbCBJbnRlcnZhbGwgd2lyZCBkYW5uIGJlcmVjaG5ldA0KKyA0KSBFcyBtdXNzIGdlcHLDvGZ0IHdlcmRlbiwgb2IgZGFzIEtvbmZpZGVuemludGVydmFsbCBhdWYgMCBmw6RsbHQsIHVuZCB3ZW5uIGphLCBkYW5uIGRpZSBOdWxsaHlwb3RoZXNlIHdpcmQgYmVpIGVpbmVtIGJlc3RpbW10ZW4gU2lnbmlmaWthbnpuaXZlYXUgYmVpYmVoYWx0ZW4uDQoNCg0KIyMjIEhpc3RvZ3JhbW0NCg0KYGBge3J9DQpnMSA8LWhpc3RfcGxvdCh3aW5lX2FsbFt3aW5lX2FsbCRjb2xvcj09J3doaXRlJyxdLCdyZXNpZHVhbC5zdWdhcicsIA0KICAgICAgICAgICAgICAgZmlsbCA9ICcjZWRhMWJhJykrDQogICAgeGxhYignV2hpdGUnKQ0KZzIgPC0gaGlzdF9wbG90KHdpbmVfYWxsW3dpbmVfYWxsJGNvbG9yPT0ncmVkJyxdLCdyZXNpZHVhbC5zdWdhcicpKw0KICAgIHhsYWIoJ1JlZCcpDQpncmlkLmFycmFuZ2UoYXJyYW5nZUdyb2IoZzEsIGcyLCBuY29sPTIpLG5yb3cgPSAxKSANCmBgYA0KRXMgaXN0IG9mZmVuc2ljaHRsaWNoLCBkYXNzIGVzIGluIGRpZXNlbSBGYWxsIGtlaW5lIE5vcm1hbHZlcnRlaWx1bmcgZ2lidC4NCg0KIyMjIERlc2tyaXB0aXZlIFN0YXRpc3Rpa2VuDQpgYGB7cn0NCnRhYmxlIDwtIGRlc2NyaWJlQnkod2luZV9hbGwkcmVzaWR1YWwuc3VnYXIsIGdyb3VwID0gd2luZV9hbGwkY29sb3IsIG1hdCA9IFQsIGRpZ2l0cyA9IDQpDQp0YWJsZVsxOjZdDQpgYGANCkltIE1pdHRlbCBsaWVndCBkaWUgVmFyaWFibGUgKipyZXNpZHVhbC5zdWdhcioqIDogPGJyPg0KDQpSb3R3ZWluOiBNID0gMi41Mzg4LCBTRCA9IDEuNDA5OSwgbiA9IDE1OTkNCldlacOfd2VpbjogTSA9IDYuMzkxNCwgU0QgPSA1LjA3MjEsIG4gPSAgNDg5OA0KDQojIyMgQmFzaWMgQm9vdHN0cmFwDQpgYGB7cn0NCiMgRXJzdGVsbHVuZyBkZXIgU3Vic2V0cw0KcmVkX3N1YnNldCA8LSB3aW5lX2FsbFt3aW5lX2FsbCRjb2xvcj09J3JlZCcsXQ0Kd2hpdGVfc3Vic2V0IDwtIHdpbmVfYWxsW3dpbmVfYWxsJGNvbG9yPT0nd2hpdGUnLF0NCiNWaWV3KHdoaXRlX3N1YnNldCkNCmBgYA0KDQoNCmBgYHtyfQ0KDQpzYW1wbGVtZWFuIDwtIGZ1bmN0aW9uKHgsIGQpIHsNCiAgcmV0dXJuKG1lYW4oeFtkXSwgbmEucm0gPSBUKSkNCn0NCg0KcmVwc19yZWQgPC0gYm9vdChyZWRfc3Vic2V0JHJlc2lkdWFsLnN1Z2FyLCBzdGF0aXN0aWM9IHNhbXBsZW1lYW4sIFI9MjAwMCkNCnJlcHNfd2hpdGUgPC1ib290KHdoaXRlX3N1YnNldCRyZXNpZHVhbC5zdWdhciwgc3RhdGlzdGljPSBzYW1wbGVtZWFuLCBSPTIwMDApDQpgYGANCg0KRXJnZWJuaXNzZSBkZXMgQm9vc3RyYXBwaW5ncyBhbnplaWdlbiBtaXR0ZWxzIEhpc3RvZ3JhbW1zDQpgYGB7cn0NCg0KYm9vdF9tZWFuc19yZWQgPC0gZGF0YS5mcmFtZSgnYm9vdF9tZWFuc19yZWQnPSByZXBzX3JlZCR0KQ0KYm9vdF9tZWFuc193aGl0ZSA8LSBkYXRhLmZyYW1lKCdib290X21lYW5zX3doaXRlJz0gcmVwc193aGl0ZSR0KQ0KDQpnMSA8LSBoaXN0X3Bsb3QoYm9vdF9tZWFuc19yZWQsJ2Jvb3RfbWVhbnNfcmVkJykNCmcyIDwtIGhpc3RfcGxvdChib290X21lYW5zX3doaXRlLCdib290X21lYW5zX3doaXRlJykNCg0KZ3JpZC5hcnJhbmdlKGFycmFuZ2VHcm9iKGcxLGcyLCBuY29sPTIpLCBucm93PTEpDQpgYGANCk9mZmVuc2ljaHRsaWNoIGVpbmUgTm9ybWFsdmVydGVpbHVuZw0KDQpgYGB7cn0NCmRpZmZfbWVhbnMgPC0gYm9vdF9tZWFuc19yZWQkYm9vdF9tZWFucyAtIGJvb3RfbWVhbnNfd2hpdGUkYm9vdF9tZWFucw0KcHJpbnQoJzk1JSBLSScpDQpxdWFudGlsZShkaWZmX21lYW5zLCBjKDAuMDI1LCAwLjk3NSkpDQpgYGANCg0KIyMjIEVpbmUgQXVzc2FnZQ0KRXMgZ2lidCBlaW5lbiBkZXV0bGljaGVuIFVudGVyc2NoaWVkIGluIGRlbiBNaXR0ZWx3ZXJ0ZW4gdm9uIFp1Y2tlciB6d2lzY2hlbiBSb3QgKCBNID0gMi41Mzg4LCBTRCA9IDEuNDA5OSwgbiA9IDE1OTkpLSB1bmQgV2Vpw593ZWluZW4gKE0gPSA2LjM5MTQsIFNEID0gNS4wNzIxLCBuID0gIDQ4OTgpICANCkRhcyA5NSUgS29uZmlkZW56aW50ZXJ2YWxsICB2b20gRGlmZmVyZW56IGRlciBNaXR0ZWx3ZXJ0ZW4gKFstNC4xNjYyNjc7IC0zLjYyNjA0NiBdKWF1ZiAwIG5pY2h0IGbDpGxsdCwgZGVzd2VnZW4ga2FubiBIMCB2ZXJ3b3JmZW4gd2VyZGVuLg0KDQoNCg0K