import pandas as pd
# Import the wrapper objects for model interaction.
from examples.example_10_advanced_ciw.ex_10_ciw_model import N
from vidigi.ciw import event_log_from_ciw_recs
from vidigi.utils import EventPosition, create_event_position_df
from vidigi.animation import animate_activity_log
import plotly.io as pio
= "notebook"
pio.renderers.default import os
import ciw
A More Complex Ciw Example with Backgrounds
View Imported Code for the ciw model
import ciw
# From https://ciw.readthedocs.io/en/latest/Tutorial/tutorial_ii.html
= ciw.create_network(
N
=[ciw.dists.Exponential(rate=0.3 / 60),
arrival_distributions
=0.2 / 60),
ciw.dists.Exponential(rate
None],
=[ciw.dists.Exponential(rate=2.0 / 60),
service_distributions
=1.4 / 60),
ciw.dists.Exponential(rate
=1.0 / 60)],
ciw.dists.Exponential(rate
=[[0.0, 0.3, 0.7],
routing
0.0, 0.0, 1.0],
[
0.0, 0.0, 0.0]],
[
=[1, 2, 2]
number_of_servers
)
42)
ciw.seed(
= ciw.Simulation(N)
Q
= 180 * 60 # 180 minutes x 60 seconds
RESULTS_COLLECTION_PERIOD
Q.simulate_until_max_time(RESULTS_COLLECTION_PERIOD)
= Q.get_all_records()
recs
'id_number', 'service_start_date']).head(20) pd.DataFrame(recs).sort_values([
id_number | customer_class | original_customer_class | node | arrival_date | waiting_time | service_start_date | service_time | service_end_date | time_blocked | exit_date | destination | queue_size_at_arrival | queue_size_at_departure | server_id | record_type | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | Customer | Customer | 2 | 7.598652 | 0.000000 | 7.598652 | 13.783888 | 21.382540 | 0.0 | 21.382540 | 3 | 0 | 0 | 1 | service |
1 | 1 | Customer | Customer | 3 | 21.382540 | 0.000000 | 21.382540 | 67.750381 | 89.132921 | 0.0 | 89.132921 | -1 | 0 | 0 | 1 | service |
6 | 2 | Customer | Customer | 2 | 83.374507 | 0.000000 | 83.374507 | 95.455204 | 178.829712 | 0.0 | 178.829712 | 3 | 0 | 0 | 1 | service |
7 | 2 | Customer | Customer | 3 | 178.829712 | 0.000000 | 178.829712 | 53.388522 | 232.218234 | 0.0 | 232.218234 | -1 | 1 | 1 | 1 | service |
2 | 3 | Customer | Customer | 2 | 110.660229 | 0.000000 | 110.660229 | 23.487693 | 134.147921 | 0.0 | 134.147921 | 3 | 1 | 2 | 2 | service |
3 | 3 | Customer | Customer | 3 | 134.147921 | 0.000000 | 134.147921 | 13.301500 | 147.449421 | 0.0 | 147.449421 | -1 | 0 | 1 | 1 | service |
4 | 4 | Customer | Customer | 2 | 119.735282 | 14.412639 | 134.147921 | 1.152617 | 135.300539 | 0.0 | 135.300539 | 3 | 2 | 1 | 2 | service |
5 | 4 | Customer | Customer | 3 | 135.300539 | 0.000000 | 135.300539 | 47.239755 | 182.540294 | 0.0 | 182.540294 | -1 | 1 | 1 | 2 | service |
16 | 5 | Customer | Customer | 2 | 193.750291 | 0.000000 | 193.750291 | 71.045918 | 264.796209 | 0.0 | 264.796209 | 3 | 0 | 1 | 1 | service |
17 | 5 | Customer | Customer | 3 | 264.796209 | 0.000000 | 264.796209 | 216.972911 | 481.769120 | 0.0 | 481.769120 | -1 | 1 | 0 | 2 | service |
12 | 6 | Customer | Customer | 2 | 195.706281 | 0.000000 | 195.706281 | 70.241394 | 265.947675 | 0.0 | 265.947675 | 3 | 1 | 0 | 2 | service |
13 | 6 | Customer | Customer | 3 | 265.947675 | 30.320583 | 296.268259 | 48.183165 | 344.451423 | 0.0 | 344.451423 | -1 | 2 | 2 | 1 | service |
8 | 7 | Customer | Customer | 1 | 204.012057 | 0.000000 | 204.012057 | 12.476853 | 216.488910 | 0.0 | 216.488910 | 3 | 0 | 0 | 1 | service |
9 | 7 | Customer | Customer | 3 | 216.488910 | 0.000000 | 216.488910 | 24.622136 | 241.111046 | 0.0 | 241.111046 | -1 | 1 | 1 | 2 | service |
10 | 8 | Customer | Customer | 1 | 237.809311 | 0.000000 | 237.809311 | 2.919980 | 240.729291 | 0.0 | 240.729291 | 3 | 0 | 0 | 1 | service |
11 | 8 | Customer | Customer | 3 | 240.729291 | 0.000000 | 240.729291 | 55.538968 | 296.268259 | 0.0 | 296.268259 | -1 | 1 | 2 | 1 | service |
14 | 9 | Customer | Customer | 1 | 258.153048 | 0.000000 | 258.153048 | 49.371898 | 307.524946 | 0.0 | 307.524946 | 3 | 0 | 0 | 1 | service |
15 | 9 | Customer | Customer | 3 | 307.524946 | 36.926477 | 344.451423 | 57.821772 | 402.273196 | 0.0 | 402.273196 | -1 | 2 | 1 | 1 | service |
20 | 10 | Customer | Customer | 1 | 519.821134 | 0.000000 | 519.821134 | 59.351398 | 579.172532 | 0.0 | 579.172532 | 2 | 0 | 0 | 1 | service |
21 | 10 | Customer | Customer | 2 | 579.172532 | 1.027521 | 580.200053 | 4.563164 | 584.763217 | 0.0 | 584.763217 | 3 | 2 | 1 | 2 | service |
= event_log_from_ciw_recs(
event_log
recs,=["cold_food", "hot_food", "till"]
node_name_list
)
"entity_id"]==13] event_log[event_log[
entity_id | pathway | event_type | event | time | resource_id | |
---|---|---|---|---|---|---|
99 | 13 | Model | arrival_departure | arrival | 671.604123 | NaN |
100 | 13 | Model | queue | hot_food_wait_begins | 671.604123 | NaN |
101 | 13 | Model | resource_use | hot_food_begins | 671.604123 | 1.0 |
102 | 13 | Model | resource_use_end | hot_food_ends | 684.914665 | 1.0 |
103 | 13 | Model | queue | till_wait_begins | 684.914665 | NaN |
104 | 13 | Model | resource_use | till_begins | 684.914665 | 1.0 |
105 | 13 | Model | resource_use_end | till_ends | 741.277635 | 1.0 |
106 | 13 | Model | arrival_departure | depart | 741.277635 | NaN |
# Create a suitable class to pass in the resource numbers to the animation function
class model_params():
def __init__(self):
self.cold_food_servers = 1
self.hot_food_servers = 2
self.tills = 2
= model_params() params
# # Create required event_position_df for vidigi animation
# event_position_df = pd.DataFrame([
# {'event': 'arrival',
# 'x': 30, 'y': 550,
# 'label': "Arrival"},
# {'event': 'cold_food_wait_begins',
# 'x': 200, 'y': 510,
# 'label': "Waiting for Cold Food"},
# {'event': 'cold_food_begins',
# 'x': 210, 'y': 370,
# 'resource':'cold_food_servers',
# 'label': "Being Served Cold Food"},
# {'event': 'hot_food_wait_begins',
# 'x': 505, 'y': 510,
# 'label': "Waiting for Hot Food"},
# {'event': 'hot_food_begins',
# 'x': 505, 'y': 370,
# 'resource':'hot_food_servers',
# 'label': "Being Served Hot Food"},
# {'event': 'till_wait_begins',
# 'x': 350, 'y': 170,
# 'label': "Waiting for Till"},
# {'event': 'till_begins',
# 'x': 350, 'y': 120,
# 'resource':'tills',
# 'label': "Being Served at Till"},
# {'event': 'depart',
# 'x': 600, 'y': 10,
# 'label': "Exit"}
# ])
# event_position_df
= create_event_position_df( [
event_position_df ='arrival', x=30, y=550, label="Arrival"),
EventPosition(event='cold_food_wait_begins', x=200, y=510, label="Waiting for Cold Food"),
EventPosition(event='cold_food_begins', x=210, y=370, resource='cold_food_servers', label="Being Served Cold Food"),
EventPosition(event='hot_food_wait_begins', x=505, y=510, label="Waiting for Hot Food"),
EventPosition(event='hot_food_begins', x=505, y=370, resource='hot_food_servers', label="Being Served Hot Food"),
EventPosition(event='till_wait_begins', x=350, y=170, label="Waiting for Till"),
EventPosition(event='till_begins', x=350, y=120, resource='tills', label="Being Served at Till"),
EventPosition(event='depart', x=600, y=10, label="Exit")
EventPosition(event
] )
# Create animation
= model_params()
params
animate_activity_log(=event_log,
event_log=event_position_df,
event_position_df=model_params(),
scenario="seconds",
simulation_time_unit="dhms",
time_display_units=True,
debug_mode=False,
setup_mode=5, # 20 seconds
every_x_time_units=True,
include_play_button=20,
entity_icon_size=15,
gap_between_entities=25,
gap_between_queue_rows=30,
gap_between_resources=525,
plotly_height=200,
frame_duration=600,
frame_transition_duration=900,
plotly_width=700,
override_x_max=600,
override_y_max=RESULTS_COLLECTION_PERIOD,
limit_duration=25,
wrap_queues_at=50,
wrap_resources_at=75,
step_snapshot_max="12:00:00",
start_time=20,
text_size=False,
display_stage_labels="https://raw.githubusercontent.com/Bergam0t/vidigi/refs/heads/main/examples/example_10_advanced_ciw/cafe_floorplan.drawio%20(1).png"
add_background_image )
Animation function called at 15:19:45
Iteration through time-unit-by-time-unit logs complete 15:19:49
Snapshot df concatenation complete at 15:19:50
Reshaped animation dataframe finished construction at 15:19:50
Placement dataframe finished construction at 15:19:50
Output animation generation complete at 15:19:57
Total Time Elapsed: 12.62 seconds