Mastering Simulation Scripting in Innoslate: A Comprehensive Guide to Automating and Customizing Simulations
Sections Available in the Scripting Guide
Function | Description |
---|---|
Innoslate Simulators | Discover the capabilities of Innoslate Simulators, empowering you to simulate and analyze complex systems and other applicable utilities. |
JavaScript Basics | Learn how to utilize JavaScript basics in the Innoslate Scripting Guides, enabling automation and customization of simulations. |
Pre-Built Scripts | Discover pre-built scripts in the Innoslate Scripting Guides to quickly apply common simulation functionalities and save development time. |
OR Decisions | Learn how to implement OR decisions in your simulation scripts to create conditional branching and decision-making scenarios. |
API Advanced Simulation | Explore advanced simulation capabilities through the Innoslate API in the Scripting Guides. |
'Inno' API Advanced Sim. | Unlock advanced simulation features with the 'Inno' API in the Innoslate Scripting Guides, providing you with powerful tools on Innoslate. |
Using I/Os | Master the usage of inputs and outputs (I/Os) in the Innoslate Scripting Guides, between simulation scripts and external systems. |
1 Innoslate Simulators
Innoslate’s discrete event and Monte Carlo simulators require little scripting for most applications. The logic execution uses the decision points and Input/Output (I/O) triggers for basic problems, but for more complex simulations you will want to learn how to add scripts, which will range from minimal to complex.
2 JavaScript Basics
JavaScript was initially created to “make web pages alive”. The programs in this language are called scripts. They can be written right in a web page’s HTML and run automatically as the page loads. Scripts are provided and executed as plain text. They don’t need special preparation or compilation to run. The syntax for JavaScript is shown.
For adding to Innoslate scripts, note the use of “let” to define a variable. Innoslate script allows either “let” or “var” to define variables. Comments can also be added using two backslashes (//). Also “print()” statements can easily be added. These statements print to the Innoslate simulator console.
The OR and LOOP decision points (special cases of the Action) already come with pre-built scripts (Probability and Resource for both and Iterations for the Loop). These can be used without any scripting on your part. Just select the script type you want, adjust the values, and submit the script, then we generate the script automatically. The code behind each decision point’s script type can be accessed by selecting ‘Script’ from the drop-down menu. An example of each is shown in the later sections below.
3 Pre-Built Scripts
3.1 OR Script
3.1.1 OR Probability
The user selects “Or Probability” from the drop-down menu, as seen, then the user can adjust the branch probabilities, in this case making Yes is 70% of the time and No is 30%.
The script that is generated is shown. Note that the comment line at the top contains the information shown in the user interface above. The comment list each branch's ID number with its corresponding assigned percentages. If changes are made it is recommended to either update assigned percentages or delete it.
3.1.2 OR Resource Script
The Or Resource script will use Resource entity attributes such as its Amount to be set and used as a condition for the Or Resource script. A Resource entity must be created first and available in the database. The branch options include logical constructs and values. This shows the user interface for the Or Resource script.
These options will be used to compare the Resource amount at the time the script is executed. This shows the resulting script from this selection. Note that the Global ID is used for getting the Resource from the database (using the Rest API: Sim.getAmountByGlobalId()). More on this is provided in the Advanced Simulator Scripting section.
3.2 Loop Script
3.2.1 Loop Probability
Loop Probability will be based on the percentages set by the user. In this figure we changed the default probabilities from 50/50 to 80/20 between the Continue and Exit branches.
This shows the generated script. The script allows the simulator to stay in the Continue branch because of the condition, “r <= 80”. If the condition is not met the simulator will leave on the Exit branch.
3.2.2 Loop Resource
The Loop Resource is similar to the Or Resource, except the condition is based on the Resource’s amount value. Figure below shows the user interface for the Loop Resource.
This references the Resource construct in the script by using the REST API, “ Sim.getAmountByGlobalId()”, and Resource’s Global ID.
3.2.3 Loop Iteration
The Loop Iteration script allows to user to tell the simulator amount of times the loop should run. Figure below shows the Loop Iterations user interface. We changed the number of iterations from the default value of 3 to 10.
Figure below shows the resulting script. Note that the “i” variable is initialized to zero outside the function and then “i” is incremented each time this function is called.
It is recommended to start with these if you are building a new script, as it will often be easier to get the exit branch identifier automatically. Note that the branch identifier is not essential for the script and if you want to reuse (copy and paste) the script into other Actions/Decision Points, then you will want to eliminate them.
We also provide “stubs” for those needing to develop scripts from scratch for onStart(), onEnd(), and prompt(). At this point, you will need to know a little JavaScript to write executable programs. Note that prompting the user only works with the discrete event simulator and will throw an error in the Monte Carlo simulator.
One more common situation is the need to make sure that decision points are synchronized with other decision points. The next section discusses this situation.
4 Synchronizing OR Decision
Often we need to make sure that when a decision is made by one Asset that another Asset uses that decision to go down a particular path. We can see this in the example below.
In this diagram, the first asset makes a decision using a standard probability script. We want the second asset to respond to that decision and go down a similar path. For this to execute properly, we need to trigger the second decision point from the first, i.e. to ensure that the second decision point does not try to execute at the same time as the first one (which it would do without the “Decision” Input/Output entity.
But we also need to pass on to the second decision point what the decision was (yes or no in this case). This synchronizing of the decision can be accomplished by setting a JavaScript global variable or putting a “Yes” or “No” in the Input/Output attribute field. Let’s look at the first one.
Figure below shows the first decision point [Decide? (Asset #1)], where it starts with the standard probability script. Then we added the “globals.set” and “print” lines.
For Asset #2’s OR script, then we get the global variable and use it instead of the probability to make the decision. We also added print statements to show it went down the correct path.
The results for a yes decision are shown.
The results for a no-decision are shown.
5 Advance Simulator Script using API
The simulator has a scripting API (Sim) to allow users to gain access to data contained in the model being executed. To use many of these APIs, you need to provide the Global ID or project-level ID. These IDs can be found when selecting an entity in the Metadata tab on the sidebar.
Sim is a utility class that references methods used to access simulation objects during simulation. The figure identifies each of the functions available in the Sim API and what they return.
Note that the table below is missing two methods:
Sim.getResourceByGlobalId(GlobalID)
Sim.setResourceByGlobalId(GlobalId, amount)
These objects include:
- Entities (Actions, Resources, I/Os, Conduits, Assets, Cost)
- Current Time
- HTTP Request
You can use these functions to get the names, numbers, descriptions, and any other related attributes of any of the entities available within the simulation. The entities are limited as the simulator only loads information on the entity classes listed above. The example below shows how to use these functions for Cost and Time. Figure below shows Actions that incur Costs. The picture shows a simple Action Diagram with two Actions.
The Action Diagram shows the incurs relationship and Cost entities for each Action. If you add the script into the Action diagram and then execute it, you will see the results in the final figure.
5.1 Using Resources in Simulators
Previous figures showed the predefined scripting capabilities in the OR and LOOP actions. These figures show how the pre-built scripts access the current amount of Resources identified by their GlobalIDs. These IDs are found in the Metadata tab of the entity view on the Action Diagram sidebar for the Resource, as seen. The scripts are able to be manipulated via user-defined scripts of an action and then plotted during the simulation.
Important information about attributes of a Resource:
Resource Entity View
Value of Resource not being between Minimum and Maximum Amount will cause the simulation to deadlock (break).
Relationships created between Actions and Resources allow for Pre-Defined Scripting to:
- produces Resources
- consumes Resources
- seizes Resources
Either the produces or seizes relationship can be selected when you drag from a green circle on a highlighted Resource onto an Action, an overlay of the two options will be provided. If you select seizes the Resource icon will turn a lighter purple and the lines will have a “seizes”. This example shows an example of the produces relationship. Click on each Action Entity and go to ‘Relationships’ on the side panel, find the ‘produces’ relationship, and define the amount to produce.
This figure shows the results of the simulation. The consumed amount of the Resource is permanently taken away from the Resource, while seized amount only takes away from the Resource during an Action’s duration.
Scripts can also be developed to change resources, with or without the Resource being directly associated with the Action.
For this example, we had the Action produce 20 units (remember units are arbitrary and must be consistently set) of the Resource using the attribute on the produces/produced by relationship. The scripts for the Actions are shown below:
The resulting simulation output is shown. Note that the produces relationship incrementing of the Resource occurs before the execution of the onEnd() script. So the net effect of the first script is to reduce the amount to 10 units from the original 20. The second script reduces the amount of the Resource by another 5 units.
5.2 Using Scripts Prompts
The Innoslate simulator can help conduct tabletop exercises, and develop standard operating procedures, and Concepts of Operations. These applications simulate how users may respond to different events and how the system reacts to the user’s input. As such, scripts to prompt the user for input have also been provided. This table below shows the prompt script methods and their purpose.
Note these prompts may only be used with the discrete event simulator. If these prompts are enabled during a Monte Carlo simulation the user will receive an error message.
An example of using this prompt is shown. The prompt method automatically returns the “response” variable to the script, so that the user only needs to use the onEnd(response) function call.
6 Advance Simulator Scripting Using ‘Inno’ API
The “Inno” APIs consist of the following methods: InnoObject, InnoEntity, InnoAttributes, InnoSimulation, InnoRelationships, and InnoLabels. These methods can only be used with the entity classes directly related to the instances included in the simulation. They cannot manipulate other classes within the database, such as Risk, Time, Measures, etc. Any changes to the attributes, relationships, and labels are only temporary and contained within the simulation. This limitation is a security feature that makes database corruption impossible. It also is essential for cyber security in a cloud environment. To make database changes, you can use the general JavaAPIs with the Enterprise version of Innoslate.
The following subsections discuss each of these methods and their usage.
6.1 InnoObject Methods
InnoObject methods enable the user to get and set most of the common attributes of any object (Name, Description, Created and Modified Dates, etc.). Table below shows these methods and their return values.
InnoObject Methods
Method | Return |
getCreated() | Creation time in milliseconds |
getCreatedBy() | The user that created the object |
getDatabase() | Database for the current entity |
getDescription() | Description text of the object |
getDescriptionAsText() | Strips out special characters and formatting |
getGlobalID() | The global ID of the entity |
getId() | The ID of the entity |
getModified() | Modified time in milliseconds |
getModifiedBy() | The user that last modified the object |
getName() | Name of the object |
isHidden() | Determines if the object is a hidden object |
isLocked() | Determines if the object is locked |
setDescription( text) | Updated entity description |
setHidden( hidden ) | Sets object as hidden |
setLocked( locked ) | Sets the locked state of the object |
setName( name ) | Updated entity name |
An example of using some of these methods is shown. The results of the simulation are shown in the Console panel in the figure.
6.2 InnoEntity Methods
InnoEntity methods enable the user to get and set most of the common attributes and properties of any class entity (Number). This table shows these methods and their return values.
InnoAttribute Methods
Method(s) | Return |
setInnoClass( name ), setInnoClassByName( name ) |
Entity Object |
setInnoClassById( id ) | Entity Object |
getInnoClassId() | Id number |
getNumber() | Entity’s Number |
hasChanged() | Boolean: true || false |
instanceOf( name ), instanceOfByName( name ) |
Boolean: true || false |
instanceOfById( id ) | |
setNumber( number ) | Entity |
An example of using some of these methods is shown. The Console panel shown in this diagram shows the simulation results for the first three actions.
6.3 InnoAttributes Methods
InnoAttributes methods enable the user to get and set any attributes of any object. This table shows these methods and their return values.
InnoAttribute Methods
Method | Input | Return |
all() | id: attribute value of all attributes | |
get( name ), getByName( name ) |
String | id: attribute value |
getById( id ) | Integer | id: attribute value |
getByProperty( property ) | InnoProperty | id: attribute value |
set( name,value ), setByName( name,value ) |
String, String | InnoEntity |
setById( i d,value ) | Integer, String | InnoEntity |
setByProperty( property,value ) | InnoProperty, String |
An example of using some of these methods is shown. The Console panel shown in this diagram shows the simulation results for these actions.
6.4 InnoSimulation Methods
InnoSimulation methods enable the user to get and set simulation scripts. This capability would enable the user to create different scripts for execution within the simulation. This table shows these methods and their return values.
InnoSimulation Methods
Method | Input | Return |
getScript() | The string of the script | |
getScript( script ) | String |
An example of using some of these methods is shown. The Console panel shown in this diagram shows the simulation results for these actions.
6.5 InnoRelationship Methods
InnoRelationship methods enable the user to get and set relationships between entities. This table shows these methods and their return values.
InnoRelationship Methods
Method | Return |
add( relationName, target ), addByName( relationName, target ) | Entity |
addById( relationId, target ) | Entity |
addByRelation( relation,target ) | |
allLazy() | The array of all InnoEntity related to Entity |
allTargetIds() | all IDs of related Entities |
allTargetIdsMap() | Map of IDs |
allTargets() | The array of InnoEntity objects |
get( name, target ), getByName( name, target ) |
EntityRelationship object if exist, or false |
getById( id,target ) | EntityRelationship object if exist, or false |
getAndRemove( name,target ) | EntityRelationship object if exist, or false |
remove( relationship ) | True if successful |
anyByIdLazy( id ) | Array of InnoRelations |
anyLazy( name ),
|
Array of InnoRelations |
anyTargetIds( name ) |
IDs of related Entities |
anyTargetIdsById( relationId ) |
IDs that have given a relationship with |
contains( relationship ) |
Boolean |
containsAny(relationName), containsAnyByName(relationName) |
Boolean |
containsAnyById( id ) | Boolean |
containsById( relationId, target ) | Boolean |
containsByName( relationName, target ) | Boolean |
countAny( relationName ), countAnyByName( relationName ) |
Integer |
countAnyById( id ) | Integer |
An example of using some of these methods is shown. The Console panel shown in this diagram shows the simulation results for these actions.
6.6 InnoLabel Methods
InnoLabel methods enable the user to perform operations like add, remove, and check for labels. This table shows these methods and their return values.
InnoLabel Methods
Method | Input | Return |
add( label ) | InnoLabel | InnoEntity |
addByName( id ) | Integer | InnoEntity |
addByName( name ) | String | InnoEntity |
all() | label id: InnoLabel pairs | |
contains( label ) | InnoLabel | Boolean |
containsById( id ) | Integer | Boolean |
containsByName ( name ) |
String | Boolean |
ids() | the array of label IDs | |
remove( InnoLabel ) | InnoLabel |
An example of using some of these methods is shown. The Console panel shown in this diagram shows the simulation results for these actions.
7 Using I/Os
We have already seen how Input/Output entities are used to control the sequencing of the Actions as a trigger. With version 4.5, a “Value” attribute was added to act as a variable in the simulation. This attribute allows information transfer to be more visual in the simulation, instead of just using global variables in the script. The value attribute is a text string and can be encoded with any data type. To access the Value attribute, you can use the Sim.getIOValueByNumber(), Sim.getIOValueById(), and Sim.getIOValueByGlobalId() methods for the “Sim” API. To set the I/O value, you will still need to use the InnoEntity methods discussed above. An example is provided below.
7.1 Using Basic I/O API
I/O can be used to store and retrieve values using the I/O construct. The I/O construct uses the following “Sim” API found:
I/O Sim APIs
Method | Input Value | Input Type | Return |
Sim.getIOValueByNumber() | Entity’s Number Attribute | String | Entity Attribute Value |
Sim.getIOValueById() | Entity’s ID | Integer | Entity Attribute Value |
Sim.getIOValueBYGlobalId() | Entity’s Global ID | integer | Entity Attribute Value |
There are two ways to retrieve the I/O value and it’s based on whether the entity has a trigger or not.
If an I/O has the following relationship used:
- “generated by”
- “received by”
The I/O will be a trigger for the entity with the “received by” relationship. An example of using some of these methods is shown. The Console panel shown in this diagram shows the simulation results for these actions.
If an I/O has only one relationship used :
- “received by”
The I/O will need to be set to ‘optional’ and this can be done by going to I/O “received by” relationship and turning the trigger field into “No” as seen. Doing this will avoid a deadlock when the simulation runs.
An example of using some of these methods is shown. The Console panel shown in this diagram shows the simulation results for these actions.
Another use of the I/O is to set value and retrieve it for later use. To set a value for an IO is to assign a variable using the API and store a new value using “attributes().set()”. An example of using some of these methods is shown. The Console panel shown in this diagram shows the simulation results for these actions.
7.2 Using Advanced I/O API
Section 7.1 provides the basics for setting and getting the IO entity value. This section will show how a user can set and get IO values from a decomposed parent diagram. This is done by making the I/O entity traced to the action entity prior to decomposing that entity. It will ensure the same IO is passed to its child entity.
To set the IO value, the user will need to handle that script in the child entity. An example of using some of these methods is shown. The Console panel shown in this diagram shows the simulation results for these actions.
Once the IO value is set by the child entity that IO value can be passed and used in the parent diagram. The user will need to make sure the IO is a trigger in the parent diagram to allow the value to be used. An example of using some of these methods is shown. The Console panel shown in this diagram shows the simulation results for these actions.
To continue learning about Simulators, Click Here.
(Next Article: Simulator API)