1. Gunakan simulasi untuk menghitung nilai pendekatan dari E[X²] untuk variabel random berdistribusi Uniform jika X ~ U(0,1). Gunakan 10.000 angka random.

n <- 10000
x <- runif(n, 0, 1)
mean(x^2)
## [1] 0.3295122

Jika \(X \sim \text{Uniform}(0,1)\), maka ekspektasi dari \(X^2\) adalah: \[ \mathbb{E}[X^2] = \int_0^1 x^2 \, dx = \left[ \frac{x^3}{3} \right]_0^1 = \frac{1}{3} \]

2. Buat masing-masing untuk n1 = 100, n2 = 1000, n3 = 10000 angka random dari N(100, 15²), lalu hitung rata-rata, simpangan baku, dan plot histogram. Berikan penjelasan hasil yang Saudara peroleh.

n_list <- c(100, 1000, 10000)
mean_list <- c()
sd_list <- c()

for (n in n_list) {
  data <- rnorm(n, mean = 100, sd = 15)
  hist(data, main = paste("Histogram N =", n), xlab = "X", col = "skyblue", breaks = 20)
  mean_list <- c(mean_list, mean(data))
  sd_list <- c(sd_list, sd(data))
}

data.frame(N = n_list, Mean = mean_list, SD = sd_list)
##       N     Mean       SD
## 1   100 101.2488 14.23113
## 2  1000 100.1425 15.07417
## 3 10000 100.0786 15.26400

Dari hasil histogram dan statistik deskriptif, semakin besar ukuran sampel, maka distribusi mendekati distribusi normal dengan parameter populasi.

3. Simulasikan distribusi binomial Bin(30, 0.25) sebanyak 5000 kali. Tentukan nilai estimasikan P(X ≥ 15).

sim_binom <- rbinom(500, size = 30, prob = 0.25)
hist(sim_binom, col = "orange", main = "Histogram Simulasi Binomial", xlab = "Jumlah Sukses")

mean(sim_binom)
## [1] 7.538
var(sim_binom)
## [1] 5.575707

Kesimpulan:

4. Buatlah function untuk rumus berikut:

\[ s = \sqrt{ \frac{\sum x^2 - \frac{(\sum x)^2}{n}}{n - 1} } \] Hitung nilai𝑠dengan membangkitkan data berdistribusi normal sebanyak data 1000, rata-rata 89, dan standar deviasi 10.

s_manual <- function(x) {
  n <- length(x)
  sqrt((sum(x^2) - (sum(x)^2) / n) / (n - 1))
}

data_norm <- rnorm(1000, mean = 89, sd = 10)
s_manual(data_norm)
## [1] 10.09124
sd(data_norm)  # Bandingkan dengan fungsi built-in
## [1] 10.09124

5. Simulasi Antrian di Bank) Sebuah bank memiliki 2 teller dengan kondisi berikut:

Kerjakanlah tugas berikut:

  1. Buatlah simulasi antrian selama 20 hari kerja
set.seed(123)

# Parameter
jam_operasi <- 6
rata_datang_per_jam <- 5
jumlah_teller <- 2
lama_hari <- 20
rata_pelayanan <- 8  # dalam menit

# Konversi waktu ke menit
waktu_hari <- jam_operasi * 60

# Simulasi 20 hari
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
hasil_simulasi <- list()

for (hari in 1:lama_hari) {
  jumlah_nasabah <- rpois(1, rata_datang_per_jam * jam_operasi)
  waktu_kedatangan <- sort(runif(jumlah_nasabah, min = 0, max = waktu_hari))
  waktu_pelayanan <- rexp(jumlah_nasabah, rate = 1/rata_pelayanan)
  
  selesai <- rep(0, jumlah_nasabah)
  mulai <- rep(0, jumlah_nasabah)
  antrian <- rep(0, jumlah_nasabah)
  teller_tersedia <- rep(0, jumlah_teller)
  
  for (i in 1:jumlah_nasabah) {
    mulai[i] <- max(waktu_kedatangan[i], min(teller_tersedia))
    selesai[i] <- mulai[i] + waktu_pelayanan[i]
    antrian[i] <- mulai[i] - waktu_kedatangan[i]
    
    teller_id <- which.min(teller_tersedia)
    teller_tersedia[teller_id] <- selesai[i]
  }
  
  hasil_simulasi[[hari]] <- data.frame(
    hari = hari,
    datang = waktu_kedatangan,
    mulai = mulai,
    selesai = selesai,
    tunggu = antrian,
    durasi = waktu_pelayanan
  )
}

# Gabungkan semua hari
simulasi_df <- bind_rows(hasil_simulasi)
  1. Hitung rata-rata waktu tunggu nasabah
rata_tunggu <- mean(simulasi_df$tunggu)
rata_tunggu  # dalam menit
## [1] 1.136017
  1. Hitung persen waktu teller sibuk bekerja
total_pelayanan <- sum(simulasi_df$durasi)
total_waktu_teller <- jumlah_teller * waktu_hari * lama_hari
persentase_sibuk <- total_pelayanan / total_waktu_teller * 100
persentase_sibuk  # dalam persen
## [1] 33.25149
  1. Bandingkan jikan bank menambah 1 teller lagi - apakah lebih efisiensi?
# Ulangi simulasi dengan 3 teller
jumlah_teller_baru <- 3
hasil_simulasi3 <- list()

for (hari in 1:lama_hari) {
  jumlah_nasabah <- rpois(1, rata_datang_per_jam * jam_operasi)
  waktu_kedatangan <- sort(runif(jumlah_nasabah, min = 0, max = waktu_hari))
  waktu_pelayanan <- rexp(jumlah_nasabah, rate = 1/rata_pelayanan)
  
  selesai <- rep(0, jumlah_nasabah)
  mulai <- rep(0, jumlah_nasabah)
  antrian <- rep(0, jumlah_nasabah)
  teller_tersedia <- rep(0, jumlah_teller_baru)
  
  for (i in 1:jumlah_nasabah) {
    mulai[i] <- max(waktu_kedatangan[i], min(teller_tersedia))
    selesai[i] <- mulai[i] + waktu_pelayanan[i]
    antrian[i] <- mulai[i] - waktu_kedatangan[i]
    
    teller_id <- which.min(teller_tersedia)
    teller_tersedia[teller_id] <- selesai[i]
  }
  
  hasil_simulasi3[[hari]] <- data.frame(
    hari = hari,
    datang = waktu_kedatangan,
    mulai = mulai,
    selesai = selesai,
    tunggu = antrian,
    durasi = waktu_pelayanan
  )
}

simulasi_df3 <- bind_rows(hasil_simulasi3)

# Bandingkan waktu tunggu rata-rata
mean(simulasi_df$tunggu)    # teller 2
## [1] 1.136017
mean(simulasi_df3$tunggu)   # teller 3
## [1] 0.04733909
  1. Buat grafik yang menunjukkan panjang antrian sepanjang hari
library(ggplot2)

simulasi_df$jam <- floor(simulasi_df$datang / 60)

antrian_per_jam <- simulasi_df %>%
  group_by(hari, jam) %>%
  summarise(panjang = n(), .groups = "drop")

# Visualisasi
ggplot(antrian_per_jam, aes(x = jam, y = panjang)) +
  geom_boxplot(fill = "skyblue") +
  labs(title = "Panjang Antrian per Jam (20 Hari)",
       x = "Jam ke- (sejak buka)",
       y = "Jumlah Nasabah") +
  theme_minimal()
## Warning: Continuous x aesthetic
## ℹ did you forget `aes(group = ...)`?

6. (Simulasi Toko Kelontong)

Bu Sari memiliki toko kelontong yang menjual beras dengan kondisi sebagai berikut:

Kerjakanlah tugas berikut:

  1. Simulasikan stok beras selama 60 hari
set.seed(123)

simulasi_stok <- function(hari_total = 60, pesan_setiap = 5, jumlah_pesan = 50) {
  stok <- numeric(hari_total)
  penjualan <- numeric(hari_total)
  kekurangan <- numeric(hari_total)
  
  stok[1] <- 100
  
  for (hari in 1:hari_total) {
    # Penjualan harian: uniform 8–15 karung
    jual <- sample(8:15, 1)
    
    # Hitung kekurangan jika stok tidak cukup
    if (stok[hari] >= jual) {
      penjualan[hari] <- jual
      kekurangan[hari] <- 0
    } else {
      penjualan[hari] <- stok[hari]
      kekurangan[hari] <- jual - stok[hari]
    }
    
    # Update stok ke hari berikutnya
    if (hari < hari_total) {
      stok[hari + 1] <- stok[hari] - penjualan[hari]
      
      # Pemesanan ulang
      if (hari %% pesan_setiap == 0) {
        stok[hari + 1] <- stok[hari + 1] + jumlah_pesan
      }
    }
  }
  
  data.frame(Hari = 1:hari_total, Stok = stok, Penjualan = penjualan, Kehabisan = kekurangan)
}

# Simulasi default
hasil_a <- simulasi_stok()
head(hasil_a)
##   Hari Stok Penjualan Kehabisan
## 1    1  100        14         0
## 2    2   86        14         0
## 3    3   72        10         0
## 4    4   62        13         0
## 5    5   49        10         0
## 6    6   89         9         0

Di atas mensimulasikan jumlah stok harian berdasarkan penjualan dan jadwal pemesanan ulang.

  1. Hitung berapa kali toko kehabisan stok
jumlah_kekurangan <- sum(hasil_a$Kehabisan > 0)
total_rugi <- sum(hasil_a$Kehabisan) * 50000

jumlah_kekurangan
## [1] 3
total_rugi
## [1] 9e+05

Menunjukkan berapa hari stok tidak mencukupi, dan total kerugian akibat kehilangan penjualan.

  1. Coba berbagai strategi: pesan 40, 50 atau 60 karung. manakah yang terbaik?
strategi <- c(40, 50, 60)
hasil_c <- lapply(strategi, function(jml) {
  df <- simulasi_stok(jumlah_pesan = jml)
  data.frame(
    Pesan = jml,
    KehabisanHari = sum(df$Kehabisan > 0),
    Rugi = sum(df$Kehabisan) * 50000
  )
})
do.call(rbind, hasil_c)
##   Pesan KehabisanHari    Rugi
## 1    40            17 8350000
## 2    50             9 3950000
## 3    60             0       0

Kesimpulan:

  1. Coba ubah frekuensi pesan: setiap 3, 5 atau 7 hari. manakah yang optimal?
frekuensi <- c(3, 5, 7)
hasil_d <- lapply(frekuensi, function(freq) {
  df <- simulasi_stok(pesan_setiap = freq)
  data.frame(
    Frekuensi = freq,
    KehabisanHari = sum(df$Kehabisan > 0),
    Rugi = sum(df$Kehabisan) * 50000
  )
})
do.call(rbind, hasil_d)
##   Frekuensi KehabisanHari    Rugi
## 1         3             0       0
## 2         5             2  700000
## 3         7            17 8700000

Kesimpulan:

  1. Buat grafik pergerakan stok dan rekomendasi untuk Bu sari
library(ggplot2)

ggplot(hasil_a, aes(x = Hari, y = Stok)) +
  geom_line(color = "darkgreen", size = 1.2) +
  geom_point(data = hasil_a[hasil_a$Kehabisan > 0, ], aes(x = Hari, y = Stok),
             color = "red", size = 2) +
  labs(title = "Pergerakan Stok Beras Selama 60 Hari",
       subtitle = "Titik merah = stok tidak cukup",
       x = "Hari",
       y = "Jumlah Stok Karung") +
  theme_minimal()
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

Rekomendasi Bu Sari: