1 Wprowadzenie

Cel: wyznaczenie obszaru ufności dla dystrybuanty nieznanego rozkładu, a nie tylko oszacowania parametrów, od jakich zależą jej wartości.

  • Brzegi tego obszaru są wykresami funkcji „przedziałami stałych” (funkcji schodkowych).

  • Jeżeli przy wyznaczaniu pasma ufności dla dystrybuanty otrzymamy lewy kraniec przedziału będący liczbą ujemną, to zastępujemy ją przez zero.

  • Jeżeli otrzymamy prawy kraniec przedziału większy od jedności, to przyjmujemy, że jest on równy jeden.

  • Określenie obszaru ufności dla dystrybuanty w przedstawiony sposób polega na wyznaczeniu przedziałowego oszacowania dla każdej wartości dystrybuanty.

1.1 Funkcja CDF

Funkcja w programie R odpowiedzialna za estymację to np. CDF z pakietu spatstat. CDF jest metodą ogólną, z metodą dla klasy “gęstość”.

Oblicza ona skumulowaną funkcję rozkładu, której gęstość prawdopodobieństwa została oszacowana i zapisana w obiekcie f. Obiekt f musi należeć do klasy “gęstość” i zazwyczaj zostałby uzyskany z wywołania funkcji gęstość.

1.2 Funkcja kde

Pakiet R o nazwie snpar zawiera kilka uzupełniających metod statystyki nieparametrycznej, w tym test kwantylowy, test trendu Coxa-Stuarta, test przebiegów, test normalnego wyniku, estymację jądra PDF i CDF, estymację regresji jądra i test jądra Kołmogorowa-Smirnowa.

Funkcja kde zawiera obliczanie zarówno nieparametrycznego estymatora jądra funkcji gęstości prawdopodobieństwa (PDF) jak i funkcji rozkładu skumulowanego (CDF).

1.3 Przykład 1.

   b <- density(runif(10))
   f <- CDF(b)
   f(0.5)
## [1] 0.4280671
   f(1)
## [1] 0.9278786
   plot(f)

1.4 Przykład 2.

x <- rnorm(200,2,3)
# with default bandwidth
# kde(x, kernel = "quar", plot = TRUE)

# with specified bandwidth
# kde(x, h = 4, kernel = "quar", plot = TRUE)

1.5 Przeczytaj

Przeczytaj artykuł naukowy “Kernel-smoothed cumulative distribution function estimation with akdensity” autorstwa Philippe Van Kerm.

1.6 Zadanie

Posłużymy się zbiorem danych diagnozy społecznej.

Na jego podstawie Twoim zadaniem jest oszacowanie rozkładu “gp64 Pana/Pani wlasny (osobisty) dochod miesieczny netto (na reke)” według województw/płci.

Postaraj się oszacować zarówno rozkład gęstości jak i skumulowanej gęstości (dystrybuanty).

data("diagnoza")
data("diagnozaDict")
# Filtrujemy dane 
data_filtered <- diagnoza %>%
  select(gp64, wojewodztwo, plec) %>%
  filter(!is.na(gp64) & gp64 > 0 & wojewodztwo != "BD/ND/FALA") %>%
  mutate(wojewodztwo = as.factor(wojewodztwo),  # Województwo
         plec = as.factor(plec))  # Płeć
# Podział województw na dwie grupy
woj_group_1 <- levels(data_filtered$wojewodztwo)[1:4]
woj_group_2 <- levels(data_filtered$wojewodztwo)[5:8]
woj_group_3 <- levels(data_filtered$wojewodztwo)[9:12]
woj_group_4 <- levels(data_filtered$wojewodztwo)[13:16]
# Obliczanie rozkładów KDE i dystrybuant
# Estymacja dla każdej kombinacji województwa i płci
kde_results <- data_filtered %>%
  group_by(wojewodztwo, plec) %>%
  summarise(density = list(density(gp64, na.rm = TRUE)), .groups = "drop")

cdf_results <- data_filtered %>%
  group_by(wojewodztwo, plec) %>%
  summarise(
    cdf = list(ecdf(gp64)),
    .groups = "drop"
  )

1.7 Wykresy gęstości i dystrubuanty skumulowa z podziałem na 2 grupy województw (dla większej czytelności)

# Wykres rozkładu gęstości dla grupy 1
plot_density_group1 <- ggplot(data_filtered %>% filter(wojewodztwo %in% woj_group_1), aes(x = gp64, color = plec)) +
  geom_density() +
  facet_wrap(~ wojewodztwo, scales = "free_y") +
  labs(
    title = "Rozkład gęstości dochodu netto (gp64) - Grupa 1 województw",
    x = "Dochód netto (zł)",
    y = "Gęstość",
    color = "Płeć"
  ) +
  scale_x_continuous(labels = scales::comma, limits = c(0, quantile(data_filtered$gp64, 0.99))) +
  theme_minimal() +
  theme(plot.title = element_text(size = 16),
        axis.text = element_text(size = 12),
        axis.title = element_text(size = 14),
        strip.text = element_text(size = 14))

# Wykres rozkładu gęstości dla grupy 2
plot_density_group2 <- ggplot(data_filtered %>% filter(wojewodztwo %in% woj_group_2), aes(x = gp64, color = plec)) +
  geom_density() +
  facet_wrap(~ wojewodztwo, scales = "free_y") +
  labs(
    title = "Rozkład gęstości dochodu netto (gp64) - Grupa 2 województw",
    x = "Dochód netto (zł)",
    y = "Gęstość",
    color = "Płeć"
  ) +
  scale_x_continuous(labels = scales::comma, limits = c(0, quantile(data_filtered$gp64, 0.99))) +
  theme_minimal() +
  theme(plot.title = element_text(size = 16),
        axis.text = element_text(size = 12),
        axis.title = element_text(size = 14),
        strip.text = element_text(size = 14))
# Wykres rozkładu gęstości dla grupy 3
plot_density_group3 <- ggplot(data_filtered %>% filter(wojewodztwo %in% woj_group_3), aes(x = gp64, color = plec)) +
  geom_density() +
  facet_wrap(~ wojewodztwo, scales = "free_y") +
  labs(
    title = "Rozkład gęstości dochodu netto (gp64) - Grupa 3 województw",
    x = "Dochód netto (zł)",
    y = "Gęstość",
    color = "Płeć"
  ) +
  scale_x_continuous(labels = scales::comma, limits = c(0, quantile(data_filtered$gp64, 0.99))) +
  theme_minimal() +
  theme(plot.title = element_text(size = 16),
        axis.text = element_text(size = 12),
        axis.title = element_text(size = 14),
        strip.text = element_text(size = 14))
# Wykres rozkładu gęstości dla grupy 4
plot_density_group4 <- ggplot(data_filtered %>% filter(wojewodztwo %in% woj_group_4), aes(x = gp64, color = plec)) +
  geom_density() +
  facet_wrap(~ wojewodztwo, scales = "free_y") +
  labs(
    title = "Rozkład gęstości dochodu netto (gp64) - Grupa 4 województw",
    x = "Dochód netto (zł)",
    y = "Gęstość",
    color = "Płeć"
  ) +
  scale_x_continuous(labels = scales::comma, limits = c(0, quantile(data_filtered$gp64, 0.99))) +
  theme_minimal() +
  theme(plot.title = element_text(size = 16),
        axis.text = element_text(size = 12),
        axis.title = element_text(size = 14),
        strip.text = element_text(size = 14))


# Wykres dystrybuanty skumulowanej dla grupy 1
plot_cdf_group1 <- ggplot(data_filtered %>% filter(wojewodztwo %in% woj_group_1), aes(x = gp64, color = plec)) +
  stat_ecdf(geom = "step") +
  facet_wrap(~ wojewodztwo, scales = "free_y") +
  labs(
    title = "Dystrybuanta skumulowana dochodu netto (gp64) - Grupa 1 województw",
    x = "Dochód netto (zł)",
    y = "Prawdopodobieństwo skumulowane",
    color = "Płeć"
  ) +
  scale_x_continuous(labels = scales::comma, limits = c(0, quantile(data_filtered$gp64, 0.99))) +
  theme_minimal() +
  theme(plot.title = element_text(size = 16),
        axis.text = element_text(size = 12),
        axis.title = element_text(size = 14),
        strip.text = element_text(size = 14))

# Wykres dystrybuanty skumulowanej dla grupy 2
plot_cdf_group2 <- ggplot(data_filtered %>% filter(wojewodztwo %in% woj_group_2), aes(x = gp64, color = plec)) +
  stat_ecdf(geom = "step") +
  facet_wrap(~ wojewodztwo, scales = "free_y") +
  labs(
    title = "Dystrybuanta skumulowana dochodu netto (gp64) - Grupa 2 województw",
    x = "Dochód netto (zł)",
    y = "Prawdopodobieństwo skumulowane",
    color = "Płeć"
  ) +
  scale_x_continuous(labels = scales::comma, limits = c(0, quantile(data_filtered$gp64, 0.99))) +
  theme_minimal() +
  theme(plot.title = element_text(size = 16),
        axis.text = element_text(size = 12),
        axis.title = element_text(size = 14),
        strip.text = element_text(size = 14))
# Wykres dystrybuanty skumulowanej dla grupy 3
plot_cdf_group3 <- ggplot(data_filtered %>% filter(wojewodztwo %in% woj_group_3), aes(x = gp64, color = plec)) +
  stat_ecdf(geom = "step") +
  facet_wrap(~ wojewodztwo, scales = "free_y") +
  labs(
    title = "Dystrybuanta skumulowana dochodu netto (gp64) - Grupa 3 województw",
    x = "Dochód netto (zł)",
    y = "Prawdopodobieństwo skumulowane",
    color = "Płeć"
  ) +
  scale_x_continuous(labels = scales::comma, limits = c(0, quantile(data_filtered$gp64, 0.99))) +
  theme_minimal() +
  theme(plot.title = element_text(size = 16),
        axis.text = element_text(size = 12),
        axis.title = element_text(size = 14),
        strip.text = element_text(size = 14))
# Wykres dystrybuanty skumulowanej dla grupy 4
plot_cdf_group4 <- ggplot(data_filtered %>% filter(wojewodztwo %in% woj_group_4), aes(x = gp64, color = plec)) +
  stat_ecdf(geom = "step") +
  facet_wrap(~ wojewodztwo, scales = "free_y") +
  labs(
    title = "Dystrybuanta skumulowana dochodu netto (gp64) - Grupa 4 województw",
    x = "Dochód netto (zł)",
    y = "Prawdopodobieństwo skumulowane",
    color = "Płeć"
  ) +
  scale_x_continuous(labels = scales::comma, limits = c(0, quantile(data_filtered$gp64, 0.99))) +
  theme_minimal() +
  theme(plot.title = element_text(size = 16),
        axis.text = element_text(size = 12),
        axis.title = element_text(size = 14),
        strip.text = element_text(size = 14))

# Wyświetlanie wykresów
print(plot_density_group1)
## Warning: Removed 28 rows containing non-finite outside the scale range
## (`stat_density()`).

print(plot_density_group2)
## Warning: Removed 78 rows containing non-finite outside the scale range
## (`stat_density()`).

print(plot_density_group3)
## Warning: Removed 40 rows containing non-finite outside the scale range
## (`stat_density()`).

print(plot_density_group4)
## Warning: Removed 33 rows containing non-finite outside the scale range
## (`stat_density()`).

print(plot_cdf_group1)
## Warning: Removed 28 rows containing non-finite outside the scale range
## (`stat_ecdf()`).

print(plot_cdf_group2)
## Warning: Removed 78 rows containing non-finite outside the scale range
## (`stat_ecdf()`).

print(plot_cdf_group3)
## Warning: Removed 40 rows containing non-finite outside the scale range
## (`stat_ecdf()`).

print(plot_cdf_group4)
## Warning: Removed 33 rows containing non-finite outside the scale range
## (`stat_ecdf()`).

Analizując zarówno gęstości, jak i dystrybuanty rozkładów, zauważamy, że kobiety mają niższy dochód netto niż mężczyźni. Szczyty (mody) rozkładów gęstości dla kobiet znajdują się na niższych wartościach niż u mężczyzn. Podobne obserwacje możemy poczynić na wykresach dystrybuanty skumulowanej, gdzie krzywe dla kobiet rosną szybciej i poziomują się, osiągając 75% w okolicach 3 000 zł, podczas gdy u mężczyzn wartość dystrybuanty na tym samym poziomie wynosi około 50%. Różnice te zmieniają się w zależności od województwa, ale ogólnie można stwierdzić, że w każdym z nich mężczyźni mają wyższy dochód netto miesięczny.

LS0tDQp0aXRsZTogIk5pZWtsYXN5Y3puZSBtZXRvZHkgc3RhdHlzdHlraSINCnN1YnRpdGxlOiAiTmllcGFyYW1ldHJ5Y3puYSBlc3R5bWFjamEgZHlzdHJ5YnVhbnR5Ig0KYXV0aG9yOiAiQWxlc2thbmRyYSBCdWtvd3NrYSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0aGVtZTogY2VydWxlYW4NCiAgICBoaWdobGlnaHQ6IHRleHRtYXRlDQogICAgZm9udHNpemU6IDhwdA0KICAgIHRvYzogdHJ1ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IGZhbHNlDQplZGl0b3Jfb3B0aW9uczogDQogIG1hcmtkb3duOiANCiAgICB3cmFwOiA3Mg0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KI2luc3RhbGwucGFja2FnZXMoImtuaXRyIikNCmxpYnJhcnkoa25pdHIpDQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpsaWJyYXJ5KHNwYXRzdGF0KQ0KbGlicmFyeShkcGx5cikNCiNkZXRhY2gobmFtZT0iZmFzdG1hcCIsIHVubG9hZCA9IFRSVUUpDQojaW5zdGFsbC5wYWNrYWdlcygiUnRvb2xzIikNCiNpbnN0YWxsLnBhY2thZ2VzKCJmYXN0bWFwIikNCiNpbnN0YWxsLnBhY2thZ2VzKCJzbnBhciIpDQojbGlicmFyeShzbnBhcikNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KFBvZ3JvbWN5RGFueWNoKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KYGBgDQoNCiMgV3Byb3dhZHplbmllDQoNCkNlbDogd3l6bmFjemVuaWUgb2JzemFydSB1Zm5vxZtjaSBkbGEgZHlzdHJ5YnVhbnR5IG5pZXpuYW5lZ28gcm96a8WCYWR1LCBhIG5pZSB0eWxrbyBvc3phY293YW5pYSBwYXJhbWV0csOzdywgb2QgamFraWNoIHphbGXFvMSFIGplaiB3YXJ0b8WbY2kuDQoNCi0gICBCcnplZ2kgdGVnbyBvYnN6YXJ1IHPEhSB3eWtyZXNhbWkgZnVua2NqaSDigJ5wcnplZHppYcWCYW1pIHN0YcWCeWNoIiAoZnVua2NqaSBzY2hvZGtvd3ljaCkuDQoNCi0gICBKZcW8ZWxpIHByenkgd3l6bmFjemFuaXUgcGFzbWEgdWZub8WbY2kgZGxhIGR5c3RyeWJ1YW50eSBvdHJ6eW1hbXkgbGV3eSBrcmFuaWVjIHByemVkemlhxYJ1IGLEmWTEhWN5IGxpY3pixIUgdWplbW7EhSwgdG8gemFzdMSZcHVqZW15IGrEhSBwcnpleiB6ZXJvLg0KDQotICAgSmXFvGVsaSBvdHJ6eW1hbXkgcHJhd3kga3JhbmllYyBwcnplZHppYcWCdSB3acSZa3N6eSBvZCBqZWRub8WbY2ksIHRvIHByenlqbXVqZW15LCDFvGUgamVzdCBvbiByw7N3bnkgamVkZW4uDQoNCi0gICBPa3JlxZtsZW5pZSBvYnN6YXJ1IHVmbm/Fm2NpIGRsYSBkeXN0cnlidWFudHkgdyBwcnplZHN0YXdpb255IHNwb3PDs2IgcG9sZWdhIG5hIHd5em5hY3plbml1IHByemVkemlhxYJvd2VnbyBvc3phY293YW5pYSBkbGEga2HFvGRlaiB3YXJ0b8WbY2kgZHlzdHJ5YnVhbnR5Lg0KDQojIyBGdW5rY2phIENERg0KDQpGdW5rY2phIHcgcHJvZ3JhbWllIFIgb2Rwb3dpZWR6aWFsbmEgemEgZXN0eW1hY2rEmSB0byBucC4gQ0RGIHogcGFraWV0dSBzcGF0c3RhdC4gQ0RGIGplc3QgbWV0b2TEhSBvZ8OzbG7EhSwgeiBtZXRvZMSFIGRsYSBrbGFzeSAiZ8SZc3RvxZvEhyIuDQoNCk9ibGljemEgb25hIHNrdW11bG93YW7EhSBmdW5rY2rEmSByb3prxYJhZHUsIGt0w7NyZWogZ8SZc3RvxZvEhyBwcmF3ZG9wb2RvYmllxYRzdHdhIHpvc3RhxYJhIG9zemFjb3dhbmEgaSB6YXBpc2FuYSB3IG9iaWVrY2llIGYuIE9iaWVrdCBmIG11c2kgbmFsZcW8ZcSHIGRvIGtsYXN5ICJnxJlzdG/Fm8SHIiBpIHphend5Y3phaiB6b3N0YcWCYnkgdXp5c2thbnkgeiB3eXdvxYJhbmlhIGZ1bmtjamkgZ8SZc3RvxZvEhy4NCg0KIyMgRnVua2NqYSBrZGUNCg0KUGFraWV0IFIgbyBuYXp3aWUgc25wYXIgemF3aWVyYSBraWxrYSB1enVwZcWCbmlhasSFY3ljaCBtZXRvZCBzdGF0eXN0eWtpIG5pZXBhcmFtZXRyeWN6bmVqLCB3IHR5bSB0ZXN0IGt3YW50eWxvd3ksIHRlc3QgdHJlbmR1IENveGEtU3R1YXJ0YSwgdGVzdCBwcnplYmllZ8OzdywgdGVzdCBub3JtYWxuZWdvIHd5bmlrdSwgZXN0eW1hY2rEmSBqxIVkcmEgUERGIGkgQ0RGLCBlc3R5bWFjasSZIHJlZ3Jlc2ppIGrEhWRyYSBpIHRlc3QgasSFZHJhIEtvxYJtb2dvcm93YS1TbWlybm93YS4NCg0KRnVua2NqYSBrZGUgemF3aWVyYSBvYmxpY3phbmllIHphcsOzd25vIG5pZXBhcmFtZXRyeWN6bmVnbyBlc3R5bWF0b3JhIGrEhWRyYSBmdW5rY2ppIGfEmXN0b8WbY2kgcHJhd2RvcG9kb2JpZcWEc3R3YSAoUERGKSBqYWsgaSBmdW5rY2ppIHJvemvFgmFkdSBza3VtdWxvd2FuZWdvIChDREYpLg0KDQojIyBQcnp5a8WCYWQgMS4NCg0KYGBge3J9DQogICBiIDwtIGRlbnNpdHkocnVuaWYoMTApKQ0KICAgZiA8LSBDREYoYikNCiAgIGYoMC41KQ0KICAgZigxKQ0KICAgcGxvdChmKQ0KYGBgDQoNCiMjIFByenlrxYJhZCAyLg0KDQpgYGB7cn0NCnggPC0gcm5vcm0oMjAwLDIsMykNCiMgd2l0aCBkZWZhdWx0IGJhbmR3aWR0aA0KIyBrZGUoeCwga2VybmVsID0gInF1YXIiLCBwbG90ID0gVFJVRSkNCg0KIyB3aXRoIHNwZWNpZmllZCBiYW5kd2lkdGgNCiMga2RlKHgsIGggPSA0LCBrZXJuZWwgPSAicXVhciIsIHBsb3QgPSBUUlVFKQ0KYGBgDQoNCg0KIyMgUHJ6ZWN6eXRhag0KDQpQcnplY3p5dGFqIGFydHlrdcWCIG5hdWtvd3kgWyJLZXJuZWwtc21vb3RoZWQgY3VtdWxhdGl2ZSBkaXN0cmlidXRpb24gZnVuY3Rpb24gZXN0aW1hdGlvbiB3aXRoIGFrZGVuc2l0eSJdKGh0dHBzOi8vam91cm5hbHMuc2FnZXB1Yi5jb20vZG9pL3BkZi8xMC4xMTc3LzE1MzY4NjdYMTIwMTIwMDMxMykgYXV0b3JzdHdhIFBoaWxpcHBlIFZhbiBLZXJtLg0KDQoNCiMjIFphZGFuaWUNCg0KUG9zxYJ1xbx5bXkgc2nEmSB6YmlvcmVtIGRhbnljaCBkaWFnbm96eSBzcG/FgmVjem5lai4gDQoNCk5hIGplZ28gcG9kc3Rhd2llIFR3b2ltIHphZGFuaWVtIGplc3Qgb3N6YWNvd2FuaWUgcm96a8WCYWR1ICJncDY0IFBhbmEvUGFuaSB3bGFzbnkgKG9zb2Jpc3R5KSBkb2Nob2QgbWllc2llY3pueSBuZXR0byAobmEgcmVrZSkiIHdlZMWCdWcgd29qZXfDs2R6dHcvcMWCY2kuDQoNClBvc3RhcmFqIHNpxJkgb3N6YWNvd2HEhyB6YXLDs3dubyByb3prxYJhZCBnxJlzdG/Fm2NpIGphayBpIHNrdW11bG93YW5laiBnxJlzdG/Fm2NpIChkeXN0cnlidWFudHkpLg0KDQpgYGB7ciB6YWRhbmllfQ0KZGF0YSgiZGlhZ25vemEiKQ0KZGF0YSgiZGlhZ25vemFEaWN0IikNCmBgYA0KDQpgYGB7cn0NCiMgRmlsdHJ1amVteSBkYW5lIA0KZGF0YV9maWx0ZXJlZCA8LSBkaWFnbm96YSAlPiUNCiAgc2VsZWN0KGdwNjQsIHdvamV3b2R6dHdvLCBwbGVjKSAlPiUNCiAgZmlsdGVyKCFpcy5uYShncDY0KSAmIGdwNjQgPiAwICYgd29qZXdvZHp0d28gIT0gIkJEL05EL0ZBTEEiKSAlPiUNCiAgbXV0YXRlKHdvamV3b2R6dHdvID0gYXMuZmFjdG9yKHdvamV3b2R6dHdvKSwgICMgV29qZXfDs2R6dHdvDQogICAgICAgICBwbGVjID0gYXMuZmFjdG9yKHBsZWMpKSAgIyBQxYJlxIcNCmBgYA0KDQpgYGB7cn0NCg0KIyBQb2R6aWHFgiB3b2pld8OzZHp0dyBuYSBkd2llIGdydXB5DQp3b2pfZ3JvdXBfMSA8LSBsZXZlbHMoZGF0YV9maWx0ZXJlZCR3b2pld29kenR3bylbMTo0XQ0Kd29qX2dyb3VwXzIgPC0gbGV2ZWxzKGRhdGFfZmlsdGVyZWQkd29qZXdvZHp0d28pWzU6OF0NCndval9ncm91cF8zIDwtIGxldmVscyhkYXRhX2ZpbHRlcmVkJHdvamV3b2R6dHdvKVs5OjEyXQ0Kd29qX2dyb3VwXzQgPC0gbGV2ZWxzKGRhdGFfZmlsdGVyZWQkd29qZXdvZHp0d28pWzEzOjE2XQ0KDQpgYGANCg0KDQpgYGB7cn0NCiMgT2JsaWN6YW5pZSByb3prxYJhZMOzdyBLREUgaSBkeXN0cnlidWFudA0KIyBFc3R5bWFjamEgZGxhIGthxbxkZWoga29tYmluYWNqaSB3b2pld8OzZHp0d2EgaSBwxYJjaQ0Ka2RlX3Jlc3VsdHMgPC0gZGF0YV9maWx0ZXJlZCAlPiUNCiAgZ3JvdXBfYnkod29qZXdvZHp0d28sIHBsZWMpICU+JQ0KICBzdW1tYXJpc2UoZGVuc2l0eSA9IGxpc3QoZGVuc2l0eShncDY0LCBuYS5ybSA9IFRSVUUpKSwgLmdyb3VwcyA9ICJkcm9wIikNCg0KY2RmX3Jlc3VsdHMgPC0gZGF0YV9maWx0ZXJlZCAlPiUNCiAgZ3JvdXBfYnkod29qZXdvZHp0d28sIHBsZWMpICU+JQ0KICBzdW1tYXJpc2UoDQogICAgY2RmID0gbGlzdChlY2RmKGdwNjQpKSwNCiAgICAuZ3JvdXBzID0gImRyb3AiDQogICkNCmBgYA0KDQojIyBXeWtyZXN5IGfEmXN0b8WbY2kgaSBkeXN0cnVidWFudHkgc2t1bXVsb3dhIHogcG9kemlhxYJlbSBuYSAyIGdydXB5IHdvamV3w7NkenR3IChkbGEgd2nEmWtzemVqIGN6eXRlbG5vxZtjaSkNCg0KYGBge3J9DQoNCiMgV3lrcmVzIHJvemvFgmFkdSBnxJlzdG/Fm2NpIGRsYSBncnVweSAxDQpwbG90X2RlbnNpdHlfZ3JvdXAxIDwtIGdncGxvdChkYXRhX2ZpbHRlcmVkICU+JSBmaWx0ZXIod29qZXdvZHp0d28gJWluJSB3b2pfZ3JvdXBfMSksIGFlcyh4ID0gZ3A2NCwgY29sb3IgPSBwbGVjKSkgKw0KICBnZW9tX2RlbnNpdHkoKSArDQogIGZhY2V0X3dyYXAofiB3b2pld29kenR3bywgc2NhbGVzID0gImZyZWVfeSIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJSb3prxYJhZCBnxJlzdG/Fm2NpIGRvY2hvZHUgbmV0dG8gKGdwNjQpIC0gR3J1cGEgMSB3b2pld8OzZHp0dyIsDQogICAgeCA9ICJEb2Now7NkIG5ldHRvICh6xYIpIiwNCiAgICB5ID0gIkfEmXN0b8WbxIciLA0KICAgIGNvbG9yID0gIlDFgmXEhyINCiAgKSArDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmNvbW1hLCBsaW1pdHMgPSBjKDAsIHF1YW50aWxlKGRhdGFfZmlsdGVyZWQkZ3A2NCwgMC45OSkpKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKQ0KDQojIFd5a3JlcyByb3prxYJhZHUgZ8SZc3RvxZtjaSBkbGEgZ3J1cHkgMg0KcGxvdF9kZW5zaXR5X2dyb3VwMiA8LSBnZ3Bsb3QoZGF0YV9maWx0ZXJlZCAlPiUgZmlsdGVyKHdvamV3b2R6dHdvICVpbiUgd29qX2dyb3VwXzIpLCBhZXMoeCA9IGdwNjQsIGNvbG9yID0gcGxlYykpICsNCiAgZ2VvbV9kZW5zaXR5KCkgKw0KICBmYWNldF93cmFwKH4gd29qZXdvZHp0d28sIHNjYWxlcyA9ICJmcmVlX3kiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUm96a8WCYWQgZ8SZc3RvxZtjaSBkb2Nob2R1IG5ldHRvIChncDY0KSAtIEdydXBhIDIgd29qZXfDs2R6dHciLA0KICAgIHggPSAiRG9jaMOzZCBuZXR0byAoesWCKSIsDQogICAgeSA9ICJHxJlzdG/Fm8SHIiwNCiAgICBjb2xvciA9ICJQxYJlxIciDQogICkgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpjb21tYSwgbGltaXRzID0gYygwLCBxdWFudGlsZShkYXRhX2ZpbHRlcmVkJGdwNjQsIDAuOTkpKSkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLA0KICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksDQogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSkNCiMgV3lrcmVzIHJvemvFgmFkdSBnxJlzdG/Fm2NpIGRsYSBncnVweSAzDQpwbG90X2RlbnNpdHlfZ3JvdXAzIDwtIGdncGxvdChkYXRhX2ZpbHRlcmVkICU+JSBmaWx0ZXIod29qZXdvZHp0d28gJWluJSB3b2pfZ3JvdXBfMyksIGFlcyh4ID0gZ3A2NCwgY29sb3IgPSBwbGVjKSkgKw0KICBnZW9tX2RlbnNpdHkoKSArDQogIGZhY2V0X3dyYXAofiB3b2pld29kenR3bywgc2NhbGVzID0gImZyZWVfeSIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJSb3prxYJhZCBnxJlzdG/Fm2NpIGRvY2hvZHUgbmV0dG8gKGdwNjQpIC0gR3J1cGEgMyB3b2pld8OzZHp0dyIsDQogICAgeCA9ICJEb2Now7NkIG5ldHRvICh6xYIpIiwNCiAgICB5ID0gIkfEmXN0b8WbxIciLA0KICAgIGNvbG9yID0gIlDFgmXEhyINCiAgKSArDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmNvbW1hLCBsaW1pdHMgPSBjKDAsIHF1YW50aWxlKGRhdGFfZmlsdGVyZWQkZ3A2NCwgMC45OSkpKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKQ0KIyBXeWtyZXMgcm96a8WCYWR1IGfEmXN0b8WbY2kgZGxhIGdydXB5IDQNCnBsb3RfZGVuc2l0eV9ncm91cDQgPC0gZ2dwbG90KGRhdGFfZmlsdGVyZWQgJT4lIGZpbHRlcih3b2pld29kenR3byAlaW4lIHdval9ncm91cF80KSwgYWVzKHggPSBncDY0LCBjb2xvciA9IHBsZWMpKSArDQogIGdlb21fZGVuc2l0eSgpICsNCiAgZmFjZXRfd3JhcCh+IHdvamV3b2R6dHdvLCBzY2FsZXMgPSAiZnJlZV95IikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlJvemvFgmFkIGfEmXN0b8WbY2kgZG9jaG9kdSBuZXR0byAoZ3A2NCkgLSBHcnVwYSA0IHdvamV3w7NkenR3IiwNCiAgICB4ID0gIkRvY2jDs2QgbmV0dG8gKHrFgikiLA0KICAgIHkgPSAiR8SZc3RvxZvEhyIsDQogICAgY29sb3IgPSAiUMWCZcSHIg0KICApICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6Y29tbWEsIGxpbWl0cyA9IGMoMCwgcXVhbnRpbGUoZGF0YV9maWx0ZXJlZCRncDY0LCAwLjk5KSkpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwNCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpDQoNCg0KIyBXeWtyZXMgZHlzdHJ5YnVhbnR5IHNrdW11bG93YW5laiBkbGEgZ3J1cHkgMQ0KcGxvdF9jZGZfZ3JvdXAxIDwtIGdncGxvdChkYXRhX2ZpbHRlcmVkICU+JSBmaWx0ZXIod29qZXdvZHp0d28gJWluJSB3b2pfZ3JvdXBfMSksIGFlcyh4ID0gZ3A2NCwgY29sb3IgPSBwbGVjKSkgKw0KICBzdGF0X2VjZGYoZ2VvbSA9ICJzdGVwIikgKw0KICBmYWNldF93cmFwKH4gd29qZXdvZHp0d28sIHNjYWxlcyA9ICJmcmVlX3kiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiRHlzdHJ5YnVhbnRhIHNrdW11bG93YW5hIGRvY2hvZHUgbmV0dG8gKGdwNjQpIC0gR3J1cGEgMSB3b2pld8OzZHp0dyIsDQogICAgeCA9ICJEb2Now7NkIG5ldHRvICh6xYIpIiwNCiAgICB5ID0gIlByYXdkb3BvZG9iaWXFhHN0d28gc2t1bXVsb3dhbmUiLA0KICAgIGNvbG9yID0gIlDFgmXEhyINCiAgKSArDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmNvbW1hLCBsaW1pdHMgPSBjKDAsIHF1YW50aWxlKGRhdGFfZmlsdGVyZWQkZ3A2NCwgMC45OSkpKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKQ0KDQojIFd5a3JlcyBkeXN0cnlidWFudHkgc2t1bXVsb3dhbmVqIGRsYSBncnVweSAyDQpwbG90X2NkZl9ncm91cDIgPC0gZ2dwbG90KGRhdGFfZmlsdGVyZWQgJT4lIGZpbHRlcih3b2pld29kenR3byAlaW4lIHdval9ncm91cF8yKSwgYWVzKHggPSBncDY0LCBjb2xvciA9IHBsZWMpKSArDQogIHN0YXRfZWNkZihnZW9tID0gInN0ZXAiKSArDQogIGZhY2V0X3dyYXAofiB3b2pld29kenR3bywgc2NhbGVzID0gImZyZWVfeSIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJEeXN0cnlidWFudGEgc2t1bXVsb3dhbmEgZG9jaG9kdSBuZXR0byAoZ3A2NCkgLSBHcnVwYSAyIHdvamV3w7NkenR3IiwNCiAgICB4ID0gIkRvY2jDs2QgbmV0dG8gKHrFgikiLA0KICAgIHkgPSAiUHJhd2RvcG9kb2JpZcWEc3R3byBza3VtdWxvd2FuZSIsDQogICAgY29sb3IgPSAiUMWCZcSHIg0KICApICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6Y29tbWEsIGxpbWl0cyA9IGMoMCwgcXVhbnRpbGUoZGF0YV9maWx0ZXJlZCRncDY0LCAwLjk5KSkpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwNCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpDQojIFd5a3JlcyBkeXN0cnlidWFudHkgc2t1bXVsb3dhbmVqIGRsYSBncnVweSAzDQpwbG90X2NkZl9ncm91cDMgPC0gZ2dwbG90KGRhdGFfZmlsdGVyZWQgJT4lIGZpbHRlcih3b2pld29kenR3byAlaW4lIHdval9ncm91cF8zKSwgYWVzKHggPSBncDY0LCBjb2xvciA9IHBsZWMpKSArDQogIHN0YXRfZWNkZihnZW9tID0gInN0ZXAiKSArDQogIGZhY2V0X3dyYXAofiB3b2pld29kenR3bywgc2NhbGVzID0gImZyZWVfeSIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJEeXN0cnlidWFudGEgc2t1bXVsb3dhbmEgZG9jaG9kdSBuZXR0byAoZ3A2NCkgLSBHcnVwYSAzIHdvamV3w7NkenR3IiwNCiAgICB4ID0gIkRvY2jDs2QgbmV0dG8gKHrFgikiLA0KICAgIHkgPSAiUHJhd2RvcG9kb2JpZcWEc3R3byBza3VtdWxvd2FuZSIsDQogICAgY29sb3IgPSAiUMWCZcSHIg0KICApICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6Y29tbWEsIGxpbWl0cyA9IGMoMCwgcXVhbnRpbGUoZGF0YV9maWx0ZXJlZCRncDY0LCAwLjk5KSkpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwNCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpDQojIFd5a3JlcyBkeXN0cnlidWFudHkgc2t1bXVsb3dhbmVqIGRsYSBncnVweSA0DQpwbG90X2NkZl9ncm91cDQgPC0gZ2dwbG90KGRhdGFfZmlsdGVyZWQgJT4lIGZpbHRlcih3b2pld29kenR3byAlaW4lIHdval9ncm91cF80KSwgYWVzKHggPSBncDY0LCBjb2xvciA9IHBsZWMpKSArDQogIHN0YXRfZWNkZihnZW9tID0gInN0ZXAiKSArDQogIGZhY2V0X3dyYXAofiB3b2pld29kenR3bywgc2NhbGVzID0gImZyZWVfeSIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJEeXN0cnlidWFudGEgc2t1bXVsb3dhbmEgZG9jaG9kdSBuZXR0byAoZ3A2NCkgLSBHcnVwYSA0IHdvamV3w7NkenR3IiwNCiAgICB4ID0gIkRvY2jDs2QgbmV0dG8gKHrFgikiLA0KICAgIHkgPSAiUHJhd2RvcG9kb2JpZcWEc3R3byBza3VtdWxvd2FuZSIsDQogICAgY29sb3IgPSAiUMWCZcSHIg0KICApICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6Y29tbWEsIGxpbWl0cyA9IGMoMCwgcXVhbnRpbGUoZGF0YV9maWx0ZXJlZCRncDY0LCAwLjk5KSkpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwNCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpDQoNCiMgV3nFm3dpZXRsYW5pZSB3eWtyZXPDs3cNCnByaW50KHBsb3RfZGVuc2l0eV9ncm91cDEpDQpwcmludChwbG90X2RlbnNpdHlfZ3JvdXAyKQ0KcHJpbnQocGxvdF9kZW5zaXR5X2dyb3VwMykNCnByaW50KHBsb3RfZGVuc2l0eV9ncm91cDQpDQpwcmludChwbG90X2NkZl9ncm91cDEpDQpwcmludChwbG90X2NkZl9ncm91cDIpDQpwcmludChwbG90X2NkZl9ncm91cDMpDQpwcmludChwbG90X2NkZl9ncm91cDQpDQoNCmBgYA0KDQoNCkFuYWxpenVqxIVjIHphcsOzd25vIGfEmXN0b8WbY2ksIGphayBpIGR5c3RyeWJ1YW50eSByb3prxYJhZMOzdywgemF1d2HFvGFteSwgxbxlIGtvYmlldHkgbWFqxIUgbmnFvHN6eSBkb2Now7NkIG5ldHRvIG5pxbwgbcSZxbxjennFum5pLiBTemN6eXR5IChtb2R5KSByb3prxYJhZMOzdyBnxJlzdG/Fm2NpIGRsYSBrb2JpZXQgem5hamR1asSFIHNpxJkgbmEgbmnFvHN6eWNoIHdhcnRvxZtjaWFjaCBuacW8IHUgbcSZxbxjenl6bi4gUG9kb2JuZSBvYnNlcndhY2plIG1vxbxlbXkgcG9jenluacSHIG5hIHd5a3Jlc2FjaCBkeXN0cnlidWFudHkgc2t1bXVsb3dhbmVqLCBnZHppZSBrcnp5d2UgZGxhIGtvYmlldCByb3NuxIUgc3p5YmNpZWogaSBwb3ppb211asSFIHNpxJksIG9zacSFZ2FqxIVjIDc1JSB3IG9rb2xpY2FjaCAzIDAwMCB6xYIsIHBvZGN6YXMgZ2R5IHUgbcSZxbxjenl6biB3YXJ0b8WbxIcgZHlzdHJ5YnVhbnR5IG5hIHR5bSBzYW15bSBwb3ppb21pZSB3eW5vc2kgb2tvxYJvIDUwJS4gUsOzxbxuaWNlIHRlIHptaWVuaWFqxIUgc2nEmSB3IHphbGXFvG5vxZtjaSBvZCB3b2pld8OzZHp0d2EsIGFsZSBvZ8OzbG5pZSBtb8W8bmEgc3R3aWVyZHppxIcsIMW8ZSB3IGthxbxkeW0geiBuaWNoIG3EmcW8Y3p5xbpuaSBtYWrEhSB3ecW8c3p5IGRvY2jDs2QgbmV0dG8gbWllc2nEmWN6bnkuDQo=