Expressions are mathematical statements that are evaluated by JaamSim. Many keywords that expect a number, string, or entity can also accept an expression that returns the appropriate type of object.
Expressions can manipulate and return the following types of entries:
· numbers (with or without units)
· strings
· objects
· arrays
· maps
· lambda functions
The rules for entering numbers, strings, and entities in an expression are given in the following table.
Numbers, Strings, and Objects
Entry |
Rule |
Examples |
Number |
If the number includes a unit, the unit must be enclosed by square brackets. |
1.0 1[m] |
String |
Strings are enclosed by double quotes. |
"Quick red fox" |
Object |
Object names are enclosed by square brackets. |
[Server1] |
Expressions are entered as a single line of text using the following syntax.
Basic Syntax for Expressions
Rule |
Example |
Result |
If an expression includes spaces, curly brackets, or double quotes, it must be enclosed by a pair of single quotes. Spaces in an expression are ignored. |
1[m]+2[m] '1[m] + 2[m]' '"abc"' |
3[m] 3[m] abc |
Rules for mathematical order of operation are respected for the standard operators: +, -, *, /, and ^. Round brackets can be used to modify the order of operation. |
1+2*3 (1+2)*3 2*3^2 (2*3)^2 |
7 9 18 36 |
All calculations must respect units. Unit conversions are performed automatically.
|
1[m]+2 1[m]+2[m] 1[m]/2[s] 1[m]/2[m] 1[m]*2[m] |
syntax error 3[m] 0.5[m/s] 0.5 2[m2] |
Outputs and attributes are referenced using a dot notation. |
[Queue1].QueueLength |
Number of entities in Queue1 |
The reserved string 'this' is used to refer to the object evaluating the expression. |
this.State |
State of the present entity. |
The reserved string 'null' is used to refer to an undefined object. |
this.obj == null |
TRUE if the output obj is undefined. |
Outputs can be chained using the dot notation. |
[Queue1].QueueList(1).State |
State of the entity at the front of the queue. |
Comments can be added at any point in an expression by enclosing the comment between a pair of hash marks ('#'). |
'1+2*3 #order of operation#' |
7 |
When developing a complex expression it is usually best to use the Input Builder tool which is available through the drop down menu for the relevant keyword in the Input Editor.
To improve readability and to avoid repeated calculations, it is possible to define one or more local variables within an expression. A local variable can take the value of any valid type, i.e. a number, string, object, array, map, or lambda function.
The following syntax is used to define a local variable:
'<variable1> = <expression1>; … <variableN> = <expressionN>; <final expression>'
For example, the expression 'x = 1; y = 2; x + y' would return the value 3.
The following mathematical functions can be used in expressions:
Basic Mathematical and Logical Functions
Function |
Description |
Example |
Result |
PI |
Mathematical constant ‘pi’ |
PI() |
3.14159… |
E |
Mathematical constant ‘e’ |
E() |
2.71828… |
min |
Smallest of a list of values |
'min(1[s], 2[s])' |
1[s] |
max |
Largest of a list of values |
'max(1[s], 2[s])' |
2[s] |
indexOfMin |
Position of the minimum in a list of values |
'indexOfMin(1[s], 2[s])' |
1 |
indexOfMax |
Position of the maximum in a list of values |
'indexOfMax(1[s], 2[s])' |
2 |
abs |
Absolute value |
'abs( -1[s] )' |
1[s] |
ceil |
Smallest (closest to negative infinity) integer that is greater than or equal to the argument |
'ceil( 5.2[s] )' |
6[s] |
floor |
Largest (closest to positive infinity) integer that is less than or equal to the argument |
'abs( 5.2[s] )' |
5[s] |
round |
Returns the closest integer to the argument, with ties rounding to positive infinity. Accepts a number with or without units. Returns an integer with the same units. |
'round(2.5[s])'
'round(-2.5[s])' |
3[s]
-2[s] |
signum |
Zero if the argument is zero, 1.0 if the argument is greater than zero, and -1.0 if the argument is less than zero. |
'signum( 5.2[s] )' |
1 |
sqrt |
Square root |
'sqrt( 4.0 )' |
2.0 |
cbrt |
Cube root. |
'cbrt( 8.0 )' |
2.0 |
% |
Modulus (remainder) operator. Used as an operator, not a function. |
'11.5 % 4' '11.5[s] % 4[s]' |
3.5 3.5[s] |
choose |
Selects from a list using an index |
'choose(2, 1[s], 2[s])' |
2[s] |
Exponential and Trignometric Functions
Function |
Description |
Example |
Result |
exp |
Exponential function |
'exp( 1 )' |
2.71828… |
ln |
Natural logarithm |
'ln( 2.71828 )' |
0.999999 |
log |
Base-10 logarithm |
'log( 100 )' |
2.0 |
sin |
Sine of an angle or dimensionless number |
'sin( 30[deg] )' |
0.5 |
cos |
Cosine of an angle or dimensionless number |
'cos( 60[deg] )' |
0.5 |
tan |
Tangent of an angle or dimensionless number |
'tan( 45[deg] )' |
1 |
asin |
Arcsine function |
'asin( 0.5 )' |
30[deg] |
acos |
Arccosine function |
'acos( 0.5 )' |
60[deg] |
atan |
Arctangent function |
'atan( 1.0 )' |
45[deg] |
atan2 |
Two-argument arctangent function. For Cartesian coordinates x and y, atan2(x,y) returns the angle for the corresponding polar coordinates. |
'atan2(1.0, -1.0)' |
135[deg] |
Functions Involving Objects
Function |
Description |
Example |
Result |
notNull |
Determines whether an entity exists. It can be used to test whether an output such as obj has been set. A better way to test for a non-null value is the expression 'this.obj != null'. |
'notNull(this.obj)'
'this.obj != null' |
0 or 1
0 or 1 |
Functions Involving Strings
Function |
Description |
Example |
Result |
+ |
Strings can be concatenated using the + operator. If necessary, the right hand side of the + operator is converted to a string. |
'"abc" + "def"'
'"abc" + 5[m]'
'"abc" + [Entity1]' |
"abcdef"
"abc5.0[m]"
"abc[Entity1]" |
format |
Constructs a string using a format string and one or more additional arguments. Each argument can be a dimensionless number, string, object, array, or map. The function mirrors the String.format method provided in Java. Each entry of % in the format string indicates a format code that inserts the next argument in the resulting output text. The full set of Java format codes is supported. The two most relevant are: %s - displays any argument as a string. %.nf - displays a number with n decimal places. |
'format("x = %s",[Entity1])'
'format("x = %s",5)'
'format("x = %.3f",5)'
'format("x = %s cm", 5[m]/1[cm])'
'format("%s x %s","abc","def")' |
"x = [Entity1]"
"x = 5.0"
"x = 5.000"
"x = 500.0 cm"
"abc x def" |
indexOfStr |
Returns the index within the specified string of the first occurrence of the specified substring, starting at the specified index. Zero is returned if the substring is not found. If the index is omitted, the entire string is searched. |
'indexOfStr("abcdefg", "cd")'
'indexOfStr("ffaffbc", "ff", 3)' |
3
4 |
length |
Returns the length of the specified string. The length is equal to the number of characters in the string. |
'length("abc")' |
3 |
parseNumber |
Converts a string to a floating point number. |
'parseNumber("1.5")' |
1.5 |
split |
Divides the specified string into an array of substrings around matches to a specified 'regex' string. An optional third 'limit' argument specifies the maximum number of substrings to return. The function mirrors the split method provided in Java. See the Java documentation for 'regex' string (regular expression). |
'split("ab:cd:ef", ":")'
'split("ab.cd.ef", "\\.")'
'split("ab.cd.ef", "\\.\", 2)' |
{"ab","cd","ef"}
{"ab","cd","ef"}
{"ab","cd.ef"} |
substring |
Returns a string that is a substring of the specified string. The substring begins at the specified beginIndex and extends to the character at index endIndex - 1. Thus the length of the substring is endIndex-beginIndex. If the endIndex is omitted, the substring extends to the end of the string. |
'substring("abcdefg", 3)
'substring("abcdefg", 3, 6)' |
"cdefg"
"cde" |
toUpperCase |
Converts the specified string to upper case characters. |
'toUpperCase("abc")' |
"ABC" |
toLowerCase |
Converts the specified string to lower case characters. |
'toLowerCase("ABC")' |
"abc" |
trim |
Removes leading and trailing whitespace from the specified string. |
'trim(" abc ")' |
"abc" |
Logical operations can also be performed in Expressions. All non-zero dimensionless values are interpreted as TRUE, while zero is interpreted as FALSE. The following are examples of syntactically valid logical Expressions:
'this.OutputA >= 1'
'(this.OutputA >= 1) && ([Entity1].OutputB == 0)'
The following logical operators are supported:
Logical Operators
Operator |
Description |
Example |
Result |
== |
Equal to |
'4.2 == 4.2' |
1 |
!= |
Not equal to |
'3.5 != 4.2' |
1 |
< |
Less than |
'3.5 < 4.2' |
1 |
<= |
Less than or equal to |
'3.5 <= 3.5' |
1 |
> |
Greater than |
'4.2 > 3.5' |
1 |
>= |
Greater than or equal to |
'3.5 >= 3.5' |
1 |
&& |
Logical AND operation |
'1 && 1' |
1 |
|| |
Logical OR operation |
'1 || 0' |
1 |
! |
Logical NOT operation |
'! 0' |
1 |
The && and || operators use short-circuited evaluation, that is, the right-hand side of the operator is only evaluated when necessary. For example, if the left-hand side of the && operator is FALSE, then the result is FALSE regardless of the value of the right-hand side. Similarly, if the left-hand side of the || operator is TRUE, then the result is TRUE regardless of the right-hand side.
Short-circuit evaluation allows an expression such as the following to be evaluated without returning an error when this.obj is null:
‘this.obj != null && this.obj.attrib > 0’
Conditional operations are implemented with the ternary operator, ?, using the following syntax:
<condition_expression> ? <true_expression> : <false_expression>
The ? operator uses short-circuited evaluation, that is, the <true_expression> is evaluated only when the <condition_expression> is TRUE and the <false_expression> is evaluated only when it is FALSE.
Examples of the conditional operator are:
'2>1 ? 5 : 4'
'this.OutputA >= 2 ? [Entity1].OutputB + 1 : 0'
Complex logical expressions can be constructed by chaining a series of ternary operators to form an 'if, else-if' type structure, e.g.:
'this.OutputA <= 2 ? 2 : (this.OutputA <= 4 ? 4 : 6)'
Note that brackets were added to this expression to improve readability – they are not mandatory.
An array is a sequence of entries that are indexed by an integer value starting with 1. A map is similar to an array except that its entries are indexed by a key (usually a string) instead of an integer. The entries in an array or map can be numbers, strings, entities, or other arrays or maps. Arrays and maps are sometimes referred to as ‘Collections’.
Arrays and Maps
Entry |
Rule |
Examples |
Array |
Arrays are enclosed by curly braces, with individual entries separated by commas.
|
{5, 6, 7}
{5[m], 6[m], 7[m]}
{"a", "b", "c"}
{[Queue1], [Queue2]}
{{1, 2}, {3, 4}} |
Map |
Maps are enclosed by curly braces with individual entries separated by commas. Each entry consists of a string (the key) followed an equal sign and the value for that key. |
{"a"=5, "b"=6, "c"=7}
{"Q1"=[Queue1],"Q2"=[Queue2]} |
Arrays and maps can be referenced in an expression using the following syntax.
Syntax for Arrays and Maps
Rule |
Example |
Result |
Entries in an array are referenced by specifying an index. The index value can be either a constant or an expression that returns a dimensionless number. A non-integer value for the index will be truncated. |
'[Queue1].QueueList(2)'
'{5,6,7}(2)' |
Second entity in the queue.
6 |
Entities in a map are referenced by specifying a key (usually a string).
|
'[Server1].StateTimes("Idle")'
'{"a"=5, "b"=6, "c"=7}("b")' |
Total time Server1 has been in its Idle state.
6 |
Entries in a nested array are referenced by providing multiple indices. |
'{{5,6}, {7,8}}(2)(1)' |
7 |
Arrays and maps can be concatenated and appended using the + operator.
|
'{1,2,3} + {4,5,6}'
'{1,2,3} + "abc"' |
{1,2,3,4,5,6}
{1,2,3,"abc"} |
A number of functions are provided that take an array or map as an argument.
Functions of Arrays and Maps
Function |
Description |
Example |
Result |
indexOf |
Index or key of the specified entry in an array or map. Zero is returned if the value is not included in the array or map. |
'indexOf( {5, -1, 2}, -1)'
'indexOf( {5, -1, 2}. 3)' |
2
0 |
indexOfMinCol |
Index or key of the smallest entry in an array or map. If this value appears in several entries, the index of the first one is returned. |
'indexOfMinCol( {5, -1, 2} )' |
2 |
indexOfMaxCol |
Index or key of the largest entry in an array or map. |
'indexOfMaxCol( {5, -1, 2} )' |
1 |
indexOfNearest |
Index or key of the entry in an array or map that is closest to the specified value. |
'indexOfNearest({5,-1,2}, 1.5)' |
3 |
maxCol |
Largest entry in an array or map. |
'maxCol( {5, -1, 2} )' |
5 |
minCol |
Smallest entry in an array or map. |
'minCol( {5, -1, 2} )' |
-1 |
range |
Generates an array of numerical values that can be used as an input to a higher-order function.
|
'range(3)'
'range(2, 4)'
'range(2, 3, 0.5)'
'range(2, 1)' |
{1,2,3}
{2,3,4}
{2,2.5,3}
{} |
size |
Number of entries in an array or map. |
'size( {5, -1, 2} )' |
3 |
sum |
Returns the sum of the entries in an array or map that contains numbers with or without units.
|
'sum( {5, -1, 2} )'
'sum( {"a"=5, "b"=-1, "c"=2} )' |
6
6 |
When several entries in an array have the same value, the functions indexOfMinCol, indexOfMaxCol, indexOf and indexOfNearest return the first index that satisfies the condition. When several entries in a map have the same value, the index returned by these functions is the first one that was entered in the map.
A lambda function is an expression that takes one or more input variables and returns a number, string, object, array, map, or another lambda function. Lambda functions can be used with higher-order functions to perform complex calculations that would otherwise require a loop structure.
Lambda Functions
Entry |
Rule |
Examples |
Lambda Function |
Input variables are enclosed by bars and separated by commas. The expression that generates the returned value is enclosed by brackets. Input variables can be a number, string, array, map, or another lambda function. The object returned can be any of these same types of objects. |
|x,y|(x + y) |
Syntax for Lambda Functions
Rule |
Example |
Result |
A lambda function can be evaluated by providing input values enclosed by brackets.
|
|x|(2*x)(5) |x,y|(x+2*y)(1,2) |x,y|(x+y)("abc","def") |
10 5 abcdef |
A lambda function with multiple inputs can be turned into one with fewer inputs by providing one or more of the inputs |
|x,y|(x+2*y)(1) |
|y|(1+2*y) |
A higher-order function is one that takes a lambda function as an argument.
Higher-Order Functions
Function |
Description |
Example |
Result |
map |
Applies a one-input lambda function to each element of an array and returns an array with the resulting values. If a two-input lambda function is specified, the second input is the index of the element in the array. |
map(|x|(2*x),{1,2})
map(|x,i|(2*i),{5,8} |
{2,4)
{2,4) |
filter |
Applies a one-input lambda function to each element of an array and returns an array with only the ones that return TRUE (i.e. a non-zero number). If a two-input lambda function is specified, the second input is the index of the element in the array. |
filter(|x|(x>2),{1,2,3,4})
filter(|x,i|(i>2),{5,6,7,8}) |
{3,4}
{7,8} |
reduce |
Applies the first input of a two-input lambda function to each element of an array. The second input to the reduce function is the initial value for an internal value maintained by the function during the calculation. The result of the calculation for each element is assigned to this internal value. After the last element is processed, the internal value is returned. The reduce function has three inputs: the function, the initial value to be assigned to the internal value, and the array to be processed. |
reduce(|x,accum|(x+accum), 0, {1,2,3})
reduce(|x,accum|(max(x,accum)), 0, {1,2,3})
reduce(|x,accum|(x||accum), 0, {0,1,0})
|
6
3
1
|
sort |
Applies a two-input lambda function to the elements of an array and returns an array that has been re-ordered so that the lambda function returns TRUE (i.e. a non-zero number) for each adjacent pair of elements. The lambda function should return FALSE for entries that are equal. |
sort(|x,y|(x>y),{2,3,1}) |
{3,2,1} |