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.