A Simple Discrete-Event Simulation: Part 73

Today I added the Bag component (number 36 in the frame above), which you can think of as a parking lot. It works largely the same way as a ProcessComponent but it doesn’t store its entities in a FIFO queue internally. Rather, it defines a list of entities with one space for each possible entity up to the defined maxCapacity of the component. An entity enters the component, gets assigned to the lowest empty index in the list, and begins working off its defined process time. When the process time ends the entity is moved over to an exit queue, which is another list of entities within the Bag component. The exit queue shows which entities are waiting to leave the Bag component, which is only relevant if the next downstream component is an exclusive one that is not currently open. I added a downstream Process component to the model in order to visually demonstrate this behavior.

The procedure for drawing the entities in the linked displayElement is a bit different than for the queue or process components. The designer should specify more entityLocs spaces than the capacity of the component. The first maxCapacity spaces are used to display the entities while they are “parked”. Any additional spaces are used to display the entities waiting in the exit queue. The Bag component in today’s version of the example model has a capacity of twelve and an additional five spaces reserved to show the exit queue. If there are more entities in the internal exit queue than there are spaces left to display them then the extras do not get displayed. One trick to make this more visually interesting, if it’s appropriate to the real process being modeled, is to assign the entity locations up to the Bag’s capacity in a semi-random order. That way the entities look like they’re parking in a more naturalistic manner rather than obediently filling spaces in regimented order. The border modeling programs I worked with at Regal Decision Systems (BorderWizard, CanSim, and SimFronteras) all allowed for this, and the effect was particularly striking in situations where there were large numbers of vehicles in a parking area. The commercial parking area at Ambassador Bridge in Detroit used to fill up in a big way when many trucks needed to park so the drivers could attend to customs paperwork. (That process has since been largely obviated by automating the paperwork so it’s completed offsite before the vehicle makes the crossing.)

Having a Bag component feed directly into another component that’s exclusive should probably be rare, but the full behavior is included. I’m thinking of my time analyzing and collecting data at dozens of border crossings where vehicles and pedestrians were almost always able to leave a Process or Bag (parking lot, literally) and go someplace else. There was effectively a non-exclusive queue in front of most processes and parking lots. That said, one can easily imagine a tightly coupled manufacturing process when internal queues have been squeezed out by design or after rearrangement following a Lean analysis.

Here’s the code for the entire Bag component.

I had to add the parameter processTimeSwitch to allow different type indices to be used for determining the process time for each entity type. The process times are provided to the component as an array of values meant to apply to different types using the function entityProcessTimeIndex(entity,this.processTimeSwitch). In the primary Process components I wanted the types to be based on a combination of the entity’s residency and process speed. In the secondary group I specified the same time for all types so it didn’t matter what indices were used. I noticed the problem when I was looking at the report output for the “Parking Lot” group when there was no Process component in place after the Bag component. I had defined process times of 30, 50, and 80 units envisioning that they would apply to citizens, LPRs, and visitors, respectively, but the process times reported for those types varied in ways I didn’t expect. Then I remembered how the entityProcessTimeIndex function worked and added a switch to it to allow different indices to be generated based on an entity’s properties. That index had to be added to the component definition for both the Bag and Process components.

Since JavaScript is so modular it should be possible to supply a custom function to the processTime parameter that embodies any combination of indices and process time values. I’ll experiment with that tomorrow.

Here’s the updated code for drawing the display element.

I tested the Bag component with and without the subsequent Process component and everything worked as it should procedurally. I also assigned the Bag and Process components to a componentGroup called “Parking Lot” and the reporting mechanism picked up the new group and reported it like a champ. However, I noticed that there were negative entity counts during some time intervals in the “Parking Lot” section of the report for each entity type. I traced this down to the erroneous assumption that exiting a Process or Bag component should always trigger recording an exit from a component group. This worked fine when the groups start with a Queue component and end with a Process component, but not so well when a group contained multiple Process and Bag components in series. I therefore have to add a test to see whether an entity is truly exiting a component group before triggering the exit reporting mechanism. That will be another part of tomorrow’s work.

Last but not least I’ll update the framework so it can be allowed to run until all entities have cleared the system, after a specified minimum running time. This is not always the desired behavior for analysis or reporting, so a switch setting will have to be included as well.

This entry was posted in Simulation and tagged , . Bookmark the permalink.

Leave a Reply