Initializing help system before first use

LP model

Topics covered in this section:

The mathematical model in the previous chapter may be transformed into the following Mosel model entered into Workbench:

model "Portfolio optimization with LP"
 uses "mmxprs"                       ! Use Xpress Optimizer

 declarations
  SHARES = 1..10                     ! Set of shares
  RISK = {2,3,4,9,10}                ! Set of high-risk values among shares
  NA = {1,2,3,4}                     ! Set of shares issued in N.-America
  RET: array(SHARES) of real         ! Estimated return in investment

  frac: array(SHARES) of mpvar       ! Fraction of capital used per share
 end-declarations

 RET:: [5,17,26,12,8,9,7,6,31,21]

! Objective: total return
 Return:= sum(s in SHARES) RET(s)*frac(s)

! Limit the percentage of high-risk values
 sum(s in RISK) frac(s) <= 1/3

! Minimum amount of North-American values
 sum(s in NA) frac(s) >= 0.5

! Spend all the capital
 sum(s in SHARES) frac(s) = 1

! Upper bounds on the investment per share
 forall(s in SHARES) frac(s) <= 0.3

! Solve the problem
 maximize(Return)

! Solution printing
 writeln("Total return: ", getobjval)
 forall(s in SHARES) writeln(s, ": ", getsol(frac(s))*100, "%")

end-model

Let us now try to understand what we have just written.

General structure

Every Mosel program starts with the keyword model, followed by a model name chosen by the user. The Mosel program is terminated with the keyword end-model.

All objects must be declared in a declarations section, unless they are defined unambiguously through an assignment (however, if you have kept the option 'noimplicit' from the Workbench model template then all entities must be declared). For example,

 Return:= sum(s in SHARES) RET(s)*frac(s)

defines Return as a linear constraint and assigns to it the expression

 sum(s in SHARES) RET(s)*frac(s)

There may be several such declarations sections at different places in a model.

In the present case, we define three sets, and two arrays:

  • SHARES is a so-called range set—i.e., a set of consecutive integers (here: from 1 to 10).
  • RISK and NA are simply sets of integers.
  • RET is an array of real values indexed by the set SHARES, its values are assigned after the declarations.
  • frac is an array of decision variables of type mpvar, also indexed by the set SHARES. These are the decision variables in our model.

The model then defines the objective function, two linear inequality constraints and one equality constraint and sets upper bounds on the variables.

As in the mathematical model, we use a forall loop to enumerate all the indices in the set SHARES.

Solving

With the procedure maximize, we call Xpress Optimizer to maximize the linear expression Return. As Mosel is itself not a solver, we specify that Xpress Optimizer is to be used with the statement

 uses "mmxprs"

at the begin of the model (the module mmxprs is documented in the `Mosel Language Reference Manual').

Instead of defining the objective function Return separately, we could just as well have written

 maximize(sum(s in SHARES) RET(s)*frac(s))

Output printing

The last two lines print out the value of the optimal solution and the solution values for all variables.

To print an additional empty line, simply type writeln (without arguments). To write several items on a single line use write instead of writeln for printing the output.

Formating

Indentation, spaces, and empty lines in our model have been added to increase readability. They are skipped by Mosel.

Line breaks: It is possible to place several statements on a single line, separating them by semicolons, like

 RISK = {2,3,4,9,10}; NA = {1,2,3,4}

But since there are no special `line end' or continuation characters, every line of a statement that continues over several lines must end with an operator (+, >=, etc.) or characters like `,' that make it obvious that the statement is not terminated.

As shown in the example, single line comments in Mosel are preceded by !. Comments over multiple lines start with (! and terminate with !).


© 2001-2025 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.