# Estimasi E[X²] untuk X ~ U(0,1)
set.seed(123)
x <- runif(10000, 0, 1)
E_X2 <- mean(x^2)
E_X2
## [1] 0.3297405
# Simulasi dari N(100, 15²)
set.seed(123)
simulasi_normal <- function(n) {
data <- rnorm(n, mean = 100, sd = 15)
mean_data <- mean(data)
sd_data <- sd(data)
hist(data, breaks = 30, col = "lightblue",
main = paste("Histogram N =", n),
xlab = "Nilai", ylab = "Frekuensi")
cat("n =", n, "\n")
cat("Rata-rata:", mean_data, "\n")
cat("Simpangan baku:", sd_data, "\n\n")
}
simulasi_normal(100)
## n = 100
## Rata-rata: 101.3561
## Simpangan baku: 13.69224
simulasi_normal(1000)
## n = 1000
## Rata-rata: 100.2862
## Simpangan baku: 15.06891
simulasi_normal(10000)
## n = 10000
## Rata-rata: 99.96336
## Simpangan baku: 14.98314
# Simulasi Binomial Bin(30, 0.25)
set.seed(123)
sim_binom <- rbinom(5000, 30, 0.25)
prob_X_lebih_15 <- mean(sim_binom >= 15)
prob_X_lebih_15
## [1] 0.0024
# Function untuk rumus simpangan baku
s_custom <- function(x) {
n <- length(x)
sqrt((sum(x^2) - (sum(x)^2)/n) / (n - 1))
}
set.seed(123)
x <- rnorm(1000, mean=89, sd=10)
s_custom(x)
## [1] 9.91695
Kerjakanlah tugas berikut: a. Buatlah simulasi antrian selama 20 hari kerja b. Hitung berapa lama rata-rata nasabah menunggu c. Hitung berapa persen waktu teller sibuk bekerja d. Bandingkan jika bank menambah 1 teller lagi – apakah lebih efisien? e. Buat grafik yang menunjukkan panjang antrian sepanjang hari
# Simulasi Antrian di Bank (Poisson & Eksponensial) Kondisi:
# λ = 5/jam, pelayanan: rata-rata 8 menit (μ = 7.5/jam), 2 teller
# 6 jam/hari × 20 hari kerja = 120 jam simulasi
# Simulasi antrian bank 20 hari kerja
library(simmer)
## Warning: package 'simmer' was built under R version 4.4.3
# Buat simulasi environment
env <- simmer("Bank Simulasi")
# Buat trajectory nasabah
traj <- trajectory("traj_nasabah") %>%
seize("teller", 1) %>%
timeout(function() rexp(1, rate = 1/8)) %>% # Pelayanan rata-rata 8 menit
release("teller", 1)
# Tambahkan resource dan generator sesuai kedatangan 5 orang per jam (setiap 12 menit)
env %>%
add_resource("teller", capacity = 1) %>%
add_generator("nasabah", traj, function() rexp(1, rate = 1/12)) %>%
run(until = 7200) # 6 jam × 20 hari = 7200 menit
## simmer environment: Bank Simulasi | now: 7200 | next: 7206.76351956559
## { Monitor: in memory }
## { Resource: teller | monitored: TRUE | server status: 0(1) | queue status: 0(Inf) }
## { Source: nasabah | monitored: 1 | n_generated: 611 }
# Ambil data kedatangan
data_arrival <- get_mon_arrivals(env, per_resource = TRUE)
# Hitung waktu tunggu: (end_time - activity_time) - start_time
data_arrival$waiting_time <- (data_arrival$end_time - data_arrival$activity_time) - data_arrival$start_time
# Tampilkan sebagian hasil
head(data_arrival[, c("start_time", "end_time", "activity_time", "waiting_time")])
## start_time end_time activity_time waiting_time
## 1 19.96423 32.60213 12.6379000 -3.552714e-15
## 2 38.47329 44.32720 5.8539147 7.105427e-15
## 3 38.81971 56.90004 12.5728370 5.507492e+00
## 4 101.62154 103.35913 1.7375952 0.000000e+00
## 5 103.98794 112.01159 8.0236485 0.000000e+00
## 6 105.57822 112.62975 0.6181586 6.433375e+00
# Hitung rata-rata waktu tunggu
rata2 <- mean(data_arrival$waiting_time, na.rm = TRUE)
cat("5b. Rata-rata waktu tunggu nasabah:", round(rata2, 2), "menit\n")
## 5b. Rata-rata waktu tunggu nasabah: 14.69 menit
# Ambil data resource
resource_data <- get_mon_resources(env)
# Urutkan berdasarkan waktu
resource_data <- resource_data[order(resource_data$time), ]
# Hitung durasi antar waktu
resource_data$duration <- c(diff(resource_data$time), 0)
# Hitung waktu sibuk total (server * durasi)
total_busy_time <- sum(resource_data$server * resource_data$duration)
# Total waktu simulasi
total_time <- 20000 # sesuai durasi run
# Hitung persentase waktu sibuk
persen_sibuk <- (total_busy_time / total_time) * 100
cat("✅ Persentase waktu teller sibuk:", round(persen_sibuk, 2), "%\n")
## ✅ Persentase waktu teller sibuk: 24.24 %
# Buat ulang environment baru
env_2teller <- simmer("Bank Simulasi - 2 Teller")
# Buat ulang trajectory yang sama
traj_2 <- trajectory("traj_nasabah") %>%
seize("teller", 1) %>%
timeout(function() rexp(1, rate = 1/8)) %>%
release("teller", 1)
# Simulasi bank dengan 2 teller
env_2teller %>%
add_resource("teller", capacity = 2) %>%
add_generator("nasabah", traj_2, function() rexp(1, rate = 1/15)) %>%
run(until = 20000)
## simmer environment: Bank Simulasi - 2 Teller | now: 20000 | next: 20003.2729956919
## { Monitor: in memory }
## { Resource: teller | monitored: TRUE | server status: 0(2) | queue status: 0(Inf) }
## { Source: nasabah | monitored: 1 | n_generated: 1280 }
# Ambil data kedatangan dan waktu tunggu
arrivals_2 <- get_mon_arrivals(env_2teller, per_resource = TRUE)
arrivals_2$waiting_time <- (arrivals_2$end_time - arrivals_2$activity_time) - arrivals_2$start_time
# Hitung rata-rata waktu tunggu
rata2_2teller <- mean(arrivals_2$waiting_time, na.rm = TRUE)
cat("✅ Rata-rata waktu tunggu dengan 2 teller:", round(rata2_2teller, 2), "menit\n")
## ✅ Rata-rata waktu tunggu dengan 2 teller: 0.39 menit
# Ambil data resource untuk 2 teller
res_2 <- get_mon_resources(env_2teller)
res_2 <- res_2[order(res_2$time), ]
res_2$duration <- c(diff(res_2$time), 0)
# Hitung total waktu sibuk
total_busy_2 <- sum(res_2$server * res_2$duration)
# Hitung persentase sibuk
persen_sibuk_2 <- (total_busy_2 / 20000) * 100
cat("✅ Persentase waktu teller sibuk (2 teller):", round(persen_sibuk_2, 2), "%\n")
## ✅ Persentase waktu teller sibuk (2 teller): 50.64 %
# Simulasi dengan 1 teller
env1 <- simmer("1 Teller")
traj1 <- trajectory("traj_nasabah") %>%
seize("teller", 1) %>%
timeout(function() rexp(1, 1/8)) %>%
release("teller", 1)
env1 %>%
add_resource("teller", capacity = 1) %>%
add_generator("nasabah", traj1, function() rexp(1, 1/15)) %>%
run(until = 20000)
## simmer environment: 1 Teller | now: 20000 | next: 20006.7350338103
## { Monitor: in memory }
## { Resource: teller | monitored: TRUE | server status: 0(1) | queue status: 0(Inf) }
## { Source: nasabah | monitored: 1 | n_generated: 1332 }
arr1 <- get_mon_arrivals(env1, per_resource = TRUE)
arr1$waiting_time <- (arr1$end_time - arr1$activity_time) - arr1$start_time
res1 <- get_mon_resources(env1)
res1 <- res1[order(res1$time), ]
res1$duration <- c(diff(res1$time), 0)
busy1 <- sum(res1$server * res1$duration)
# Simulasi dengan 2 teller
env2 <- simmer("2 Teller")
traj2 <- trajectory("traj_nasabah") %>%
seize("teller", 1) %>%
timeout(function() rexp(1, 1/8)) %>%
release("teller", 1)
env2 %>%
add_resource("teller", capacity = 2) %>%
add_generator("nasabah", traj2, function() rexp(1, 1/15)) %>%
run(until = 20000)
## simmer environment: 2 Teller | now: 20000 | next: 20040.895940186
## { Monitor: in memory }
## { Resource: teller | monitored: TRUE | server status: 0(2) | queue status: 0(Inf) }
## { Source: nasabah | monitored: 1 | n_generated: 1313 }
arr2 <- get_mon_arrivals(env2, per_resource = TRUE)
arr2$waiting_time <- (arr2$end_time - arr2$activity_time) - arr2$start_time
res2 <- get_mon_resources(env2)
res2 <- res2[order(res2$time), ]
res2$duration <- c(diff(res2$time), 0)
busy2 <- sum(res2$server * res2$duration)
# Buat tabel ringkasan
hasil <- data.frame(
Skenario = c("1 Teller", "2 Teller"),
Rata2_Waktu_Tunggu = c(mean(arr1$waiting_time, na.rm = TRUE),
mean(arr2$waiting_time, na.rm = TRUE)),
Persen_Teller_Sibuk = c(busy1/20000 * 100, busy2/20000 * 100)
)
# Tampilkan hasil
print(hasil)
## Skenario Rata2_Waktu_Tunggu Persen_Teller_Sibuk
## 1 1 Teller 8.8986927 51.90629
## 2 2 Teller 0.4765797 52.41769
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.4.2
# Ambil data dari simulasi terakhir (misal: env2 / 2 teller)
res_plot <- get_mon_resources(env2)
# Filter data antrian saja
res_queue <- subset(res_plot, resource == "teller")
# Buat plot panjang antrian
ggplot(res_queue, aes(x = time, y = queue)) +
geom_line(color = "steelblue", size = 1) +
labs(title = "📊 Panjang Antrian Sepanjang Hari",
subtitle = "Simulasi Antrian Bank (2 Teller)",
x = "Waktu (menit)",
y = "Jumlah Antrian") +
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.
Tugas: a. Simulasikan stok 60 hari b. Hitung berapa kali kehabisan stok c. Coba strategi pemesanan 40, 50, 60 karung d. Coba ubah frekuensi pesan: tiap 3, 5, 7 hari e. Buat grafik pergerakan stok + rekomendasi
set.seed(123)
# Parameter awal
hari <- 60
stok_awal <- 100
frekuensi_pesan <- 5
jumlah_pesan <- 50
kerugian_per_karung <- 50000
# Permintaan harian (uniform 8–15)
permintaan_harian <- sample(8:15, hari, replace = TRUE)
# Vektor hasil simulasi
stok <- numeric(hari)
stok[1] <- stok_awal - permintaan_harian[1]
for (i in 2:hari) {
# Tambah stok jika hari pemesanan
if ((i - 1) %% frekuensi_pesan == 0) {
stok[i] <- stok[i-1] + jumlah_pesan
} else {
stok[i] <- stok[i-1]
}
# Kurangi stok sesuai permintaan
stok[i] <- stok[i] - permintaan_harian[i]
# Jika negatif, diset 0 untuk real stok
stok[i] <- max(0, stok[i])
}
# Gabungkan jadi data frame
simulasi_stok <- data.frame(
Hari = 1:hari,
Permintaan = permintaan_harian,
Stok = stok
)
head(simulasi_stok, 10)
## Hari Permintaan Stok
## 1 1 14 86
## 2 2 14 72
## 3 3 10 62
## 4 4 13 49
## 5 5 10 39
## 6 6 9 80
## 7 7 9 71
## 8 8 13 58
## 9 9 10 48
## 10 10 12 36
jumlah_kehabisan <- sum(stok == 0)
cat("6b. Toko kehabisan stok sebanyak", jumlah_kehabisan, "hari\n")
## 6b. Toko kehabisan stok sebanyak 3 hari
simulasi_strategi <- function(jumlah_pesan) {
stok <- numeric(hari)
stok[1] <- stok_awal - permintaan_harian[1]
for (i in 2:hari) {
if ((i - 1) %% frekuensi_pesan == 0) {
stok[i] <- stok[i-1] + jumlah_pesan
} else {
stok[i] <- stok[i-1]
}
stok[i] <- stok[i] - permintaan_harian[i]
stok[i] <- max(0, stok[i])
}
sum(stok == 0)
}
strategi_hasil <- data.frame(
Pesan = c(40, 50, 60),
Hari_Habis = sapply(c(40, 50, 60), simulasi_strategi)
)
strategi_hasil
## Pesan Hari_Habis
## 1 40 15
## 2 50 3
## 3 60 0
simulasi_frekuensi <- function(frekuensi_pesan) {
stok <- numeric(hari)
stok[1] <- stok_awal - permintaan_harian[1]
for (i in 2:hari) {
if ((i - 1) %% frekuensi_pesan == 0) {
stok[i] <- stok[i-1] + jumlah_pesan
} else {
stok[i] <- stok[i-1]
}
stok[i] <- stok[i] - permintaan_harian[i]
stok[i] <- max(0, stok[i])
}
sum(stok == 0)
}
frekuensi_hasil <- data.frame(
Frekuensi_Hari = c(3, 5, 7),
Hari_Habis = sapply(c(3, 5, 7), simulasi_frekuensi)
)
frekuensi_hasil
## Frekuensi_Hari Hari_Habis
## 1 3 0
## 2 5 3
## 3 7 19
library(ggplot2)
ggplot(simulasi_stok, aes(x = Hari, y = Stok)) +
geom_line(color = "darkgreen", size = 1.2) +
geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
labs(title = "Grafik Pergerakan Stok Beras Bu Sari Selama 60 Hari",
x = "Hari", y = "Stok (karung)") +
theme_minimal()