Praktikum dan Tugas Simulasi Monte Carlo

Dalam statistika dan teori probabilitas, nilai ekspektasi (expected value) adalah ukuran penting yang menggambarkan rata-rata jangka panjang dari suatu variabel acak. Secara teoritis, nilai ini dapat diperoleh langsung apabila distribusi probabilitasnya telah diketahui. Namun, pada banyak permasalahan nyata, distribusi tersebut sering kali tidak tersedia secara jelas, sehingga diperlukan pendekatan lain melalui simulasi.

Salah satu metode yang umum digunakan adalah simulasi Monte Carlo, yaitu teknik yang menggunakan pengambilan sampel acak secara berulang untuk memperkirakan nilai parameter tertentu. Dengan metode ini, hasil perhitungan teoritis atau manual dapat dibandingkan dengan pendekatan empiris yang diperoleh dari data simulasi.

Praktikum

tabel_permintaan <- data.frame(
  permintaan = c(50, 60, 70, 80, 90),
  frekuensi = c(10, 20, 40, 20, 10)
)
print(tabel_permintaan)
##   permintaan frekuensi
## 1         50        10
## 2         60        20
## 3         70        40
## 4         80        20
## 5         90        10
# total frekuensi
total_frekuensi <- sum(tabel_permintaan$frekuensi)

# peluang
total_frekuensi <- sum(tabel_permintaan$frekuensi)
tabel_permintaan$probabilitas <- tabel_permintaan$frekuensi / total_frekuensi

print(tabel_permintaan)
##   permintaan frekuensi probabilitas
## 1         50        10          0.1
## 2         60        20          0.2
## 3         70        40          0.4
## 4         80        20          0.2
## 5         90        10          0.1
# Probabilitas kumulatif
tabel_permintaan$probabilitas_kumulatif <- cumsum(tabel_permintaan$probabilitas)
print(tabel_permintaan)
##   permintaan frekuensi probabilitas probabilitas_kumulatif
## 1         50        10          0.1                    0.1
## 2         60        20          0.2                    0.3
## 3         70        40          0.4                    0.7
## 4         80        20          0.2                    0.9
## 5         90        10          0.1                    1.0
# interval dengan +1 untuk lower bound
tabel_permintaan$batas_bawah<- c(1, head(tabel_permintaan$probabilitas_kumulatif, -1) * 100 + 1)
tabel_permintaan$batas_atas <- tabel_permintaan$probabilitas_kumulatif * 100

print(tabel_permintaan)
##   permintaan frekuensi probabilitas probabilitas_kumulatif batas_bawah
## 1         50        10          0.1                    0.1           1
## 2         60        20          0.2                    0.3          11
## 3         70        40          0.4                    0.7          31
## 4         80        20          0.2                    0.9          71
## 5         90        10          0.1                    1.0          91
##   batas_atas
## 1         10
## 2         30
## 3         70
## 4         90
## 5        100
# ekspektasi Berdasarkan distribusi peluang yang sudah dihitung sebelumnya
nilai_ekspektasi <- sum(tabel_permintaan$permintaan * tabel_permintaan$probabilitas)
cat("Ekspektasi permintaan:", nilai_ekspektasi, "\n")
## Ekspektasi permintaan: 70
permintaan_simulasi <- function(n, tabel_permintaan) {
  # Bilangan acak dari 1 sampai 100 (diskrit sesuai interval)
  bilangan_acak <- sample(1:100, n, replace = TRUE)
  
  # Fungsi bantu untuk menentukan demand berdasarkan interval
  get_demand <- function(x) {
    index <- which(x >= tabel_permintaan$batas_bawah & x <= tabel_permintaan$batas_atas)
    if (length(index) == 0) {
      return(NA)  # atau fallback ke 70 jika mau pakai nilai tengah
    } else {
      return(tabel_permintaan$permintaan[index])
    }
  }
  
  prediksi_permintaan <- sapply(bilangan_acak, get_demand)
  
 # Hapus NA jika ada
  result <- data.frame(
    bilangan_acak = bilangan_acak,
    prediksi_permintaan = prediksi_permintaan
  )
  result <- na.omit(result)
  
  return(result)
}
set.seed(5)
# a. 5 hari
sim_5 <- permintaan_simulasi(5, tabel_permintaan)
print(head(sim_5, 10))
##   bilangan_acak prediksi_permintaan
## 1            66                  70
## 2            57                  70
## 3            79                  80
## 4            75                  80
## 5            41                  70
cat("Rata-rata permintaan:", mean(sim_5$prediksi_permintaan), "\n")
## Rata-rata permintaan: 74
set.seed(20)
# a. 20 hari
sim_20 <- permintaan_simulasi(20, tabel_permintaan)
print(head(sim_20, 10))
##    bilangan_acak prediksi_permintaan
## 1             38                  70
## 2             63                  70
## 3              2                  50
## 4             98                  90
## 5             29                  60
## 6             94                  90
## 7             62                  70
## 8             45                  70
## 9             41                  70
## 10            67                  70
cat("Rata-rata permintaan:", mean(sim_20$prediksi_permintaan), "\n")
## Rata-rata permintaan: 71
set.seed(100)
# c. 100 hari
sim_100 <- permintaan_simulasi(100, tabel_permintaan)
print(head(sim_100, 10))
##    bilangan_acak prediksi_permintaan
## 1             74                  80
## 2             89                  80
## 3             78                  80
## 4             23                  60
## 5             86                  80
## 6             70                  70
## 7              4                  50
## 8             55                  70
## 9             70                  70
## 10            98                  90
cat("Rata-rata permintaan:", mean(sim_100$prediksi_permintaan), "\n")
## Rata-rata permintaan: 69.19192
set.seed(1000)
# d. 1000 hari
sim_1000 <- permintaan_simulasi(1000, tabel_permintaan)
print(head(sim_1000, 10))
##    bilangan_acak prediksi_permintaan
## 1             68                  70
## 2             43                  70
## 3             86                  80
## 4             51                  70
## 5             88                  80
## 6             29                  60
## 7             99                  90
## 8             61                  70
## 9             18                  60
## 10            22                  60
cat("Rata-rata permintaan:", mean(sim_1000$prediksi_permintaan), "\n")
## Rata-rata permintaan: 70.12097
perbandingan <- data.frame(
  Metode = c("Ekspektasi Teoritis", "Simulasi 5 hari","Simulasi 20 hari", "Simulasi 100 hari", "Simulasi 1000 hari"),
  Permintaan_Rata_Rata = c(
    round(nilai_ekspektasi, 2),
    round(mean(sim_5$prediksi_permintaan), 2),
    round(mean(sim_20$prediksi_permintaan), 2),
    round(mean(sim_100$prediksi_permintaan), 2),
    round(mean(sim_1000$prediksi_permintaan), 2)
  )
)

# Tampilkan tabel
print(perbandingan)
##                Metode Permintaan_Rata_Rata
## 1 Ekspektasi Teoritis                70.00
## 2     Simulasi 5 hari                74.00
## 3    Simulasi 20 hari                71.00
## 4   Simulasi 100 hari                69.19
## 5  Simulasi 1000 hari                70.12

#Kesimpulan Semakin besar jumlah hari simulasi, rata-rata hasil simulasi cenderung mendekati nilai ekspektasi teoritis. Simulasi dengan jumlah kecil (5 atau 20 hari) menghasilkan fluktuasi yang lebih besar, sedangkan simulasi dalam jumlah besar (1000 hari) memberikan estimasi yang lebih akurat dan konsisten.

Tugas 1

Lakukan modifikasi pada salah satu kode program yang telah diberikan dengan mengubah jumlah simulasi menjadi 1.000, 5.000, dan 20.000. Jalankan simulasi untuk masing-masing kondisi tersebut, kemudian bandingkan nilai ekspektasi yang dihasilkan dengan nilai ekspektasi hasil perhitungan manual. Selanjutnya, analisis bagaimana perubahan jumlah simulasi memengaruhi kedekatan hasil simulasi terhadap nilai teoritis, serta jelaskan mengapa peningkatan jumlah simulasi dapat menghasilkan estimasi yang lebih stabil dan akurat.

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

tabel_permintaan
##   permintaan frekuensi
## 1         50        10
## 2         60        20
## 3         70        40
## 4         80        20
## 5         90        10
# Probabilitas
tabel_permintaan$probabilitas <- 
  tabel_permintaan$frekuensi /
  sum(tabel_permintaan$frekuensi)

tabel_permintaan
##   permintaan frekuensi probabilitas
## 1         50        10          0.1
## 2         60        20          0.2
## 3         70        40          0.4
## 4         80        20          0.2
## 5         90        10          0.1
# Probabilitas kumulatif
tabel_permintaan$probabilitas_kumulatif <- 
  cumsum(tabel_permintaan$probabilitas)

tabel_permintaan
##   permintaan frekuensi probabilitas probabilitas_kumulatif
## 1         50        10          0.1                    0.1
## 2         60        20          0.2                    0.3
## 3         70        40          0.4                    0.7
## 4         80        20          0.2                    0.9
## 5         90        10          0.1                    1.0
# Interval bilangan acak
tabel_permintaan$batas_bawah <- 
  c(1, 11, 31, 71, 91)

tabel_permintaan$batas_atas <- 
  c(10, 30, 70, 90, 100)

tabel_permintaan
##   permintaan frekuensi probabilitas probabilitas_kumulatif batas_bawah
## 1         50        10          0.1                    0.1           1
## 2         60        20          0.2                    0.3          11
## 3         70        40          0.4                    0.7          31
## 4         80        20          0.2                    0.9          71
## 5         90        10          0.1                    1.0          91
##   batas_atas
## 1         10
## 2         30
## 3         70
## 4         90
## 5        100
# Ekspektasi manual
ekspektasi_manual <- sum(
  tabel_permintaan$permintaan *
  tabel_permintaan$probabilitas
)

cat("Ekspektasi manual =",
    ekspektasi_manual)
## Ekspektasi manual = 70
# Fungsi simulasi
permintaan_simulasi <- function(
  n,
  tabel_permintaan
){

  bilangan_acak <- sample(
    1:100,
    n,
    replace = TRUE
  )

  get_demand <- function(x){

    index <- which(
      x >= tabel_permintaan$batas_bawah &
      x <= tabel_permintaan$batas_atas
    )

    return(
      tabel_permintaan$permintaan[index]
    )
  }

  prediksi_permintaan <- sapply(
    bilangan_acak,
    get_demand
  )

  result <- data.frame(
    bilangan_acak = bilangan_acak,
    prediksi_permintaan =
      prediksi_permintaan
  )

  return(result)
}
# Simulasi 1000
set.seed(1000)
hasil_1000 <- permintaan_simulasi(
  1000,
  tabel_permintaan
)

ekspektasi_1000 <- mean(
  hasil_1000$prediksi_permintaan
)

cat(
  "Ekspektasi simulasi 1000 =",
  ekspektasi_1000
)
## Ekspektasi simulasi 1000 = 70.12
# Simulasi 5000
set.seed(5000)
hasil_5000 <- permintaan_simulasi(
  5000,
  tabel_permintaan
)

ekspektasi_5000 <- mean(
  hasil_5000$prediksi_permintaan
)

cat(
  "Ekspektasi simulasi 5000 =",
  ekspektasi_5000
)
## Ekspektasi simulasi 5000 = 70.088
# Simulasi 20000
set.seed(20000)
hasil_20000 <- permintaan_simulasi(
  20000,
  tabel_permintaan
)

ekspektasi_20000 <- mean(
  hasil_20000$prediksi_permintaan
)

cat(
  "Ekspektasi simulasi 20000 =",
  ekspektasi_20000
)
## Ekspektasi simulasi 20000 = 69.892
# Tabel Perbandingan
perbandingan <- data.frame(
  jumlah_simulasi =
    c(1000, 5000, 20000),

  hasil_simulasi =
    c(
      ekspektasi_1000,
      ekspektasi_5000,
      ekspektasi_20000
    ),

  ekspektasi_manual =
    ekspektasi_manual
)

perbandingan
##   jumlah_simulasi hasil_simulasi ekspektasi_manual
## 1            1000         70.120                70
## 2            5000         70.088                70
## 3           20000         69.892                70

#Kesimpulan Hasil simulasi menunjukkan bahwa seluruh nilai sudah mendekati ekspektasi teoritis 70. Perbedaan kecil pada simulasi 20000 kali merupakan akibat variasi acak yang normal dalam metode Monte Carlo. Semakin banyak simulasi akan membuat hasil lebih stabil dalam jangka panjang, meskipun pada satu percobaan tertentu tidak selalu paling dekat dengan nilai teoritis.

Tugas 2

Bangkitkanlah data dengan distribusi eksponensial untuk variabel permintaan sebanyak 10 data permintaan, dan data dengan distribusi normal untuk variabel frekuensi a. prediksikan permintaan selama 5 hari ke depan b. prediksikan permintaan selama 20 hari ke depan c. prediksikan permintaan selama 100 hari ke depan d. prediksikan permintaan selama 1000 hari ke depan

rm(list = ls())
set.seed(123)

# Bangkitkan 10 data permintaan
permintaan <- round(
  rexp(10, rate = 1/70)
)

permintaan
##  [1]  59  40  93   2   4  22  22  10 191   2
# Bangkitkan 10 data frekuensi
frekuensi <- round(
  rnorm(10, mean = 10, sd = 3)
)

# Supaya tidak negatif
frekuensi[frekuensi < 1] <- 1

frekuensi
##  [1]  9 14 11 11 10  8 15 11  4 12
# Gabungkan data
data_simulasi <- data.frame(
  permintaan = permintaan,
  frekuensi = frekuensi
)

data_simulasi
##    permintaan frekuensi
## 1          59         9
## 2          40        14
## 3          93        11
## 4           2        11
## 5           4        10
## 6          22         8
## 7          22        15
## 8          10        11
## 9         191         4
## 10          2        12
# Hitung probabilitas
data_simulasi$probabilitas <-
  data_simulasi$frekuensi /
  sum(data_simulasi$frekuensi)

data_simulasi
##    permintaan frekuensi probabilitas
## 1          59         9   0.08571429
## 2          40        14   0.13333333
## 3          93        11   0.10476190
## 4           2        11   0.10476190
## 5           4        10   0.09523810
## 6          22         8   0.07619048
## 7          22        15   0.14285714
## 8          10        11   0.10476190
## 9         191         4   0.03809524
## 10          2        12   0.11428571
# Probabilitas kumulatif
data_simulasi$prob_kumulatif <-
  cumsum(data_simulasi$probabilitas)

data_simulasi
##    permintaan frekuensi probabilitas prob_kumulatif
## 1          59         9   0.08571429     0.08571429
## 2          40        14   0.13333333     0.21904762
## 3          93        11   0.10476190     0.32380952
## 4           2        11   0.10476190     0.42857143
## 5           4        10   0.09523810     0.52380952
## 6          22         8   0.07619048     0.60000000
## 7          22        15   0.14285714     0.74285714
## 8          10        11   0.10476190     0.84761905
## 9         191         4   0.03809524     0.88571429
## 10          2        12   0.11428571     1.00000000
# Interval angka acak 1-100
data_simulasi$batas_bawah <-
  c(1,
    head(
      floor(
        data_simulasi$prob_kumulatif[-10] * 100
      ) + 1,
      -0
    )
  )
data_simulasi$batas_atas <-
  floor(
    data_simulasi$prob_kumulatif * 100
  )

data_simulasi
##    permintaan frekuensi probabilitas prob_kumulatif batas_bawah batas_atas
## 1          59         9   0.08571429     0.08571429           1          8
## 2          40        14   0.13333333     0.21904762           1         21
## 3          93        11   0.10476190     0.32380952           1         32
## 4           2        11   0.10476190     0.42857143           1         42
## 5           4        10   0.09523810     0.52380952           1         52
## 6          22         8   0.07619048     0.60000000           1         60
## 7          22        15   0.14285714     0.74285714           1         74
## 8          10        11   0.10476190     0.84761905           1         84
## 9         191         4   0.03809524     0.88571429           1         88
## 10          2        12   0.11428571     1.00000000           1        100
# Perbaiki batas bawah manual
data_simulasi$batas_bawah <- c(
  1,
  data_simulasi$batas_atas[
    1:9
  ] + 1
)

data_simulasi
##    permintaan frekuensi probabilitas prob_kumulatif batas_bawah batas_atas
## 1          59         9   0.08571429     0.08571429           1          8
## 2          40        14   0.13333333     0.21904762           9         21
## 3          93        11   0.10476190     0.32380952          22         32
## 4           2        11   0.10476190     0.42857143          33         42
## 5           4        10   0.09523810     0.52380952          43         52
## 6          22         8   0.07619048     0.60000000          53         60
## 7          22        15   0.14285714     0.74285714          61         74
## 8          10        11   0.10476190     0.84761905          75         84
## 9         191         4   0.03809524     0.88571429          85         88
## 10          2        12   0.11428571     1.00000000          89        100
# Fungsi simulasi Monte Carlo
simulasi_mc <- function(n){

  bilangan_acak <- sample(
    1:100,
    n,
    replace = TRUE
  )

  hasil <- numeric(n)

  for(i in 1:n){

    idx <- which(
      bilangan_acak[i] >=
      data_simulasi$batas_bawah &

      bilangan_acak[i] <=
      data_simulasi$batas_atas
    )

    hasil[i] <-
      data_simulasi$permintaan[idx]
  }

  return(
    data.frame(
      hari = 1:n,
      random = bilangan_acak,
      prediksi_permintaan = hasil
    )
  )
}
# a. Prediksi 5 hari
hasil_5 <- simulasi_mc(5)
hasil_5
##   hari random prediksi_permintaan
## 1    1     76                  10
## 2    2     15                  40
## 3    3     32                  93
## 4    4      7                  59
## 5    5      9                  40
mean(
  hasil_5$prediksi_permintaan
)
## [1] 48.4
# b. Prediksi 20 hari
hasil_20 <- simulasi_mc(20)
hasil_20
##    hari random prediksi_permintaan
## 1     1     41                   2
## 2     2     74                  22
## 3     3     23                  93
## 4     4     27                  93
## 5     5     60                  22
## 6     6     53                  22
## 7     7      7                  59
## 8     8     53                  22
## 9     9     27                  93
## 10   10     96                   2
## 11   11     38                   2
## 12   12     89                   2
## 13   13     34                   2
## 14   14     93                   2
## 15   15     69                  22
## 16   16     72                  22
## 17   17     76                  10
## 18   18     63                  22
## 19   19     13                  40
## 20   20     82                  10
mean(
  hasil_20$prediksi_permintaan
)
## [1] 28.2
# c. Prediksi 100 hari
hasil_100 <- simulasi_mc(100)

mean(
  hasil_100$prediksi_permintaan
)
## [1] 39.89
# d. Prediksi 1000 hari
hasil_1000 <- simulasi_mc(1000)

mean(
  hasil_1000$prediksi_permintaan
)
## [1] 34.377
# Ringkasan hasil
hasil_akhir <- data.frame(
  Metode = c(
    "Ekspektasi Teoritis",
    "Simulasi 5 hari",
    "Simulasi 20 hari",
    "Simulasi 100 hari",
    "Simulasi 1000 hari"
  ),

  Permintaan_Rata_Rata = c(
    sum(
      data_simulasi$permintaan *
      data_simulasi$probabilitas
    ),
    mean(
      hasil_5$prediksi_permintaan
    ),
    mean(
      hasil_20$prediksi_permintaan
    ),
    mean(
      hasil_100$prediksi_permintaan
    ),
    mean(
      hasil_1000$prediksi_permintaan
    )
  )
)

hasil_akhir
##                Metode Permintaan_Rata_Rata
## 1 Ekspektasi Teoritis             34.09524
## 2     Simulasi 5 hari             48.40000
## 3    Simulasi 20 hari             28.20000
## 4   Simulasi 100 hari             39.89000
## 5  Simulasi 1000 hari             34.37700

#Kesimpulan: Hasil simulasi menunjukkan bahwa jumlah periode simulasi sangat memengaruhi kestabilan prediksi permintaan. Simulasi jangka pendek menghasilkan fluktuasi besar, sedangkan simulasi jangka panjang memberikan rata-rata yang semakin dekat dengan ekspektasi teoritis. Dalam kasus ini, simulasi 1000 hari memberikan hasil terbaik karena paling mendekati nilai teoritis.