The declaration block
The role of the declaration block is to give a name, a type, and a structure to the entities that the processing part of the program/model will use. The type of a value defines its domain (for instance integer or real) and its structure, how it is organized, stored (for instance a reference to a single value or an ordered collection in the form of an array). The declaration block is composed of a list of declaration statements enclosed between the instructions declarations and end-declarations.
declarations Declare_stat [ Declare_stat ...] end-declarations |
Several declaration blocks may appear in a single source file but a symbol introduced in a given block cannot be used before that block. Once a name has been assigned to an entity, it cannot be reused for anything else.
Elementary types
Elementary objects are used to build up more complex data structures like sets or arrays. It is, of course, possible to declare an entity as a reference to a value of one of these elementary types. Such a declaration looks as follows:
ident1 [, ident2 ...]: [shared] type_name |
where type_name is the type of the objects to create. Each of the identifiers identi is then declared as a reference to a value of the given type. The type name may be either a basic type (integer, real, string, boolean), an MP type (mpvar, linctr), an external type or a user defined type (see section User defined types). MP types are related to Mathematical Programming and allow declaration of decision variables and linear constraints. Note that the linear constraint objects can also be used to store linear expressions. External types are defined by modules (the documentation of each module describes how to use the type(s) it implements). The qualifier shared identifies variables that will be shared between several concurrent models (see Section Data sharing between models). Only entities of basic types and external types supporting sharing can be shared.
declarations i,j: integer str: string x,y,z: mpvar end-declarations
Basic types
- integer: an integer value between -2147483648 and 2147483647. Integers may also be expressed in hexadecimal by using the prefix 0x or 0X (e.g. 0x7b is the same as 123)
- real: a real value between -1.7e+308 and 1.7e+308. Floating point numbers expressed in hexadecimal can also be used as real constants. The general form of such a constant is 0xh.hhhp[+/-]ddd where 'h' are hexadecimal digits and 'd' decimal digits (e.g. 0x1.9p+3 is the same as 12.5)
- string: some text.
- boolean: the result of a Boolean (logical) expression. The value of a Boolean entity is either the symbol true or the symbol false.
After its declaration, each entity receives an initial value of 0, an empty string, or false depending on its type.
MP types
Two special types are provided for mathematical programming.
Sets
Sets are used to group an unordered collection of elements of a given type. Set elements are unique: if an element is added several times it is only contained once in the set. Declaring a set consists of defining the type of elements to be collected.
The general form of a set declaration is:
ident1 [, ident2 ...] : [shared] [dynamic] set of [constant] type_name |
where type_name is one of the elementary types. Each of the identifiers identi is then declared as a set of the given type. The qualifier shared identifies sets that will be shared between several concurrent models (see Section Data sharing between models). Only sets of basic types can be shared. If the qualifier dynamic is used the corresponding set(s) will never be finalized (see Section About automatic finalization and procedure finalize).
A set may collect references to constant elements of a native type (the type must support constant declaration): this kind of set will be created if the type name is preceded by the constant keyword. As opposed to an ordinary set, a set of constant references behaves as if it was collecting values of the native type entities instead of their references. For instance adding 2 different variables of some native type to a normal set will always result in 2 elements added to the set. However a single element will be added to a set of constant references if these 2 variables have the same content (or the same textual representation). Moreover, since references are not directly collected, any change to a variable previously added to a set of constant references has no impact on the content of this set.
A particular set type is also available that should be preferred to the general form wherever possible because of its better efficiency: the range set is an ordered collection of consecutive integers in a given interval. The declaration of a range set is achieved by:
ident1 [, ident2 ...] : [shared] [dynamic] range [set of integer] |
Each of the identifiers identi is then declared as a range set of integers. Every newly created set is empty.
declarations s1: set of string r1: range end-declarations
Lists
Lists are used to group a collection of elements of a given type. An element can be stored several times in a list and order of the elements is specified by construction. Declaring a list consists of defining the type of elements to be collected.
The general form of a list declaration is:
ident1 [, ident2 ...] : [shared] list of type_name |
where type_name is one of the elementary types. Each of the identifiers identi is then declared as a list of the given type. The qualifier shared identifies lists that will be shared between several concurrent models (see Section Data sharing between models). Only lists of basic types can be shared.
Every newly created list is empty.
declarations l1: list of string l2: list of real end-declarations
A list element can be accessed using its order number. The first element has number 1 and index values inferior to 1 point to elements starting from the end of the list. For instance if l is a list, l(2) is the second element of this list, l(0) is the last element of the list and l(-1) its predecessor.
Arrays
An array is a collection of labelled objects of a given type. A label is defined by a list of indices taking their values in domains characterized by sets: the indexing sets. An array may be either dense or sparse: every possible index tuple is associated to a cell in a dense array while sparse arrays are created empty. The cells are then created explicitly (cf. procedure create) or when they are assigned a value (cf. Section Assignment) and the array may then grow `on demand'. It is also possible to delete some or all cells of a dynamic array using the procedure delcell. A cell that has not been created can be identified using the exists function and its value is the default initial value of the type of the array. The general form of an array declaration is:
ident1 [, ident2 ...] : [shared] [dynamic|hashmap] array(list_of_sets) of type_name |
where list_of_sets is a list of set declarations/expressions separated by commas and type_name is one of the elementary types. Each of the identifiers identi is then declared as an array of the given type and indexed by the given sets. In the list of indexing sets, a set declaration can be anonymous (i.e. rs:set of real can be replaced by set of real if no reference to rs is required) or shortened to the type of the set (i.e. set of real can be replaced by real in that context). The qualifier shared identifies arrays that will be shared between several concurrent models (see Section Data sharing between models). Only arrays of basic types and indiced by shared or constant sets of basic types can be shared.
declarations e: set of string t1:array ( e, rs:set of real, range, integer ) of real t2:array ( {"i1","i2"}, 1..3 ) of integer end-declarations
By default an array is dense (or static). For best performane it is better to index static arrays with constant sets or initialize and finalize indexing sets as soon as possible (cf. procedure finalize). An array is sparse (or dynamic) and created empty if either the qualifier dynamic or hashmap is used. Arrays declared with either of these qualifiers behave the same but their internal representation differ: the dynamic representation requires less memory and is faster for linear enumeration while the hashmap representation is faster for random access.
Note that once a set is employed as an indexing set, Mosel makes sure that its size is never reduced in order to guarantee that no entry of any array becomes inaccessible. Such a set is called fixed.
Special case of dynamic arrays of a type not supporting assignment
Certain types do not have assignment operators: for instance, writing x:=1 is a syntax error if x is of type mpvar. If an array of such a type is defined as dynamic the corresponding cells are not created. In that case, it is required to create each of the relevant entries of the array by using the procedure create since entries cannot be defined by assignment.
Records
A record is a finite collection of objects of any type. Each component of a record is called a field and is characterized by its name (an identifier) and its type. The general form of a record declaration is:
ident1 [, ident2 ...] : record field1 [, field2 ...]: type_name [...] end-record |
where fieldi are the identifiers of the fields of the record and type_name one of the elementary types. Each of the identifiers identi is then declared as a record including the listed fields.
Example:
declarations r1: record i,j:integer r:real end-record end-declarations
Each record declaration is considered unique by the compiler. In the following example, although r1 and r2 have the same definitions, they are not of the same type (but r3 is of course of the type of r2):
declarations r1: record i,j:integer end-record r2,r3: record i,j:integer end-record end-declarations
Constants
A constant is an identifier for which the value is known at declaration time and that will never be modified. The general form of a constant declaration is:
identifier = Expression |
where identifier is the name of the constant and Expression its initial and only value. The expression must be of one of the basic types, a set or a list of one of these types, a native type supporting constant definition, or a record type containing only basic types.
Example:
declarations STR='my const string' I1=12 R=1..10 ! constant range S={2.3,5.6,7.01} ! constant set L=[2,4,6] ! constant list end-declarations
The compiler supports two kinds of constants: a compile time constant is a constant which value can be computed by the compiler. A run time constant will be known only when the model is run.
Example:
parameters P=0 end-parameters declarations I=1/3 ! compile time constant J=P*2 ! run time constant end-declarations
User defined types
Naming new types
A new type may be defined by associating an identifier to a type declaration. The general form of a type definition is:
identifier = Type_def |
where Type_def is a type (elementary, set, list, array or record) to be associated to the symbol identifier. After such a definition, the new type may be used wherever a type name is required.
Example:
declarations entier=integer setint=set of entier i:entier ! <=> i:integer s:setint ! <=> s:set of integer end-declarations
Note that only compile time constant or globally defined sets are allowed as indices to array types:
declarations ar1=array(1..10) of integer ! OK ar2=array(range) of integer ! incorrect R:range ar3=array(R) of integer ! OK end-declarations
Combining types
Thanks to user defined types one can create complex data structures by combining structures offered by the language. For instance an array of sets may be defined as follows:
declarations typset=set of integer a1:array(1..10) of typset end-declarations
In order to simplify the description of complex data structures, the Mosel compiler can generate automatically the intermediate user types. Using this property, the example above can be written as follows (both arrays a1 and a2 are of the same type):
declarations a2:array(1..10) of set of integer end-declarations
© 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.