1. Simulasi untuk menghitung E[X^2] dengan X ~ U(0,1)

set.seed(123)
x <- runif(10000, 0, 1)
EX2 <- mean(x^2)
EX2
## [1] 0.3297405

2. Simulasi dari distribusi Normal

set.seed(123)
n1 <- 100; n2 <- 1000; n3 <- 10000
samples <- list(rnorm(n1, 100, sqrt(15^2)), rnorm(n2, 100, sqrt(15^2)), rnorm(n3, 100, sqrt(15^2)))
names(samples) <- c("n=100", "n=1000", "n=10000")
sapply(samples, mean)
##     n=100    n=1000   n=10000 
## 101.35609 100.28622  99.96336
sapply(samples, sd)
##    n=100   n=1000  n=10000 
## 13.69224 15.06891 14.98314
par(mfrow=c(1,3))
for (i in 1:3) {
  hist(samples[[i]], main=names(samples)[i], xlab="Value", col="lightblue", breaks=20)
}

Kesimpulan: Semakin besar ukuran sampel, hasil simulasi rata-rata dan simpangan baku semakin mendekati nilai teoritisnya. Histogram juga semakin menyerupai distribusi normal. Ini membuktikan bahwa ukuran sampel memengaruhi akurasi estimasi statistik.

3. Simulasi distribusi Binomial

set.seed(123)
sim_binom <- rbinom(5000, size=30, prob=0.25)
mean(sim_binom >= 15)
## [1] 0.0024

4. Fungsi untuk menghitung simpangan baku

std_custom <- function(x) {
  n <- length(x)
  sqrt((sum(x^2) - (sum(x)^2) / n) / (n - 1))
}
data <- rnorm(1000, mean=89, sd=10)
std_custom(data)
## [1] 10.02151

#5. Simulasi Antrian di Bank #(a) Simulasi antrian selama 20 hari kerja

if (!require(simmer)) install.packages("simmer", dependencies = TRUE)
## Loading required package: simmer
## Warning: package 'simmer' was built under R version 4.3.3
library(simmer)

set.seed(123)
bank_simulation <- function(teller_count=2, days=20) {
  env <- simmer("bank")
  arrival_rate <- 5  # nasabah per jam
  service_rate <- 1 / (8/60)  # 8 menit per nasabah
  customer <- trajectory("customer path") %>%
    seize("teller", 1) %>%
    timeout(function() rexp(1, service_rate)) %>%
    release("teller", 1)
  env %>%
    add_resource("teller", teller_count) %>%
    add_generator("customer", customer, function() rexp(1, arrival_rate)) %>%
    run(until = 6 * 60 * days)
  env
}

env2 <- bank_simulation(2, 20)

print(env2)
## simmer environment: bank | now: 7200 | next: 7200.16700962862
## { Monitor: in memory }
## { Resource: teller | monitored: TRUE | server status: 2(2) | queue status: 0(Inf) }
## { Source: customer | monitored: 1 | n_generated: 35889 }
head(get_mon_arrivals(env2))
##        name start_time  end_time activity_time finished replication
## 1 customer1  0.2840135 0.2915083   0.007494797     TRUE           1
## 2 customer2  0.2903290 0.3334053   0.041896972     TRUE           1
## 3 customer0  0.1686915 0.3458988   0.177207316     TRUE           1
## 4 customer4  0.3826826 0.5166599   0.133977341     TRUE           1
## 5 customer5  0.3885133 0.5669423   0.050282377     TRUE           1
## 6 customer6  0.4845562 0.6802471   0.113304817     TRUE           1

b. rata-rata waktu tunggu

arrivals <- get_mon_arrivals(env2)
mean(arrivals$end_time - arrivals$start_time)
## [1] 0.1493617

Berdasarkan hasil simulasi, rata-rata waktu tunggu nasabah di bank selama 20 hari kerja adalah sekitar 0,15 jam atau sekitar 9 menit. Ini menunjukkan bahwa sistem pelayanan cukup efisien dalam melayani nasabah dengan dua teller.

c. Persentase waktu teller sibuk

resources2 <- get_mon_resources(env2)
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.3.3
## 
## Attaching package: 'dplyr'
## The following object is masked from 'package:simmer':
## 
##     select
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
resources2 %>%
  group_by(resource) %>%
  summarise(utilization = sum(server) / (max(time) * 2))
## # A tibble: 1 × 2
##   resource utilization
##   <chr>          <dbl>
## 1 teller          5.40

Hasil simulasi menunjukkan bahwa teller bekerja dengan tingkat utilisasi sekitar 539,7%, yang berarti terjadi overload pada sistem. Nilai ini menunjukkan bahwa beban kerja jauh melebihi kapasitas dua teller, sehingga banyak nasabah harus menunggu dan sistem tidak berjalan efisien.

d. Simulasi 3 teller dan bandingkan

resources2 <- get_mon_resources(env2)

library(dplyr)
resources2 %>%
  group_by(resource) %>%
  summarise(utilization = sum(server) / (max(time) * 3))
## # A tibble: 1 × 2
##   resource utilization
##   <chr>          <dbl>
## 1 teller          3.60

Setelah bank menambah jumlah teller menjadi 3, tingkat utilisasi turun menjadi sekitar 359,8%. Meskipun masih di atas 100%, namun dibandingkan sebelumnya (539,7% dengan 2 teller), ini menunjukkan peningkatan efisiensi sistem. Beban kerja per teller berkurang, sehingga waktu tunggu nasabah kemungkinan besar juga menurun dan pelayanan menjadi lebih lancar.

e. Grafik panjang antrian

library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.3.3
ggplot(resources2, aes(time, queue)) +
  geom_line(color="blue") +
  labs(title="Panjang Antrian", x="Waktu (menit)", y="Antrian")

6. Simulasi Toko Kelontong Bu Sari

# a. simulasi stok selama 60 hari
set.seed(123)
hari <- 60
penjualan <- runif(hari, min=8, max=15)
stok <- numeric(hari)
stok[1] <- 100 - penjualan[1]

for (i in 2:hari) {
  stok[i] <- stok[i-1] - penjualan[i]
  if (i %% 5 == 0) stok[i] <- stok[i] + 50
}
plot(1:hari, stok, type="l", col="darkgreen", main="Pergerakan Stok Harian", xlab="Hari", ylab="Stok")

# b. Hitung berapa kali kehabisan stok

sum(stok <= 0)
## [1] 15

c. Strategi jumlah pemesanan 40,50,60

strategi_jumlah <- function(pesan=50) {
  stok <- numeric(hari)
  stok[1] <- 100 - penjualan[1]
  for (i in 2:hari) {
    stok[i] <- stok[i-1] - penjualan[i]
    if (i %% 5 == 0) stok[i] <- stok[i] + pesan
  }
  return(sum(stok <= 0))
}

strategi_jumlah(40)
## [1] 40
strategi_jumlah(50)
## [1] 15
strategi_jumlah(60)
## [1] 0

Semakin besar jumlah pemesanan, semakin kecil kemungkinan toko kehabisan stok. Pemesanan 40 karung menyebabkan stok habis 40 kali, 50 karung habis 15 kali, dan 60 karung tidak habis sama sekali. Maka, pemesanan 60 karung setiap 5 hari adalah strategi terbaik untuk mencegah kehabisan stok.

d.Strategi frekuensi pemesanan: tiap 3, 5, 7 hari

strategi_frekuensi <- function(freq=5) {
  stok <- numeric(hari)
  stok[1] <- 100 - penjualan[1]
  for (i in 2:hari) {
    stok[i] <- stok[i-1] - penjualan[i]
    if (i %% freq == 0) stok[i] <- stok[i] + 50
  }
  return(sum(stok <= 0))
}

strategi_frekuensi(3)
## [1] 0
strategi_frekuensi(5)
## [1] 15
strategi_frekuensi(7)
## [1] 45

frekuensi pesan terbaik adalah setiap 3 hari untuk meminimalkan kerugian akibat kehabisan stok.

e. Grafik stok dengan beberapa strategi

plot_strategi <- function(freq=5, pesan=50, col="blue") {
  stok <- numeric(hari)
  stok[1] <- 100 - penjualan[1]
  for (i in 2:hari) {
    stok[i] <- stok[i-1] - penjualan[i]
    if (i %% freq == 0) stok[i] <- stok[i] + pesan
  }
  lines(1:hari, stok, col=col)
}

plot(1:hari, rep(NA, hari), ylim=c(-10, 120), type="n", xlab="Hari", ylab="Stok", main="Perbandingan Strategi Stok")
plot_strategi(5, 50, "blue")
plot_strategi(5, 40, "red")
plot_strategi(3, 50, "green")
legend("topright", legend=c("50/5 hari", "40/5 hari", "50/3 hari"), col=c("blue", "red", "green"), lty=1)