Initializing help system before first use

Embedding a Mosel model in an application

Mosel models frequently need to be embedded in applications so they can be deployed easily. In this chapter we discuss

  • how to generate a deployment template,
  • the meaning and use of BIM files,
  • embedding Mosel models into a host application,
  • the use of parameterized model and BIM files,
  • how to export matrix files with Mosel, and
  • how to create an Xpress Insight application from a model file.

Generating a deployment template

Open menu File » New From Template and select the entry Mosel deployment - Java. (For deployment with C, C#, or any other supported language the procedure is similar.)

Chap678/deploy1j.png

Figure 10.1: Choosing the deployment type

This will open a new file in the editor window with the resulting code:

Chap678/deploy2j.png

Figure 10.2: Code preview

Find the constant with the value test.bim near the top of the file and change its value to the name of your BIM file (e.g. foliodata.bim). Use the menu File » Save As... to set the name (folio.java) and location of the new file. At the top of the code window a standard compilation line for Java under Windows is shown. To use it with the file we have just generated, replace RunModel.java by the name of our file, folio.java.

The Java program may be run on all systems for which Mosel is available. To compile under Linux or Solaris use:

javac -cp .:${XPRESSDIR}/lib/xprm.jar folio.java

For other systems please refer to the examples makefile of the corresponding Mosel distribution.

BIM files

Mosel models are typically distributed in the form of a BIM file (BInary Model file). A BIM file is a compiled version of the .mos model file that is portable across all platforms for which Mosel is available. It does not include any data read from external files. These must still be provided in separate files, thus making it possible to run the same BIM file with different data sets (see section Parameters below).

To generate a BIM file with Workbench you may use Run » Build or equivalently, click on the button Chap678/butcomp.png. The BIM file will then be created in the same directory as the Mosel file by appending the extension .bim to the file name (instead of .mos). You may also use the Compiler Options dialog (opened either from the Run menu or by clicking on the tools button Chap678/buttools.png) to configure, for example, various debugging settings for the compilation.

It is also possible to execute Mosel source files (.mos) directly from an application (see the following section). In this case the BIM file does not need to be generated.

Embedding Mosel models into a host application

Executing Mosel models

The following simple Java program can be used to run a Mosel model that is provided in the form of a BIM file (for simplicity's sake we are leaving out any kind of error handling):

import com.dashoptimization.*;

public class folio
{
 public static void main(String[] args) throws Exception
 {
  XPRM mosel;
  XPRMModel model;

  mosel = new XPRM();                         // Initialize Mosel
  model = mosel.loadModel("foliodata.bim");   // Load compiled model
  model.run();                                // Run the model

  System.out.println("Model execution returned: " + model.getResult());
 }
}

This Java program may be run on all systems for which Mosel is available. Under Windows use these commands to compile and run the program:

javac -classpath .:%XPRESSDIR%\lib\xprm.jar folio.java
java -classpath .:%XPRESSDIR%\lib\xprm.jar folio

To compile under Linux or Solaris use:

javac -cp .:${XPRESSDIR}/lib/xprm.jar folio.java

If we also wish to create the BIM file from the Java application, we may compile, load, and run the Mosel model foliodata.mos directly from the Java program, for instance as shown in the following code fragment. The compilation functionality is equally contained in the JAR file xprm.jar so that we can use the same compilation command as before.

import com.dashoptimization.*;

public class folio
{
 public static void main(String[] args) throws Exception
 {
  XPRM mosel;
  XPRMModel model;

  mosel = new XPRM();                         // Initialize Mosel
  mosel.compile("foliodata.mos");             // Compile the model
  model = mosel.loadModel("foliodata.bim");   // Load compiled model
  model.run();                                // Run the model

  System.out.println("Model execution returned: " + model.getResult());
 }
}

Parameters

In Chapter 4 we have shown how to modify parameter settings with Workbench or when running the Mosel standalone version (for instance in batch files or scripts). The model parameters may also be reset when a Mosel model or BIM file is embedded in an application, making it possible to solve many different problem instances without having to change the model source.

In this example we modify the name of the result file and the settings for two numerical parameters of our model foliodata.mos. All other model parameters will take the default values specified at their definition in the model.

import com.dashoptimization.*;

public class folioparam
{
 public static void main(String[] args) throws Exception
 {
  XPRM mosel;
  XPRMModel model;

  mosel = new XPRM();                        // Initialize Mosel
  mosel.compile("foliodata.mos");            // Compile the model
  model = mosel.loadModel("foliodata.bim");  // Load compiled model
                                             // Set the run-time parameters
  model.execParams = "OUTFILE=result2.dat,MAXRISK=0.4,MAXVAL=0.25";
  model.run();                               // Run the model

  System.out.println("`foliodata' returned: " + model.getResult());
 }
}

Retrieving solution information

After running a model, it is possible to retrieve information about the model objects and the solution of the (last) optimization run. The following example shows how to test the problem status and retrieve the objective function value.

import com.dashoptimization.*;

public class folioobj
{
 public static void main(String[] args) throws Exception
 {
  XPRM mosel;
  XPRMModel model;

  mosel = new XPRM();                        // Initialize Mosel
  mosel.compile("foliodata.mos");            // Compile the model
  model = mosel.loadModel("foliodata.bim");  // Load compiled model
  model.run();                               // Run the model

  // Test whether a solution is found and print the objective value
  if(model.getProblemStatus()==XPRMModel.PB_OPTIMAL)
    System.out.println("Objective value: " + model.getObjectiveValue());
 }
}

Matrix files

Exporting matrices

If the optimization process with Xpress Optimizer is started from within a Mosel program, or if the solving procedure is part of the application into which a Mosel model has been embedded, then the problem matrix is loaded in memory into the solver without writing it out to a file (which would be expensive in terms of running time). However, in certain cases it may still be required to be able to produce a matrix. With Xpress, the user has the choice between two matrix formats: extended MPS and extended LP format, the latter being in general more easily human-readable since constraints are printed in algebraic form.

With Mosel, there are several possibilities for generating a matrix:

  1. With a matrix generation statement in the model file:
    to create an MPS matrix for our problem add the line
      exportprob(EP_MPS, "folio", Return)
    for an LP format matrix (which we intend to maximize at some point) add the line
      exportprob(EP_MAX, "folio", Return)
    immediately before or instead of the optimization statement.
  2. From a Java application after having executed the model file:
      XPRMModel model;
      model.exportProblem("m", "folio");
    This will output the matrix in MPS format. To print with LP format change the first argument of exportProblem:
      model.exportProblem("p", "folio");

Deployment to Xpress Insight

Xpress Insight embeds Mosel models into a multi-user application for deploying optimization models in a distributed client-server architecture. Through the Xpress Insight GUI, business users interact with Mosel models to evaluate different scenarios and model configurations without directly accessing to the model itself.

Preparing the model file

For embedding a Mosel model into Xpress Insight, we need to make a few edits to the Mosel model in order to establish the connection between Mosel and Xpress Insight.

Firstly, we need to load the package mminsight that provides the required additional functionality. Since Insight manages the data scenarios, we only need to read in data from the original sources when loading the scenario (also referred to as baseline run) into Insight (triggered by the test of the run mode with insightgetmode in the model below). Scenario data will otherwise be input directly from Xpress Insight at the insertion point marked with insightpopulate. All model entities that are to be managed by Xpress Insight need to be declared as public. Furthermore, the solver call to start the optimization is replaced by insightminimize / insightmaximize.

The resulting model file folioinsight.mos (based on foliodata.mos) has the following contents—this model can also simply be run standalone, e.g. from Workbench or the Mosel command line, this is the case handled by INSIGHT_MODE_NONE.

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

 parameters
  DATAFILE= "folio.dat"              ! File with problem data
  MAXRISK = 1/3                      ! Max. investment into high-risk values
  MAXVAL = 0.3                       ! Max. investment per share
  MINAM = 0.5                        ! Min. investment into N.-American values
 end-parameters

 public declarations
  SHARES: set of string              ! Set of shares
  RISK: set of string                ! Set of high-risk values among shares
  NA: set of string                  ! Set of shares issued in N.-America
  RET: array(SHARES) of real         ! Estimated return in investment
 end-declarations

 case insightgetmode of
  INSIGHT_MODE_LOAD: do              ! 'Load data' mode: Read data, then stop
       initializations from DATAFILE
        RISK RET NA
       end-initializations
       exit(0)
      end-do
  INSIGHT_MODE_RUN:                  ! 'Run' mode: Inject scen. data, continue
      insightpopulate
  INSIGHT_MODE_NONE:                 ! Standalone run: Read data and continue
      initializations from DATAFILE
       RISK RET NA
      end-initializations
  else
      writeln("Unknown execution mode")
      exit(1)
 end-case

 public declarations
  frac: array(SHARES) of mpvar       ! Fraction of capital used per share
  Return, LimitRisk, LimitAM, TotalOne: linctr   ! Constraints
 end-declarations

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

! Limit the percentage of high-risk values
 LimitRisk:= sum(s in RISK) frac(s) <= MAXRISK

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

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

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

! Solve the problem through Xpress Insight
 insightmaximize(Return)

end-model

Note that we have removed all solution output from this model: we are going to use Xpress Insight for representing the results.

The app archive

Xpress Insight expects models to be provided in compiled form, that is, as BIM files—see Section BIM files on how to generate BIM files from the model source. Since Xpress Insight executes Mosel models in a distributed architecture (so, possibly not on the same machine from where the model file is input) we recommend to include any input data files used by the model in the Xpress Insight app archive. The app archive is a ZIP archive that contains the BIM file and the optional subdirectories model_resources (data files), client_resources (custom view definitions), and source (Mosel model source files). For our example, we create a ZIP archive folioinsight.zip with the file folioinsight.bim and the data file folio.dat in the subdirectory model_resources.

With Xpress Workbench, select the option 'Create and Insight project' at startup to create the directory structure expected by Insight and replace the template model, configuration, and data files by the files of your Mosel project. Then select the button Chap9/butarchive.png to create the app archive or Chap9/butdeploy.png to publish the app directly to Insight.

Working with the Xpress Insight Web Client

Open the Xpress Insight Web Client by directing your web browser to the Web Client entry page: with a default desktop installation of Xpress Insight this will be the page http://localhost:8860/insight

Chap9/xi48entry.png

Figure 10.3: Xpress Insight web client entry page

If you have currently loaded any apps in Insight these will show up on the Web Client entry page, otherwise this page only displays the 'Upload app' icon. We now upload the app archive folioinsightxml.zip that adds a VDL view definition file and an XML configuration file to the archive folioinsight.zip. The Mosel model has been extended with the array CtrSol to store some result and data values in a convenient format for display (note the use of annotation marker !@insight.manage that is required to inform Xpress Insight that these data are not input but result values):

 !@insight.manage=result
 public declarations
  CTRS: set of string                            ! Constraint names
  CTRINFO: set of string                         ! Constraint info type
  CtrSol: dynamic array(CTRS,CTRINFO) of real    ! Solution values
 end-declarations

! Save solution values for GUI display
 CtrSol::("Limit high risk shares", ["Activity","Lower limit","Upper limit"])
          [LimitRisk.act,0,MAXRISK]
 CtrSol::("Limit North-American", ["Activity","Lower limit","Upper limit"])
          [LimitAM.act,MINAM,1]
 forall(s in SHARES | frac(s).sol>0) do
  CtrSol("Limit per value: "+s,"Activity"):= frac(s).sol
  CtrSol("Limit per value: "+s,"Upper limit"):= MAXVAL
  CtrSol("Limit per value: "+s,"Lower limit"):= 0
 end-do

Optionally, we can also add annotations to individual declarations in order to configure the GUI display of model entities:

 public declarations
  SHARES: set of string              !@insight.alias Shares
  RET: array(SHARES) of real         !@insight.alias Estimated return in investment
  frac: array(SHARES) of mpvar       !@insight.alias Fraction used
  Return: linctr                     !@insight.alias Total return
  TotalOne: linctr                   !@insight.hidden true
 end-declarations

Once you have successfully loaded the app archive, the app 'Portfolio Optimization' will show up as a new icon:

Chap9/xi48entry2.png

Figure 10.4: Xpress Insight web client after loading the Portfolio app

Select the 'Portfolio Optimization' app icon to open the app.

Chap9/xi48proj.png

Figure 10.5: App entry page

Now click on the text Click here to select scenarios in the shelf to create a scenario. In the 'Scenario Explorer' window, select 'Scenario 1' and confirm with Close.

Chap9/xi48scen.png

Figure 10.6: Scenario creation in the Xpress Insight web client

Use the Load entry from the drop-down menu on the scenario name in the shelf to load the baseline data.

Chap9/xi48scen2.png

Figure 10.7: Scenario menu in the Xpress Insight web client

After loading the scenario the view display changes, showing the input data of our optimization model. You can edit these data by entering new values into the input fields or table cells. Use the Run button on the view or the corresponding entry in the scenario menu to run the model with the data shown on screen.

Chap9/xi48scen3.png

Figure 10.8: Display after scenario loading

After a successful model run the placeholder message no results available in the lower half of our view is replaced by the results display, as shown below.

Chap9/xi48scen4.png

Figure 10.9: VDL view with input and result data elements

You can create new scenarios from existing ones (selecting 'Clone' in the scenario menu) or with the original input data by selecting 'New scenario' in the Scenario Explorer window. The results of multiple scenarios can be displayed in a single view for comparison.

Chap9/xi48scencomp.png

Figure 10.10: VDL view comparing several scenarios

VDL

VDL (View Definition Language) is a markup language for the creation of views for Xpress Insight apps from a set of predefined components and built-in styling options. Optionally, VDL view definitions can be extended with HTML tags and Javascript code for further customization. The view 'Portfolio data' shown in Figure VDL view with input and result data elements is created entirely from the following VDL view definition (file folio.vdl in the subdirectory client_resources of the app archive). All data entities marked as 'editable' can be modified by the UI user.

<vdl version="4.0">
  <vdl-page class="compact">
  <!-- VDL header and 'page' must always be present;
       option compact: narrow spacing -->

    <!-- Structural element 'section': print header text for a section -->
    <vdl-section heading="Configuration">

      <!-- Structural element 'row': arrange contents in rows -->
      <vdl-row>
        <!-- Several columns within a 'row' for display side-by-side,
             dividing up the total row width of 12 via 'size' setting
             on each column. -->
        <vdl-column size="5">
          <!-- A form groups several input elements -->
          <vdl-form>
            <!-- Input fields for constraint limits -->
            <vdl-field parameter="MAXRISK" size="3" label-size="9"
              label="Maximum investment into high-risk values"/>
            <vdl-field parameter="MAXVAL" size="3" label-size="9"
              label=" Maximum investment per share"/>
            <vdl-field parameter="MINAM" size="3" label-size="9"
              label="Minimum investment into North-American values" />
            <!-- default sizes: 2 units each -->
          </vdl-form>
        </vdl-column>
        <vdl-column size="4">
          <!-- Display editable input values, default table format -->
          <vdl-table>
            <vdl-table-column entity="RET" editable="true"/>
          </autotable>
        </vdl-column>
        <vdl-column size="3">
          <vdl-form>
            <!-- 'Run' button to launch optimization -->
            <vdl-execute-button caption="Run optimization"/>
          </vdl-form>
        </vdl-column>
      </vdl-row>
    </vdl-section>

    <!-- Structural element 'section'; configuration options:
         display: with option 'none' nothing gets displayed by default
         if_results-available: display style will change to visible
           once result values become available (after model execution) -->
    <vdl-section heading="Results" class="if-results-available"
        style="display: none">

      <vdl-row>
        <!-- Display inline text element with the objective value -->
        Total expected return: &#163;<span
          vdl-text="=scenario.entities.Return.value" />
      </vdl-row>

      <vdl-row>
        <vdl-column size="4" heading="Portfolio composition">
          <!-- Display the 'frac' solution values, default table format -->
          <vdl-table>
            <vdl-table-column entity="frac" render="=formatRender">
            </vdl-table-column>
          </vdl-table>
        </vdl-column>
        <vdl-column size="1">
        </vdl-column>
        <vdl-column size="4">
          <!-- Display the 'frac' solution values as a pie chart -->
          <vdl-chart>
            <vdl-chart-series entity="frac" type="pie"></vdl-chart-series>
          </vdl-chart>
        </vdl-column>
      </vdl-row>
    </vdl-section>
  </vdl-page>
</vdl> 

VDL views need to be declared in an app archive via an XML configuration file (the so-called companion file). Both file types can be created and edited using the Workbench editor (select File » New From Template » VDL file or Companion file respectively). The following companion file definition integrates the VDL view folio.vdl and a second view 'Scenario comparison' into our example app folioinsightxml.zip.

<?xml version="1.0" encoding="iso-8859-1"?>
<model-companion version="3.0"
 xmlns="http://www.fico.com/xpress/optimization-modeler/model-companion" >
  <client>
    <view-group title="Main">
      <vdl-view title="Portfolio data" default="true" path="folio.vdl" />
      <vdl-view title="Scenario comparison" default="false" path="foliocompare.vdl"/>
    </view-group>
  </client>
</model-companion>