A Simple Discrete-Event Simulation: Part 63

Today I finally implemented the first part of the reporting capability. So far the system keeps track of the total time spent trying to get through the major process areas and through the entire system as well. The entities are time stamped when they enter the system and also when they enter a new process area. The results are collected in time buckets (which have been set to 30 units in this example) whenever an entity leaves a process area or exits the entire system.

Determining when the entities enter and leave the entire system is straightforward but determining when they enter and leave each process area is more complex. What I did was create a componentGroup property for each component in the model. The various Process components, either singly or in groups, determine the process areas. The Queue components that feed each Process components or set of Process components are also given the same componentGroup label. Path components are not given labels and do not figure into this calculation (for now). Process components 1, 2, and 3, along with Queue components 0, 1, 2, and 3 were labeled as being part of the “Primary” group. Process components 10 and 11 and Queue component 10 were labeled as the “Secondary” group. A default group is created for the entire “System.” For the current iteration of the code I labeled all of the components by hand using a setComponentGroup method. It should be possible to only label the Process components and then have the system automatically identify the Queues that feed them but there are some complications that may arise with that. (I’ll add a note to the To Do list.)

When a Queue component or Process component receives an entity it checks to see if the entity’s componentGroup label is different than that of the component itself. If it is, then the entity’s componentGroup is given the value of the component and the entity is time stamped. Here’s where the fun begins: at this point the system updates a counter in the current interval bucket of the global stats data structure. In our current system this happens in Queue components 0 and 10. When the entity is forwarded from a Process component the remainder of the data is written to the global stats data structure. This involves incrementing a count, adding the elapsed residence time for the process area to an accumulator, checking to see if the residence time is a new highest or lowest value for the current interval, recording the new number of entities in the process area, and checking to see whether that value is a new high or low for the current interval.

A new stats timing component updates the bucket index at defined intervals (again, 30 time units for our example), and ensures that the global stats data structure is expanded to hold the next interval’s data. When the model run is complete the data is processed to output nice tables of results in the scrolling text area. It generates a table for each process area and each table includes a line for each time interval and a line for the totalized results for the run. Go ahead and run the model and see what results it generates. I’ve included an example output here.

A good bit of thought can go into what each of these results actually mean. For now, the residence time in the system and each process area is simply the total time the entity spent there. If we want to know how long an entity waited to be processed, however, that would be a different story. In that case we’d have to subtract the amount of time it takes to traverse the queues and links within a process area. If an entity passed straight through without delay then we’d say that the waiting time was zero, would we not? There are also counters for the number of entities in each area, but we may or may not want to count the ones that are actively being processed in a Process component. We’ll explore this going forward, and I’ll add still another To Do item.

This capability can be made a lot more complex. Statistics can be captured for different meta time periods (e.g. by day as well as by interval and for the run as a whole) or counts can be added for each component or group of like components (e.g., the number of entities using each entry or exit, the number processed in each “Primary” Process component or each “Secondary” process component). Resource use and availability can also be added when those features are added to the model. Graph and formatted print outputs can also be generated. The possibilities are almost endless, but this was a pretty fair start.

Posted in Simulation | Tagged , | Leave a comment

A Simple Discrete-Event Simulation: Part 62

Today I added the ability for the user to control how the display is updated. Two new buttons have been added to the button row between the 2D display and the 3D display. The second button from the right, labeled “Time” when the page is initialized, indicating that the animations will only be updated on a time interval determined by a new display control timer component. The base multiple is set to 0.5 so the model will process as many discrete-event items during each interval of that length, at which time it will update the appropriate displays. This is done once per screen refresh cycle. This makes the animation much easier to watch, and it also ensure that simulated time advances at a consistent rate. Clicking on that button will change the display to “Ops,” short for Operations, indicating that only one discrete-event item will be processed per screen refresh, and the displays will be updated in the manner we’ve seen up until now.

The rightmost button, labeled “x1” to start, governs the multiplier for the time interval. Clicking on it changes the display to “x2” and multiplies the default time interval for time-based updates by two. The multiplier applies to whatever the base time interval is. If the base interval is set to 0.25 time units then setting the multiplier to two will result in updates occurring every 0.5 time units. The multiplier value does not apply when the display is in “Ops” mode. In theory the multiplier could be set to any positive value above zero (including fractional values) but the demo uses one and two for simplicity.

Last but not least notice that changing the multiplier value takes effect after the next update is completed. This is because the next discrete-event item that triggers the display update has already been inserted into the future events queue using the old multiplier value.

Posted in Simulation | Tagged | Leave a comment

A Simple Discrete-Event Simulation: Part 61

If everything is right to this point then additional components and logic should be able to be added in any way desired. The complexity was increased by quite a lot and only turned up one minor code change. That’s a win in my book. I also compressed the 2D display components a little bit more.

What we have here is a system with three primary process points. Twenty percent of the entities processed are routed over to the secondary queue, which feeds two secondary processes. From there, twenty percent of the entities go to the secondary exit while most go to the primary exit. This might represent a manufacturing system with a primary inspection step. Items failing the inspection get sent to a secondary process to see if the issue can be fixed. If not, the item gets scrapped. If the model was of a simple land border crossing the secondary exit would represent a return to the country of origin. With just a few components we can model a wide variety of processes, but that won’t stop us from adding even more components to give us even more capabilities.

The simulation is taking longer and longer to run with increasing complexity, as we might expect. However, the framework currently redraws the scene after every individual event is processed and can only update sixty times per second. This is great for single-step debugging but a little painful to watch. What we’ll do, then, is change the framework to update the display in uniform increments of modeled time. That speeds things up a lot when a bunch of things are happening in rapid succession but slows things down when not much is happening. I will ultimately give the user complete control over how this update process is handled, including the ability to run the model with no animated display at all. At some point the various animations are only there to confirm that the model is working the way we want it to. The results it generates are entirely independent of the display.

Results? We’ll talk about how to generate those going forward as well.

Posted in Simulation | Tagged | Leave a comment

A Simple Discrete-Event Simulation: Part 60

Here the rendering output is piped through a transform that produces a stereoscopic display with slightly offset views. Make the element full screen then check it out using your favorite 3D goggles (Google Cardboard should do nicely).

Here’s a direct link if you can’t expand the frame to full screen in a mobile browser. Click here! Be sure the device is in landscape mode before activating the link.

Posted in Simulation | Tagged , , , | Leave a comment

A Simple Discrete-Event Simulation: Part 59

After attaching some new functionality, drawing the paths using the DisplayElements objects, defining 3D elements using the information already available, and learning some more about the Three.js framework and WebGL, we have a nice 3D display. There are many possible improvements but this illustrates the basic capability nicely.

Posted in Simulation | Tagged , , | Leave a comment

A Simple Discrete-Event Simulation: Part 58

Today I started experimenting with the Three.js framework that supports the creation of WebGL apps in most modern browsers. I started from the most basic example I saw demonstrated at a recent JavaScript Meetup in Baltimore. I then began to dig around to figure out how to add an modify things the way I wanted them. I first figured out how to display both the faces and the vertices of 3D shapes, and then I figured out how to make the camera fly around the correct axis to maintain the perspective I was going for. If x is left and right, y is up and down, and z is into the screen, then to make it look like you’re a helicopter flying around a landscape while always looking toward the same point you have to assume that the y-axis is the vertical about which you orbit (revolve) along or above the x-z plane. Now that I have that sorted out a lot of the rest of rendering the simulation in 3D should be fairly straightforward, if detailed and time-consuming.

Here’s the basic code so far.

I’m used to doing most of this sort of thing on my own by managing my own coordinates, transforms, perspecitives, and renderings, but I never fully studied hidden surface algorithms, shading, and so on. Learning this framework gives me a lot more leverage, and my existing experience helps me understand the whole thing easily enough.

Posted in Simulation | Tagged , , | Leave a comment

A Simple Discrete-Event Simulation: Part 57

Today I got a number of things done. I’ll describe them briefly but forego the code listings for today. Too much going on.

I created an external way to graphically represent the non-Path components. These work roughly the same way as the data display objects I’ve been using (and am still using for the Arrivals component, which doesn’t even have to be displayed) but take up much less space and display the entities that are within them. The entities in components are also colored differently depending on whether they have finished their process or traversed their queue. A bare minimum of queue information is provided, and this could probably be eliminated for the simple, one-element process component. This method of display should make things much more visually clear to the user.

The incoming and outgoing nodes are included in the representation of each component. This process will be extended to handle display of the Path components as well, for consistency.

The start and end coordinates of all Path components are now set automatically by referencing the incoming or outgoing node on the non-Path component to which they are attached. The start and end locations still have to be established manually where Path components are attached to each other in series. Still, this saves a lot of hassle for the designer. The code for this was added near then end of the verifyModel function.

This new representation allows more complex systems to be represented in less space. Eventually a lot of the labels and internal information can be squeezed out as well, to allow even more information to be displayed. The amount of information to display or not display should be as flexible and configurable as possible.

The original data display objects are still available. I plan to make them visible by user request to monitor more details than are shown in this newly streamlined version.

Posted in Simulation | Tagged | Leave a comment

A Simple Discrete-Event Simulation: Part 56

I the process of working off some of the TODO: items I have sprinkled through the code I ended up fleshing out the model verification function. It is called after everything is defined but before the model runs. I haven’t let a negative finding prevent the model from running — yet — since I currently have a working configuration. The function also ensures that certain settings are initialized.

Here’s the function itself. Explanations and supplementary listings follow.

The function starts out by verifying that all previous and next component links exists and are valid in a number of ways. Here’s an example of the most general formation. A customized version of the verifyLinks method was created for each component type. Component types that do not support one type of link or another (e.g., Exit components do not include forward connections) do not test those elements. It is possible that these methods can be even more standardized and modularized, and I may look into that at some point.

In general, the method ensures that the count of connections is not zero, that the list of connections does contain references to something, that the references are to objects, that the objects are (likely to be) components by testing for the presences of the componentType property, and that the connections are not to types of components that make no sense (e.g., Entry components cannot be connected to Exit components and vice versa).

The function continues by setting the value of the exclusive property for each Path component based the exclusive property of its terminating non-Path component. This assumes that the exclusive property of each non-Path component has already been set.

Here’s the getNextExclusive function I had to define in the Path component. I noticed that I do this pass-through thing frequently and should come up with a consistent naming convention for methods like this.

The verifyModel function then tests the nextComponentList links of every Entry component to ensure that all connected components are defined to be non-exclusive. Here’s the code for the A customized version of the verifyLinks method was created for each component type. method.

Finally, I moved the mechanism for assigning destination component indices for forward links to here.

Some of the methods return error codes, and these are placed in the scrolling text area. The messages include detailed notes about the components and connections that are incorrectly configured.

I have a comment in place to implement a mechanism to assign the desired distribution method based on the nature of the downstream connections.

I currently have the routing logic attached to the individual components, but there is also a need to ensure that certain combinations of destinations can be reached from the point of view of an entity moving through a system. Moreover, destinations may need to be identitied in an aggregate way, like a toll plaza containing many booths. I will implement a test mechanism to address that process at some point as well.

There are many more things that can be tested or automated in this or similar functions. However, this was a pretty good start.

Last but not least, and not related to this project, I was able to complete another class on Udemy over the weekend, this time about Sass and SCSS.

Posted in Simulation | Tagged | Leave a comment

A Simple Discrete-Event Simulation: Part 55

Today I got a lot of updates into the mechanism for forwarding entities from one component to another. The changes were chiefly made to the Queue and Process components with some supplementary changes to the Path component. The first change involved saving the destination chosen when an entity first tries to exit a component. This only applies when using model routing logic. The component then keeps trying to forward the entity to the chosen location until it is successful, at which point it resets the savedDestination property to its initialized value of -1, meaning that the method should generate a new destination.

The next changes involved handling pull requests from downstream components. When an exclusive component forwards an entity it sends a request back to a previous component to forward an entity if one is available. There are several things to consider during this process. One is that the request is only sent if the discharging component goes from being at capacity to being at less than capacity. If a component (usually a Queue in this case) is not at capacity then the upstream component(s) should have been able to forward entities to the present component as needed, so there is no reason to send the pull request. The second consideration is important when there are multiple upstream components that might be pulled from. The code was changed to select the entity that has been waiting the longest. I discussed this in yesterday’s post and I still have to address the method of setting the “age” of each entity.

Finally, I changed the pull mechanism to ensure that the item is forwarded to the component that requested it. It would make no sense to send a pull request and have the upstream component randomly generate a new destination and send the entity someplace else. In order to do this I had to add a new array to the Queue and Process components to store the index of the first non-Path component linked to in each of the nextComponentList references. The array is initialized using the new getNextComponentIDs method, which has to be called when the components are defined and linked but before the model runs. The componentID of the pulling component is relayed to the upstream component, which then cycles through its own downstream connection indices until it finds a match (which it should be guaranteed to do). Once the match is found the upstream component can forward the entity (if it’s available) to the proper downstream component. This method of selecting a forwarding destination overrides the one normally used.

Here’s the new code for the forwardEntity method:

Here’s the new code for the pullFromPrevious method:

Here’s the new code for the getNextComponentIDs method:

The Path component was modified so the pullFromPrevious method could relay the index of the requesting element.

The Path component was also modified to add a method to pass requests for component IDs through multiple paths.

Blissfully I think I’m pretty close to getting the major routing and plumbing issues worked out so I can move on with things that are more “fun” and interesting. That said, the hard part will be done when it’s done. I’ll begin next week by working off the comments and TODOs in the code.

At the end of another week here is the current To Do list:

  • Standardize linking and exclusivity process
  • Resolve and standardize new vs. advance issue
  • Rework drawing of Path components so correct elements are always on top
  • New property for forward exclusivity as opposed to receiving exclusivity.
  • Formalize and implement method of receiving from multiple upstream components in turn. Implementing and observing this may illuminate the behaviors that will need to be implemented for the general path solution described in one or more previous posts.
  • 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
  • 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
  • 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
  • Create suite of test configurations to exercise every combination of connections and support regression testing.
  • 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

Finally, just for kicks and giggles, I was inspired by a demo I saw at a recent Meetup of the three.js framework for creating 3D models simply. I’m therefore going to add an item to the list to render a simulated system in 3D. I’ll keep it simple, but it should still be pretty punchy. If I go really crazy I’ll run that through a simple VR framework I also saw demoed. I’m sure it won’t be as easy as the speaker made it look, but it’s so much fun it might be a good thing to do over the holidays.

Posted in Simulation | Tagged | Leave a comment

A Simple Discrete-Event Simulation: Part 54

Today I updated the mechanism by which the components pull entities from previous components when there are multiple options. This involves pulling the entity that has been waiting the longest. Each entity is timestamped using a new member named forwardAttemptTime, for which a getter and setter have also been created. In the current implementation the value is set to Infinity when an entity is received and then to the current time when an entity completes its minimum traverse time for Queue components or its process time for Process components. I’m thinking this needs to be updated to the time each entity finishes its traverse or process and then reaches the head of the queue, instead. In this case the timestamp could be stored once with each component rather than once for each entity within each component. That’s how I originally implemented the mechanism. It didn’t work because I updated the timestamp every time a forward was attempted whether it was successful or not. It would have worked correctly if the timestamp is updated correctly. I’ll experiment with that and report back tomorrow. In the meantime the existing animation illustrates the intent.

Here’s the important bit of code. It polls all backwards connections to find the one whose head entity has been waiting the longest. This is why the default value for the timestamp is Infinity and not zero. Once the oldest item is identified the call is sent back to forward the entity to the current component.

Here’s the code that gets the relevant forwardAttemptTime value from Queue and Process components. Per the discussion above this may be reworked.

Here’s the code that defines the example system.

Thinking about this also points out that the pullFromPrevious method needs to call the forwardEntity method from the sending component so it’s guaranteed to forward the requested entity to the right place. If the previous entity has only one forward connection, which is the case in our present example, then there’s no way to make an error. However, if the upstream component is using distributed or model routing logic the situation could become much more complicated. If an upstream component is using distribution logic then it’s safe for the receiving component to request the pull because all of the upstream component’s possible destinations are equally valid. If an upstream component is using model routing logic, however, and the waiting entity is not scheduled to be forwarded to the requesting component, then the pull would not be allowed. Indeed, in this case the upstream component should not even be picked in this case. I’ve added a comment to the code to remind myself of this.

Posted in Simulation | Tagged | Leave a comment