-
Notifications
You must be signed in to change notification settings - Fork 44
Description
Hello there 👋
I'm trying to understand how ciw handles deterministic arrivals and services in a simple queue simulation. Specifically, I'm seeing fewer arrivals than expected, and I'd appreciate some guidance on whether this is a bug or expected behavior. I am working on simulating a very simple queue where:
- Arrivals occur exactly once per hour
- Each arrival is serviced in exactly one hour
- The simulation runs for a total of 24 hours
Since arrivals are deterministic, I would like to see the theoretical number of arrivals match what ciw returns after the simulation, and there appears to be a discrepancy (which may totally be user error on my side 😅 ). Curious if anyone can help out and opine on some of the issues I'm having.
In this dummy experiment, I would expect 24 arrivals in the system. However, I'm producing 22 arrivals in this simulation:
N = ciw.create_network(
arrival_distributions=[ciw.dists.Deterministic(value=1)],
service_distributions=[ciw.dists.Deterministic(value=1)],
number_of_servers=[1]
)
ciw.seed(1)
Q = ciw.Simulation(N)
sim_time = 24
Q.simulate_until_max_time(sim_time)
recs = pd.DataFrame(Q.get_all_records())
# there is a gap here.. I think some of this might be clipping at the upper limit (but not sure why there aren't 23 tickets then..)
print('Theoretical Arrivals: ', sim_time)
print('Actual Arrivals: ', recs.shape[0])
Interestingly, there also appears to be some influence of the number of servers. Suppose I have a the following shift schedule, which maps to EST business hours in UTC times. I intend any arrivals outside of business hours to join the waiting queue and then be serviceable in business hours. This produces 20 arrivals and similarly I would expect 24 arrivals (1 per hour for 24 hours).
# create network
N = ciw.create_network(
arrival_distributions=[ciw.dists.Deterministic(value=1)],
service_distributions=[ciw.dists.Deterministic(value=1)],
number_of_servers=[
ciw.Schedule(
numbers_of_servers=[0, 5, 0],
shift_end_dates=[13, 20, 24]
)],
)
# calculate metrics
ciw.seed(2)
Q = ciw.Simulation(N)
sim_time = 24
Q.simulate_until_max_time(sim_time)
recs = pd.DataFrame(Q.get_all_records())
# there is more of a gap here, not sure why servers would impact the arrivals process (it shouldn't)
print('Theoretical Arrivals: ', sim_time)
print('Actual Arrivals: ', recs.shape[0])
Finally, if I introduce customer classes, this effect is compounded even further. Suppose I have an experiment where:
- We have
num_customercustomer classes, which each arrive at the same deterministic rate. (NB I intentionally do not want to thin these by multiplying by the proportion of the customer as documented, happy to go into more detail if needed) - We service each class at the same deterministic rate
For this simulation, I would expect num_customer * 24 arrivals (240 in this case), but am seeing 22 arrivals.
num_customers = 10
arrivals_distributions = {f'customer_{i}': [ciw.dists.Deterministic(value=1)] for i in range(0, num_customers)}
services_distributions = {f'customer_{i}': [ciw.dists.Deterministic(value=1)] for i in range(0, num_customers)}
# create network
N = ciw.create_network(
arrival_distributions=arrivals_distributions,
service_distributions=services_distributions,
number_of_servers=[1]
)
# calculate metrics
ciw.seed(2)
Q = ciw.Simulation(N)
sim_time = 24
Q.simulate_until_max_time(sim_time)
recs = pd.DataFrame(Q.get_all_records())
print('Theoretical Arrivals: ', num_customers * sim_time)
print('Actual arrivals: ', recs.shape[0])
# tickets per customer
recs.groupby('customer_class').agg(num_tickets=('id_number', 'count'))
Any advice would be really appreciated! Thanks all