CaseStudyForm
Title Modelling Requests to a Courier Service
DateSubmitted 9 Aug 2009
CaseStudyType TeachingCaseStudy
OperationsResearchTopics SimulationModelling
ApplicationAreas Logistics
ProblemDescription A courier company offers a service for delivering packages within the Inner City area in under an hour.

An Inner City courier leaves the distribution centre if EITHER there are 10 deliveries to make OR it has been 15 minutes since the "oldest" delivery request arrived, i.e., the first request that arrived after the last delivery run departed. The courier company works for 8 hours a day and starts each day with no deliveries to make.

The courier company has collected data on the time between requests for the Inner City deliveries as well as the time required to make Inner City deliveries. They want to know how many deliveries their Inner City couriers make each day and also how long they are on the road during a day.

ProblemFormulation To simplify the modelling we will abstract 2 sections of the problem:

1. Requests for Inner City deliveries;
2. Delivery runs for Inner City deliveries;

We start by assuming we can model these accurately using random variables, so we can concentrate on the remaining logic in the system. Figure 1 shows a flow diagram for the Inner City deliveries.

Figure 1 Flow Diagram for Inner City Deliveries

The way to implement this flow diagram will differ depending on the simulation modelling tools used.

ComputationalModel To model the flow diagram from Figure 1 we first abstract the requests for deliveries and the delivery runs as Arena submodels. The submodel for requests only generates requests, so a single submodel with only an exit point is needed. The submodel for a delivery run has the load of deliveries as input and outputs the load of deliveries after the delivery run finishes, so it has a single entry and exit point. The following flash tutorial shows how to add the appropriate submodels in Arena:

Table 1 Submodel Inputs

| Name | =Requests for Inner City Delivery=| | Number of Entry Points | `0` | | Number of Exit Points | `1` |

| Name | =Inner City Delivery Run=| | Number of Entry Points | `1` | | Number of Exit Points | `1` |

Table 1 shows the input value for the submodels.

Next, we want queues that store delivery entities until a delivery run occurs. We define a boolean variable `Loading Inner City` that is 1 when an inner city courier may be loaded for delivery and 0 otherwise. We then add a Hold module that stores deliveries until `Loading Inner City` is 1. Remember that Hold modules that `Scan for Condition` only scan for the condition when a calendar event occurs. The next flash tutorial shows how to add a Hold module and a Variable to implement this queue for Inner City deliveries. Table 2 also summarises the input for the Variable and Hold modules.

Table 2 Inputs for the Variable and Hold modules | Name | `Loading Inner City` | | Initial Values | `0` |

| Name | `Wait for Inner City Delivery` | | *Type*| `Scan for Condition` | | Condition | Loading Inner City == 1 |

Next, we want to create logical entities to take care of triggering delivery runs if the oldest delivery request has waited long enough. First, we create an Expression that acts like a constant and stores the maximum time a delivery will wait before a courier run must deliver it. Table 3 shows the input for this Expression.

Table 3 Expression Input

| Name | `Inner City Max Time` | | Expression Values | `15` |

Note that the main difference between Variables and Expressions is that Variables can change during a simulation. The value of an Expression may change, but the actual Expression will not. Note also that we could have simply "hard coded" the 15 into our model, but by using Expressions we can easily change this time later if the courier operation changes.

Now, we add a Variable that holds the time the oldest undelivered inner city delivery request arrived. Table 4 shows the input for this Variable.

Table 4 Variable Input

| Name | `Inner City Oldest Undelivered` |

Each time a delivery request comes in we use a Decide module to check if there are any other requests waiting. If there are no other deliveries waiting we note down its arrival time in `Inner City Oldest Undelivered` using an Assign module. The following flash tutorial shows how to add the Decide and Assign modules:

Next we create a timing entity using a Separate module. The duplicate entity then waits for the maximum time before a delivery run must deliver the oldest request (i.e., `Inner City Max Time`) using a Delay module and then leaves the system. This may seem like a waste of simulation modules, but the departure of this duplicate entity from the model creates a calendar event which will cause all Hold modules using `Scan for Condition` to check their conditions. The original request joins the queue of requests waiting to be delivered (it will be the first one in the queue of course). The following flash tutorial shows how to create the timing entity for the Inner City deliveries:

Table 5 Module inputs

| Name | `Any Inner City Deliveries Waiting?` | | Type | `2-way by Condition` | | If | `Expression` | | Value | `NQ(Wait for Inner City Delivery.Queue) > 0` |

| Name | `Save Inner City Oldest Undelivered` | | *Assignments (secondary dialog via Add button)*|| || Type | `Variable` | || Variable Name | `Inner City Oldest Undelivered` | || New Value | =TNOW=|

| Name | `Create Inner City Timer` | | Type | `Duplicate Original` | | # of Duplicates | `1` |

| Name | `Wait Inner City Max Time` | | Delay Time | `Inner City Max Time` | | Units | `Minutes` |

Table 5 shows the inputs for the modules added.

Now that a timer entity has been created and delayed 15 minutes, we need to check if this timer should trigger a delivery. Once the 15 minutes is up, we check if the current simulation time is 15 minutes or more from the last recorded `Inner City Oldest Undelivered`. If is is, then a delivery must be made, so `Loading Inner City` is set to 1. Otherwise a delivery has been made within the last 15 minutes, so this timer is simply discarded. The following flash tutorial shows how to trigger deliveries using the timer:

Table 6 Module inputs

| Name | `Is Inner City Oldest Undelivered?` | | Type | `2-way by Condition` | | If | `Expression` | | Value | `TNOW - Inner City Oldest Undelivered >=` `Inner City Max Time` |

| Name | `Trigger Inner City Delivery` | | *Assignments (secondary dialog via Add button)*|| || Type | `Variable` | || Variable Name | `Loading Inner City` | || New Value | =1=|

| Name | `Remove Timer` |

Table 6 shows the inputs for the modules added.

Now deliveries are triggered by the maximum time elapsing, so we need to ensure they are triggered by the maximum load being present. We add a new Expression `Inner City Max Load` for the maximum load required before a delivery is made and use this Expression to check whether to trigger a delivery or not (see Table 7).

Table 7 Module inputs

| Name | `Inner City Max Load` | | Expression Values | `10` |

| Name | `Max Inner City Deliveries?` | | Type | `2-way by Condition` | | If | `Expression` | | Value | `NQ(Wait for Inner City Delivery.Queue) + 1 ==` `Inner City Max Load` |

| Name | `Make Inner City Delivery` | | *Assignments (secondary dialog via Add button)*|| || Type | `Variable` | || Variable Name | `Loading Inner City` | || New Value | =1=|

The following flash tutorial shows how to trigger deliveries when the maximum load is reached:

Now we have triggered a delivery either using a timer or by reaching the maximum load. Next, we have to load all the currently waiting deliveries, but to do this we need to record what the load will be. The following flash tutorial shows how to record the load for a delivery triggered by a timer or by the maximum load being reached:

Table 8 Module inputs

| Name | `Make Inner City Delivery` | | *Assignments (secondary dialog via Add button)*|| || Type | `Variable` | || Variable Name | `Current Load` | || New Value | =NQ(Wait for Inner City Delivery.Queue) + 1=|

| Name | `Trigger Inner City Delivery` | | *Assignments (secondary dialog via Add button)*|| || Type | `Variable` | || Variable Name | `Current Load` | || New Value | =NQ(Wait for Inner City Delivery.Queue)=|

Table 8 shows the inputs for the modules added.

Next, we batch the load together, signal we have finished loading and make a delivery run. Table 9 shows the inputs for the required modules.

Table 9 Module inputs

| Name | `Create Inner City Load` | | *Batch Size*| `Current Load` |

| Name | `Stop Inner City Delivery Trigger` | | *Assignments (secondary dialog via Add button)*|| || Type | `Variable` | || Variable Name | `Loading Inner City` | || New Value | =0=|

The following flash tutorial shows how to batch a load and make a delivery run:

Finally, once the delivery run has been made, the deliveries are complete so the load may be split into individual delivery requests again and removed from the simulation. The following flash tutorial shows how to split the load and remove the requests:

Table 10 shows the inputs to the modules added.

Table 10 Inputs for modules

| Name | `Split Inner City Load` | | *Type*| `Split Existing Batch` |

| Name | `Delivery Complete` |

Now the logic of the Inner City part of the model is complete except for the arrivals and delivery runs.

Your complete model should look like that in Figure 2.

Figure 2 Courier Model with complete Inner City and Metropolitan logic

### Initial Distributions

Once you have completed the Inner City logic of the model, you will need to add some distributions to "drive" your simulation. To start off with we will try some simple distributions. Use exponential interarrival times with mean 10 minutes for Inner City delivery requests (make sure to use EXPO(10)). We will use a triangular distribution with min, mode and max of 10, 15, 20 for Inner City delivery runs. If you are unsure how to add and edit Create and Process modules, you should complete the Output Buffering case study before continuing. Add the appropriate Create and Process modules to your submodels. Connect them to the appropriate entry and exit points. Finally, make sure you have an infinite number of couriers by editing the capacity of your Resources (click on the Resources module in the Basic Process template and look for Capacity.

Now run your model for 50 replications. Each replication should run for 8 hours (i.e., 1 day of the courier operation) and the Base Time Units are minutes.

Results

Figure 4 Initial output from the Courier Model

After running you model you should get the output shown in Figure 4, such that the delivery time is within [23.1611, 23.9611] minutes, the number of Inner City couriers busy on average is within [0.5233, 0.5633] with 95% confidence and the average number time of deliveries in a day is within [17.0500, 18.2700] with 95% confidence. However, we are just using some very crude estimates of input data to verify our model.

You can also use animation to enhance (and check) your model. The following flash tutorial shows how to add the animation to your model. For example, you could animate the resources and queues, e.g., show a courier on the bike and packages "stacking" up:

You could change the Seize Area (this must be checked in your resource picture, see Figure 5), so an entity being served by the resource appears in an appropriate place, e.g., on the back of the bike:

Figure 5 Highlighted Seize Area in Resource picture dialog

You could change the Entity Picture during the simulation to reflect what is happening, e.g., a package for the batched deliveries (on the back of the bike):

You could add visualisations to monitor values during simulation, e.g., the number of deliveries waiting:

Figure 6 shows some screen shots of the animation elements during a simulation.

Figure 6 Animation screen shots

Conclusions The simulation model developed in this case study is only a starting point for experimentation. The logic of the system being modelled has been correctly implemented, but the input is based on rough estimates and more work needs to be done to get valid inputs and compare the simulation model for a range of different input options.

This work is done in another case study, Input and Output for a Courier Service Model.

ExtraForExperts

Topic attachments
I Attachment History Action Size Date Who Comment
png courier_flow.png r6 r5 r4 r3 r2 manage 41.3 K 2012-07-20 - 08:41 MichaelOSullivan
flv CourierServiceModel_Submodels.flv r2 r1 manage 579.6 K 2012-07-19 - 03:55 MichaelOSullivan
flv CourierServiceModel_SeizeArea.flv r1 manage 597.2 K 2012-07-20 - 12:06 TWikiAdminUser
flv CourierServiceModel_Level.flv r1 manage 1624.9 K 2012-07-20 - 12:22 TWikiAdminUser
flv CourierServiceModel_Hold.flv r2 r1 manage 1641.5 K 2012-07-20 - 10:10 TWikiAdminUser
flv CourierServiceModel_Delivered.flv r1 manage 1677.5 K 2012-07-20 - 10:11 TWikiAdminUser
flv CourierServiceModel_Load.flv r3 r2 r1 manage 2095.9 K 2012-07-20 - 10:11 TWikiAdminUser
flv CourierServiceModel_Send.flv r1 manage 2630.8 K 2012-07-20 - 10:13 TWikiAdminUser
flv CourierServiceModel_Timing.flv r2 r1 manage 2948.1 K 2012-07-20 - 10:27 TWikiAdminUser
flv CourierServiceModel_Decide.flv r3 r2 r1 manage 3616.1 K 2012-07-20 - 10:21 TWikiAdminUser
flv CourierServiceModel_EntityPictures.flv r1 manage 4472.8 K 2012-07-20 - 12:23 TWikiAdminUser
flv CourierServiceModel_TimedTrigger.flv r2 r1 manage 4864.6 K 2012-07-20 - 10:32 TWikiAdminUser
flv CourierServiceModel_MaxTrigger.flv r1 manage 5055.0 K 2012-07-20 - 10:12 TWikiAdminUser
flv CourierServiceModel_Animate.flv r2 r1 manage 5271.9 K 2012-07-20 - 12:04 TWikiAdminUser
Edit | Attach | Watch | Print version |  | Backlinks | View topic | Raw edit | More topic actions...
Topic revision: r31 - 2012-07-24 - TWikiAdminUser

 Home OpsRes Web P View Edit Account
 Edit Attach
Copyright © 2008-2022 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback