Expressions

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.

Syntax

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.

Local Variables

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.

Functions

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

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’

Conditionals

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.

Arrays and Maps

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.

Lambda Functions and Higher-Order Functions

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}