The full XPress-Mosel 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.
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).
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
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.
As in general formal programming languages, basic identifiers can be of the following four types.
There are two special types of identifier
There are several types of IP constraints that can be applied to variables.
y is_semcont 5
y must be 0 or in the interval [5, ∞).
y is_semint 5
y must be 0 or in the set {5, 6, ...}.
y is_partint 5
y must be in the set {0, 1, 2, 3, 4} or in the interval [5, ∞).
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_freeAn 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 ...]) ExpressionThe sum operator adds the terms defined by its iterator(s). For example
sum(i in 1..10) i*isums the squares from 1 to 10.
The prod operator multiplies the terms defined by its iterator(s). For example
prod(i in 1..10) icalculates (10!): the factorial of 10.
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.
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.
There are several loop structures.
If it applies to only one statement then the following simple form can be used.
forall (Iteration list) Statement
If it applies to more than one statement then the following form must be used.
forall (Iteration list) do
Statement list
end-do
The iteration list can take many forms. An example of a standard loop over a set of integers is as follows.
forall (i
in 1..10)
Statement
Repeating a statement list until Boolean expression is true is achieved as follows.
repeat
Statement list
until Boolean expression
Repeating a statement list, increasing x from l by d until x exceeds u is achieved as follows.
x := l
repeat
Statement list
x += d
until x > u
For full documentation on the forall, while and repeat syntax see the loops section of the Mosel reference guide.
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.
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)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.
function getact(c: linctr): real
function getcoeff(c: linctr): real
returns the RHS coefficient of constraint c.
function getcoeff(c: linctr, x:mpvar): real
returns the coefficient of variable x in constraint c.
function getdual(c: linctr): real
function getobjval: real
function getrcost(x:mpvar): real
function getslack(c: linctr): real
function getsol(x:mpvar): real
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.
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.
function maxlist(i1:integer, i2:integer[,
i3:integer...]):integer
returns the maximum value of a list of integers.
function maxlist(r1:real, r2:real[, r3:real...]):real
returns the maximum value of a list of reals.
function minlist(i1:integer, i2:integer[,
i3:integer...]):integer
returns the minimum value of a list of integers.
function minlist(r1:real, r2:real[, r3:real...]):real
returns the minimum value of a list of reals.
function ceil(r:real): integer
such thatfunction floor(r:real): integer
such thatfunction round(r:real): integer
such thatThere 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.
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.
The general form of a procedure definition is:
procedure name_proc [(list_of_parms)]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.
The definition of a function is very similar to the one of a procedure:
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):integermay be used as follows.
writeln("3*12=", multiply_by_3(12)) ! Call the functionFor further information, see Procedures and functions in the full Mosel documentation.
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_typewhere the procedure or function Func_name will be defined later in the source file.
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.
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.