How to define and use simulation variables
In the ASM toolbox, simulation variables can be used for the following purposes:
- Programming the simulation behaviour - eg.specifying the number of iteration cycles for particular tasks, or making the duration reduce on subsequent iterations.
- Modelling influences on the process - eg. such that the duration and failure probability of tasks depends on the expertise of the person executing them, the maturity of input information, etc.
- Instrumenting the simulation, to capture aspects of process performance (eg. KPIs) which can be used as part of simulation experiments. Eg. counting the number of iterations of certain tasks on different simulation runs, measuring a time delay of interest, capturing the rate of information evolution, etc.
In the ASM, simulation variables are also used to develop virtual experiments for exploring aspects of processes and evaluating how they can be improved.
To use simulation variables, you must first decide on their scope and then create them (for getting started, create them in 'global' scope by right-clicking 'Process variable group' node in the project-explorer tree displayed on the left-hand pane of CAM window; they will then be visible for use in all tasks in that workspace). Once created, variables become available for configuring tasks in the model, and for configuring virtual experiments.
Continue reading for explanations of how variables can be used to address common modelling needs, and for more information on variable scope.
Using simulation variables to make an iteration happen exactly N times
Iteration is driven by the iteration construct (green diamond) that initiates it. In the 'outcome' tab of this task, select the option "Model the decision using functions of process variables" from the drop-down list at the very top of the dialog. This allows you to configure the task's outcome for specific situations, rather than having a probability of failure.
A text box will appear "Iterate again IF...."
To specify a certain number of iterations, we can use the function ASMTaskIterationsCompleted(). The first time the task is about to be completed, the value returned by this function will be 0 (because the task does not strictly complete until AFTER the outcome has been selected). The second time, it will be 1, etc.
Therefore, to make the task "fail" on the first 5 times it is executed and "succeed" on all future iterations, we can enter the following function into the text box:
ASMTaskIterationsCompleted()<5
Using simulation variables to make an iteration happen between N and M times
For instance, you may wish an iteration to happen 2,3, or 4 times, with equal probability of each situation.
To do this we can build upon the configuration explained above. In the "iterate again IF..." box, we must use the function:
ASMTaskIterationsCompleted()<N
Where N is a variable defined in your model. We must set up the variable N at the start of the simulation, so that it takes the value of 2,3, or 4, with equal probability of each value. The value must be determined at the start of each simulation run and then held constant during the remainder of each simulation run, so that the function shown above will evaluate in the same way as the first situation (happen EXACTLY N times).
To do this we can create the value N as a global variable (ie. in the "Variables" tab on the left-hand-side of the main CAM window). In our ASM process flowchart, we also need to create a "dummy" task which will be the first task executed. This task will setup the variable for each simulation run.
For instance, to set N to fall between 2 and 4, in the post-processing tab of the "dummy" task we would set N up as follows:
[N = ] rand() * 3 + 1
How does this function work?
rand() returns a uniformly-distributed random number between 0 and 1. rand() * 3 therefore returns a number between 0 and 3. rand() * 3 + 1 returns a uniformly-distributed random number between 1 and 4. The extreme values will never occur in practice. We might for instance get 2.34553245 for a given evaluation of the function. When N is evaluated on each iteration of the iteration construct according to the first expression above, this will give the desired behaviour.
Using simulation variables to create conditional task durations (eg. reducing after a certain number of iterations)
By default (ie. after creating) an ASM task has duration specified by a probability density function (ie., a triangular PDF). If you wish the duration of the task to be dependent on the values of process variables, or to make it change on subsequent attempts, you must first open the task properties dialog for that task. Then, navigate to the 'Duration' tab under the 'Behaviour' pane of the dialog. Use the list box at the top of the 'Duration' tab to select the option 'Function of the process variables' instead of the default, which is 'Point, Uniform or Triangular Distribution'. The content of the pane will change, allowing you to enter a function which will be evaluated each time the task is attempted to determine its duration on that attempt.
To illustrate, lets consider that you wish to configure the task such that its duration is a certain value on the first attempt, and another value on all subsequent attempts. To do this you need to use conditional logic in the function specifying task duration. For instance, instead of writing directly into the field:
5
...to set the duration as exactly 5 days, you might use:
if(ASMTaskIterationsCompleted()<1,5,3)
which would set the duration to be 5 days if no iterations of the task have yet been completed (ie, if this is the first attempt of the task). Otherwise, the duration would be set to 3 days. In this case, the function ASMTaskIterationsCompleted() is a standard function, however any logical construct could be used. Likewise, a variable or another IF statement could be used in place of the numbers 5 and/or 3.
Using simulation variables to create conditional outcomes (eg. probability of iteration decreases after a certain number of iterations)
ASM models including iteration (ie. green diamonds, also called 'iteration constructs') can be configured to determine the circumstance under which iterations occur. To access the options, open the task properties dialog for the iteration construct; in the 'behaviour' pane, select the 'outcome' tab. (the same can be done for a red box 'compound task' that has multiple possible outcomes)
The option available by default, ie. just after creating a new iteration construct, is to set the probability of each outcome occurring, as a fixed value. In other words, you can enter two numbers which together determine how likely Iterate again is to occur on any given attempt of the task, relative to how likely Continue process is to occur. (if these numbers are chosen to add up to 1.0, they represent probabilities of each outcome occurring; otherwise, they represent weighted likelihood).
If you would like the probability of "Iterate again" to reduce on subsequent iterations, you need to select the option "Model the decision using functions of the process variables" from the list at the top of the tab (just above the fields where you would enter the numbers). This will cause the fields in the dialog to change, such that you can enter a logical expression instead of a probability. The expression is evaluated each time the task is completed, to determine which outcome is selected.
Then you could enter a function such as:
rand() < if(ASMTaskIterationsCompleted()<1,0.8, if(ASMTaskIterationsCompleted()<2,0.6, if(ASMTaskIterationsCompleted()<3,0.4,0.3)))
This function will cause the probability of iteration to be 0.8 on the first attempt of the task, 0.6 on the second attempt (if the task does not succeed the first time!), 0.4 on the third, and 0.3 on all subsequent attempts.
The rand() function generates a uniformly-distributed random number in the range 0 to 1. The value will be different each time the function is evaluated.
The if blocks operate as explained above, generating the probability which will be compared against the random number.
Scope of simulation variables
Variables can be created with different scopes, which determines which tasks can access and change them during a simulation:
- Task scope. The variable is defined within a particular task. It cannot be 'seen' outside that task. Task scope variables are useful for setting properties of the task, or for counting iterations, or for programming behaviour which depends on the 'history' of the task. For instance, an iteration construct may be programmed to 'fail' a specified number of times using a task variable which specifies that number, and another variable which counts the previous iterations.
- Info/material scope. The variable is defined within an info/material item (via the properties dialog for that item, eg. accessible on the 'Info/materials' tab of the main CAM window). An Info/material scope variable can be 'seen' by tasks which use that item as input or output. This is useful for describing, eg, 'meta-data' associated with the information created during a process. For instance, a task's duration may depend on the 'confidence' in an item of input information, where confidence is determined by the previous tasks which modified that information item. Each task would then modify the 'confidence' variable upon completion (using the post-processing tab of the task properties dialog) and have duration specified as a function of the 'confidence' variable (specified using the duration tab of the task properties dialog). Only tasks which create/require a particular info/material item would be able to change its confidence value. For more information on info/material items in the ASM model, see here.
- Sub/sheet scope. The variable is defined within a worksheet (or sub-sheet), via the properties dialog for the sub/sheet (right-click the worksheet background and select 'properties'). The variable can be accessed by any task within that sheet, or within a sub-sheet of it.
- Global scope. The variable is defined in the workspace, via the 'Variables' tab at the top-left of the main CAM window. All tasks anywhere in the workspace (in any workbook, worksheet or subsheet) can access and modify it.
For simple configurations, it is usually sufficient to define all variables in global scope. Other scopes are useful mainly when many variables are used to program a simulation, when some variables have the same name (eg. many info/material items, each with its own 'confidence' variable), or when you want to encapsulate the behaviour of a task or sub-process, and make it dependent upon variables associated with its inputs (the subprocess can then form a simulation building block which may then be copied and pasted)
After defining variables, they will become visible in the behaviour part of the task properties dialogs - eg. in the duration/outcome/preprocessing/postprocessing tabs. Each tab will show only those variables which are accessible ("in scope") to the given task. Variables out of scope for a given task will not be shown. The tabs also show a list of standard functions which can be used (such as MAX, MIN etc), and provides some help which explains how to use those functions.
If several variables visible to a given task have the same name, and you wish to use them in functions that determine the task`s behaviour, it is necessary to use the variable UID (Unique IDentifier) to distinguish between them. Use the function 'getVariableValue()', passing the UID, to access the specific variable of interest. For instance, you might write getVariableValue("45528") where the number 45528 refers to the UID of a particular variable. This would return the value of the variable at the time the function is called. The getVariableValue() function is described in the functions pane in the task properties tabs, and variable UIDs are also shown in the task properties tabs.