A Simple Discrete-Event Simulation: Part 43

Today I went through and cleaned up each of the component definitions in the process of implementing the ability to rerun the simulation without having to refresh the browser page. Beyond just neatening up the code for each component I added a reset function which resets all of its state properties but leaves the established configuration properties (definition, layout, and linking) in place. The reset function then just has to cycle through each component in the listOfComponents array and call the reset function for each. I can then just reset the discrete-event timing mechanisms and a handful of other global control/state variables (which should ultimately be given their own namespace and separate file). The global timing mechanisms and control variables should be reset before the list of components, since resetting the components sometimes refers to the global values (mostly the global simulation clock).

Here’s the snippet that gets executed when the Reset button is clicked, along with one example of a reset method in a component object. As a side note I found it interesting that the parameters to the JavaScript closure constructors are always available, like that’s just another way of declaring an internal member property. I’m sure I’ve made use of this effect previously, but the awareness just became conscious.

I made sure the components were all drawn once the system was initialized and when it is reset, so they’re visible before the simulation starts running. I’m thinking I’ll want to split the drawing of paths up so that the lines are drawn with all of the other objects and then the nodes and entities are drawn separately and later, so nodes always sit on top of both components and entities always sit on top of components and nodes.

I also noticed that certain aspects of the Queue component behave a bit differently if there is an assumed minimum traversal time, as would be the case for a physical queue, vs. a zero traversal time as would be the case for a logical or information-only queue. I’ll sort that out in a future post, at which I’ll make the same modifications (if and as needed) for the Path and Process components, which maintain internal queue mechanisms of their own. I have thought that processes represented by Process components must always involve a non-zero processing time but I also recognize that some processes only involve making instantaneous decisions. That may call for a new kind of primitive component type.

Another thing I realized as I was reviewing and cleaning things up today was that my original concept of handling discrete event queue items was that they would be created once, with a call to feq.newItem, and then recycled back into the future events queue continuously using the advance function. However, in a lot of cases components will “lose” the future events queue item when they reach a state where they must wait to be activated by an external event. In this case they cannot rely on being able to recycle and existing future events queue item because the handle to it may have been lost. This situation is made even more confusing by the fact that there can be multiple discrete-event timing items active at any one time within a component (i.e., there can be numerous pucks), so keeping track of them might be problematic.

The advance function as it was written (and still survives in the current incarnation of the Arrivals component because it effectively operates independently of any other component). I’m thinking I need to expand the concept of the advance function so it figures out whether to use an existing discrete-event timing item or whether it needs to create a new one. It shouldn’t be too hard to create a handle for the necessary item; the Component code “knows” whether a component is going to be left alone to “die” (i.e., not be recycled through the future events queue and be automatically garbage collected).

The feqCurrent item is always the most recent item pulled from the future events queue. If it’s going to be recycled back into the future events queue we can use the existing advance function. If a new event needs to be created we might implement an “advanceNew” function to create a new item, or we can simply hijack the existing item. I’m going to have to draw out the state values as things proceed so I am perfectly clear on what’s needed. I could simply create new objects for every item I’m going to put into the queue whether it’s recycled or new, but relying on automatic garbage collection to keep up with objects that would be created at such a great rate (this is the most common thing that happens in a discrete-event simulation model, after all) seems extremely wasteful.

It also occurs to me that when defining forward links of paths to downstream components that the process of defining an accompanying upstream link can be automated when the need for it is detected. This would have to be the case when linking to downstream components that are not guaranteed to be able to receive new entities (i.e., they must clear before sending an open signal back upstream to the sending component). This also says that the definition for whether the linking path is exclusive or not is actually defined by the nature of the downstream component being linked to, so the linking path should take on this characteristic automatically, and define the required upstream link, based on whether the linked-to downstream component is exclusive.

It may be that the minimum definitions should be generated by the designer and that upstream links should be defined automatically as part of the post-definition and verification process. A verification process should be implemented to test that all required elements are defined and that the required components and connections are in place to support every defined routing. The direction of paths should be considered as part of this as well.

If that all seems less than clear I feel your pain, but these very insights were the main purpose of today’s explorations. I’m going to work on implementing the cleanup of the linking and exclusivity process tomorrow and the new vs. advance issue in the post after that.

Including thoughts from previous posts and some other items that need to get done, here’s the current to do list. It’s going to keep me plenty busy as you can see. I’m likely to take breaks from this project to work on other things, but since this is something I’ve always wanted to do on my own so I’ll always come back to it. I’m also sure that I’ll continue to add to this list. The main thing is that I’ve gotten the project to a takeoff point where it’s fun to work on and produces highly visible results.

  • Standardize linking and exclusivity process
  • Resolve and standardize new vs. advance issue
  • Rework drawing of Path components so correct elements are always on top
  • Rework the Queue mechanism to flexibly handle finite-traversal time and zero-traversal time configurations
  • Revisit distribution logic to make sure it’s cycling the way it should be.
  • Learn JavaScript’s prototype object pattern and re-implement everything in that in place of the closure pattern I’ve been using; I’ll want to bite that bullet before this thing goes much farther
  • Expand Path component representation so it can incorporate multiple line segments
  • Add ability to sense reaching tail end of FIFO queue based on stopping to wait on a Path component; collect statistics accordingly (possibly add wait flag to entities so they can test against the next entity in line)
  • Look into creating a zero-duration, zero-queue decision component
  • Create standardized routing mechanism (to components of different types) based on process logic (vs. distribution logic to multiple components of the same type)
  • Implement mechanism to identify combinations of related components into groups (e.g., a group of tollbooths represent a single toll plaza)
  • Gather and report system-, component-, and group-level statistics
  • Add ability to stream large volumes of output information which can be post-processed and quantified via a parsing mechanism
  • Streamline the process of defining the endpoints of Path components (i.e., attach standard nodes to other components and connect to those automatically, which will greatly save on the number of x,y locations the designer must specify manually)
  • Add an edit mode that allows designers to change component properties interactively (ultimately including being able to drag them)
  • Use the new, completely external mechanism for displaying component data
  • Describe how abstract representation can be used to represent detailed layouts and interactions; include ability to flag or alarm situations which would cause conflicts in the real world that would not necessarily be captured in a model unless specifically tested for
  • Add the ability to graph outputs as part of reporting
  • Add scrolling, animated graphs to illustrate progress as simulations run
  • Include ability for users to call up component and entity status by written or graphical display interactively while runs are in progress
  • Create streamlined graphical representations of all component types; create data display for Path components
  • Add ability to display entities inside relevant non-path components
  • Abstract the current x,y locations of all elements and scale them to the screen so the user can zoom in and out
  • Add ability for users to interactively change things during runs
  • Add Monte Carlo mechanisms to various timing and routing events (beyond what’s already been demonstrated)
  • Allow designer to build Monte Carlo and other distributions from acquired data using standardized tools
  • Add ability to perform multiple runs and statistically quantify generated outputs
  • Make simulation display update at regular intervals of simulated time rather than intervals defined by individual events; also make this “speed” scalable
  • Include ability to add arbitrary graphic elements to models (labels, keys, tables, etc.)
  • Include ability to display an underlay “below” the model display (e.g., a floor plan of a modeled process)
  • Allow user to turn off display and run model in “fire-and-forget” mode where it generates results without wasting time redrawing graphics.
  • Allow user to selectively turn different display elements on and off
  • Add ability to assign open/close schedules for components and groups
  • Add ability to introduce multiple types of entities in model with different processing rules for routing and timing
  • Add ability to combine multiple queues into a single, logical unit
  • Add ability to adapt stand base components to represent varied and specialized things (this applies mostly to Process components)
  • Add ability to save and restore model definitions (in files/XML and in databases, requires PHP/MySql, Node.js or other back end capability)
  • Add ability to represent more abstract processes:
    • Reintroduce wait..until mechanism that uses the current events queue
    • Include pools of resources that are needed by different processes
    • Implement non-FIFO queues or collections that receive and forward entities based on arbitrary (user-defined) criteria
    • Include ability to accept events that happen according to fixed schedules rather than random ones (e.g., to match observed data)
    • Include the ability to change representation of entities and components to represent state changes (by color, shape, labels, flags, etc.)
    • Support input and editing of modular packages of information used to define and drive models
    • Add ability to represent BPM processes using standard BPMN notation
  • Really complex stuff
    • Develop more complex, arbitrary node-and-link representation of model, which brings up worlds of complications on its own!
    • Polish related sections of code and break them into modules which can be included on a modular basis
    • Make modules and examples distributable for use by a wider community
      • Write documentation for modules as needed
      • Share on GitHub
      • Create dedicated project page on my website
      • Update and enhance my custom Graph component as well as the simulation framework
  • Re-implement this system in a more appropriate language like C++ or at least Java
This entry was posted in Simulation and tagged , . Bookmark the permalink.

Leave a Reply