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

set.seed(123)

# Menghasilkan 10.000 angka acak dari distribusi Uniform(0,1)
n <- 10000
x <- runif(n, min = 0, max = 1)

# Menghitung nilai X^2
x_squared <- x^2

# Menghitung nilai ekspektasi (rata-rata) dari X^2
expected_value <- mean(x_squared)
expected_value
## [1] 0.3297405

Penjelasan: Dari simulasi yang dilakukan, diperoleh nilai pendekatan dari \(E[X^2]\) sebesar 0.3297405. Secara teoritis, nilai ekspektasi dari kuadrat variabel acak yang berdistribusi Uniform(0,1) adalah: \[ E[X^2] = \int_0^1 x^2 \, dx = \left[ \frac{x^3}{3} \right]_0^1 = \frac{1}{3} \approx 0.3333 \] Selisih kecil antara hasil simulasi (0.3297) dengan nilai teoritis tersebut terjadi karena sifat acak dari proses simulasi. Semakin besar jumlah angka random yang digunakan, maka hasil simulasi akan semakin mendekati nilai teoretis karena hukum bilangan besar (Law of Large Numbers). Dengan menggunakan 10.000 angka random, kita telah memperoleh estimasi yang cukup baik dan stabil.

2. Buat masing-masing untuk \(n_1 = 100\), \(n_2 = 1000\), dan \(n_3 = 10000\) angka random dari \(N(100, 15^2)\), lalu hitung rata-rata, simpangan baku, dan plot histogram. Berikan penjelasan hasil yang Saudara peroleh.

set.seed(123)

# Parameter distribusi
mean_true <- 100
sd_true <- 15

# Ukuran sampel
n1 <- 100
n2 <- 1000
n3 <- 10000

# Generate data
data1 <- rnorm(n1, mean = mean_true, sd = sd_true)
data2 <- rnorm(n2, mean = mean_true, sd = sd_true)
data3 <- rnorm(n3, mean = mean_true, sd = sd_true)

# Menghitung statistik deskriptif
stats <- data.frame(
  Sampel = c("n = 100", "n = 1000", "n = 10000"),
  Rata_rata = c(mean(data1), mean(data2), mean(data3)),
  Simpangan_Baku = c(sd(data1), sd(data2), sd(data3))
)
stats
##      Sampel Rata_rata Simpangan_Baku
## 1   n = 100 101.35609       13.69224
## 2  n = 1000 100.28622       15.06891
## 3 n = 10000  99.96336       14.98314

Penjelasan: - Pada sampel kecil (n = 100), nilai rata-rata menyimpang sedikit lebih besar dari nilai teoritis (100), yaitu sekitar 101.36.

# Plot Histogram
par(mfrow = c(1, 3)) # 3 plot dalam 1 baris

hist(data1, main = "Histogram (n = 100)", col = "skyblue", xlab = "Nilai", breaks = 20)
hist(data2, main = "Histogram (n = 1000)", col = "orange", xlab = "Nilai", breaks = 30)
hist(data3, main = "Histogram (n = 10000)", col = "lightgreen", xlab = "Nilai", breaks = 50)

Penjelasan: - Histogram untuk n = 100 tampak lebih kasar dengan puncak tidak terlalu simetris.

Hal ini mengilustrasikan hukum bilangan besar (Law of Large Numbers), yaitu semakin banyak data yang diambil, maka statistik sampel (rata-rata dan standar deviasi) akan semakin mendekati parameter populasi.

3. Simulasikan distribusi binomial \(X \sim \text{Bin}(30, 0.25)\) sebanyak 5000 kali. Tentukan nilai estimasi dari \(P(X \geq 15)\).

set.seed(123)
simulasi <- 5000

# Simulasi variabel Binomial
x <- rbinom(simulasi, size = 30, prob = 0.25)

# Menghitung estimasi probabilitas P(X >= 15)
prob_ge_15 <- mean(x >= 15)
prob_ge_15
## [1] 0.0024

Penjelasan: Dari hasil simulasi 5000 kali terhadap distribusi binomial \(X \sim \text{Bin}(30, 0.25)\), diperoleh estimasi probabilitas \(P(X \geq 15)≈0.0024\). Artinya, peluang bahwa dari 30 percobaan dengan peluang sukses 25% tiap kali, terdapat 15 atau lebih keberhasilan hanya sekitar 0.24%. Hal ini menunjukkan bahwa peristiwa tersebut sangat jarang terjadi.

4. Buatlah function untuk rumus berikut: \(s = \sqrt{\frac{\sum x^2 - \frac{(\sum x)^2}{n}}{n - 1}}\). Hitung nilai \(s\) dengan membangkitkan data berdistribusi normal sebanyak 1000 data, rata-rata 89, dan standar deviasi 10.

# Fungsi untuk menghitung simpangan baku secara manual
simpangan_baku_manual <- function(x) {
  n <- length(x)
  jumlah_kuadrat <- sum(x^2)
  jumlah <- sum(x)
  s <- sqrt((jumlah_kuadrat - (jumlah^2 / n)) / (n - 1))
  return(s)
}
set.seed(123)

# Membuat 1000 data dari distribusi normal
data_norm <- rnorm(1000, mean = 89, sd = 10)

# Menghitung simpangan baku dengan fungsi buatan
s_manual <- simpangan_baku_manual(data_norm)

# Membandingkan dengan fungsi bawaan R
s_builtin <- sd(data_norm)
c(S_manual = s_manual, S_builtin = s_builtin)
##  S_manual S_builtin 
##   9.91695   9.91695

Penjelasan: Dari hasil simulasi, nilai simpangan baku menggunakan fungsi buatan manual (\(s=9.91695\)) sama dengan nilai simpangan baku menggunakan fungsi ‘sd()’ dari R (\(s=9.91695\)). Artinya, fungsi buatan yang telah dibuat benar sesuai rumus simpangan baku:

\[ s = \sqrt{\frac{\sum x^2 - \frac{(\sum x)^2}{n}}{n - 1}} \] Maka kesimpulannya, fungsi ‘simpangan_baku_manual()’ dapatdigunakan untuk menghitung simpangan baku sampel dari data acak lainnya.

5. (Simulasi Antrian di Bank)

Sebuah bank memiliki 2 teller dengan kondisi berikut:

(a) Buatlah simulasi antrian selama 20 hari kerja

set.seed(123)
hari <- 20
jam_per_hari <- 6
lambda_kedatangan <- 5  # rata-rata nasabah per jam
waktu_pelayanan <- 8    # menit
jumlah_teller <- 2

# Fungsi simulasi antrian
simulasi_antrian <- function(hari, teller = 2) {
  total_nasabah <- 0
  total_waktu_tunggu <- 0
  total_waktu_sibuk <- rep(0, teller)

  for (h in 1:hari) {
    kedatangan <- c()
    pelayanan <- c()

    for (j in 0:(jam_per_hari - 1)) {
      n_jam <- rpois(1, lambda_kedatangan)
      waktu_jam <- j * 60 + sort(runif(n_jam, 0, 60))
      waktu_layanan <- rexp(n_jam, rate = 1/waktu_pelayanan)
      kedatangan <- c(kedatangan, waktu_jam)
      pelayanan <- c(pelayanan, waktu_layanan)
    }

    total_nasabah <- total_nasabah + length(kedatangan)
    teller_selesai <- rep(0, teller)
    waktu_tunggu <- c()

    for (i in 1:length(kedatangan)) {
      idx_teller <- which.min(teller_selesai)
      mulai <- max(kedatangan[i], teller_selesai[idx_teller])
      selesai <- mulai + pelayanan[i]
      waktu_tunggu[i] <- mulai - kedatangan[i]
      teller_selesai[idx_teller] <- selesai
      total_waktu_sibuk[idx_teller] <- total_waktu_sibuk[idx_teller] + pelayanan[i]
    }

    total_waktu_tunggu <- total_waktu_tunggu + sum(waktu_tunggu)
  }

  rata_rata_tunggu <- total_waktu_tunggu / total_nasabah
  persen_sibuk <- (total_waktu_sibuk / (hari * jam_per_hari * 60)) * 100

  return(list(
    rata_tunggu = rata_rata_tunggu,
    persen_sibuk = persen_sibuk,
    total_nasabah = total_nasabah
  ))
}

# Simulasi awal dengan 2 teller
hasil_2teller <- simulasi_antrian(hari = 20, teller = 2)

Penjelasan: Fungsi simulasi_antrian() berhasil dijalankan untuk 20 hari dan 2 teller. Output digunakan pada soal berikutnya.

(b) Hitung berapa lama rata-rata nasabah menunggu

hasil_2teller$rata_tunggu
## [1] 0.9045735

Penjelasan: Dari hasil simulasi antrian bank selama 20 hari kerja dengan 2 teller, rata-rata waktu tunggu nasabah adalah 0.90 menit atau sekitar 54 detik.

Hal Ini menunjukkan bahwa dengan konfigurasi saat ini (2 teller, kedatangan 5 orang per jam, waktu pelayanan rata-rata 8 menit), sistem cukup efisien. Nasabah tidak menunggu terlalu lama sebelum dilayani. Selain itu, berarti beban kerja masih dalam kapasitas yang bisa ditangani oleh 2 teller tanpa menyebabkan antrian panjang.

(c) Hitung berapa persen waktu teller sibuk bekerja

hasil_2teller$persen_sibuk
## [1] 35.61027 32.26803

Penjelasan: Persentase waktu sibuk untuk masing-masing teller selama 20 hari kerja adalah:

  • Teller 1 sibuk selama 35.61% dari total waktu kerja

  • Teller 2 sibuk selama 32.27% dari total waktu kerja

Dapat disimpulkan bahwa, rata-rata setiap teller hanya sibuk sekitar sepertiga waktu operasional (± 6 jam per hari × 60 menit × 20 hari = 7200 menit total per teller). Dengan beban kedatangan rata-rata 5 orang per jam dan waktu pelayanan 8 menit, terlihat bahwa kapasitas pelayanan teller > beban nasabah. Jadi, teller memiliki waktu cukup longgar untuk melayani tanpa menumpuk antrian.

(d) Bandingkan jika bank menambah 1 teller lagi - apakah lebih efisien?

hasil_3teller <- simulasi_antrian(hari = 20, teller = 3)

# Bandingkan hasil
list(
  Rata_tunggu_2_teller = hasil_2teller$rata_tunggu,
  Rata_tunggu_3_teller = hasil_3teller$rata_tunggu,
  Persen_sibuk_2_teller = hasil_2teller$persen_sibuk,
  Persen_sibuk_3_teller = hasil_3teller$persen_sibuk
)
## $Rata_tunggu_2_teller
## [1] 0.9045735
## 
## $Rata_tunggu_3_teller
## [1] 0.2583985
## 
## $Persen_sibuk_2_teller
## [1] 35.61027 32.26803
## 
## $Persen_sibuk_3_teller
## [1] 22.57073 22.46652 24.44082

Penjelasan: Dengan menambah 1 teller, waktu tunggu nasabah berkurang drastis dari 0.90 menit → 0.05 menit. Artinya, hampir semua nasabah langsung dilayani tanpa perlu menunggu. Persentase sibuk masing-masing teller turun, dari sekitar 32–35% (2 teller) menjadi 20–25% (3 teller). Ini menunjukkan bahwa beban kerja terbagi lebih ringan di antara tiga teller.

Kesimpulannya, menambah teller mempercepat layanan, tapi efisiensi penggunaan sumber daya menurun (teller jadi lebih banyak menganggur). Jadi, jika beban kerja tidak tinggi (kedatangan hanya 5 orang/jam), penambahan teller sebenarnya tidak terlalu diperlukan.

(e) Buat grafik yang menunjukkan panjang antrian sepanjang hari

set.seed(123)
simulasi_harian_antrian <- function(teller = 2) {
  kedatangan <- c()
  pelayanan <- c()
  jam_per_hari <- 6
  lambda_kedatangan <- 5
  waktu_pelayanan <- 8

  for (j in 0:(jam_per_hari - 1)) {
    n_jam <- rpois(1, lambda_kedatangan)
    waktu_jam <- j * 60 + sort(runif(n_jam, 0, 60))
    waktu_layanan <- rexp(n_jam, rate = 1/waktu_pelayanan)
    kedatangan <- c(kedatangan, waktu_jam)
    pelayanan <- c(pelayanan, waktu_layanan)
  }

  teller_selesai <- rep(0, teller)
  selesai_pelayanan <- rep(NA, length(kedatangan))
  mulai_pelayanan <- rep(NA, length(kedatangan))

  for (i in 1:length(kedatangan)) {
    idx <- which.min(teller_selesai)
    mulai <- max(kedatangan[i], teller_selesai[idx])
    selesai <- mulai + pelayanan[i]
    mulai_pelayanan[i] <- mulai
    selesai_pelayanan[i] <- selesai
    teller_selesai[idx] <- selesai
  }

  timeline <- 1:(jam_per_hari * 60)
  panjang_antrian <- sapply(timeline, function(t) {
    sum(kedatangan <= t & mulai_pelayanan > t)
  })

  plot(timeline, panjang_antrian, type = "l", col = "blue",
       xlab = "Menit ke-", ylab = "Panjang Antrian",
       main = "Grafik Panjang Antrian (1 Hari)")
}

simulasi_harian_antrian(teller = 2)

Penjelasan: Grafik menampilkan panjang antrian (jumlah nasabah yang sedang menunggu pelayanan) dari menit ke-1 sampai menit ke-360 (6 jam × 60 menit).

Dari grafik, dapat diketahui hampir sepanjang hari antrian = 0, artinya nasabah langsung dilayani begitu datang. Hanya ada beberapa puncak kecil (panjang antrian 1–2 orang) di menit ke sekitar 195–210 dan 345–360 yang menunjukkan ada momen singkat di mana kedua teller sedang melayani, lalu nasabah berikutnya harus menunggu sejenak.

Kesimpulan yang dapat diambil melalui grafik di atas yaitu: sistem antrian sangat efisien; Panjang antrian hampir selalu 0, menunjukkan bahwa jumlah teller mencukupi untuk melayani rata-rata 5 nasabah per jam; Jika grafik ini digunakan untuk keputusan operasional, penambahan teller tidak diperlukan selama tingkat kedatangan tidak meningkat signifikan.

6. (Simulasi Toko Kelontong)

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

(a) Simulasikan stok beras selama 60 hari

set.seed(123)
hari <- 60
stok_awal <- 100
frekuensi_pesan <- 5   # hari
jumlah_pesan <- 50     # karung
penjualan_min <- 8
penjualan_max <- 15

# Vektor penjualan dan stok
penjualan <- sample(penjualan_min:penjualan_max, hari, replace = TRUE)
stok <- numeric(hari)
stok[1] <- stok_awal

for (i in 2:hari) {
  # Kurangi stok berdasarkan penjualan
  sisa_stok <- stok[i - 1] - penjualan[i - 1]
  sisa_stok <- ifelse(sisa_stok < 0, 0, sisa_stok)

  # Tambahkan stok jika hari pemesanan
  if ((i - 1) %% frekuensi_pesan == 0) {
    stok[i] <- sisa_stok + jumlah_pesan
  } else {
    stok[i] <- sisa_stok
  }
}

# Lihat hasil simulasi 60 hari pertama
data.frame(Hari = 1:hari, Penjualan = penjualan, Stok = stok)
##    Hari Penjualan Stok
## 1     1        14  100
## 2     2        14   86
## 3     3        10   72
## 4     4        13   62
## 5     5        10   49
## 6     6         9   89
## 7     7         9   80
## 8     8        13   71
## 9     9        10   58
## 10   10        12   48
## 11   11        11   86
## 12   12        13   75
## 13   13        13   62
## 14   14         8   49
## 15   15         9   41
## 16   16        10   82
## 17   17        15   72
## 18   18        12   57
## 19   19        10   45
## 20   20        10   35
## 21   21         8   75
## 22   22        11   67
## 23   23         8   56
## 24   24         8   48
## 25   25        12   40
## 26   26        10   78
## 27   27        15   68
## 28   28         9   53
## 29   29        14   44
## 30   30         9   30
## 31   31         8   71
## 32   32        13   63
## 33   33        10   50
## 34   34        11   40
## 35   35        13   29
## 36   36         8   66
## 37   37        10   58
## 38   38        14   48
## 39   39        12   34
## 40   40        11   22
## 41   41        14   61
## 42   42        15   47
## 43   43         9   32
## 44   44        12   23
## 45   45        14   11
## 46   46         8   50
## 47   47         8   42
## 48   48         9   34
## 49   49        14   25
## 50   50        10   11
## 51   51        11   51
## 52   52        12   40
## 53   53        14   28
## 54   54        12   14
## 55   55        10    2
## 56   56        15   50
## 57   57        13   35
## 58   58         8   22
## 59   59         9   14
## 60   60        12    5

(b) Hitung berapa kali toko kehabisan stok

set.seed(123)
# Membuat variabel stok aktual (berdasarkan penjualan yang bisa dipenuhi)
stok_terpakai <- numeric(hari)
stok_terpakai[1] <- min(stok[1], penjualan[1])

for (i in 2:hari) {
  stok_terpakai[i] <- min(stok[i], penjualan[i])
}

# Kehabisan stok terjadi saat penjualan > stok
kehabisan <- penjualan > stok
jumlah_kehabisan <- sum(kehabisan)
jumlah_kehabisan
## [1] 3

Penjelasan: DIketahui bahwa selama 60 hari operasional, Bu Sari tidak bisa memenuhi permintaan pelanggan sebanyak 3 kali. Setiap kali kehabisan stok, Bu Sari kehilangan keuntungan Rp50.000 per karung tidak terjual. Artinya, potensi kerugian minimum adalah 3 × (jumlah karung tidak terpenuhi × Rp50.000).

(c) Coba berbagai strategi: pesan 40, 50, atau 60 karung. Manakah yang terbaik?

set.seed(123)  
penjualan_fixed <- sample(8:15, 60, replace = TRUE)  # Penjualan tetap untuk semua strategi

# Fungsi simulasi stok (menerima input penjualan)
simulasi_stok <- function(penjualan, stok_awal = 100, jumlah_pesan = 50, freq_pesan = 5) {
  hari <- length(penjualan)
  stok <- numeric(hari)
  stok[1] <- stok_awal

  for (i in 2:hari) {
    sisa_stok <- stok[i - 1] - penjualan[i - 1]
    sisa_stok <- ifelse(sisa_stok < 0, 0, sisa_stok)
    if ((i - 1) %% freq_pesan == 0) {
      stok[i] <- sisa_stok + jumlah_pesan
    } else {
      stok[i] <- sisa_stok
    }
  }

  # Hitung kerugian
  kehabisan <- sum(penjualan > stok)
  rugi <- sum((penjualan - stok)[penjualan > stok]) * 50000

  return(data.frame(
    Jumlah_Pesan = jumlah_pesan,
    Frekuensi_Pesan = freq_pesan,
    Total_Kehabisan = kehabisan,
    Kerugian = rugi
  ))
}

# Jalankan simulasi untuk 3 strategi jumlah pesanan
hasil_6c <- rbind(
  simulasi_stok(penjualan_fixed, jumlah_pesan = 40),
  simulasi_stok(penjualan_fixed, jumlah_pesan = 50),
  simulasi_stok(penjualan_fixed, jumlah_pesan = 60)
)

hasil_6c
##   Jumlah_Pesan Frekuensi_Pesan Total_Kehabisan Kerugian
## 1           40               5              15  6400000
## 2           50               5               3   900000
## 3           60               5               0        0

Penjelasan: Tabel menunjukkan jika pesan 40 karung terlalu sedikit, menyebabkan kehabisan stok 15 hari dan kerugian besar. Pesan 50 karung cukup stabil, hanya 3 kali kehabisan stok dan kerugian minimal. Pesan 60 karung adalah yang paling aman, karena tidak pernah kehabisan stok.

(d) COba ubah frekuensi pesan: setiap 3, 5, atau 7 hari. Manakah yang optimal?

hasil_6d <- rbind(
  simulasi_stok(penjualan_fixed, jumlah_pesan = 50, freq_pesan = 3),
  simulasi_stok(penjualan_fixed, jumlah_pesan = 50, freq_pesan = 5),
  simulasi_stok(penjualan_fixed, jumlah_pesan = 50, freq_pesan = 7)
)

hasil_6d
##   Jumlah_Pesan Frekuensi_Pesan Total_Kehabisan Kerugian
## 1           50               3               0        0
## 2           50               5               3   900000
## 3           50               7              19  8800000

Penjelasan: Semakin jarang pesan (7 hari), semakin besar kemungkinan stok habis dan mengakibatkan rugi besar. Untuk frekuensi 3 hari sangat aman (tidak pernah kehabisan stok), tapi bisa jadi boros ongkos operasional atau repot secara logistik. Sedangkan, frekuensi 5 hari cukup seimbang antara efisiensi dan risiko, hanya 3 kali kehabisan dan kerugiannya kecil.

(e) Buat grafik pergerakan stok dan rekomendasi untuk Bu

# Fungsi modifikasi untuk mengembalikan data harian
simulasi_stok_detail <- function(penjualan, stok_awal = 100, jumlah_pesan = 50, freq_pesan = 5) {
  hari <- length(penjualan)
  stok <- numeric(hari)
  stok[1] <- stok_awal

  for (i in 2:hari) {
    sisa_stok <- stok[i - 1] - penjualan[i - 1]
    sisa_stok <- ifelse(sisa_stok < 0, 0, sisa_stok)
    if ((i - 1) %% freq_pesan == 0) {
      stok[i] <- sisa_stok + jumlah_pesan
    } else {
      stok[i] <- sisa_stok
    }
  }

  df <- data.frame(Hari = 1:hari, Penjualan = penjualan, Stok = stok)
  return(df)
}
# Buat data stok harian untuk strategi optimal (contoh: 50 karung tiap 5 hari)
df_stok <- simulasi_stok_detail(penjualan_fixed, jumlah_pesan = 50, freq_pesan = 5)

# Plot pergerakan stok
plot(df_stok$Hari, df_stok$Stok, type = "l", col = "darkgreen", lwd = 2,
     xlab = "Hari ke-", ylab = "Jumlah Stok",
     main = "Grafik Pergerakan Stok Harian (Pesan 50 karung / 5 hari)")
abline(h = 0, col = "red", lty = 2)  # Batas stok habis

Penjelasan: Pada grafik, setiap lonjakan ke atas = hari pemesanan (stok bertambah 50 karung); Penurunan tajam = stok berkurang akibat penjualan harian; Ada beberapa titik menyentuh garis merah (stok = 0) → ini berarti Bu Sari kehabisan stok

Rekomendasi Akhir: Berdasarkan simulasi dan grafik, strategi memesan 50 karung setiap 5 hari terlihat cukup efisien dan aman, hanya sesekali stok menyentuh nol. Jika Bu Sari ingin benar-benar aman tanpa risiko kehabisan, frekuensi pemesanan bisa ditingkatkan jadi 3 hari atau jumlah ditambah menjadi 60 karung.