import simpy
import pandas as pd
import random
from vidigi.animation import animate_activity_log
from vidigi.logging import EventLogger
from vidigi.utils import EventPosition, create_event_position_df
A very simple example with one server
Step 1. Import required libraries
vidigi
simpy
- for simulation model (or see the Ciw functions and examples elsewhere in this documentation)random
- for generating random arrivalspandas
- for managing dataframes
Step 2. Set up simulation parameters
# Simple simulation parameters
= 50
SIM_DURATION = 1
NUM_SERVERS = 1.0
ARRIVAL_RATE = 3.0 SERVICE_TIME
Step 3. Write model code with event logs
Create a simple simulation model using simpy
.
On the left is a basic simpy
model. If not familiar check out simpy
documentation for intro to simpy.
On the right is how we incorporate vidigi
. Information for vidigi
collected in a list of dictionaries which we will convert into a dataframe. You need a arrival_departure
event.
Simple SimPy Model
def patient_generator(env, server, event_log):
"""Generate patients arriving at the shop"""
= 0
patient_id
while True:
+= 1
patient_id
# Start the patient process
env.process(patient_process(env, patient_id, server, event_log))
# Wait for next arrival
yield env.timeout(random.expovariate(ARRIVAL_RATE))
def patient_process(env, patient_id, server, event_log):
"""Process a single patient through the system"""
# Request server
with server.request() as request:
yield request
# Service time
= random.expovariate(1.0/SERVICE_TIME)
service_duration yield env.timeout(service_duration)
# Run the simulation
def run_simulation():
= simpy.Environment()
env = simpy.Resource(env, capacity=NUM_SERVERS)
server = []
event_log
# Start patient generator
env.process(patient_generator(env, server, event_log))
# Run simulation
=SIM_DURATION) env.run(until
With Vidigi Modifications
def patient_generator(env, server, logger):
"""Generate patients arriving at the shop"""
= 0
patient_id
while True:
+= 1
patient_id
# Log arrival
=patient_id)
logger.log_arrival(entity_id
# Start the patient process
env.process(patient_process(env, patient_id, server, logger))
# Wait for next arrival
yield env.timeout(random.expovariate(ARRIVAL_RATE))
def patient_process(env, patient_id, server, logger):
"""Process a single patient through the system"""
# Log start of queue wait
=patient_id, event='queue_wait_begins')
logger.log_queue(entity_id
# Request server
with server.request() as request:
yield request
# Log service start
=patient_id, event="service_begins", resource_id=1)
logger.log_resource_use_start(entity_id
# Service time
= random.expovariate(1.0/SERVICE_TIME)
service_duration yield env.timeout(service_duration)
# Log service start
=patient_id, event="service_complete", resource_id=1)
logger.log_resource_use_end(entity_id
# Log departure
=patient_id)
logger.log_departure(entity_id
# Run the simulation
def run_simulation():
= simpy.Environment()
env = simpy.Resource(env, capacity=NUM_SERVERS)
server = EventLogger(env=env)
logger
# Start patient generator
env.process(patient_generator(env, server, logger))
# Run simulation
=SIM_DURATION)
env.run(until
return logger.to_dataframe()
Step 4. Run simulation
# Run simulation and get event log
= run_simulation()
event_log_df print(f"Generated {len(event_log_df)} events")
Generated 134 events
Step 5. Create event positions dataframe
# Define positions for animation
= create_event_position_df([
event_positions ='arrival', x=0, y=350, label="Entrance"),
EventPosition(event='queue_wait_begins', x=250, y=250, label="Queue"),
EventPosition(event='service_begins', x=250, y=150, resource='server', label="Being Served"),
EventPosition(event='depart', x=250, y=50, label="Exit")
EventPosition(event ])
Step 6. Create animation
Explaining:
plotly_height
andplotly_width
override_x_max
andoverride_y_max
setup_mode
every_x_time_units
# Create animation
animate_activity_log(=event_log_df,
event_log=event_positions,
event_position_df=1,
every_x_time_units=600,
plotly_height=360,
override_x_max=SIM_DURATION
limit_duration )