Expressions
Expressions are, together with the keywords, the major building blocks of a language. This section summarizes the different basic operators and connectors used to build expressions.
Expressions are constructed using constants, operators and identifiers (of objects or functions). If an identifier appears in an expression its value is the value referenced by this identifier. In the case of a set, a list, an array or a record, it is the whole structure. To access a single cell of an array, it is required to 'dereference' this array. The dereferencing of an array is denoted as follows:
array_ident (Exp1 [, Exp2 ...]) |
where array_ident is the name of the array and Expi an expression of the type of the ith indexing set of the array. The type of such an expression is the type of the array and its value the value stored in the array with the label 'Exp1 [, Exp2 ...]'. In order to access the cell of an array of arrays, the list of indices for the second array has to be appended to the list of indices of the first array. For instance, the array a:array(1..10) of array(1..10) of integer can be dereferenced with a(1,2).
Similarly, to access the field of a record, it is required to 'dereference' this record. The dereferencing of a record is denoted as follows:
record_ident.field_ident |
where record_ident is the name of the record and field_ident the name of the required field.
Dereferencing arrays of records is achieved by combining the syntax for the two structures. For instance a(1).b
A function call is denoted as follows:
function_ident or function_ident (Exp1 [, Exp2 ...]) |
where function_ident is the name of the function and Expi the ith parameter required by this function (note that function parameters are evaluated from right to left). The first form is for a function requiring no parameter.
The special function if is an operator that allows one to make a selection among expressions. Its syntax is the following:
if (Bool_expr, Exp1, Exp2) |
which evaluates to Exp1 if Bool_expr is true or Exp2 otherwise. The type of this expression is the type of Exp1 and Exp2 which must be of the same type.
Parentheses may be used to modify the predefined evaluation order of the operators (see Table Priority and evaluation order of operators in Mosel) or simply to group subexpressions.
Priority | Operators | Sense of evaluation |
---|---|---|
1 | () {} [] . if count function calls type conversions | → |
2 | -unary ^ | ← |
3 | * / div mod prod inter | → |
4 | + -binary sum union max min | → |
5 | < <= > >= = <> in not in | → |
6 | not | → |
7 | and | → |
8 | or | → |
9 | array | → |
Operators that result in statements are discussed in other sections:
- assignment operators: := += -= (see Section Assignment)
- inline array initialization: :: (see Section Inline initialization))
Table Meaning of operators for different expression types summarizes the meaning and applicability of operators that are discussed for the different expression types in the following sections.
Type | Operators | Description |
---|---|---|
All expressions | () | Changing the evaluation order |
All expect linear constraints | if | Inline 'if' |
Arithmetic expressions | count | Counter |
^ | Exponential operator | |
* / prod | Multiplication and division | |
div mod | Integer division and modulo | |
+ - sum | Addition and substraction | |
max min | Maximum and minimum value | |
< <= > >= = <> | Comparators | |
String expressions | + | Concatenation |
- | Difference | |
< <= > >= = <> | Comparators (see Section Boolean expressions) | |
Set expressions | {} | Constant set definition |
* inter | Intersection | |
+ union | Union | |
- | Difference | |
< <= | Subset | |
> >= | Superset | |
= <> | Equality and difference of contents | |
in not in | Set element | |
range set | Constructors; clone operators | |
List expressions | [] | Constant list definition |
+ sum | Concatenation | |
- | Difference | |
= <> | Equality and difference of contents | |
list | Constructor; clone operator | |
Boolean expressions | not | Negation |
and | Logic 'and' | |
or | Logic 'or' | |
Linear constraint expressions | * | Multiplication (one operand must be of numerical type) |
+ - sum | Addition / subtraction | |
<= >= = | Relational operators | |
Automatic arrays | :: | Inline array initialization (see Section Inline initialization) |
= <> | Equality and difference of contents | |
array | Constructor |
Type conversions and constructors
The Mosel compiler operates automatic conversions to the type required by a given operator in the following cases:
- in the dereference list of an array:
integer → real; - in a function or procedure parameter list:
integer → real, linctr;
real → linctr;
mpvar → linctr; - anywhere else:
integer → real, string, linctr;
real → string, linctr;
mpvar → linctr;
boolean → string.
It is possible to force a basic type conversion using the type name as a function (i.e. integer, real, string, boolean). In the case of string, the result is the textual representation of the converted expression. In the case of boolean, for numerical values, the result is true if the value is nonzero and for strings the result is true if the string is the word `true'. When converting a real to an integer the result is the integral part of the number (no rounding is performed). Note that explicit conversions are not defined for MP types, and structured types (e.g. linctr(x) is a syntax error).
For generating numerical values from strings it is in general preferrable to use the subroutines parseint/parsereal that provide error handling functionality in place of the basic conversion available through integer/real.
! Assuming A=3.6, B=2 integer(A+B) ! = 5 string(A-B) ! = "1.6" real(integer(A+B)) ! = 5.6 (because the compiler simplifies the expression)
Some native and record types might be used as function names to create new instances of the corresponding type (see the documentation of each individual type for a list of possible constructors). If the only argument of such a function call is an entity of the same type the result is a copy of the argument (the type must support assignment). For record types a specific syntax makes it possible to create and initialise each field of the newly created entity in a single operation:
type_name (.field1:=val1 [, .field2:=val2 ...]) |
where type_name is the name of a record type and fieldi one of its fields to be initialised with the corresponding vali value.
The constructor array (see Automatic arrays) for creating new arrays ad-hoc is an aggregate operator, via list (see List expressions), set and range (see Set expressions) it is possible to perform transformations between set and list structures.
Aggregate operators
An operator is said to be aggregate when it is associated to a list of indices for each of which a set or list of values is defined. This operator is then applied to its operands for each possible tuple of values (e.g. the summation operator sum is an aggregate operator). The general form of an aggregate operator is:
Aggregate_ident (Iterator1 [, Iterator2 ...]) Expression or count (Iterator1 [, Iterator2 ...]) |
where the Aggregate_ident is the name of the operator and Expression an expression compatible with this operator (see below for the different available operators). The type of the result of such an aggregate expression is the type of Expression. The count operator does not require an additional expression: its value, an integer, corresponds to the number of times the expression of another aggregate operator used with the same iterator list would be evaluated (i.e. it is equivalent to sum(iteratorlist) 1).
An iterator is one of the following constructs:
SetList_expr or ident1 [, ident2 ...] in SetList_expr [| Bool_expr] or ident = Expression [| Bool_expr] or ident as counter |
The first form gives the list of the values to be taken without specifying an index name. With the second form, the indices named identi take successively all values of the set or list defined by SetList_expr. With the third form, the index ident is assigned a single value (which must be a scalar). For the second and third cases, the scope of the created identifier is limited to the scope of the operator (i.e. it exists only for the following iterators and for the operand of the aggregate operator). Moreover, an optional condition can be stated by means of Bool_expr which can be used as a filter to select the relevant elements of the domain of the index. It is important to note that this condition is evaluated as early as possible. As a consequence, a Boolean expression that does not depend on any of the defined indices in the considered iterator list is evaluated only once, namely before the aggregate operator itself and not for each possible tuple of indices. The last form of an iterator declares a counter for the operator: the value of the corresponding symbol is incremented each time the operator's expression is evaluated. For this case, if ident has been declared before, it must be integer or real and its value is not reset. Otherwise, as for indices, the scope of the created integer identifier is limited to the scope of the operator and its initial value is 0. There can be only one counter for a given aggregate operator.
The Mosel compiler performs loop optimization when function exists is used as the first factors of the condition in order to enumerate only those tuples of indices that correspond to actual cells in the array instead of all possible tuples. To be effective, this optimization requires that sets used to declare the array on which the exist condition applies must be named and the same sets must be used to define the index domains. Moreover, the maximum speedup is obtained when order of indices is respected and all indices are defined in the same aggregate operator.
An index is considered to be a constant: it is not possible to change explicitly the value of a named index (using an assignment for instance).
Arithmetic expressions
Numerical constants can be written using the common scientific notation. Arithmetic expressions are naturally expressed by means of the usual operators (+, -, *, / division, unary -, unary +, ^ raise to the power). For integer values, the operators mod (remainder of division) and div (integral division) are also defined. Note that mpvar objects are handled like real values in expression.
The sum (summation) aggregate operators is defined on integers, real and mpvar. The aggregate operators prod (product), min (minimum) and max (maximum) can be used on integer and real values.
x*5.5+(2+z)^4+cos(12.4) sum(i in 1..10) (min(j in s) t(i)*(a(j) mod 2))
String expressions
Constant strings of characters must be quoted with single (') or double quote (") and may extend over several lines. Strings enclosed in double quotes may contain C-like escape sequences introduced by the 'backslash' character (\a \b \f \n \r \t \v \xxx \uhhhh with xxx being the character code as an octal number and hhhh a Unicode code as a four hexadecimal digits number).
Each sequence is replaced by the corresponding control character (e.g. \n is the `new line' command) or, if no control character exists, by the second character of the sequence itself (e.g. \\ is replaced by '\').
The escape sequences are not interpreted if they are contained in strings that are enclosed in single quotes.
Example:
'c:\ddd1\ddd2\ddd3' is understood as c:\ddd1\ddd2\ddd3 "c:\ddd1\ddd2\ddd3" is understood as c:ddd1ddd2ddd3 |
There are two basic operators for strings: the concatenation, written '+' and the difference, written '-'.
"a1b2c3d5"+"e6" ! = "a1b2c3d5e6" 'a1b2c3d5'-"3d5" ! = "a1b2c"
A constant string may also take 2 additional forms: initialised from the content of an external file or as a portion of the current input file. For the first case, a text string enclosed in backquotes will be replaced by the content of the file identified by this enclosed text. For the second case, a line ending by the backquote character optionally followed by some label (consisting in any sequence of characters not including backquote) will be interpreted as the beginning of a text block. The end of this text block is marked by a line starting with the previously used label (if any) followed by the backquote character.
Example:
`afile.txt` ! This string is the content of "afile.txt" `MyMarker line1 line2 MyMarker` ! This string is equivalent to "line1\nline2\n"
Set expressions
Constant sets are described using one of the following constructs:
{[ Exp1 [, Exp2 ...]]} or Integer_exp1 .. Integer_exp2 |
The first form enumerates all the values contained in the set and the second form, restricted to sets of integers, gives an interval of integer values. This form implicitly defines a range set.
The basic operators on sets are the union written +, the difference written - and the intersection written *.
The aggregate operators union and inter can also be used to build up set expressions.
{1,2,3}+{4,5,6}-(5..8)*{6,10} ! = {1,2,3,4,5} {'a','b','c'}*{'b','c','d'} ! = {'b','c'} union(i in 1..4|i<>2) {i*3} ! = {3,9,12}
If several range sets are combined in the same expression, the result is either a range or a set of integers depending on the continuity of the produced domain. If range sets and sets of integers of more than one element are combined in an expression, the result is a set of integers. It is however possible to convert a set of integers to a range by using the notation range(setexpr) where setexpr is a set expression which result is either a set of integers or a range. Similarly stating set(lstexpr) will generate a set from the elements of the list expression lstexpr.
List expressions
A constant list consist in a list of expressions enclosed in square brackets:
[[ Exp1 [, Exp2 ...]]] |
There are two basic operators for lists: the concatenation, written '+' and the difference, written '-'. The aggregate operator sum can also be used to build up list expressions (the operator union behaves like sum when applied to lists).
[1,2,3]+[1,2,3] ! = [1,2,3,1,2,3] [1,2,3,4]-[3,4] ! = [1,2] sum(i in 1..3) [i*3] ! = [3,6,9]
A list can also be constructed from the elements of a set using the syntax list(setexpr) where setexpr is a set expression.
Boolean expressions
A Boolean expression is an expression whose result is either true or false. The traditional comparators are defined on integer and real values: <, <=, =, <> (not equal), >=, >.
These operators are also defined for string expressions. In that case, the order is defined by the ISO-8859-1 character set (i.e. roughly: punctuation < digits < capitals < lower case letters < accented letters).
With sets, the comparators <= (`is subset of'), >= (`is superset of'), = (`equality of contents') and <> (`difference of contents') are defined. These comparators must be used with two sets of the same type. Moreover, the operator `expr in Set_expr' is true if the expression expr is contained in the set Set_expr. The opposite, the operator not in is also defined.
With lists, the comparators = (`equality of contents') and <> (`difference of contents') are defined. These comparators must be used with two lists of the same type.
With arrays, the comparators = (`equality of contents') and <> (`difference of contents') are defined. These comparators must be used with two arrays of the same type and this type must support the requested operator (for instance arrays of mpvar cannot be compared).
With records, the comparators = (`equality of contents') and <> (`difference of contents') are defined. These comparators must be used with two records of the same type and all fields of this record type must support the requested operator (for instance records including mpvar entries cannot be compared).
To combine Boolean expressions, the operators and (logical and) and or (logical or) as well as the unary operator not (logical negation) can be used. The evaluation of an arithmetic expression stops as soon as its value is known.
The aggregate operators and and or are the natural extension of their binary counterparts.
3<=v1 and v2>=45 or t<>r and not r in {1..10} and(i in 1..10) 3<=arr(i)
Linear constraint expressions
Linear constraints are built up using linear expressions on the decision variables (type mpvar).
The different forms of constraints are:
Linear_expr or Linear_expr1 Ctr_cmp Linear_expr2 or Linear_expr SOS_type or mpvar_ref mpvar_type1 or mpvar_ref mpvar_type2 Arith_expr |
In the case of the first form, the constraint is unconstrained and is just a linear expression. For the second form, the valid comparators are <=, >=, = (range constraints may be created using the procedure setrange). The third form is used to declare special ordered sets. The types are then is_sos1 and is_sos2. The coefficients of the variables in the linear expression are used as weights for the SOS (as a consequence, a 0-weighted variable cannot be represented this way, procedure makesos1 or makesos2 has to be used instead).
The last two types are used to set up special types for decision variables. The first series does not require any extra information: is_continuous (default), is_integer, is_binary, is_free. Continuous and integer variables have the default lower bound 0, binary variables only take the values 0 or 1, and 'free' means that the variable is unbounded (i.e. ranging from -∞ to +∞). The second series of types is associated with a threshold value stated by an arithmetic expressions: is_partint for partial integer, the value indicates the limit up to which the variable must be integer, above which it is continuous. For is_semcont (semi-continuous) and is_semint (semi-continuous integer) the value gives the semi-continuous limit of the variable (that is, the lower bound on the part of its domain that is continuous or consecutive integers respectively). Note that these constraints on single variables are also considered as common linear constraints.
3*y+sum(i in 1..10) x(i)*i >= z-t x is_free ! Define an unbounded variable x <= -2 ! Upper bound on x t is_integer ! Define an integer variable t=0,1,2,... t >= -7 ! Change lower bound on t: t=-7,-6,-5,... sum(i in 1..10) i*x(i) is_sos1 ! SOS1 {x(1),x(2),...} with ! weights 1,2,... y is_semint 5 ! y=0 or y=5,6,... y <= 20 ! Upper bound on y: y=0 or y=5,6,...,20
Internally all linear constraints are stored in the same form: a linear expression (including a constant term) and a constraint type (the right hand side is always 0). This means, the constraint expression 3*x>=5*y-10 is internally represented by: 3*x-5*y+10 and the type `greater than or equal to'. When a reference to a linear constraint appears in an expression, its value is the linear expression it contains. For example, if the identifier ctl refers to the linear constraint 3*x>=5*y-10, the expression z-x+ctl is equal to: z-2*x-5*y+10.
Note that the value of a unary constraint of the type x is_type threshold is x-threshold.
Automatic arrays
The array keyword can be used as an aggregate operator in order to create an array that will exist only for the duration of the expression.
array (Iterator1 [, Iterator2 ...]) Expression |
here, the iterators define the indices of the array and the expression, the associated values.
This automatic array may be used wherever a reference to an array is expected: for instance to save the solution values of an array of decision variables in an initialization block (see Section Initialization block).
initializations to "mydata.txt" evaluation of array(i in 1..10) x(i).sol as "mylabel" end-initializations
© 2001-2020 Fair Isaac Corporation. All rights reserved. This documentation is the property of Fair Isaac Corporation (“FICO”). Receipt or possession of this documentation does not convey rights to disclose, reproduce, make derivative works, use, or allow others to use it except solely for internal evaluation purposes to determine whether to purchase a license to the software described in this documentation, or as otherwise set forth in a written software license agreement between you and FICO (or a FICO affiliate). Use of this documentation and the software described in it must conform strictly to the foregoing permitted uses, and no other use is permitted.