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.4554264
   f(1)
## [1] 0.9776819
   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 4 grupy województw

# 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. Największa róznica między dochodami pomiędzy kobietami, a mężczyznami ma miejsce w województwach: Śląskim i Kujawsko-pomorskim. Najmniejsza z kolei w województwach:Warmińsko-mazurskim i Lubuskim.

LS0tDQp0aXRsZTogIk5pZWtsYXN5Y3puZSBtZXRvZHkgc3RhdHlzdHlraSINCnN1YnRpdGxlOiAiTmllcGFyYW1ldHJ5Y3puYSBlc3R5bWFjamEgZHlzdHJ5YnVhbnR5Ig0KYXV0aG9yOiAiQWxlc2thbmRyYSBCdWtvd3NrYSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0aGVtZTogY2VydWxlYW4NCiAgICBoaWdobGlnaHQ6IHRleHRtYXRlDQogICAgZm9udHNpemU6IDhwdA0KICAgIHRvYzogdHJ1ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IGZhbHNlDQplZGl0b3Jfb3B0aW9uczogDQogIG1hcmtkb3duOiANCiAgICB3cmFwOiA3Mg0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KI2luc3RhbGwucGFja2FnZXMoImtuaXRyIikNCmxpYnJhcnkoa25pdHIpDQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpsaWJyYXJ5KHNwYXRzdGF0KQ0KbGlicmFyeShkcGx5cikNCiNkZXRhY2gobmFtZT0iZmFzdG1hcCIsIHVubG9hZCA9IFRSVUUpDQojaW5zdGFsbC5wYWNrYWdlcygiUnRvb2xzIikNCiNpbnN0YWxsLnBhY2thZ2VzKCJmYXN0bWFwIikNCiNpbnN0YWxsLnBhY2thZ2VzKCJzbnBhciIpDQojbGlicmFyeShzbnBhcikNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KFBvZ3JvbWN5RGFueWNoKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KYGBgDQoNCiMgV3Byb3dhZHplbmllDQoNCkNlbDogd3l6bmFjemVuaWUgb2JzemFydSB1Zm5vxZtjaSBkbGEgZHlzdHJ5YnVhbnR5IG5pZXpuYW5lZ28gcm96a8WCYWR1LCBhIG5pZSB0eWxrbyBvc3phY293YW5pYSBwYXJhbWV0csOzdywgb2QgamFraWNoIHphbGXFvMSFIGplaiB3YXJ0b8WbY2kuDQoNCi0gICBCcnplZ2kgdGVnbyBvYnN6YXJ1IHPEhSB3eWtyZXNhbWkgZnVua2NqaSDigJ5wcnplZHppYcWCYW1pIHN0YcWCeWNoIiAoZnVua2NqaSBzY2hvZGtvd3ljaCkuDQoNCi0gICBKZcW8ZWxpIHByenkgd3l6bmFjemFuaXUgcGFzbWEgdWZub8WbY2kgZGxhIGR5c3RyeWJ1YW50eSBvdHJ6eW1hbXkgbGV3eSBrcmFuaWVjIHByemVkemlhxYJ1IGLEmWTEhWN5IGxpY3pixIUgdWplbW7EhSwgdG8gemFzdMSZcHVqZW15IGrEhSBwcnpleiB6ZXJvLg0KDQotICAgSmXFvGVsaSBvdHJ6eW1hbXkgcHJhd3kga3JhbmllYyBwcnplZHppYcWCdSB3acSZa3N6eSBvZCBqZWRub8WbY2ksIHRvIHByenlqbXVqZW15LCDFvGUgamVzdCBvbiByw7N3bnkgamVkZW4uDQoNCi0gICBPa3JlxZtsZW5pZSBvYnN6YXJ1IHVmbm/Fm2NpIGRsYSBkeXN0cnlidWFudHkgdyBwcnplZHN0YXdpb255IHNwb3PDs2IgcG9sZWdhIG5hIHd5em5hY3plbml1IHByemVkemlhxYJvd2VnbyBvc3phY293YW5pYSBkbGEga2HFvGRlaiB3YXJ0b8WbY2kgZHlzdHJ5YnVhbnR5Lg0KDQojIyBGdW5rY2phIENERg0KDQpGdW5rY2phIHcgcHJvZ3JhbWllIFIgb2Rwb3dpZWR6aWFsbmEgemEgZXN0eW1hY2rEmSB0byBucC4gQ0RGIHogcGFraWV0dSBzcGF0c3RhdC4gQ0RGIGplc3QgbWV0b2TEhSBvZ8OzbG7EhSwgeiBtZXRvZMSFIGRsYSBrbGFzeSAiZ8SZc3RvxZvEhyIuDQoNCk9ibGljemEgb25hIHNrdW11bG93YW7EhSBmdW5rY2rEmSByb3prxYJhZHUsIGt0w7NyZWogZ8SZc3RvxZvEhyBwcmF3ZG9wb2RvYmllxYRzdHdhIHpvc3RhxYJhIG9zemFjb3dhbmEgaSB6YXBpc2FuYSB3IG9iaWVrY2llIGYuIE9iaWVrdCBmIG11c2kgbmFsZcW8ZcSHIGRvIGtsYXN5ICJnxJlzdG/Fm8SHIiBpIHphend5Y3phaiB6b3N0YcWCYnkgdXp5c2thbnkgeiB3eXdvxYJhbmlhIGZ1bmtjamkgZ8SZc3RvxZvEhy4NCg0KIyMgRnVua2NqYSBrZGUNCg0KUGFraWV0IFIgbyBuYXp3aWUgc25wYXIgemF3aWVyYSBraWxrYSB1enVwZcWCbmlhasSFY3ljaCBtZXRvZCBzdGF0eXN0eWtpIG5pZXBhcmFtZXRyeWN6bmVqLCB3IHR5bSB0ZXN0IGt3YW50eWxvd3ksIHRlc3QgdHJlbmR1IENveGEtU3R1YXJ0YSwgdGVzdCBwcnplYmllZ8OzdywgdGVzdCBub3JtYWxuZWdvIHd5bmlrdSwgZXN0eW1hY2rEmSBqxIVkcmEgUERGIGkgQ0RGLCBlc3R5bWFjasSZIHJlZ3Jlc2ppIGrEhWRyYSBpIHRlc3QgasSFZHJhIEtvxYJtb2dvcm93YS1TbWlybm93YS4NCg0KRnVua2NqYSBrZGUgemF3aWVyYSBvYmxpY3phbmllIHphcsOzd25vIG5pZXBhcmFtZXRyeWN6bmVnbyBlc3R5bWF0b3JhIGrEhWRyYSBmdW5rY2ppIGfEmXN0b8WbY2kgcHJhd2RvcG9kb2JpZcWEc3R3YSAoUERGKSBqYWsgaSBmdW5rY2ppIHJvemvFgmFkdSBza3VtdWxvd2FuZWdvIChDREYpLg0KDQojIyBQcnp5a8WCYWQgMS4NCg0KYGBge3J9DQogICBiIDwtIGRlbnNpdHkocnVuaWYoMTApKQ0KICAgZiA8LSBDREYoYikNCiAgIGYoMC41KQ0KICAgZigxKQ0KICAgcGxvdChmKQ0KYGBgDQoNCiMjIFByenlrxYJhZCAyLg0KDQpgYGB7cn0NCnggPC0gcm5vcm0oMjAwLDIsMykNCiMgd2l0aCBkZWZhdWx0IGJhbmR3aWR0aA0KIyBrZGUoeCwga2VybmVsID0gInF1YXIiLCBwbG90ID0gVFJVRSkNCg0KIyB3aXRoIHNwZWNpZmllZCBiYW5kd2lkdGgNCiMga2RlKHgsIGggPSA0LCBrZXJuZWwgPSAicXVhciIsIHBsb3QgPSBUUlVFKQ0KYGBgDQoNCg0KIyMgUHJ6ZWN6eXRhag0KDQpQcnplY3p5dGFqIGFydHlrdcWCIG5hdWtvd3kgWyJLZXJuZWwtc21vb3RoZWQgY3VtdWxhdGl2ZSBkaXN0cmlidXRpb24gZnVuY3Rpb24gZXN0aW1hdGlvbiB3aXRoIGFrZGVuc2l0eSJdKGh0dHBzOi8vam91cm5hbHMuc2FnZXB1Yi5jb20vZG9pL3BkZi8xMC4xMTc3LzE1MzY4NjdYMTIwMTIwMDMxMykgYXV0b3JzdHdhIFBoaWxpcHBlIFZhbiBLZXJtLg0KDQoNCiMjIFphZGFuaWUNCg0KUG9zxYJ1xbx5bXkgc2nEmSB6YmlvcmVtIGRhbnljaCBkaWFnbm96eSBzcG/FgmVjem5lai4gDQoNCk5hIGplZ28gcG9kc3Rhd2llIFR3b2ltIHphZGFuaWVtIGplc3Qgb3N6YWNvd2FuaWUgcm96a8WCYWR1ICJncDY0IFBhbmEvUGFuaSB3bGFzbnkgKG9zb2Jpc3R5KSBkb2Nob2QgbWllc2llY3pueSBuZXR0byAobmEgcmVrZSkiIHdlZMWCdWcgd29qZXfDs2R6dHcvcMWCY2kuDQoNClBvc3RhcmFqIHNpxJkgb3N6YWNvd2HEhyB6YXLDs3dubyByb3prxYJhZCBnxJlzdG/Fm2NpIGphayBpIHNrdW11bG93YW5laiBnxJlzdG/Fm2NpIChkeXN0cnlidWFudHkpLg0KDQpgYGB7ciB6YWRhbmllfQ0KZGF0YSgiZGlhZ25vemEiKQ0KZGF0YSgiZGlhZ25vemFEaWN0IikNCmBgYA0KDQpgYGB7cn0NCiMgRmlsdHJ1amVteSBkYW5lIA0KZGF0YV9maWx0ZXJlZCA8LSBkaWFnbm96YSAlPiUNCiAgc2VsZWN0KGdwNjQsIHdvamV3b2R6dHdvLCBwbGVjKSAlPiUNCiAgZmlsdGVyKCFpcy5uYShncDY0KSAmIGdwNjQgPiAwICYgd29qZXdvZHp0d28gIT0gIkJEL05EL0ZBTEEiKSAlPiUNCiAgbXV0YXRlKHdvamV3b2R6dHdvID0gYXMuZmFjdG9yKHdvamV3b2R6dHdvKSwgICMgV29qZXfDs2R6dHdvDQogICAgICAgICBwbGVjID0gYXMuZmFjdG9yKHBsZWMpKSAgIyBQxYJlxIcNCmBgYA0KDQpgYGB7cn0NCg0KIyBQb2R6aWHFgiB3b2pld8OzZHp0dyBuYSBkd2llIGdydXB5DQp3b2pfZ3JvdXBfMSA8LSBsZXZlbHMoZGF0YV9maWx0ZXJlZCR3b2pld29kenR3bylbMTo0XQ0Kd29qX2dyb3VwXzIgPC0gbGV2ZWxzKGRhdGFfZmlsdGVyZWQkd29qZXdvZHp0d28pWzU6OF0NCndval9ncm91cF8zIDwtIGxldmVscyhkYXRhX2ZpbHRlcmVkJHdvamV3b2R6dHdvKVs5OjEyXQ0Kd29qX2dyb3VwXzQgPC0gbGV2ZWxzKGRhdGFfZmlsdGVyZWQkd29qZXdvZHp0d28pWzEzOjE2XQ0KDQpgYGANCg0KDQpgYGB7cn0NCiMgT2JsaWN6YW5pZSByb3prxYJhZMOzdyBLREUgaSBkeXN0cnlidWFudA0KIyBFc3R5bWFjamEgZGxhIGthxbxkZWoga29tYmluYWNqaSB3b2pld8OzZHp0d2EgaSBwxYJjaQ0Ka2RlX3Jlc3VsdHMgPC0gZGF0YV9maWx0ZXJlZCAlPiUNCiAgZ3JvdXBfYnkod29qZXdvZHp0d28sIHBsZWMpICU+JQ0KICBzdW1tYXJpc2UoZGVuc2l0eSA9IGxpc3QoZGVuc2l0eShncDY0LCBuYS5ybSA9IFRSVUUpKSwgLmdyb3VwcyA9ICJkcm9wIikNCg0KY2RmX3Jlc3VsdHMgPC0gZGF0YV9maWx0ZXJlZCAlPiUNCiAgZ3JvdXBfYnkod29qZXdvZHp0d28sIHBsZWMpICU+JQ0KICBzdW1tYXJpc2UoDQogICAgY2RmID0gbGlzdChlY2RmKGdwNjQpKSwNCiAgICAuZ3JvdXBzID0gImRyb3AiDQogICkNCg0KYGBgDQoNCiMjIFd5a3Jlc3kgZ8SZc3RvxZtjaSBpIGR5c3RydWJ1YW50eSBza3VtdWxvd2EgeiBwb2R6aWHFgmVtIG5hIDQgZ3J1cHkgd29qZXfDs2R6dHcgDQoNCmBgYHtyfQ0KDQojIFd5a3JlcyByb3prxYJhZHUgZ8SZc3RvxZtjaSBkbGEgZ3J1cHkgMQ0KcGxvdF9kZW5zaXR5X2dyb3VwMSA8LSBnZ3Bsb3QoZGF0YV9maWx0ZXJlZCAlPiUgZmlsdGVyKHdvamV3b2R6dHdvICVpbiUgd29qX2dyb3VwXzEpLCBhZXMoeCA9IGdwNjQsIGNvbG9yID0gcGxlYykpICsNCiAgZ2VvbV9kZW5zaXR5KCkgKw0KICBmYWNldF93cmFwKH4gd29qZXdvZHp0d28sIHNjYWxlcyA9ICJmcmVlX3kiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUm96a8WCYWQgZ8SZc3RvxZtjaSBkb2Nob2R1IG5ldHRvIChncDY0KSAtIEdydXBhIDEgd29qZXfDs2R6dHciLA0KICAgIHggPSAiRG9jaMOzZCBuZXR0byAoesWCKSIsDQogICAgeSA9ICJHxJlzdG/Fm8SHIiwNCiAgICBjb2xvciA9ICJQxYJlxIciDQogICkgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpjb21tYSwgbGltaXRzID0gYygwLCBxdWFudGlsZShkYXRhX2ZpbHRlcmVkJGdwNjQsIDAuOTkpKSkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLA0KICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksDQogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSkNCg0KIyBXeWtyZXMgcm96a8WCYWR1IGfEmXN0b8WbY2kgZGxhIGdydXB5IDINCnBsb3RfZGVuc2l0eV9ncm91cDIgPC0gZ2dwbG90KGRhdGFfZmlsdGVyZWQgJT4lIGZpbHRlcih3b2pld29kenR3byAlaW4lIHdval9ncm91cF8yKSwgYWVzKHggPSBncDY0LCBjb2xvciA9IHBsZWMpKSArDQogIGdlb21fZGVuc2l0eSgpICsNCiAgZmFjZXRfd3JhcCh+IHdvamV3b2R6dHdvLCBzY2FsZXMgPSAiZnJlZV95IikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlJvemvFgmFkIGfEmXN0b8WbY2kgZG9jaG9kdSBuZXR0byAoZ3A2NCkgLSBHcnVwYSAyIHdvamV3w7NkenR3IiwNCiAgICB4ID0gIkRvY2jDs2QgbmV0dG8gKHrFgikiLA0KICAgIHkgPSAiR8SZc3RvxZvEhyIsDQogICAgY29sb3IgPSAiUMWCZcSHIg0KICApICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6Y29tbWEsIGxpbWl0cyA9IGMoMCwgcXVhbnRpbGUoZGF0YV9maWx0ZXJlZCRncDY0LCAwLjk5KSkpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwNCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpDQojIFd5a3JlcyByb3prxYJhZHUgZ8SZc3RvxZtjaSBkbGEgZ3J1cHkgMw0KcGxvdF9kZW5zaXR5X2dyb3VwMyA8LSBnZ3Bsb3QoZGF0YV9maWx0ZXJlZCAlPiUgZmlsdGVyKHdvamV3b2R6dHdvICVpbiUgd29qX2dyb3VwXzMpLCBhZXMoeCA9IGdwNjQsIGNvbG9yID0gcGxlYykpICsNCiAgZ2VvbV9kZW5zaXR5KCkgKw0KICBmYWNldF93cmFwKH4gd29qZXdvZHp0d28sIHNjYWxlcyA9ICJmcmVlX3kiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUm96a8WCYWQgZ8SZc3RvxZtjaSBkb2Nob2R1IG5ldHRvIChncDY0KSAtIEdydXBhIDMgd29qZXfDs2R6dHciLA0KICAgIHggPSAiRG9jaMOzZCBuZXR0byAoesWCKSIsDQogICAgeSA9ICJHxJlzdG/Fm8SHIiwNCiAgICBjb2xvciA9ICJQxYJlxIciDQogICkgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpjb21tYSwgbGltaXRzID0gYygwLCBxdWFudGlsZShkYXRhX2ZpbHRlcmVkJGdwNjQsIDAuOTkpKSkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLA0KICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksDQogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSkNCiMgV3lrcmVzIHJvemvFgmFkdSBnxJlzdG/Fm2NpIGRsYSBncnVweSA0DQpwbG90X2RlbnNpdHlfZ3JvdXA0IDwtIGdncGxvdChkYXRhX2ZpbHRlcmVkICU+JSBmaWx0ZXIod29qZXdvZHp0d28gJWluJSB3b2pfZ3JvdXBfNCksIGFlcyh4ID0gZ3A2NCwgY29sb3IgPSBwbGVjKSkgKw0KICBnZW9tX2RlbnNpdHkoKSArDQogIGZhY2V0X3dyYXAofiB3b2pld29kenR3bywgc2NhbGVzID0gImZyZWVfeSIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJSb3prxYJhZCBnxJlzdG/Fm2NpIGRvY2hvZHUgbmV0dG8gKGdwNjQpIC0gR3J1cGEgNCB3b2pld8OzZHp0dyIsDQogICAgeCA9ICJEb2Now7NkIG5ldHRvICh6xYIpIiwNCiAgICB5ID0gIkfEmXN0b8WbxIciLA0KICAgIGNvbG9yID0gIlDFgmXEhyINCiAgKSArDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmNvbW1hLCBsaW1pdHMgPSBjKDAsIHF1YW50aWxlKGRhdGFfZmlsdGVyZWQkZ3A2NCwgMC45OSkpKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKQ0KDQoNCiMgV3lrcmVzIGR5c3RyeWJ1YW50eSBza3VtdWxvd2FuZWogZGxhIGdydXB5IDENCnBsb3RfY2RmX2dyb3VwMSA8LSBnZ3Bsb3QoZGF0YV9maWx0ZXJlZCAlPiUgZmlsdGVyKHdvamV3b2R6dHdvICVpbiUgd29qX2dyb3VwXzEpLCBhZXMoeCA9IGdwNjQsIGNvbG9yID0gcGxlYykpICsNCiAgc3RhdF9lY2RmKGdlb20gPSAic3RlcCIpICsNCiAgZmFjZXRfd3JhcCh+IHdvamV3b2R6dHdvLCBzY2FsZXMgPSAiZnJlZV95IikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkR5c3RyeWJ1YW50YSBza3VtdWxvd2FuYSBkb2Nob2R1IG5ldHRvIChncDY0KSAtIEdydXBhIDEgd29qZXfDs2R6dHciLA0KICAgIHggPSAiRG9jaMOzZCBuZXR0byAoesWCKSIsDQogICAgeSA9ICJQcmF3ZG9wb2RvYmllxYRzdHdvIHNrdW11bG93YW5lIiwNCiAgICBjb2xvciA9ICJQxYJlxIciDQogICkgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpjb21tYSwgbGltaXRzID0gYygwLCBxdWFudGlsZShkYXRhX2ZpbHRlcmVkJGdwNjQsIDAuOTkpKSkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLA0KICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksDQogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSkNCg0KIyBXeWtyZXMgZHlzdHJ5YnVhbnR5IHNrdW11bG93YW5laiBkbGEgZ3J1cHkgMg0KcGxvdF9jZGZfZ3JvdXAyIDwtIGdncGxvdChkYXRhX2ZpbHRlcmVkICU+JSBmaWx0ZXIod29qZXdvZHp0d28gJWluJSB3b2pfZ3JvdXBfMiksIGFlcyh4ID0gZ3A2NCwgY29sb3IgPSBwbGVjKSkgKw0KICBzdGF0X2VjZGYoZ2VvbSA9ICJzdGVwIikgKw0KICBmYWNldF93cmFwKH4gd29qZXdvZHp0d28sIHNjYWxlcyA9ICJmcmVlX3kiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiRHlzdHJ5YnVhbnRhIHNrdW11bG93YW5hIGRvY2hvZHUgbmV0dG8gKGdwNjQpIC0gR3J1cGEgMiB3b2pld8OzZHp0dyIsDQogICAgeCA9ICJEb2Now7NkIG5ldHRvICh6xYIpIiwNCiAgICB5ID0gIlByYXdkb3BvZG9iaWXFhHN0d28gc2t1bXVsb3dhbmUiLA0KICAgIGNvbG9yID0gIlDFgmXEhyINCiAgKSArDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmNvbW1hLCBsaW1pdHMgPSBjKDAsIHF1YW50aWxlKGRhdGFfZmlsdGVyZWQkZ3A2NCwgMC45OSkpKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKQ0KIyBXeWtyZXMgZHlzdHJ5YnVhbnR5IHNrdW11bG93YW5laiBkbGEgZ3J1cHkgMw0KcGxvdF9jZGZfZ3JvdXAzIDwtIGdncGxvdChkYXRhX2ZpbHRlcmVkICU+JSBmaWx0ZXIod29qZXdvZHp0d28gJWluJSB3b2pfZ3JvdXBfMyksIGFlcyh4ID0gZ3A2NCwgY29sb3IgPSBwbGVjKSkgKw0KICBzdGF0X2VjZGYoZ2VvbSA9ICJzdGVwIikgKw0KICBmYWNldF93cmFwKH4gd29qZXdvZHp0d28sIHNjYWxlcyA9ICJmcmVlX3kiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiRHlzdHJ5YnVhbnRhIHNrdW11bG93YW5hIGRvY2hvZHUgbmV0dG8gKGdwNjQpIC0gR3J1cGEgMyB3b2pld8OzZHp0dyIsDQogICAgeCA9ICJEb2Now7NkIG5ldHRvICh6xYIpIiwNCiAgICB5ID0gIlByYXdkb3BvZG9iaWXFhHN0d28gc2t1bXVsb3dhbmUiLA0KICAgIGNvbG9yID0gIlDFgmXEhyINCiAgKSArDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmNvbW1hLCBsaW1pdHMgPSBjKDAsIHF1YW50aWxlKGRhdGFfZmlsdGVyZWQkZ3A2NCwgMC45OSkpKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKQ0KIyBXeWtyZXMgZHlzdHJ5YnVhbnR5IHNrdW11bG93YW5laiBkbGEgZ3J1cHkgNA0KcGxvdF9jZGZfZ3JvdXA0IDwtIGdncGxvdChkYXRhX2ZpbHRlcmVkICU+JSBmaWx0ZXIod29qZXdvZHp0d28gJWluJSB3b2pfZ3JvdXBfNCksIGFlcyh4ID0gZ3A2NCwgY29sb3IgPSBwbGVjKSkgKw0KICBzdGF0X2VjZGYoZ2VvbSA9ICJzdGVwIikgKw0KICBmYWNldF93cmFwKH4gd29qZXdvZHp0d28sIHNjYWxlcyA9ICJmcmVlX3kiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiRHlzdHJ5YnVhbnRhIHNrdW11bG93YW5hIGRvY2hvZHUgbmV0dG8gKGdwNjQpIC0gR3J1cGEgNCB3b2pld8OzZHp0dyIsDQogICAgeCA9ICJEb2Now7NkIG5ldHRvICh6xYIpIiwNCiAgICB5ID0gIlByYXdkb3BvZG9iaWXFhHN0d28gc2t1bXVsb3dhbmUiLA0KICAgIGNvbG9yID0gIlDFgmXEhyINCiAgKSArDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmNvbW1hLCBsaW1pdHMgPSBjKDAsIHF1YW50aWxlKGRhdGFfZmlsdGVyZWQkZ3A2NCwgMC45OSkpKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKQ0KDQojIFd5xZt3aWV0bGFuaWUgd3lrcmVzw7N3DQpwcmludChwbG90X2RlbnNpdHlfZ3JvdXAxKQ0KcHJpbnQocGxvdF9kZW5zaXR5X2dyb3VwMikNCnByaW50KHBsb3RfZGVuc2l0eV9ncm91cDMpDQpwcmludChwbG90X2RlbnNpdHlfZ3JvdXA0KQ0KcHJpbnQocGxvdF9jZGZfZ3JvdXAxKQ0KcHJpbnQocGxvdF9jZGZfZ3JvdXAyKQ0KcHJpbnQocGxvdF9jZGZfZ3JvdXAzKQ0KcHJpbnQocGxvdF9jZGZfZ3JvdXA0KQ0KDQpgYGANCg0KDQpBbmFsaXp1asSFYyB6YXLDs3dubyBnxJlzdG/Fm2NpLCBqYWsgaSBkeXN0cnlidWFudHkgcm96a8WCYWTDs3csIHphdXdhxbxhbXksIMW8ZSBrb2JpZXR5IG1hasSFIG5pxbxzenkgZG9jaMOzZCBuZXR0byBuacW8IG3EmcW8Y3p5xbpuaS4gU3pjenl0eSAobW9keSkgcm96a8WCYWTDs3cgZ8SZc3RvxZtjaSBkbGEga29iaWV0IHpuYWpkdWrEhSBzacSZIG5hIG5pxbxzenljaCB3YXJ0b8WbY2lhY2ggbmnFvCB1IG3EmcW8Y3p5em4uIFBvZG9ibmUgb2JzZXJ3YWNqZSBtb8W8ZW15IHBvY3p5bmnEhyBuYSB3eWtyZXNhY2ggZHlzdHJ5YnVhbnR5IHNrdW11bG93YW5laiwgZ2R6aWUga3J6eXdlIGRsYSBrb2JpZXQgcm9zbsSFIHN6eWJjaWVqIGkgcG96aW9tdWrEhSBzacSZLCBvc2nEhWdhasSFYyA3NSUgdyBva29saWNhY2ggMyAwMDAgesWCLCBwb2RjemFzIGdkeSB1IG3EmcW8Y3p5em4gd2FydG/Fm8SHIGR5c3RyeWJ1YW50eSBuYSB0eW0gc2FteW0gcG96aW9taWUgd3lub3NpIG9rb8WCbyA1MCUuIFLDs8W8bmljZSB0ZSB6bWllbmlhasSFIHNpxJkgdyB6YWxlxbxub8WbY2kgb2Qgd29qZXfDs2R6dHdhLCBhbGUgb2fDs2xuaWUgbW/FvG5hIHN0d2llcmR6acSHLCDFvGUgdyBrYcW8ZHltIHogbmljaCBtxJnFvGN6ecW6bmkgbWFqxIUgd3nFvHN6eSBkb2Now7NkIG5ldHRvIG1pZXNpxJljem55LiBOYWp3acSZa3N6YSByw7N6bmljYSBtacSZZHp5IGRvY2hvZGFtaSBwb21pxJlkenkga29iaWV0YW1pLCBhIG3EmcW8Y3p5em5hbWkgbWEgbWllanNjZSB3IHdvamV3w7NkenR3YWNoOiDFmmzEhXNraW0gaSBLdWphd3Nrby1wb21vcnNraW0uIE5ham1uaWVqc3phIHoga29sZWkgdyB3b2pld8OzZHp0d2FjaDpXYXJtacWEc2tvLW1henVyc2tpbSBpIEx1YnVza2ltLg0K