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.