Initializing help system before first use

Usage Examples

Topics covered in this chapter:

Simple Model

This is a version of the 'chess2' example, modified to be an Xpress Insight app. It demonstrates how to write a model so that Xpress Insight can capture or inject the model's input data, depending upon the run mode, while still allowing the model developer to run the model from outside of Xpress Insight, e.g. from the Mosel command line.

model Chess2
 uses "mmxprs"                     ! Load the Xpress Optimizer
 uses "mminsight"                  ! Load the Insight interface

 public declarations
  ! Model inputs
  UnitTypes: set of string
  ResourceTypes: set of string

  ResourceLimits: array(ResourceTypes) of real
  ProfitPerUnit: array(UnitTypes) of real
  UnitResourceRequirements: array(UnitTypes,ResourceTypes) of real

  ! Mathematical model objects (providing model results)
  unitstobuild: array(UnitTypes) of mpvar
  ResourceLimitConstraints: array(ResourceTypes) of linctr
  MaxProfit: linctr
 end-declarations

 ! Procedure to populate model with initial input data
 procedure loaddata
  ProfitPerUnit:: (["small","large"])[5,20]
  UnitResourceRequirements:: (["small"],["wood","mc_time"]) [1,3]
  UnitResourceRequirements:: (["large"],["wood","mc_time"]) [3,2]
  ResourceLimits:: (["wood","mc_time"])[200,400]

  finalize( UnitTypes )
  finalize( ResourceTypes )
 end-procedure

 ! Procedure to build and solve optimization problem
 procedure solvemodel
  ! Build whole units only
  forall(u in UnitTypes) unitstobuild(u) is_integer

  ! Define profit
  MaxProfit:= sum(u in UnitTypes) ProfitPerUnit(u)*unitstobuild(u)

  ! Don't use more than available resources
  forall(r in ResourceTypes)
   ResourceLimitConstraints(r) := ( sum(u in UnitTypes)
    UnitResourceRequirements(u,r)*unitstobuild(u) ) <= ResourceLimits(r)

  ! Solve the mixed integer problem
  insightmaximize(MaxProfit)

  ! Print the solution to the run log
  writeln("Solution:\n Objective: ", getobjval)
  forall(u in UnitTypes)
   writeln(u, ":", unitstobuild(u).sol)
 end-procedure

 ! Define actions to perform in 'load' execution mode
 !@insight.execmodes.LOAD
 public procedure doload
  ! Scenario is being 'loaded' through Xpress Insight
  ! Initialize input arrays and then terminate
  loaddata
 end-procedure

 ! Define actions to perform in 'run' execution mode
 !@insight.execmodes.RUN
 public procedure dorun
  ! Scenario is being 'run' through Xpress Insight
  ! Populate with Insight scenario data and then solve optimization
  insightpopulate
  solvemodel
 end-procedure

 ! Define actions to perform when model is run standalone (without Xpress Insight)
 !@insight.execmodes.NONE
 public procedure doloadandrun
  ! Model is being run outside of Xpress Insight, e.g. from the Mosel command-line tool
  ! Initialize input arrays then solve optimization
  loaddata
  solvemodel
 end-procedure

 ! Automatically call the procedure with annotation matching the current execution mode
 insightdispatch
end-model

Insight will by default manage all public entities of supported types in the scenario, with entities storing linctr and mpvar values in the result data and all others in the input, but you can change this by adding annotations as described in section Annotations.

Annotations

The handling of model (schema) entities by Insight and certain global settings such as execution modes are configured via annotations to the Mosel model. The following Mosel model extract shows some examples of annotation definitions.

 !@insight.manage=input
 public declarations        ! All entities declared here are managed as input
  !@insight.alias City Names
  !@insight.descr Set of all cities
  Cities: set of string
  TrafficLevels: array(Cities,Cities) of real
 end-declarations

 !@insight.manage result    ! All entities declared here are managed as results
 public declarations
  routetaken: array(Cities,Cities) of mpvar
 end-declarations

 ! Data structures used internally in the model
 !@insight.manage ignore    ! All entities declared here are not managed by Insight
 declarations
  Distances: array(Cities,Cities) of real
 end-declarations

 ! The 'insight.execmodes' annotations would normally immediately precede the subroutines
 ! that implement the execution mode.

 ! Define an execution mode 'analyzedata'

 (!@insight.execmodes.analyzedata.
   @descr Analyzing input data
   @clearinput false
  !)
 public procedure doanalyze
  loaddata
  analyzedata
 end-procedure

 !@insight.execmodes.LOAD
 public procedure doload
  loaddata
 end-procedure

Accessing Attachments

As described in the Developer Guide, Xpress Insight allows files to be attached to an app or scenario. While the model is running within Xpress Insight, the Mosel interface will allow you to query, read and edit attachments of the scenario being run, as well as query and read (but not edit) attachments of the app to which that scenario belongs.

To demonstrate the use of an app and scenario attachments, in this example we have a Distances array that we want to populate with distances between cities. As this data will not change, it would be very wasteful to store a copy of these in every scenario of the app, so we store them in a file distances.dat which is attached to the app. In the example, we call insightgetappattach to copy this file to the working directory and then populate the Distances array from this. (The Distances array is annotated as ignored by Xpress Insight, so it will not be part of the Insight scenario data model.)

To demonstrate the use of scenario attachments, we then save the model's results to a file decorated with today's date, and attach this file to the current scenario.

model RoutePlanner
 uses "mmxprs"                     ! Load the Xpress Optimizer
 uses "mminsight"                  ! Load the Insight interface

 ! Input data - stored in Insight scenario
 !@insight.manage input
 public declarations
  EvaluationDate: string
  Cities: set of string
  TrafficLevels: array(Cities,Cities) of real
 end-declarations

 ! Result data - stored in Insight scenario
 !@insight.manage result
 public declarations
  routetaken: array(Cities,Cities) of mpvar
 end-declarations

 ! Data structures used internally in the model
 !@insight.manage ignore
 declarations
  Distances: array(Cities,Cities) of real
 end-declarations

 ! Procedure to build and solve optimization problem
 procedure runproblem
  ! Download app attachment
  if insightgetmode <> INSIGHT_MODE_NONE then
   ! Model is running within Insight, so download distances.dat from Insight server
   insightgetappattach("distances.dat")
   if insightattachstatus<>INSIGHT_ATTACH_OK then
    writeln_("Failed to download app attachment")
    exit(1)
   end-if
  else
   ! Model is running outside of Insight, attachments are not accessible
   ! so copy from some other location
   fcopy( '/Users/me/myfiles/distances.dat', 'distances.dat' )
  end-if
  ! Load into model
  initializations from "distances.dat"
   Distances
  end-initializations

  ! Perform optimization
  buildproblem
  optimizeproblem

  ! Capture results to file
  ROUTES_FNAME := "result-"+EvaluationDate+".dat"
  fopen(ROUTES_FNAME,F_OUTPUT)
  forall (s in Cities, d in Cities | routetaken(s,d).sol=1)
   writeln(s,"->",d)
  fclose(F_OUTPUT)

  ! Store as scenario attachment
  if insightgetmode <> INSIGHT_MODE_NONE then
   ! Model is running within Insight, so upload distances.dat to Insight server
   insightputscenattach(ROUTES_FNAME)
   if insightattachstatus<>INSIGHT_ATTACH_OK then
    writeln_("Failed to upload scenario attachment")
    exit(1)
   end-if
  end-if
 end-procedure

 !@insight.execmodes.LOAD
 public procedure doload
  loaddata
 end-procedure

 !@insight.execmodes.RUN
 public procedure dorun
  insightpopulate
  runproblem
 end-procedure

 !@insight.execmodes.NONE
 public procedure doloadandrun
  loaddata
  runproblem
 end-procedure

 insightdispatch

end-model

For clarity, the implementation of the loaddata, buildproblem and optimizeproblem procedures have been omitted from the example.

Inter-Scenario Data Access

You can also initialize your data structures with values from external scenarios using the mminsight.scenariodata I/O driver with a standard Mosel initializations-from block. For example, the following model initializes the array "Distances" from an array called "CityDrivingDistances" in a scenario "USDrivingDistances" in an app named "DrivingDistancesModel"

model RoutePlanner
 uses "mmxprs"                     ! Load the Xpress Optimizer
 uses "mminsight"                  ! Load the Insight interface

 ! Input data - stored in Insight scenario
 !@insight.manage input
 public declarations
  Cities: set of string
  TrafficLevels: array(Cities,Cities) of real
 end-declarations

 ! Result data - stored in Insight scenario
 !@insight.manage result
 public declarations
  routetaken: array(Cities,Cities) of mpvar
 end-declarations

 ! Data structures used internally in the model
 !@insight.manage ignore
 declarations
  Distances: array(Cities,Cities) of real
 end-declarations

 ! Procedure to build and solve optimization problem
 procedure runproblem
  ! Populate 'Distances' array
  if insightgetmode <> INSIGHT_MODE_NONE then
   ! Populate 'Distances' array from the remote scenario
   initializations from "mminsight.scenariodata:/DrivingDistancesModel/USDrivingDistances"
    Distances as "CityDrivingDistances"
   end-initializations
  else
   ! Model is running outside of Insight, so populate driving distances from local file
   initializations from "/Users/me/myfiles/distances.dat"
    Distances
   end-initializations
  end-if

  ! Perform optimization
  buildproblem
  optimizeproblem
 end-procedure

 !@insight.execmodes.LOAD
 public procedure doload
  loaddata
 end-procedure

 !@insight.execmodes.RUN
 public procedure dorun
  insightpopulate
  runproblem
 end-procedure

 !@insight.execmodes.NONE
 public procedure doloadandrun
  loaddata
  runproblem
 end-procedure

 insightdispatch

end-model

For clarity, the implementation of the loaddata, buildproblem and optimizeproblem procedures have been omitted from the example.

Type Marshalling

The Insight schema will usually contain entities of basic types (boolean, integer, real and string), and sets and arrays of these. The type marshalling features allow values of external types (types added to Mosel by modules such as mmsystem) to be stored as strings in the Insight schema. Type marshalling can be enabled globally for a type, e.g.:

 !@insight.marshal.type datetime string
 ! All values of type datetime will be represented by string in the Insight schema

 !@insight.manage input
 public declarations
  today: datetime
  ! will be treated as 'string' in Insight schema

  AllDatesIn2000: set of constant datetime
  ! will be treated as 'set of string' in Insight schema

  Birthdays: array(set of string) of datetime
  ! will be treated as 'array of string' in Insight schema

  now: time
  ! will not be in Insight schema; no annotation for type 'time'
 end-declarations

Or for individual entities, e.g.:

!@insight.manage input
 public declarations
  !@insight.marshal.value string
  today: datetime
  ! will be treated as 'string' in Insight schema

  !@insight.marshal.value string
  AllDatesIn2000: set of constant datetime
  ! will be treated as 'set of string' in Insight schema

  !@insight.marshal.value string
  Birthdays: array(set of string) of datetime
  ! will be treated as 'array of string' in Insight schema

  yesterday: datetime
  ! will not be in Insight schema; no marshalling annotation for this entity
 end-declarations

When applying the type marshalling to a set or array, the conversion will be applied to the values within the collection, not the collection itself (e.g. 'set of datetime' becomes 'set of string', not a scalar 'string' concatenating everything within the set.

The type marshalling annotations can be applied to any module type that supports conversion to and from string. In the standard Xpress installation, these are the types to which the annotation can be applied:

  • date
  • datetime
  • text
  • time

There are a few restrictions on using either type marshalling annotation:

  • Marshalling can only be applied to module types as described above - not records, lists or nested types such as 'set of set of string'.
  • When used with a set, the set must be declared set of constant to ensure it cannot contain duplicate values.
  • For date/time/datetime types, the default string format will always be used, ignoring the datefmt, timefmt and datetimefmt parameters.
  • Trying to marshal a native type that does not support conversion both to and from string will result in an error when running the scenario, not when loading the app into Insight.

Partial Execution Modes

By default, a non-LOAD execution mode will populate all the input entities and then capture all the result (and update-after-execution) entities at the end of the model. But an execution mode can choose to read or capture just some of the entities - for example, if your scenario has some big arrays but your execution mode just edits a couple of scalars, you can choose to just populate and capture those scalars and avoid the overhead of reading the array into memory.

To select which entities to populate at the start of your execution mode, just pass a list or set of the names to the insightpopulate subroutine, e.g.:

 !@insight.manage input
 public declarations
   UserIDs: set of integer
   UserNames: dynamic array(UserIDs) of string
   UserEmails: dynamic array(UserIDs) of string
   UserAges: dynamic array(UserIDs) of integer
 end-declarations

 !@insight.execmodes.LOAD
 public procedure doload
  insightpopulate(['UserNames', 'UserEmails'])

  ! Log out the user names and emails
  forall (id in UserIDs) do
    writeln('User #', id, ': ', UserNames[id], ' (', UserEmails[id], ')')
  end-do

  ! UserAges array will not have been populated
  assert(UserAges.size=0)
 end-procedure

To select which entities to capture at the end of the execution mode, pass a list of the entity names to the insightcapture procedure, e.g.:

 !@insight.manage input
 public declarations
   input_scalar: integer

   !@insight.update.afterexecution true
   updateable_scalar: integer
 end-declarations

 !@insight.manage result
 public declarations
   result_scalar1, result_scalar2: integer
 end-declarations

 !@insight.execmodes.RUN
 public procedure dorun
  insightpopulate

  ! Do calculations here
  updateable_scalar := updateable_scalar + 1
  result_scalar1 := input_scalar * 2

  ! Capture updated values of updateable_scalar and result_scalar1 but not result_scalar2
  insightcapture(['updateable_scalar', 'result_scalar1'])
 end-procedure

If you call this subroutine, then entities not in this list will not be updated in the Insight scenario - this includes entities annotated insight.update.afterexecution true.

Index sets of arrays will be populated or captured automatically if the array name appears in the list passed to insightpopulate or insightcapture - there is no need to list these explicitly (although it is not an error to include them).


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