Implementation of Supermarket lp's
the supermarket model
Entrance
(multiplexer)
configuration:
number-of-inputchannels
delay
state:
none
behaviour:
when an event enters:
add delay to event.timestamp
event.outputchannel = out [only 1
outputchannel]
Exit
(demultiplexer)
configuration:
none
Note that in general a demultiplexer has the number of outputchannels
as configuration parameter.
state:
none
behaviour:
when customer-event enters:
if customer-event.is-on-foot = true
customer-event.outputchannel
= to-town
else
customer-event.outputchannel
= to-parking
Parking
configuration:
parking-capacity
average-walk-to-entrance-time
free-space-search-time in function of number-of-parked-cars
let's assume that this function
is linear:
free-space-search-time = search-factor * number-of-parked-cars
state:
number-of-parked-cars
behaviour:
when car-event enters:
if parking is full then [full if
number-of-parked-cars
= parking-capacity]
search-time =
search-factor * parking-capacity
add search-time to car-event.timestamp
[time that event leaves is always time in plus a certain delay]
car-event.outputchannel
= to town [event leaves at channel to town]
[the same event
leaves the lp. In the next part, a new event is created]
else
create customer-event
customer-event.is-on-foot
= false
search-time = search-factor
* state.number-of-parked-cars
customer-event.timestamp
= car-event.timestamp + search-time + average-walk-to-entrance-time
customer-event.outputchannel
= to entrance
increase state.number-of-parked-cars
when customer-event enters
car-event.timestamp = customer-event.timestamp
+ average-walk-to-entrance-time
car-event.outputchannel = to town
delete customer-event [delete unused
events]
decrease state.number-of-parked-cars
Town
configuration:
average-number-of-customers [number of
customers per time unit]
percentage-on-foot [percentage of customers
that come on foot]
state:
none
behaviour:
when trigger-event enters:
is-on-foot = random(percentage-on-foot)
[pick a random variable, with an average probability of percentage-on-foot]
if is-on-foot then
create customer-event
customer-event.is-on-foot
= true
customer-event.timestamp
= trigger-event.timestamp
customer-event.outputchannel
= to entrance
else
create car-event
car-event.timestamp
= trigger-event.timestamp
car-event.outputchannel
= to parking
end
trigger-delay = random(average-number-of-customers)
[random number around average]
add trigger-delay to trigger-event
trigger-event.outputchannel = feedback
channel
when car-event or customer-event enters
delete event
Floor
configuration:
average-shop-time
percentage-goto-butcher
percentage-goto-info
state:
none
behaviour:
when customer-event from entrance enters
add average-shop-time to customer-event.timestamp
if random(percentage-goto-butcher) then
customer-event.outputchannel
= to butcher
else
if random(percentage-goto-info)
then
customer-event.outputchannel
= to info
else
customer-event.outputchannel
= to pay-desk
when customer-event from info or butcher
customer-event.outputchannel = to
pay-desk
[this is a usefull simplification, we suppose that customers
don’t go to info and butcher, we also don’t add an extra delay here, it
is already added]
Queue (butcher, info)
In this implementation of a queue, the events are not really kept in a
queue. Instead we immediately calculate the time that the event will be
handled. This is an important principle in Event-based simulation, calculate
as far as possible in the future.
configuration:
average-service-time [to handle 1 customer]
state:
time-of-next-customer [time that the next
customer can be handled]
behaviour:
when customer enters
service-time = random(average-service-time)
if customer.timestamp > time-of-next-customer
[the queue
is empty, the customer doesn’t have to wait]
time-of-next-customer
= customer.timestamp + service-time
else
add service-time
to time-of-next-customer
customer.timestamp = time-of-next-customer
customer.outputchannel = only
output
Desk-select
This lp is a special kind of demultiplexer. The customer chooses an open
pay-desk with the minimal number of waiting customers. Thus, the pay-desk-info
event should also contain the number of waiting customers. The pay-desk
lp will send an event each time a changement of its situation happens:
when it opens or closes, when a customer enters or leaves. So the desk-select
should remember the situations of all pay-desks.
configuration:
Number-of-pay-desks [= number of output
channels]
state:
Is-pay-desk-open[Number-of-pay-desks] (array)
Number-waiting-customers[Number-of-pay-desks]
behaviour:
When a customer-event enters:
Select open & minimal queue
pay-desk [this will be a procedure]
Customer.outputchannel = to selected
pay-desk
When an pay-desk-info-event enters:
Is-pay-desk-open[pay-desk-info-event.inputChannel]
= pay-desk-info-event.isOpen
Number-waiting-customers[pay-desk-info-event.inputChannel]
= pay-desk-info-event.number-of-waiting-customers
Pay-desk
This is a subtype of a queue (see butcher & info). First, we have to
add the decision mechanism to determine when the pay-desk open or closes.
Second, we have to send changements to its state to the desk-select lp.
We will not develop this here, but it is more complex than one thinks at
first glance! Implementing the close pay-desk is simple, close pay-desk
when number of waiting customers becomes smaller than a certain number.
But with the above queue implementation, the events are immediately sent
out, but then we don’t know if more events will enter in that time. Next,
deciding whether to open a pay-desk or not, is a centralised mechanism
(when the total number of waiting customers is large), it cannot be decided
by the pay-desk lp itself.
To solve the above problems, there are 2 major approaches: we can create
a centralised decision-lp that communicate with allpay-desk lp’s, or we
can create 1 big lp that cover all pay-desks and even the desk-select!!
We will not implement this here, it is simply to show typical problems
that have to be faced.