This is the simulation:
import salabim as sim
class Customer(sim.Component):
def process(self):
# first we shuffle the checkout queues
checkout_queues_in_random_order = env.Pdf(env.checkout_queues, 1).sample(n=len(env.checkout_queues))
# then we sort them, largest available quantity first. As sorted is stable equal available quantity queues
# are kept in the same (shuffled) order
checkout_queues_in_random_order_sorted_on_available_quantity = sorted(
checkout_queues_in_random_order, key=lambda checkout_queue: checkout_queue.available_quantity(), reverse=True
)
# then we join the joint queue
self.enter(env.joint_queue)
# and now we try and grab a place in one of the checkout queues
yield self.to_store(checkout_queues_in_random_order_sorted_on_available_quantity, item=self)
# if we indeed could get a place, we leave the joint queue
self.leave(env.joint_queue)
class Checkout(sim.Component):
def setup(self):
self.queue = env.Store(f"{self.name()}.queue", capacity=env.maximum_queue_length_at_checkpoint)
self.queue.animate(x=600, y=50 + self.sequence_number() * 100, title=f"queue for {self.sequence_number()}")
# the service queue is only used for animation and could be used for statistics
self.service = env.Store(f"{self.name()}.service")
self.service.animate(x=700, y=50 + self.sequence_number() * 100, title=f"client at {self.sequence_number()}")
def process(self):
while True:
truck = yield self.from_store(self.queue)
truck.enter(self.service)
yield self.hold(env.service_time)
truck.leave(self.service)
def main():
global env
env = sim.Environment()
env.number_of_checkpoints = 4
env.maximum_queue_length_at_checkpoint = 2
env.service_time = env.Uniform(100, 900)
env.customer_iat = env.Uniform(40, 200)
env.animate(True)
env.speed(100)
env.modelname("Demo supermarket")
env.checkout_queues = [Checkout().queue for _ in range(env.number_of_checkpoints)]
env.joint_queue = env.Queue("joint_queue")
env.joint_queue.animate(x=400, y=50 + env.number_of_checkpoints / 2 * 100)
env.ComponentGenerator(Customer, iat=env.customer_iat)
env.run(env.inf)
if __name__ == "__main__":
main()