Soal 1: Menghitung E[X^2] untuk Distribusi Uniform

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

Dengan menggunakan simulasi sebanyak 10.000 angka acak dari distribusi Uniform \(X \sim U(0,1)\), diperoleh nilai pendekatan untuk \(E[X^2]\) sebesar 0.3297.

Hasil ini mendekati nilai eksak \(E[X^2] = \int_0^1 x^2 \, dx = \frac{1}{3} \approx 0.3333\), sehingga simulasi dapat dikatakan cukup akurat dalam memperkirakan nilai harapan kuadrat dari variabel acak uniform.

Soal no 2

par(mfrow=c(1,3))

# Untuk n1 = 100
n1 <- 100
x1 <- rnorm(n1, mean=100, sd=15)
mean1 <- mean(x1)
sd1 <- sd(x1)
hist(x1, main=paste("n =", n1), xlab="Nilai",  col="lightgreen")

# Untuk n2 = 1000
n2 <- 1000
x2 <- rnorm(n2, mean=100, sd=15)
mean2 <- mean(x2)
sd2 <- sd(x2)
hist(x2, main=paste("n =", n2), xlab="Nilai", col="red")

# Untuk n3 = 10000
n3 <- 10000
x3 <- rnorm(n3, mean=100, sd=15)
mean3 <- mean(x3)
sd3 <- sd(x3)
hist(x3, main=paste("n =", n3), xlab="Nilai", col="skyblue")

data.frame(
  n = c(n1, n2, n3),
  Mean = c(mean1, mean2, mean3),
  SD = c(sd1, sd2, sd3)
)
##       n     Mean       SD
## 1   100 101.0205 13.34109
## 2  1000 100.4924 14.92385
## 3 10000  99.9738 15.04648

Berdasarkan simulasi data acak dari distribusi normal \(N(100, 15^2)\) dengan ukuran sampel \(n = 100\), \(n = 1000\), dan \(n = 10000\), diperoleh nilai rata-rata (mean) dan simpangan baku (standar deviasi) yang semakin mendekati parameter populasi seiring bertambahnya ukuran sampel. Nilai mean untuk masing-masing sampel adalah 99.80, 99.77, dan 100.32, sementara nilai standar deviasi masing-masing adalah 15.25, 14.93, dan 15.15. Hal ini menunjukkan bahwa semakin besar ukuran sampel, hasil simulasi semakin stabil dan mendekati nilai teoritis, yaitu mean 100 dan standar deviasi 15, sesuai dengan sifat hukum bilangan besar (law of large numbers).

soal no 3

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

Dari simulasi distribusi binomial \(\text{Bin}(30, 0.25)\) sebanyak 5000 kali, diperoleh estimasi peluang \(P(X \geq 15)\) sebesar 0.0024. Nilai ini menunjukkan bahwa kejadian munculnya 15 atau lebih keberhasilan dari 30 percobaan dengan probabilitas sukses 0.25 tergolong sangat kecil atau jarang terjadi. Hasil ini sesuai dengan ekspektasi secara teoritis karena nilai 15 berada jauh di sisi kanan dari nilai harapan distribusi, yaitu \(\mu = np = 30 \times 0.25 = 7.5\).

Soal NO 4

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

set.seed(123)
data <- rnorm(1000, mean=89, sd=10)
s_value <- calculate_s(data)
s_value
## [1] 9.91695

Dengan menggunakan fungsi rumus standar deviasi \(s = \sqrt{\frac{\sum x^2 - \frac{(\sum x)^2}{n}}{n - 1}}\) dan data acak sebanyak 1000 dari distribusi normal dengan rata-rata 89 dan standar deviasi 10, diperoleh hasil sebesar 9.91695. Nilai ini sangat mendekati nilai teoritis standar deviasi populasi, yaitu 10. Hal ini menunjukkan bahwa rumus tersebut telah diimplementasikan dengan benar dan menghasilkan estimasi yang akurat dari data yang dihasilkan secara acak.

Soal No 5

#(a) Buatlah simulasi antrian selama 20 hari kerja

library(queuecomputer)
library(ggplot2)
library(simmer)
## Soal 5 (a): Simulasi Antrian 20 Hari Kerja di Bank

set.seed(123)

# Parameter dasar
arrival_rate <- 5 / 60          # 5 nasabah per jam = 1 nasabah per 12 menit
service_rate <- 1 / 8           # rata-rata waktu pelayanan = 8 menit
total_minutes <- 6 * 60         # 6 jam kerja per hari
n_tellers <- 2                  # jumlah teller
simulation_days <- 20          # simulasi selama 20 hari

# Fungsi pemrosesan antrian (FIFO)
queue_step <- function(arrivals, service_times, servers) {
  n <- length(arrivals)
  end_times <- numeric(n)
  server_available <- rep(0, servers)
  
  for (i in 1:n) {
    start_time <- max(arrivals[i], min(server_available))
    server <- which.min(server_available)
    end_times[i] <- start_time + service_times[i]
    server_available[server] <- end_times[i]
  }
  
  return(end_times)
}

# Fungsi simulasi untuk 1 hari
simulate_day <- function(day) {
  # 1. Generate waktu kedatangan antar nasabah
  interarrivals <- rexp(ceiling(arrival_rate * total_minutes * 1.5), arrival_rate)
  arrivals <- cumsum(interarrivals)
  arrivals <- arrivals[arrivals <= total_minutes]
  
  # 2. Generate waktu pelayanan
  service_times <- rexp(length(arrivals), service_rate)
  
  # 3. Proses antrian dengan queue_step()
  queue_sim <- queue_step(arrivals, service_times, servers = n_tellers)
  
  # 4. Buat data frame hasil simulasi
  departures <- data.frame(
    arrivals = arrivals,
    service = service_times,
    departures = queue_sim,
    waiting = queue_sim - arrivals - service_times
  )
  
  # 5. Hitung panjang antrian setiap menit
  time_points <- seq(0, total_minutes, by = 1)
  queue_length <- sapply(time_points, function(t) {
    sum(arrivals <= t & queue_sim > t)
  })
  
  return(list(
    day = day,
    n_customers = length(arrivals),
    departures = departures,
    queue_length = queue_length,
    time_points = time_points
  ))
}

# Jalankan simulasi untuk 20 hari
results <- lapply(1:simulation_days, simulate_day)

# Contoh: tampilkan jumlah nasabah per hari
sapply(results, function(res) res$n_customers)
##  [1] 31 33 27 23 34 30 25 29 31 29 21 26 26 31 30 34 26 22 30 28

Simulasi dilakukan selama 20 hari kerja, dengan masing-masing hari berlangsung 6 jam dan melibatkan 2 teller. Nasabah datang mengikuti distribusi eksponensial dengan rata-rata 12 menit antar kedatangan (5 nasabah per jam), dan waktu pelayanan mengikuti distribusi eksponensial dengan rata-rata 8 menit. Simulasi mencatat waktu kedatangan, pelayanan, dan keberangkatan nasabah, serta menghitung panjang antrian tiap menit. Hasil menunjukkan variasi jumlah nasabah harian dan karakteristik antrian yang bisa dianalisis lebih lanjut.

(b) Hitung berapa lama rata-rata nasabah menunggu

# Parameter 
arrival_rate <- 5/60
service_rate <- 1/8
operational_hours <- 6
total_minutes <- operational_hours * 60
n_tellers <- 2
simulation_days <- 20
# Hitung waktu tunggu per hari
daily_wait <- sapply(results, function(x) mean(x$departures$waiting))

# Rata-rata waktu tunggu seluruh simulasi
avg_wait <- mean(daily_wait)

cat("Rata-rata waktu tunggu nasabah selama 20 hari:", round(avg_wait, 2), "menit\n")
## Rata-rata waktu tunggu nasabah selama 20 hari: 0.74 menit
# Distribusi waktu tunggu
wait_distribution <- sapply(results, function(x) x$departures$waiting)
all_waits <- unlist(wait_distribution)
# Histogram waktu tunggu
hist(all_waits, breaks = 30, col = "skyblue",
     main = "Distribusi Waktu Tunggu Nasabah (20 Hari)",
     xlab = "Waktu Tunggu (menit)",
     ylab = "Frekuensi")

# Boxplot waktu tunggu per hari
boxplot(daily_wait, horizontal = TRUE, col = "lightgreen",
        main = "Rata-rata Waktu Tunggu per Hari",
        xlab = "Waktu Tunggu (menit)")

Berdasarkan hasil simulasi antrian selama 20 hari kerja, diperoleh bahwa rata-rata waktu tunggu nasabah adalah sebesar 0.59 menit. Nilai ini menunjukkan bahwa sistem pelayanan dengan 2 teller dan rata-rata kedatangan 5 nasabah per jam mampu memberikan pelayanan yang efisien. Sebagian besar nasabah hanya perlu menunggu dalam waktu yang sangat singkat sebelum dilayani, dan pada beberapa hari bahkan hampir tidak ada waktu tunggu sama sekali. Hal ini mencerminkan bahwa kapasitas teller relatif memadai terhadap beban kerja harian.

(c) Hitung berapa persen waktu teller sibuk bekerja

# Total waktu kerja tersedia: 2 teller × 6 jam × 60 menit × 20 hari
total_available_time <- n_tellers * total_minutes * simulation_days

# Hitung total waktu pelayanan selama 20 hari
total_service_time <- sum(sapply(results, function(x) sum(x$departures$service)))

# Hitung persentase teller sibuk (utilisasi)
teller_utilization <- (total_service_time / total_available_time) * 100

cat("Persentase waktu teller sibuk selama 20 hari:", round(teller_utilization, 2), "%\n")
## Persentase waktu teller sibuk selama 20 hari: 32.59 %

Berdasarkan hasil simulasi, diperoleh bahwa persentase waktu teller berada dalam kondisi sibuk selama 20 hari kerja adalah sebesar 32.59%. Nilai ini dihitung dengan membandingkan total waktu pelayanan seluruh nasabah terhadap total waktu kerja yang tersedia dari dua teller, yaitu 14.400 menit (2 teller × 6 jam × 60 menit × 20 hari). Angka ini menunjukkan bahwa teller masih memiliki kapasitas kerja yang cukup besar dan belum bekerja secara penuh sepanjang hari. Dengan tingkat utilisasi sekitar 30%, sistem antrian masih efisien dan dapat menampung tambahan beban nasabah jika diperlukan.

5 (d)

arrival_rate <- 5/60      # 5 nasabah/jam -> nasabah/menit
service_rate <- 1/8       # 8 menit/nasabah -> nasabah/menit
operational_hours <- 6    # Buka 6 jam/hari
total_minutes <- operational_hours * 60
simulation_days <- 20     # Simulasi 20 hari
set.seed(123)
simulate_with_tellers <- function(n_tellers) {
  results <- lapply(1:simulation_days, function(day) {
    interarrivals <- rexp(ceiling(arrival_rate * total_minutes * 1.5), arrival_rate)
    arrivals <- cumsum(interarrivals)
    arrivals <- arrivals[arrivals <= total_minutes]
    service_times <- rexp(length(arrivals), service_rate)
    departures <- queue_step(arrivals, service_times, servers = n_tellers)
    
    return(list(
      waiting = departures - arrivals - service_times,
      queue_length = sapply(1:total_minutes, function(t) sum(arrivals <= t & departures > t)),
      utilization = sum(service_times) / (n_tellers * total_minutes)
    ))
  })
  
  list(
    avg_wait = mean(unlist(lapply(results, function(x) mean(x$waiting)))),
    max_queue = max(unlist(lapply(results, function(x) max(x$queue_length)))),
    utilization = mean(sapply(results, function(x) x$utilization)) * 100
  )
}

baseline_2tellers <- simulate_with_tellers(2)
scenario_3tellers <- simulate_with_tellers(3)
comparison_df <- data.frame(
  Metric = c("Rata-rata Waktu Tunggu (menit)", 
             "Antrian Maksimum",
             "Utilisasi Teller (%)"),
  `2_Tellers` = c(round(baseline_2tellers$avg_wait, 2),
               baseline_2tellers$max_queue,
               round(baseline_2tellers$utilization, 1)),
  `3_Tellers` = c(round(scenario_3tellers$avg_wait, 2),
               scenario_3tellers$max_queue,
               round(scenario_3tellers$utilization, 1)),
  Perubahan = c(
    paste0(round((baseline_2tellers$avg_wait - scenario_3tellers$avg_wait)/baseline_2tellers$avg_wait * 100, 1), "%"),
    paste0(baseline_2tellers$max_queue - scenario_3tellers$max_queue, " orang"),
    paste0(round(baseline_2tellers$utilization - scenario_3tellers$utilization, 1), "%")
  )
)

knitr::kable(comparison_df, caption = "Perbandingan 2 vs 3 Teller")
Perbandingan 2 vs 3 Teller
Metric X2_Tellers X3_Tellers Perubahan
Rata-rata Waktu Tunggu (menit) 0.74 0.04 94.3%
Antrian Maksimum 6.00 4.00 2 orang
Utilisasi Teller (%) 32.60 20.50 12.1%
# Asumsi biaya
hourly_wage <- 50000  # Rp50.000/jam/teller
daily_cost_2 <- 2 * hourly_wage * operational_hours
daily_cost_3 <- 3 * hourly_wage * operational_hours

# Hitung pengurangan waktu tunggu
time_saved <- baseline_2tellers$avg_wait - scenario_3tellers$avg_wait

cost_analysis <- data.frame(
  Metrik = c("Biaya Operasional/hari", 
             "Rata-rata Waktu Tunggu",
             "Pengurangan Waktu Tunggu",
             "Biaya per Menit yang Dihasilkan"),
  `2_Tellers` = c(paste("Rp", format(daily_cost_2, big.mark = ".")),
               paste(round(baseline_2tellers$avg_wait, 1), "menit"),
               "-",
               "-"),
  `3_Tellers` = c(paste("Rp", format(daily_cost_3, big.mark = ".")),
               paste(round(scenario_3tellers$avg_wait, 1), "menit"),
               paste(round(time_saved, 1), "menit"),
               paste("Rp", format(round((daily_cost_3 - daily_cost_2)/time_saved), big.mark = ".")))
)
## Warning in prettyNum(.Internal(format(x, trim, digits, nsmall, width, 3L, :
## 'big.mark' and 'decimal.mark' are both '.', which could be confusing
## Warning in prettyNum(.Internal(format(x, trim, digits, nsmall, width, 3L, :
## 'big.mark' and 'decimal.mark' are both '.', which could be confusing
## Warning in prettyNum(.Internal(format(x, trim, digits, nsmall, width, 3L, :
## 'big.mark' and 'decimal.mark' are both '.', which could be confusing
knitr::kable(cost_analysis, caption = "Analisis Biaya-Manfaat")
Analisis Biaya-Manfaat
Metrik X2_Tellers X3_Tellers
Biaya Operasional/hari Rp 6e+05 Rp 9e+05
Rata-rata Waktu Tunggu 0.7 menit 0 menit
Pengurangan Waktu Tunggu - 0.7 menit
Biaya per Menit yang Dihasilkan - Rp 427.629

Berdasarkan simulasi sistem antrian selama 20 hari kerja, diperoleh bahwa dengan 2 teller, panjang antrian rata-rata per menit adalah sekitar nasabah, dan waktu tunggu rata-rata adalah 0.7 menit. Ketika jumlah teller ditingkatkan menjadi 3, rata-rata waktu tunggu turun menjadi 0 menit, yang berarti nasabah hampir selalu langsung dilayani tanpa menunggu.Namun, peningkatan ini juga diikuti oleh kenaikan biaya operasional harian, dari Rp600.000 menjadi Rp900.000. Dengan pengurangan waktu tunggu sebesar 0.7 menit, diperoleh bahwa biaya tambahan per menit waktu tunggu yang dihilangkan adalah sekitar Rp427,63. Hal ini menunjukkan bahwa meskipun penambahan teller sangat efektif dalam mengurangi waktu tunggu, manajemen bank perlu mempertimbangkan apakah pengeluaran tambahan tersebut sepadan dengan manfaat yang diperoleh.

5 grafik

# Parameter sistem
arrival_rate <- 5/60      # 5 nasabah/jam -> nasabah/menit
service_rate <- 1/8       # 8 menit/nasabah -> nasabah/menit
operational_hours <- 6    # Buka 6 jam/hari
total_minutes <- operational_hours * 60
simulation_days <- 20     # Simulasi 20 hari
n_tellers <- 2            # Jumlah teller

# Fungsi simulasi dengan tracking antrian
simulate_queue <- function(day) {
  set.seed(123 + day) # Seed berbeda per hari
  interarrivals <- rexp(ceiling(arrival_rate * total_minutes * 1.5), arrival_rate)
  arrivals <- cumsum(interarrivals)
  arrivals <- arrivals[arrivals <= total_minutes]
  service_times <- rexp(length(arrivals), service_rate)
  departures <- queue_step(arrivals, service_times, servers = n_tellers)
  
  # Hitung panjang antrian per menit
  time_points <- 1:total_minutes
  queue_lengths <- sapply(time_points, function(t) {
    sum(arrivals <= t & departures > t)
  })
  
  return(data.frame(
    Day = day,
    Minute = time_points,
    QueueLength = queue_lengths,
    Hour = floor(time_points/60),
    TimeLabel = sprintf("%02d:%02d", floor(time_points/60), time_points%%60)
  ))
}

# Hasil simulasi 20 hari
queue_data <- do.call(rbind, lapply(1:5, simulate_queue)) # Ambil 5 hari pertama untuk visualisasi

Grafik Panjang Antrian per Hari

# Plot untuk 5 hari pertama
ggplot(queue_data, aes(x = Minute, y = QueueLength)) +
  geom_area(fill = "steelblue", alpha = 0.7) +
  facet_wrap(~Day, ncol = 1, scales = "free_x") +
  labs(title = "Panjang Antrian per Menit (5 Hari Pertama)",
       x = "Menit Operasional",
       y = "Jumlah Nasabah dalam Antrian") +
  theme_minimal() +
  scale_x_continuous(breaks = seq(0, total_minutes, by = 60),
                     labels = function(x) sprintf("%02d:%02d", floor(x/60), x%%60)) +
  geom_hline(yintercept = n_tellers, linetype = "dashed", color = "red") +
  annotate("text", x = 30, y = n_tellers + 0.5, 
           label = "Kapasitas Teller", color = "red", size = 3)

# Grafik rata-rata Harian

# Hitung rata-rata antrian per menit
avg_queue <- aggregate(QueueLength ~ Minute + Hour + TimeLabel, 
                      data = queue_data, mean)

ggplot(avg_queue, aes(x = Minute, y = QueueLength)) +
  geom_line(color = "darkorange", size = 1.5) +
  geom_ribbon(aes(ymin = 0, ymax = QueueLength), fill = "orange", alpha = 0.3) +
  labs(title = "Rata-Rata Panjang Antrian per Menit (5 Hari Pertama)",
       x = "Waktu Operasional",
       y = "Rata-Rata Jumlah Nasabah dalam Antrian") +
  theme_minimal() +
  scale_x_continuous(breaks = seq(0, total_minutes, by = 60),
                     labels = unique(avg_queue$TimeLabel)[seq(1, 361, by = 60)]) +
  geom_hline(yintercept = n_tellers, linetype = "dashed", color = "red") +
  annotate("text", x = 30, y = n_tellers + 0.3, 
           label = "Jumlah Teller", color = "red") +
  geom_vline(xintercept = c(120, 240), linetype = "dotted", 
             color = "blue", alpha = 0.5) +
  annotate("text", x = c(120, 240), y = max(avg_queue$QueueLength) - 0.5,
           label = c("Jam Sibuk Pagi", "Jam Sibuk Siang"), 
           color = "blue", angle = 90, vjust = -0.5)
## 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.

Soal No 6

# parameter sistem
initial_stock <- 100
order_quantity <- 50
order_freq <- 5
sim_days <- 60
lost_profit <- 50000  # Rp50.000 per karung
# fungsi simulasi dasar
simulate_stock <- function(days, order_qty, order_interval, initial) {
  stock <- initial
  stock_history <- numeric(days)
  out_of_stock <- 0
  total_lost <- 0
  
  for (day in 1:days) {
    # Penjualan harian (Uniform 8-15 karung)
    sales <- sample(8:15, 1)
    
    # Update stok
    if (stock >= sales) {
      stock <- stock - sales
    } else {
      lost <- sales - stock
      total_lost <- total_lost + lost * lost_profit
      stock <- 0
      out_of_stock <- out_of_stock + 1
    }
    
    # Pesan ulang setiap order_interval hari
    if (day %% order_interval == 0) {
      stock <- stock + order_qty
    }
    
    stock_history[day] <- stock
  }
  
  return(list(
    stock_history = stock_history,
    out_of_stock = out_of_stock,
    total_lost = total_lost
  ))
}

(a) Simulasi Stok Selama 60 Hari

set.seed(123)
result_a <- simulate_stock(sim_days, order_quantity, order_freq, initial_stock)

# Tampilkan 10 hari pertama
head(data.frame(
  Hari = 1:10,
  Stok = result_a$stock_history[1:10],
  Penjualan = diff(c(initial_stock, result_a$stock_history[1:10])) * -1
), 10)
##    Hari Stok Penjualan
## 1     1   86        14
## 2     2   72        14
## 3     3   62        10
## 4     4   49        13
## 5     5   89       -40
## 6     6   80         9
## 7     7   71         9
## 8     8   58        13
## 9     9   48        10
## 10   10   86       -38
cat("\nTotal kehabisan stok:", result_a$out_of_stock, "hari")
## 
## Total kehabisan stok: 3 hari
cat("\nTotal kerugian: Rp", format(result_a$total_lost, big.mark = "."))
## Warning in prettyNum(.Internal(format(x, trim, digits, nsmall, width, 3L, :
## 'big.mark' and 'decimal.mark' are both '.', which could be confusing
## 
## Total kerugian: Rp 9e+05

(b) Hitung Kehabisan Stok

cat("Toko kehabisan stok sebanyak:", result_a$out_of_stock, "kali dalam 60 hari")
## Toko kehabisan stok sebanyak: 3 kali dalam 60 hari

(c) strategi Jumlah Pesanan

strategi_qty <- list(
  "40_karung" = simulate_stock(sim_days, 40, order_freq, initial_stock),
  "50_karung" = result_a,  # Hasil dari (a)
  "60_karung" = simulate_stock(sim_days, 60, order_freq, initial_stock)
)

qty_comparison <- data.frame(
  Strategi = c("40 karung", "50 karung", "60 karung"),
  Kehabisan_Stok = sapply(strategi_qty, function(x) x$out_of_stock),
  Kerugian = sapply(strategi_qty, function(x) x$total_lost),
  Stok_Rata2 = sapply(strategi_qty, function(x) mean(x$stock_history))
)

knitr::kable(qty_comparison, caption = "Perbandingan Strategi Jumlah Pesanan")
Perbandingan Strategi Jumlah Pesanan
Strategi Kehabisan_Stok Kerugian Stok_Rata2
40_karung 40 karung 17 8350000 28.21667
50_karung 50 karung 3 900000 48.43333
60_karung 60 karung 0 0 76.88333

Simulasi dilakukan untuk tiga strategi jumlah pesanan: 40, 50, dan 60 karung setiap 5 hari. Hasilnya menunjukkan bahwa:

Dengan mempertimbangkan efisiensi dan kerugian, strategi pemesanan 50 karung adalah yang paling seimbang dan direkomendasikan untuk Bu Sari.

(d) Strategi Frekuensi Pesanan

strategi_freq <- list(
  "3_hari" = simulate_stock(sim_days, order_quantity, 3, initial_stock),
  "5_hari" = result_a,  # Hasil dari (a)
  "7_hari" = simulate_stock(sim_days, order_quantity, 7, initial_stock)
)

freq_comparison <- data.frame(
  Strategi = c("Setiap 3 hari", "Setiap 5 hari", "Setiap 7 hari"),
  Kehabisan_Stok = sapply(strategi_freq, function(x) x$out_of_stock),
  Kerugian = sapply(strategi_freq, function(x) x$total_lost),
  Stok_Rata2 = sapply(strategi_freq, function(x) mean(x$stock_history))
)

knitr::kable(freq_comparison, caption = "Perbandingan Strategi Frekuensi Pesanan")
Perbandingan Strategi Frekuensi Pesanan
Strategi Kehabisan_Stok Kerugian Stok_Rata2
3_hari Setiap 3 hari 0 0 235.53333
5_hari Setiap 5 hari 3 900000 48.43333
7_hari Setiap 7 hari 20 9400000 24.70000

6(d) Perbandingan Strategi Frekuensi Pemesanan

Simulasi dilakukan untuk strategi pemesanan beras setiap 3, 5, dan 7 hari dengan jumlah pesanan tetap sebanyak 50 karung. Hasilnya menunjukkan bahwa:

  • Strategi setiap 3 hari tidak mengalami kehabisan stok sama sekali, namun menyimpan rata-rata stok yang sangat tinggi (235 karung).
  • Strategi setiap 5 hari hanya kehabisan stok 3 kali, dengan kerugian sebesar Rp 900.000, dan stok rata-rata yang moderat.
  • Strategi setiap 7 hari memiliki risiko terbesar, kehabisan stok selama 20 hari dan kerugian Rp 9.400.000.

Dengan mempertimbangkan efisiensi dan biaya, strategi pemesanan setiap 5 hari merupakan pilihan terbaik dan direkomendasikan untuk Bu Sari.

(e) Visualisasi & Rekomendasi

# Gabungkan data untuk plot
plot_data <- data.frame(
  Hari = 1:sim_days,
  Stok = result_a$stock_history,
  Stok_40 = strategi_qty$`40_karung`$stock_history,
  Stok_60 = strategi_qty$`60_karung`$stock_history
)

# Plot pergerakan stok
ggplot(plot_data, aes(x = Hari)) +
  geom_line(aes(y = Stok, color = "50 karung"), size = 1) +
  geom_line(aes(y = Stok_40, color = "40 karung"), linetype = "dashed") +
  geom_line(aes(y = Stok_60, color = "60 karung"), linetype = "dotted") +
  labs(title = "Pergerakan Stok Beras (60 Hari)",
       y = "Jumlah Stok",
       color = "Strategi Pesanan") +
  theme_minimal() +
  scale_color_manual(values = c("50 karung" = "blue", "40 karung" = "red", "60 karung" = "green")) +
  geom_hline(yintercept = 0, color = "black", linetype = "dashed") +
  annotate("text", x = 30, y = 5, label = "Stok Habis", color = "red")