Modelling with Xpress

Documentation

The full Mosel Language Reference manual is hard to use (at first) so, set out below, is some basic documentation, with links to the appropriate page of the reference manual in some cases.

model statement

The beginning of the model is indicated by the model statement. The model name can be any string. Optionally, the end of the model can be indicated by end-model statement. Any text following this statement is ignored (so can be used to add comments).

uses statement

The uses statement indicates which Xpress libraries should be loaded. You will always need to load mmxprs using the following statement

uses "mmxprs"

There are several other libraries, three of which will be used in this course

declarations block

A declarations block gives a name, type and structure to identifiers used to create the model. Note that the word "identifiers" is used rather than "variables". The latter is commonly used in general formal programming languages but clearly has a special meaning within a modelling system.

A declarations block is composed of a list of declaration statements enclosed between declarations and end-declarations. There may be several declarations blocks in a given file. An identifier cannot be used before it has been declared and, once a name has been assigned to an identifier, it cannot be reused for anything else.

Basic types

As in general formal programming languages, basic identifiers can be of the following four types.

MP types

There are two special types of identifier

IP types

There are several types of IP constraints that can be applied to variables.

Other types

Decision variables in Mosel are, by default, non-negative. Finite lower bounds can be defined explicitly. A decision variable can be given an infinite lower (and upper) bound using the is_free statement. For example

y is_free

Aggregate operators

An aggregate applies to a list of indices for each of which a set or list of values is defined. The sum (summation) aggregate operator is defined on identifier that are integer, real and mpvar. The aggregate operators prod (product), min (minimum) and max (maximum) can be used on integer and real values. They take the form

Aggregate_ident (Iterator1 [, Iterator2 ...]) Expression

Sum

The sum operator adds the terms defined by its iterator(s). For example

sum(i in 1..10) i*i

sums the squares from 1 to 10.

Prod

The prod operator multiplies the terms defined by its iterator(s). For example

prod(i in 1..10) i

calculates (10!): the factorial of 10.

Max

The max operator finds the maximum of the terms defined by its iterator(s). For example

max(i in 1..10) a(i)

finds the maximum value of the first 10 entries in the array a.

Min

The min operator finds the minimum of the terms defined by its iterator(s). For example

min(i in 1..10) a(i)

finds the minimum value of the first 10 entries in the array a.

Loops

There are several loop structures.

For full documentation on the forall, while and repeat syntax see the loops section of the Mosel reference guide.

if blocks

The basic form of the if block in Xpress-Mosel is as follows.

if (Boolean expression 1) then
Statement list
elif (Boolean expression 2) then
Statement list
else
Statement list
end-if

For full documentation on the if (and case) block syntax see the selections section of the Mosel reference guide.

Optimization statement

The solution of the model is determined by a single function call whose argument is the function to be optimized. In addition to

maximize(Objective)

there is, naturally,

minimize(Objective)

Getting data

Once a problem has been solved, it will usually be necessary to extract data about the solution. There is a set of functions that can be used to do this.

Setting data

The procedure setcoeff modifies constraint coefficients.

procedure setcoeff(c: linctr, r:real)
sets the RHS coefficient of constraint c.

procedure setcoeff(c: linctr, x:mpvar, r:real)
sets the coefficient of variable x in constraint c.

Generic functions

There are many "obvious" generic functions in Xpress such as (natural) logarithms (ln) log, exponential exp and trigonometrical functions. Other, less obvious ones are given below.

I/O handling

There are several routines for opening, closing and switching streams for input to and output from Xpress-Mosel programmes. Click on the routine name to get full documentation.

Output is written using write and writeln statements. The only difference between them is that writeln ends the line. These may make use of the formatting function strfmt.

Procedures and functions

Mosel allows structured programming via the use of procedures and functions. Procedures and functions may both receive arguments, define local data and call themselves recursively.

Procedures

The general form of a procedure definition is:

procedure name_proc [(list_of_parms)]
    Proc_body
end-procedure

where name_proc is the name of the procedure and list_of_parms its list of formal parameters (if any). This list is composed of symbol declarations separated by commas. The body of the procedure is the usual list of statements and declaration blocks except that no procedure or function definition can be included. For example

procedure myproc
    writeln("In myproc")
end-procedure

procedure withparams(a:array(r:range) of real, i, j:integer)
    writeln("I received: i=", i, " j=", j)
    forall(n in r) writeln("a(", n, ")=", a(n))
end-procedure

declarations
    mytab:array(1..10) of real
end-declarations

myproc                     ! Call myproc
withparams(mytab, 23,67)   ! Call withparams

For further information, see Procedures and functions in the full Mosel documentation.

Functions

The definition of a function is very similar to the one of a procedure:

function name_func [(List_of_params)]: Type
    Function body
end-function

The only difference with a procedure is that the function type must be specified: it can be any type name except mpvar. A value must be assigned to a value during the execution of the function. For example

function multiply_by_3(i:integer):integer
    returned := i*3
end-function

may be used as follows.

writeln("3*12=", multiply_by_3(12))       ! Call the function

For further information, see Procedures and functions in the full Mosel documentation.

Forward declaration

During the compilation phase of a source file, only symbols that have been previously declared can be used at any given point. A forward declaration is provided for these uses: it consists of stating only the header of a subroutine that will be defined later. The general form of a forward declaration is:

forward procedure Proc_name [(List_of_params)]

or

forward function Func_name [(List_of_params)]: Basic_type

where the procedure or function Func_name will be defined later in the source file.

Problem status

The status of (the solution of) a problem can be determined using the value of the function getprobstat. This is an integer which can be compared (in an if statement) with the following Xpress integer-valued parameters.

In normal circumstances getprobstat will indicate only optimality, infeasibility or unboundedness. There is further documentation on getprobstat.

Xpress-IVE plotting routines

There are several routines for plotting data in the "user graph" pane of the right window of Xpress-IVE. To use any of them the library mmive must be loaded via a uses statement.

The most useful plotting routines are the following four.

The following integer values representing colours are defined when mmive is loaded: IVE_BLACK, IVE_BLUE, IVE_CYAN, IVE_GREEN, IVE_MAGENTA, IVE_RED, IVE_WHITE, IVE_YELLOW. Additional colours can be defined using the function IVE_RGB.


Back to Modelling with Xpress home page