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
- die Stichprobe ist repräsentativ für die Grundgesamtheit.
- genügende Stichprobengröße -> es müssen viele Teilstichproben gezogen werden (in der Regel mindestens 1000 mal)
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?
Wie werden Hypothesen mit einem Bootstrap getestet?
- Bootstrap-Verteilungen der Parameter in A und B werden erstellt
- Dann wird deren Differenz (Matrixsubtraktion) berechnet
- Das Konfidenzintervall Intervall wird dann berechnet
- 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