How to Simulate Reneging Customers

Ciw allows customers to renege, that is leave a queue after a certain amount of time waiting for service. In Ciw, this works by sampling from a reneging_time_distribution, giving the date that that customer will renege if their service has not started by that time.

For example, let’s say we have an M/M/1, \(\lambda = 5\) and \(\mu = 2\), queue where customers renege if they have spend more than 6 time units in the queue:

>>> import ciw
>>> N = ciw.create_network(
...     arrival_distributions=[ciw.dists.Exponential(5)],
...     service_distributions=[ciw.dists.Exponential(2)],
...     number_of_servers=[1],
...     reneging_time_distributions=[ciw.dists.Deterministic(6)]
... )

>>> ciw.seed(0)
>>> Q = ciw.Simulation(N, exact=5)
>>> Q.simulate_until_max_time(10)

Reneging events are recorded as DataRecords and so are collected along with service records with the get_all_records method. They are distinguished by the record_type field (services have service record type, while reneging events have renege record types).

For the above example, we see that no customer receiving service waited longer than 6 time units, as expected. We also see that all four reneging events happened after the customer waited 6 time units:

>>> recs = Q.get_all_records()
>>> max([r.waiting_time for r in recs if r.record_type == 'service'])
Decimal('5.8880')

>>> [r.waiting_time for r in recs if r.record_type == 'renege']
[Decimal('6.0000'), Decimal('6.0000'), Decimal('6.0000'), Decimal('6.0000')]

By default, when a customer reneges, they leave the network, that is they are sent to the exit node.

Note: Similarly to all other customer-level keyword arguments, reneging_time_distributions can take either a list of distributions indicating which reneging distribution to use at each node in the network; or dictionary mapping customer classes to these lists, allowing different reneging time distributions for each customer class.