Running Mosel models
The moselexec function
The simplest way to run a Mosel program from MATLAB is using the moselexec function, as in:
>> moselexec burglar.mos
This compiles and runs the Mosel program burglar.mos located in the current folder (or prints an error message if the file cannot be found). You can of course specify a full path as in
>> moselexec C:/xpressmp/examples/mosel/Modeling/burglar.mos
or use the XPRESSDIR environment variable to point to the Xpress installation folder:
>> moselexec(fullfile(getenv('XPRESSDIR'),'/examples/mosel/Modeling/burglar.mos'))
By specifying the optional output arguments retcode and exitcode, the moselexec function can also return the compilation and execution result code and the program exit status, or both, for example solving this tiny example example_m1.mos:
model "example_m1" exit(10) end-model
would yield
>> [retcode, exitcode]=moselexec('example_m1.mos') retcode = 0 exitcode = 10
where the value zero for retcode means that the program has run without errors, and exitcode has the value specified in the model.
Please refer to moselexec in the reference section for further details.
The I/O driver
The Mosel I/O driver for MATLAB makes it possible to exchange data between Mosel programs and the MATLAB workspace. This driver supports reading a MATLAB value as a Mosel generalized file stream, and importing and exporting data from and to MATLAB in Mosel initializations from and initializations to blocks.
Note that this driver is available only when executing Mosel programs from within the MATLAB environment.
Extended file names
Mosel uses an extend file name format to represent 'files' that can be accessed through specialized I/O drivers. The format for the MATLAB driver is
matlab.mws:expression
where matlab is the name of the Mosel module, mws is the name of the I/O driver name (MATLAB WorkSpace) and expression can either be a current variable name of the caller workspace, or any MATLAB expression returning a single value. In the case of a MATLAB expression, the latter will be evaluated in the caller workspace at the time of file opening. For example, the following Mosel program
model "example_m2" uses "mmsystem"; fcopy("matlab.mws:message", "") writeln end-model
would read the MATLAB variable message and print it to the MATLAB console. You can test it with the following MATLAB commands
>> message='Hello, World!'; >> moselexec('example_m2.mos') Hello, World!
String handling
When reading a string variable, the I/O driver automatically converts it from MATLAB native 16-bit multibyte Unicode characters to the 8-bit ASCII format used by Mosel (if you prefer to convert the string using a different encoding, you can explicitly convert it to a raw byte stream beforehand with the MATLAB function unicode2native). If the source string is a string array that contains several rows, then these are copied, one column at a time, into a single string. Finally, if the source variable is a cell array containing strings, all strings are read successively with newline characters added at the end of each one.
It is thus possible to use a MATLAB cell array to store a Mosel program, one line per cell, and then execute it without using external files, as in the following example.
>> mos={ 'model "example_m3" ' ' uses "mmxprs", "mmnl"; ' ' declarations ' ' a:mpvar ' ' end-declarations ' ' minimize(a*a-5*a+10) ' ' writeln(getobjval) ' 'end-model ' }; >> moselexec('matlab.mws:mos') 3.75
Initializations from blocks
The matlab.mws I/O driver can be used in Mosel initialization blocks to read MATLAB values and set MATLAB variables. In this case, the filename should just be "matlab.mws:", without any expression, and the expression can eventually be specified as the label associated to the identifier being initialized.
Consider the following Mosel program
model "example_m4" declarations answer: integer foo: real var: real today: string i: range Data: array(i) of real end-declarations initializations from "matlab.mws:" answer as "42" foo var as "bar" today as "date" Data as "sum(magic(foo*bar))" end-initializations writeln("answer to ultimate question: ", answer) writeln("foo: ", foo) writeln("bar: ", var) writeln("today: ", today) writeln("data: ", Data) end-model
and its execution from MATLAB
>> foo=pi; >> bar=exp(1); >> moselexec('example_m4.mos'); answer to ultimate question: 42 foo: 3.14159 bar: 2.71828 today: 01-May-2014 data: [260,260,260,260,260,260,260,260]
Here, the expression used to initialize the variable answer is "42", that is, a literal value. Variable foo doesn't specify an initialization label, so the default is used—the default label is the identifier itself and thus the MATLAB variable foo is read. The label for variable var explicitly says to read the MATLAB variable bar. The expression used to initialize today is the MATLAB function date which returns a string with today's date. And finally, Data is an array read from a MATLAB expression that builds a magic square of size 8 and calculates the sums of values in every column (which should be all equal in magic squares, as shown in the output).
MATLAB sparse matrices can be read into dynamic arrays to set only non-zero elements:
>> mos={ 'model "example_m5" ' ' declarations ' ' I,J: range ' ' Sparse: dynamic array(I,J) of real' ' end-declarations ' ' initializations from "matlab.mws:" ' ' Sparse as "sprand(4,4,.5)" ' ' end-initializations ' ' writeln("sparse is: ", Sparse) ' ' writeln("row indices: ", I) ' ' writeln("col indices: ", J) ' 'end-model ' }; >> moselexec('matlab.mws:mos'); sparse is: [(1,3,0.24285),(2,1,0.917424),(2,2,0.269062),(2,3,0.7655),(4,1,0.188662)... row indices: 1..4 col indices: 1..3
In the above example, Sparse is a 2-dimensional dynamic array containing only 6 values after initialization from a MATLAB 4 4 sparse random matrix, and index set J (in this execution) contains only the values 1, 2, and 3 as the matrix happened to have all zeros in column 4. Note also that array indices start from 1 which is the MATLAB convention.
Initializations to blocks
Mosel data can be exported to MATLAB using initializations to blocks. The filename should just be "matlab.mws:" in this case too, and labels can be used to specify MATLAB variable names to export to (if no label is specified, the name of the identifier is used). In MATLAB, these variables are set in the caller workspace, eventually overwriting their previous value.
The following example shows how to export a scalar value (simplexiter), the optimal objective and solution values into MATLAB variables. The model, foliomat.mos, is a modified version of the portfolio optimization example from the "Getting Started with Xpress" guide.
model "Portfolio optimization with LP - MATLAB" uses "mmxprs" declarations SHARES: range RISK: set of integer NA: set of integer RET: array(SHARES) of real frac: array(SHARES) of mpvar simplexiter: integer end-declarations initializations from "matlab.mws:" RISK NA RET end-initializations Return:= sum(s in SHARES) RET(s)*frac(s) sum(s in RISK) frac(s) <= 1/3 sum(s in NA) frac(s) >= 0.5 sum(s in SHARES) frac(s) = 1 forall(s in SHARES) frac(s) <= 0.3 maximize(Return) simplexiter:=getparam("XPRS_simplexiter") initializations to "matlab.mws:" simplexiter evaluation of getobjval as "objval" evaluation of array(s in SHARES) frac(s).sol as "frac" end-initializations exit(getprobstat) end-model
This can be executed from MATLAB after defining RISK, NA and RET input data and results will be available as MATLAB variables as shown below.
>> RET = [5 17 26 12 8 9 7 6 31 21]; >> RISK = [2 3 4 9 10]; >> NA = [1 2 3 4]; >> [r,e]=moselexec('foliolp_mat.mos'); >> objval objval = 14.0667 >> frac' ans = 0.3000 0 0.2000 0 0.0667 0.3000 ...
Using MATLAB functions in Mosel
We have already seen how MATLAB functions can be called in initializations from blocks (including user-defined functions). Since these blocks can be used at arbitrary positions in Mosel programs, it is possible to combine this with initializations to blocks to load some data into MATLAB, evaluate a MATLAB function on this data and retrieve results back into Mosel. The following example shows a fibonacci function implemented in MATLAB and a Mosel program that also defines a fibonacci function that just calls the MATLAB one (note however that this is neither reentrant nor thread-safe).
MATLAB code (fibonacci.m):
function f=fibonacci(n) if n<2, f=n; return, end s=[0 1]; for i=2:n, s=[s(2) sum(s)]; end f=s(2); end
Mosel model fib-relay.mos:
model "fib_relay" function fibonacci(i:integer):integer initializations to "matlab.mws:" i end-initializations initializations from "matlab.mws:" returned as "fibonacci(i)" end-initializations end-function forall(i in 1..10) writeln("fibonacci(", i, ")=", fibonacci(i)) end-model
Example run:
>> moselexec('fib_relay.mos'); fibonacci(1)=1 fibonacci(2)=1 fibonacci(3)=2 fibonacci(4)=3 fibonacci(5)=5 ...
Supported types
The matlab.mws driver supports all basic types of Mosel (boolean, integer, real, string) and the structures set, range, list and array of basic types. On the MATLAB side, the supported types are n-dimensional arrays and cell arrays of the basic numeric, logical or char classes (including sparse matrices). Only the real part of arrays is always used. Since MATLAB uses 1-based integer indices, Mosel arrays must also use this same convention when imported/exported to MATLAB. If necessary, data is silently casted to the appropriate type without any warning in case of truncation or loss of precision (for example when reading a Mosel integer from a fractional MATLAB double value).
© 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.