A Simple Discrete-Event Simulation: Part 44

Tackling the first item on yesterday’s to do list requires thinking about what we want to implement in an organized way. I found that writing out the requirements helped clarify things. Here’s what we need component by component:

Arrivals component
  in: N/A
  out: entryList[] – array of logical connections to entry components

Entry component
  in: N/A – these components can always accept entities from the Arrivals component
  out: nextComponentList[] – distributes entities downstream to a mix of component types according to model routing logic

Queue component
  in: previousComponentList[] – these components can either be configured to always accept entities from upstream components of all types or refuse to accept entities subject to a defined capacity; in the latter case the Queue will have to be able to cycle through the incoming connections in turn to accept or retrieve new entities; see the propagation discussion in the description of the Process component directly below.
  out: nextComponentList[] – distributes entities downstream to a collection of similar components using plaza distribution logic

Process component
  in: previousComponent – links to single upstream component only; if the component is a path the path propagates the isOpen value; retrieves entity when clear
  out: nextComponentList[] – distributes entities downstream to a mix of component types according to model routing logic

Exit component
  in: N/A – these components can always accept entities
  out: N/A

Path component
  in: previousComponent – links to single upstream component only, propagates isOpen status and retrieval requests from downstream components
  out: nextComponent – links to single downstream component only, propagates isOpen status and retrieval requests from downstream components

The Path components should be implemented in a way that allow multiple units to be strung together in series and carry on the same propagation behavior. The propagation of statuses and requests should stop when the chain reaches an upstream component that is not a path. (There are several ways of implementing this that might save some of the propagation details.)

This list reminds me that we’re ultimately going to need some more component types. I can think of two for now. A Control governs the destinations to which an entity can be forwarded. A Bag is a container that can hold numerous entities that can be received and forwarded according to arbitrary, non-FIFO or non-LIFO logic. I guess this means we should also define a Stack component, doesn’t it? With these definitions in mind:

Control component
  in: previousComponentList[] – links to multiple upstream components
  out: nextComponentList[] – links to multiple downstream components; purpose is to control access or distribution to downstream components according to external rules

Bag component (think: parking lot)
  in: previousComponentList[] – links to multiple upstream components
  out: nextComponentList[] – links to multiple downstream components; distributes entities downstream to a mix of component types according to model routing logic

Stack component
  in: previousComponentList[] – links to multiple upstream components(?)
  out: nextComponentList[] – links to multiple downstream components(?); distributes entities downstream to a mix of component types according to model routing logic

I’m sure a use case for the stack component can be identified, but I haven’t come up with one yet that makes it clear in my mind what capabilities it should have. On the lean/TDD/YAGNI principle I’m not going to implement this until it is needed.

Next time I’ll work on implementing this. It occurred to me when I did an analysis of these ideas a couple of years ago that it might be a good idea to embed Queue capabilities into Process components, effectively merging the two types into one. There could still be a need for a separate queue object (to feed multiple processes that each have their own embedded small queue). Beyond the case of independent queues feeding queues that feed processes, it also occurs to me that queues are almost solely used to feed processes. The idea of general queues feeding process queues also suggests that the Queue component (or at least the queue-merged-with-process component) may need to implement an isOpen test based on having a limited capacity. This would involve duplicating all of the upstream permission and retrieval behaviors of the Process component.

In the not-too-distant future I’m going to look into making processes be able to handle multiple entities in parallel (independently and possibly in batches) and serial. Remember that we’re just using the Path components as logical connectors to make the process flow more visually clear, in reality the components could all be stitched together without using paths at all using the rules we’ve defined. Indeed, that’s where this exercise started.

Looking at how this has evolved, finally, I can’t help but wonder if I shouldn’t just include the ability to support multiple upstream (previousComponentList[]) links to the Process components as well. I’m going to sleep on that one.

This discussion adds a few more items to the to do list:

  • Add Control, Bag, and Stack components
  • Expand function of Process components to handle multiple entities in parallel, in effect making a single component function as if it were multiple, associated ones
  • Discrete-event simulation frameworks often include the concept of sets (logical containers that that be iterated and compared for intersection and so on, so that idea should be implemented; this would expand on things were doing now with lists of components and entities; the need for this was inspired by thinking about the bag data structure in general
  • Ponder the idea of implementing a combined Queue-Process component
This entry was posted in Simulation and tagged . Bookmark the permalink.

Leave a Reply