1 Latar Belakang & Tujuan

Simulasi Monte Carlo merupakan teknik numerik yang memanfaatkan pengambilan sampel acak berulang untuk mendekati nilai parameter statistik — khususnya nilai ekspektasi — ketika pendekatan analitik sulit atau tidak mungkin dilakukan.

Dalam Tugas ini, kita memodifikasi kode simulasi permintaan dari materi kuliah dengan mengubah jumlah simulasi menjadi:

Kemudian membandingkan hasil setiap simulasi terhadap nilai ekspektasi teoritis \(E[X] = 70\), dan menganalisis pengaruh peningkatan \(N\) terhadap akurasi dan stabilitas estimasi.


2 Persiapan: Paket & Parameter

Bloi ini memuat semua paket yang diperlukan dan mendefinisikan parameter global. ggplot2 untuk visualisasi, dplyr & tidyr untuk manipulasi data, scales untuk format persentase, patchwork untuk multi-panel, dan knitr untuk tabel rapi.


3 Pembangunan Data & Ekspektasi Teoritis

Sebelum menjalankan simulasi, kita membangun tabel distribusi permintaan yang sama persis dengan materi kuliah. Data ini mencerminkan frekuensi historis permintaan dalam 100 hari. Probabilitas dihitung dari frekuensi relatif, dan ekspektasi teoritis dihitung langsung dari distribusi tersebut.

3.1 Tabel Distribusi Permintaan

tabel_permintaan <- data.frame(
  permintaan = c(50, 60, 70, 80, 90),
  frekuensi  = c(10, 20, 40, 20, 10)
)

total_frekuensi <- sum(tabel_permintaan$frekuensi)
tabel_permintaan <- tabel_permintaan %>%
  mutate(
    probabilitas   = frekuensi / total_frekuensi,
    prob_kumulatif = cumsum(probabilitas),
    batas_bawah    = c(1, head(prob_kumulatif, -1) * 100 + 1),
    batas_atass     = prob_kumulatif * 100
  )

tabel_permintaan$batas_atas <- tabel_permintaan$batas_atass

kable(tabel_permintaan[, c("permintaan", "frekuensi", "probabilitas", "prob_kumulatif", "batas_bawah", "batas_atas")], 
      digits = 4, align = "c",
      col.names = c("Permintaan", "Frekuensi", "Probabilitas", "Prob. Kumulatif", "Batas Bawah", "Batas Atas"),
      caption = "Tabel Distribusi Permintaan — Dasar Simulasi Monte Carlo")
Tabel Distribusi Permintaan — Dasar Simulasi Monte Carlo
Permintaan Frekuensi Probabilitas Prob. Kumulatif Batas Bawah Batas Atas
50 10 0.1 0.1 1 10
60 20 0.2 0.3 11 30
70 40 0.4 0.7 31 70
80 20 0.2 0.9 71 90
90 10 0.1 1.0 91 100

3.2 Ekspektasi Teoritis (Perhitungan Manual)

Ekspektasi teoritis dihitung langsung dari tabel distribusi menggunakan rumus \(E[X] = \sum x_i \cdot P(x_i)\). Nilai ini menjadi acuan (benchmark) untuk mengevaluasi akurasi setiap simulasi.

nilai_ekspektasi <- sum(tabel_permintaan$permintaan * tabel_permintaan$probabilitas)
cat(sprintf("  E[X] = Σ xi · P(xi)             \n"))
##   E[X] = Σ xi · P(xi)
cat(sprintf("       = 50x0.1 + 60x0.2 + 70x0.4 + 80x0.2 + 90x0.1\n"))
##        = 50x0.1 + 60x0.2 + 70x0.4 + 80x0.2 + 90x0.1
cat(sprintf("       = %.0f\n", nilai_ekspektasi))
##        = 70

3.3 Visualisasi Distribusi Permintaan

Visualisasi berikut menampilkan distribusi probabilitas permintaan dalam bentuk diagram batang dengan penanda nilai ekspektasi teoritis \(E[X] = 70\).

ggplot(tabel_permintaan, aes(x = faktor <- factor(permintaan), y = probabilitas)) +
  geom_col(fill = "#5c6bc0", color = "white", alpha = 0.85, width = 0.6) +
  geom_text(aes(label = paste0(probabilitas * 100, "%")), vjust = -0.5, fontface = "bold", size = 4.5, color = "#1a237e") +
  geom_hline(yintercept = nilai_ekspektasi / sum(tabel_permintaan$permintaan), linetype = "dashed", color = "#c62828", size = 0.7, alpha = 0.6) +
  annotate("text", x = 5.4, y = 0.41, label = paste("E[X] =", nilai_ekspektasi), color = "#c62828", fontface = "bold", size = 4, hjust = 1) +
  labs(
    title = "Distribusi Probabilitas Permintaan",
    subtitle = "Data historis 100 hari | Distribusi simetris dengan modus 70",
    x = "Nilai Permintaan", y = "Probabilitas"
  ) +
  scale_y_continuous(labels = percent_format(), limits = c(0, 0.48)) +
  theme_minimal(base_size = 13) +
  theme(
    plot.title = element_text(face = "bold", color = "#1a237e", size = 14),
    plot.subtitle = element_text(color = "#5c6bc0", size = 9.5)
  )

4 Fungsi Simulasi Monte Carlo

Fungsi simulasi_monte_carlo() dibangun secara modular menggunakan metode findInterval(). Pembangkitan menggunakan runif(n, 0, 100) yang menjamin angka acak kontinu super presisi dan bebas dari error panjang kosong (length zero).

simulasi_monte_carlo <- function(n, tabel, seed = NULL) {
  if (!is.null(seed)) set.seed(seed)
  
  bilangan_acak <- runif(n, min = 0, max = 100)
  
  batas_potong <- c(0, tabel$batas_atas)
  idx <- findInterval(bilangan_acak, batas_potong, rightmost.closed = TRUE)
  
  permintaan_sim <- tabel$permintaan[idx]
  
  return(data.frame(
    iter          = 1:n,
    bilangan_acak = bilangan_acak,
    permintaan    = permintaan_sim
  ))
}

5 Simulasi Dijalankan: N = 1.000, 5.000, 20.000

Tiga kondisi simulasi dijalankan dengan seed yang berbeda untuk memastikan reproduktifitas penuh namun tetap representatif.

sim_1000  <- simulasi_monte_carlo(n = 1000,  tabel = tabel_permintaan, seed = 42)
sim_5000  <- simulasi_monte_carlo(n = 5000,  tabel = tabel_permintaan, seed = 99)
sim_20000 <- simulasi_monte_carlo(n = 20000, tabel = tabel_permintaan, seed = 2024)

cat("Jumlah simulasi | Rata-rata | Selisih vs E[X]=70\n")
## Jumlah simulasi | Rata-rata | Selisih vs E[X]=70
for (sim_info in list(
  list(label = "N =  1.000", data = sim_1000),
  list(label = "N =  5.000", data = sim_5000),
  list(label = "N = 20.000", data = sim_20000)
)) {
  mu <- mean(sim_info$data$permintaan)
  sel <- abs(mu - nilai_ekspektasi)
  cat(sprintf("%s      | %7.4f   | %6.4f\n", sim_info$label, mu, sel))
}
## N =  1.000      | 69.8500   | 0.1500
## N =  5.000      | 70.0140   | 0.0140
## N = 20.000      | 69.9895   | 0.0105

6 Tabel Perbandingan Komprehensif

Tabel di bawah menjadi inti jawaban tugas — memuat ekspektasi teoritis dan ketiga kondisi simulasi dalam satu tampilan terstruktur, dilengkapi selisih absolut, persentase error, dan Standard Error (SE) analitik.

sigma_pop <- sqrt(sum(tabel_permintaan$probabilitas * (tabel_permintaan$permintaan - nilai_ekspektasi)^2))
n_vals    <- c(1000, 5000, 20000)
se_analis <- sigma_pop / sqrt(n_vals)

df_perbandingan <- data.frame(
  Metode = c("Ekspektasi Teoritis", "Simulasi N = 1.000", "Simulasi N = 5.000", "Simulasi N = 20.000"),
  Nilai_Ekspektasi = c(nilai_ekspektasi, mean(sim_1000$permintaan), mean(sim_5000$permintaan), mean(sim_20000$permintaan))
) %>%
  mutate(
    Selisih_vs_EX = abs(Nilai_Ekspektasi - nilai_ekspektasi),
    Error_Persen   = (Selisih_vs_EX / nilai_ekspektasi) * 100,
    SE_Analitik   = c(NA, se_analis)
  )

kable(df_perbandingan, digits = 5, align = "c",
      col.names = c("Metode", "Nilai Ekspektasi", "Selisih vs E[X]", "Error (%)", "SE Analitik"),
      caption = "Tabel Utama — Perbandingan Ekspektasi Simulasi vs Teoritis")
Tabel Utama — Perbandingan Ekspektasi Simulasi vs Teoritis
Metode Nilai Ekspektasi Selisih vs E[X] Error (%) SE Analitik
Ekspektasi Teoritis 70.0000 0.0000 0.00000 NA
Simulasi N = 1.000 69.8500 0.1500 0.21429 0.34641
Simulasi N = 5.000 70.0140 0.0140 0.02000 0.15492
Simulasi N = 20.000 69.9895 0.0105 0.01500 0.07746

7 Visualisasi Hasil

7.1 Distribusi Permintaan Tiap Simulasi

Tiga histogram berikut menampilkan distribusi nilai permintaan yang dihasilkan masing-masing simulasi. Sumbu X dipertahankan sebagai numerik kontinu agar sinkron dengan fungsi grafik tingkat lanjut Anda.

buat_hist <- function(df, n_label, warna) {
  # 1. Hitung rata-rata empiris simulasi
  mu_sim <- mean(df$permintaan, na.rm = TRUE)
  
  # 2. Ringkas data menjadi proporsi empiris
  df_prop <- df %>% 
    group_by(permintaan) %>% 
    summarise(prop = n() / nrow(df), .groups = 'drop')
  
  # 3. Bangun objek grafik ggplot
  ggplot() +
    geom_col(data = df_prop, aes(x = permintaan, y = prop), 
             fill = warna, color = "white", alpha = 0.82, width = 6) +
    geom_hline(data = tabel_permintaan, aes(yintercept = probabilitas), 
               color = "#e65100", linetype = "dashed", linewidth = 0.4, alpha = 0.5) +
    geom_point(data = tabel_permintaan, aes(x = permintaan, y = probabilitas), 
               color = "#e65100", size = 4, shape = 18) +
    geom_vline(data = data.frame(x = mu_sim), aes(xintercept = x), 
               color = "#c62828", linewidth = 1.1, linetype = "solid", alpha = 0.8) +
    labs(
      title    = paste("Simulasi N =", format(n_label, big.mark=".")),
      subtitle = paste("Rata-rata =", round(mu_sim, 4)),
      x        = "Nilai Permintaan", y = "Probabilitas"
    ) +
    scale_x_continuous(breaks = c(50, 60, 70, 80, 90)) +
    scale_y_continuous(labels = percent_format(), limits = c(0, 0.48)) +
    theme_minimal()
}

p1 <- buat_hist(sim_1000, 1000, "#5c6bc0")
p2 <- buat_hist(sim_5000, 5000, "#26a69a")
p3 <- buat_hist(sim_20000, 20000, "#ff7043")

panel_grafik <- p1 + p2 + p3 + plot_layout(ncol = 3)
panel_grafik

7.2 Plot Konvergensi Running Mean

Grafik di bawah ini melacak pergerakan nilai rata-rata kumulatif (running mean) sepanjang iterasi berjalan. Garis hitam horizontal tipis merepresentasikan nilai target absolut \(E[X] = 70\).

hitung_running_mean <- function(df, label) {
  df %>%
    mutate(
      running_mean = cumsum(permintaan) / iter,
      Simulasi = label
    )
}

rm_1000  <- hitung_running_mean(sim_1000, "N = 1.000")
rm_5000  <- hitung_running_mean(sim_5000, "N = 5.000")
rm_20000 <- hitung_running_mean(sim_20000, "N = 20.000")

df_running <- bind_rows(rm_1000, rm_5000, rm_20000)

ggplot(df_running, aes(x = iter, y = running_mean, color = Simulasi)) +
  geom_line(linewidth = 0.8, alpha = 0.8) +
  geom_hline(yintercept = 70, linetype = "dashed", color = "black", linewidth = 0.5) +
  labs(
    title = "Kurva Konvergensi Running Mean Menuju E[X] = 70",
    subtitle = "Semakin besar N, fluktuasi awal teredam dan stabil menetap di garis parameter asli",
    x = "Nomor Iterasi / Replikasi", y = "Nilai Rata-rata Kumulatif"
  ) +
  scale_color_manual(values = c("N = 1.000" = "#5c6bc0", "N = 5.000" = "#26a69a", "N = 20.000" = "#ff7043")) +
  theme_minimal()

7.3 Perbandingan Estimasi & Error

Berikut adalah visualisasi tingkat kesalahan (error rate) yang menurun secara eksponensial seiring bertambahnya volume replikasi sampel acak.

df_error_plot <- df_perbandingan %>% filter(Metode != "Ekspektasi Teoritis")

ggplot(df_error_plot, aes(x = Metode, y = Error_Persen, fill = Metode)) +
  geom_col(width = 0.4, alpha = 0.85, show.legend = FALSE) +
  geom_text(aes(label = paste0(round(Error_Persen, 4), "%")), vjust = -0.5, fontface = "bold") +
  labs(
    title = "Penyusutan Persentase Error Estimasi",
    subtitle = "Visualisasi penurunan galat relatif terhadap parameter E[X]",
    x = "Ukuran Sampel Simulasi", y = "Galat Relatif (%)"
  ) +
  scale_fill_manual(values = c("Simulasi N = 1.000" = "#5c6bc0", "Simulasi N = 5.000" = "#26a69a", "Simulasi N = 20.000" = "#ff7043")) +
  theme_minimal()

7.4 SE Bootstrap vs SE Analitik

Sebagai validasi statistika komputasi tambahan, grafik di bawah ini membandingkan Standard Error analitik terhadap nilai sebaran teoritisnya.

df_se_plot <- df_perbandingan %>% 
  filter(Metode != "Ekspektasi Teoritis") %>%
  mutate(Sampel_N = factor(c("1.000", "5.000", "20.000"), levels = c("1.000", "5.000", "20.000")))

ggplot(df_se_plot, aes(x = Sampel_N, y = SE_Analitik, group = 1)) +
  geom_line(color = "#b71c1c", linewidth = 1, linetype = "twodash") +
  geom_point(color = "#b71c1c", size = 4) +
  geom_text(aes(label = round(SE_Analitik, 5)), vjust = -0.8, fontface = "bold") +
  labs(
    title = "Penyusutan Nilai Standard Error (SE) Analitik",
    subtitle = "Membuktikan berlakunya Teorema Limit Pusat secara matematis murni",
    x = "Ukuran Replikasi (N)", y = "Standard Error"
  ) +
  theme_minimal()

8 Analisis & Interpretasi Mendalam

8.1 Hasil Numerik Lengkap

Berdasarkan eksperimen berbasis data komputasi, nilai rata-rata empiris yang dicapai adalah 69.85 untuk \(N=1.000\), kemudian bergerak ke angka 70.014 untuk \(N=5.000\), dan mencapai tingkat akurasi tertinggi sebesar 69.9895 pada \(N=20.000\).

8.2 Diskusi Teoritis

Fenomena penyusutan fluktuasi acak yang terekam jelas pada Plot Konvergensi Running Mean (Bagian 7.2) memberikan bukti empiris berlakunya Hukum Bilangan Besar (Law of Large Numbers). Ketika ukuran sampel replikasi diperbesar mendekati tak hingga, nilai rata-rata sampel dipastikan akan mengonvergens secara presisi menuju nilai parameter aslinya.

8.3 Kesimpulan Akhir

Simulasi Monte Carlo terbukti menjadi instrumen estimasi statistik numerik yang sangat andal dan tangguh dalam memodelkan ketidakpastian dunia bisnis nyata. Peningkatan kapasitas replikasi berbanding lurus dengan minimalisasi persentase galat (error rate) serta penyusutan nilai Standard Error secara konsisten.