R
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Data Structures
-
Section 4: Data Manipulation
-
Section 5: Visualization and Statistics
-
Section 6: Advanced R
-
Section 7: Practical Projects
-
Section 8: Interview Practice
-
Section 9: More Practice Exercises
-
Section 10: Shiny Apps in Depth
-
Section 11: More Data Wrangling
-
Section 12: Tidyverse Deep Dive
-
Section 13: Statistical Modeling Deep Dive
-
Section 14: Machine Learning in R
-
Section 15: R Visualization Deep Dive
-
Section 16: R Package Development Deep Dive
-
Section 17: R for Reproducible Research
-
Section 18: R and Databases
-
Section 19: R Performance Optimization
-
Section 20: Bioinformatics and Specialized R
-
Section 21: More Shiny Practice
-
Section 22: More Practice Exercises
-
Section 23: R Data Structures Deep Dive
-
Section 24: More Interview and Review
-
Section 25: R for Business Analytics
-
Section 26: R Text Mining and NLP
-
Section 27: R Spatial Data Analysis
-
Section 28: R Deep Learning
-
Section 29: Advanced Statistical Techniques
-
Section 30: R Object Systems Deep Dive
-
Section 31: R Environments and Metaprogramming
-
Section 32: R for Finance
-
Section 33: R for Clinical and Health Data
-
Section 34: More Shiny Advanced Practice
-
Section 35: R Data Cleaning Deep Dive
-
Section 36: R Reporting Automation
-
Section 37: More Practical Projects Round 2
-
Section 38: R Ecosystem and Career
-
Section 39: More Visualization Practice
-
Section 40: R for Experimentation
-
Section 41: R for Genomics and Bioinformatics Deep Dive
-
Section 42: R for Marketing Analytics
-
Section 43: R Data Import/Export Deep Dive
-
Section 44: R String Processing Deep Dive
-
Section 45: R for Actuarial and Insurance Analytics
-
Section 46: R Testing and Quality Assurance Deep Dive
-
Section 47: R Version Control and Collaboration
-
Section 48: R Advanced Functional Programming
-
Section 49: R for Supply Chain and Operations
-
Section 50: More Practice Exercises Round 3
-
Section 51: R Dashboards and BI Integration
-
Section 52: R Data Governance and Ethics
-
Section 53: More Modeling Practice
-
Section 54: R Final Capstone Projects
-
Section 55: R for Sports Analytics
-
Section 56: More Interview Practice Round 2
-
Section 57: R Networking and APIs
-
Section 58: R for Environmental Science
-
Section 59: R Notebook and Documentation Practices
-
Section 60: More Data Wrangling Mastery
-
Section 61: R for A/B Testing at Scale
-
Section 62: R Package Ecosystem Deep Dive
197: Simulation Modeling for Logistics Networks
Imagine you're running a high-end bakery that delivers custom cakes across the city. You have a limited number of delivery drivers and a few staging areas where cakes sit waiting for a ride. If you just guess how many drivers you need, you'll either waste money on idle staff or, worse, have expensive cakes melting on a loading dock because no one was available to move them. To solve this without risking your business, you'd probably sketch out a "what-if" scenario on a whiteboard: "What happens if I get 50 orders on a Friday but only have 3 drivers?"
Simulation modeling in R is essentially that whiteboard sketch, but powered by math and code. Instead of guessing, we create a "digital twin" of your logistics network. Here is how the bakery analogy maps directly to the simulation concepts we're using today:
- The Cake (The Entity): This is the individual unit moving through your system. In logistics, this could be a pallet, a shipping container, or a single parcel.
- The Loading Dock (The Queue): This is where entities wait when the next step in the process is full. We track the length of this queue to find our bottlenecks.
- The Driver (The Resource): This is the limited capacity. A driver can only move one cake at a time. If all drivers are busy, the "entity" stays in the "queue."
- The Drive Time (The Stochastic Delay): In the real world, a trip doesn't always take 20 minutes. Sometimes it's 15, sometimes it's 45 due to traffic. We model this using probability distributions rather than fixed numbers.
Defining the Logistics Flow with Simmer
For this, we'll use the simmer package. It's a discrete-event simulation (DES) framework. Unlike a standard loop, DES jumps from one event (like a package arriving) to the next, ignoring the empty space in between, which makes it incredibly efficient for logistics.
library(simmer)
First, we define the "trajectory"—the path a package takes. I like to think of this as the "Standard Operating Procedure" (SOP) for the shipment.
# Define the SOP for a package
package_trajectory <- trajectory("package_path") %>%
set_attribute("arrival_time", function() {now(env)}) %>%
seize("truck") %>%
timeout(function() {rnorm(1, mean = 120, sd = 20)}) %>% # Transit time: 2 hours avg
release("truck")
Notice that rnorm call. I'm not saying the trip takes 120 minutes; I'm saying it usually takes 120, but it varies. That's where the real insight comes from. If you only model the average, you'll never see the system crash during a peak surge.
Wiring the Network and Running the Clock
Now we need to actually build the environment and tell R how many "resources" (trucks) we have. This is where you can play "What If?" by changing a single digit.
env <- simmer("LogisticsNet") %>%
add_resource("truck", capacity = 5) %>% # We have 5 trucks
add_generator("package", package_trajectory, function() {rexp(1, 1/30)}) # New package every 30 mins avg
env %>% run(until = 1000) # Run for 1000 minutes of simulated time
I used rexp (exponential distribution) for the generator because shipments rarely arrive on a perfect clock; they arrive in clusters. This is a common mistake I see—using a fixed interval for arrivals. Real logistics are messy; your model should be too.
Extracting the Bottleneck Data
Running the simulation is the easy part. The value is in the data. We want to know: How long were the packages waiting?
arrivals <- get_mon_arrivals(env)
resources <- get_mon_resources(env)
# Calculate average waiting time
avg_wait <- mean(arrivals$`activity_time` - (arrivals$`end_time` - arrivals$`start_time`))
print(paste("Average Time in System:", round(avg_wait, 2), "minutes"))
If that average wait time is too high, you don't just "hope for the best." You go back to your add_resource line, bump the capacity from 5 to 6, and run it again. You've just performed a cost-benefit analysis without spending a dime on a new truck.
📋 Practical Task
Exercise: Optimizing the Regional Distribution Hub
You have been tasked with auditing a regional hub that ships medical supplies. The hub currently has 8 loading bays. Supplies arrive following an exponential distribution with an average of 15 minutes between arrivals. The loading process (seizing the bay and finishing the load) takes an average of 45 minutes, with a standard deviation of 10 minutes.
Your goal: Write a simulation script using simmer to determine the average time a shipment spends in the system. Then, determine the minimum number of loading bays required to ensure the average time a shipment spends in the system (including waiting) stays below 60 minutes.
Your code should include:
- A trajectory defining the seizure and release of the "bay" resource.
- A generator that simulates the arrivals.
- A loop or a series of runs that tests different bay capacities (starting at 8) until the 60-minute threshold is met.
- A final print statement identifying the optimal number of bays.
There are no comments for now.