{"id":1200,"date":"2016-12-05T15:47:41","date_gmt":"2016-12-05T20:47:41","guid":{"rendered":"http:\/\/rpchurchill.com\/?p=1200"},"modified":"2016-12-05T15:56:52","modified_gmt":"2016-12-05T20:56:52","slug":"a-simple-discrete-event-simulation-part-52","status":"publish","type":"post","link":"https:\/\/rpchurchill.com\/wordpress\/posts\/2016\/12\/05\/a-simple-discrete-event-simulation-part-52\/","title":{"rendered":"A Simple Discrete-Event Simulation: Part 52"},"content":{"rendered":"<p>Today I reworked the future events mechanism to streamline it in a big way.  I knew it needed this and the essential insight about how to do it occurred to me in the shower about ten days ago.  I decided to do this now because I was going cross-eyed looking at the connection logic, which itself needs one more extension.<\/p>\n<p>The main insight involved the need to recycle the reference to the most recent future event item or to create a new future event item.  New items are generated as needed and placed in the future events queue.  Items are then pulled off the queue in time order and processed one by one.   The items are stored in the <code>feqCurrent<\/code> variable, which can be updated and recycled back into the queue.  The variable should then be set to <code>null<\/code>, which signals that a new event item will have to be created so it can be placed into the future events queue.<\/p>\n<p>I also created standalone functions to process the reuse or generation of new future event items.  The <code>advance<\/code> function defines and event that takes place by a specified offset from the current time, whenever that is.  That&#8217;s the most commonly used function and models a fixed delay, process time, or event duration in general.  The <code>jump<\/code> function works the same way except that the absolute time (from time zero, the beginning of the simulation) is used.  This function is more likely to be used to specify a schedule of known events as the simulation is initialized.<\/p>\n<p>The code is shown below in its now much abbreviated form.<\/p>\n<pre class=\"toolbar-overlay:false wrap:false height-set:true lang:default decode:true \">\r\n    \/\/future events queue item\r\n    function FutureEventItem(time,entity,nextState,entity2) {\r\n      this.activationTime = 0.0;\r\n      this.entity = entity;\r\n      this.nextState = nextState;\r\n      this.entity2 = entity2;\r\n      if (time >= globalSimClock) {\r\n        this.activationTime = time;                 \/\/activate at specified absolute time, if in future\r\n      } else {\r\n        displayProgressText(\"Invalid time past time supplied A.  Element ID: \"+entity.entityID+\" Current Time: \"+globalSimClock+\" Specified Time: \"+time.toFixed(6));  \/\/alert on invalid time\r\n      }\r\n      this.getActivationTime = function() {\r\n        return this.activationTime;\r\n      };\r\n      this.getEntity = function() {\r\n        return this.entity;\r\n      };\r\n      this.getNextState = function() {\r\n        return this.nextState;\r\n      };\r\n      this.getEntity2 = function() {\r\n        return this.entity2;\r\n      };\r\n      this.update = function(time,entity,nextState,entity2) {\r\n        this.activationTime = time;\r\n        this.entity = entity;\r\n        this.nextState = nextState;\r\n        this.entity2 = entity2;\r\n      };\r\n    }  \/\/FutureEventItem\r\n    \r\n    var feqCurrent;  \/\/global feqItem\r\n    \r\n    function FutureEventsQueue() {\r\n      this.feq = [];\r\n      this.feqSize = 0;\r\n      this.insertTime = 0.0;\r\n      this.getFirstItem = function() {\r\n        var feqItem = this.feq.splice(0,1);\r\n        if (feqItem.length) {\r\n          var t = feqItem[0].getActivationTime();\r\n          updateSimClock(t);\r\n          this.feqSize--;\r\n          return feqItem;\r\n        } else {\r\n          \/\/alert(\"no items in FEQ to retrieve \"+this.feqSize);  \/\/flag end of sim\r\n        }\r\n      };\r\n      this.findLaterTime = function(item) {\r\n        return item.getActivationTime() > globalInsertTime;\r\n      };\r\n      this.insertItem = function(time,type,entity,nextState,entity2) {\r\n        if (type == \"advance\") {\r\n          time += globalSimClock;\r\n        }\r\n        if (feqCurrent) {\r\n          feqCurrent.update(time,entity,nextState,entity2);\r\n        } else {\r\n          feqCurrent = new FutureEventItem(time,entity,nextState,entity2);\r\n        }\r\n        globalInsertTime = time;  \/\/always uses absolute time\r\n        if (this.feqSize == 0) {  \r\n          this.feq[0] = feqCurrent;\r\n          this.feqSize++;\r\n        } else {\r\n          \/\/find index of feq item to insert before  \/\/findIndex is a native JavaScript method of the Array object\r\n          var insertIndex = this.feq.findIndex(this.findLaterTime);\r\n          \/\/insert the element\r\n          if (insertIndex < 0) {\r\n            insertIndex = this.feq.length;\r\n          }\r\n          this.feq.splice(insertIndex,0,feqCurrent);\r\n          this.feqSize++;\r\n        }\r\n        feqCurrent = null;\r\n      };\r\n    }  \/\/FutureEventsQueue\r\n    \r\n    \/\/initialize future events queue\r\n    var feq = new FutureEventsQueue();\r\n\r\n    function advance(byTime,entity,nextState,entity2) {\r\n      feq.insertItem(byTime,\"advance\",entity,nextState,entity2);\r\n    }  \/\/advance\r\n\r\n    function jump(toTime,entity,nextState,entity2) {\r\n      feq.insertItem(toTime,\"absolute\",entity,nextState,entity2);\r\n    }  \/\/jump\r\n<\/pre>\n<p>Here are a couple of examples of the <code>advance<\/code> function in use.  The second example shows the extra parameter being used to reference an entity that needs to be processed within a component.<\/p>\n<pre class=\"toolbar-overlay:false wrap:false height-set:true lang:default decode:true \">\r\n      this.receiveEntity = function(entity) {  \/\/EntryComponent\r\n        \/\/display what's going to happen\r\n        this.entryTime = globalSimClock;\r\n        this.entryEntityID = entity.entityID;\r\n        this.activity = \"receive entity\";\r\n        displayProgressText(\"Entry comp. \"+this.componentID+\" injects entity: \"+entity.entityID+\" at time \"+globalSimClock.toFixed(6));\r\n        \/\/set timer to clear the display after a bit\r\n        this.endEntryDisplayTime = globalSimClock+this.displayDelay;\r\n        this.entryCount++;\r\n        advance(this.displayDelay,this,\"clearEntryDisplay\");\r\n        \/\/send it someplace\r\n        this.forwardEntity(entity);\r\n      };\r\n<\/pre>\n<pre class=\"toolbar-overlay:false wrap:false height-set:true lang:default decode:true \">\r\n      this.receiveEntity = function(entity) {  \/\/PathComponent\r\n        \/\/receive the entity\r\n        entity.setLocalEntryTime();  \/\/record time entity entered queue\r\n        if (this.exclusive) {\r\n          entity.setPermission(true);\r\n        }\r\n        entity.setLocation(this.x1,this.y1);\r\n        advance(this.maxRefreshTime,this,\"move\",entity);\r\n        this.traverseQueue.unshift(0.0);\r\n        this.entityQueue.unshift(entity);\r\n        this.countInQueue++;\r\n        \/\/display what was done\r\n        this.entryTime = globalSimClock;\r\n        this.entryEntityID = entity.entityID;\r\n        displayProgressText(\"Path comp. \"+this.componentID+\" receives entity: \"+this.entryEntityID+\" at time \"+globalSimClock.toFixed(6));\r\n        if (this.exclusive) {\r\n          this.isOpen();\r\n        }\r\n      };\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Today I reworked the future events mechanism to streamline it in a big way. I knew it needed this and the essential insight about how to do it occurred to me in the shower about ten days ago. I decided &hellip; <a href=\"https:\/\/rpchurchill.com\/wordpress\/posts\/2016\/12\/05\/a-simple-discrete-event-simulation-part-52\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[60],"tags":[121],"_links":{"self":[{"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/posts\/1200"}],"collection":[{"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/comments?post=1200"}],"version-history":[{"count":4,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/posts\/1200\/revisions"}],"predecessor-version":[{"id":1204,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/posts\/1200\/revisions\/1204"}],"wp:attachment":[{"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/media?parent=1200"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/categories?post=1200"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/tags?post=1200"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}