Initializing help system before first use

Folio - Advanced modelling and solving tasks


Type: Portfolio optimization
Rating: 3 (intermediate)
Description: Advanced modelling and solving tasks for a portfolio optimization problem:
  • Defining an integer solution callback (foliocb.mos)
  • Using the solution enumerator for multiple MIP solutions (folioenumsol.mos)
  • Handling infeasibility
    • handling infeasibility through deviation variables (folioinfeas.mos)
    • retrieving infeasible row/column from presolve (folioinfcause.mos)
    • retrieving IIS - LP or MIP infeasible (folioiis.mos, foliomiis.mos)
    • using the built-in infeasibility repair functionality (foliorep.mos)
    • same as foliorep, using an 'mpsol' object (foliorep_sol.mos)
  • Data transfer in memory
    • running foliomemio.mos with data transfer in memory (runfolio.mos)
    • same running foliomemio2.mos, grouping tables with identical index sets in "initializations" blocks (runfolio2.mos)
    • master model running several model instances in parallel (runfoliopar.mos)
  • Remote models on a distributed architecture
    • running foliomemio.mos on a remote instance of Mosel (runfoliodistr.mos)
    • master model running several model instances in parallel, each on a different (remote) instance of Mosel (runfoliopardistr.mos)
  • Remote execution via XPRD
    • See examples in the Mosel Whitepapers directory moselpar/XPRD
  • XML and JSON data formats
    • reading data from an XML file, solution output in XML format on screen and to a new file (folioxml.mos, folioxmlqp.mos)
    • generate HTML output file as an XML document (runfolioxml.mos)
    • using JSON-format data files, reading data from a JSON file, solution output in JSON format on screen and to a new file (foliojson.mos)
  • HTTP
    • starting an HTTP server managing requests from HTTP clients (foliohttpsrv.mos)
    • HTTP client exchanging XML data files with an HTTP server (foliohttpclient.mos)
File(s): foliomip3.mos, foliomemio.mos, foliomemio2.mos, foliocbio.mos, foliocb.mos, folioenumsol.mos, folioinfeas.mos, folioinfcause.mos, folioiis.mos, foliomiis.mos, foliorep.mos, foliorep_sol.mos, runfolio.mos, runfolio2.mos, runfoliopar.mos, runfoliodistr.mos, runfoliopardistr.mos, folioxml.mos, folioxmlqp.mos, runfolioxml.mos, foliojson.mos, foliohttpsrv.mos, foliohttpclient.mos
Data file(s): folio5.dat, folio10.dat, folio250.dat, folio.xml, folioqp.xml, folioqpvar.xml, folio.json


foliomip3.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file foliomip3.mos
   ``````````````````
   Modeling a MIP problem 
   to perform portfolio optimization.
   -- Extending the problem with constraints on 
      the geographical and sectorial distributions --
   -- Working with a larger data set --
   
  (c) 2008 Fair Isaac Corporation
      author: S.Heipcke, Dec. 2008
*******************************************************!)

model "Portfolio optimization with MIP"
 uses "mmxprs"

 parameters
  MAXRISK = 1/3                     ! Max. investment into high-risk values
  MINREG = 0.2                      ! Min. investment per geogr. region
  MAXREG = 0.5                      ! Max. investment per geogr. region
  MAXSEC = 0.25                     ! Max. investment per ind. sector
  MAXVAL = 0.2                      ! Max. investment per share
  MINVAL = 0.1                      ! Min. investment per share
  MAXNUM = 7                        ! Max. number of different assets
                                    ! 6,7: difficult, 4: infeas, 5,8+:easy  
  DATAFILE = "folio250.dat"         ! File with problem data
 end-parameters

 declarations
  SHARES: set of string              ! Set of shares
  RISK: set of string                ! Set of high-risk values among shares
  REGIONS: set of string             ! Geographical regions
  TYPES: set of string               ! Share types (ind. sectors)

  LOC: array(REGIONS) of set of string ! Sets of shares per geogr. region
  RET: array(SHARES) of real         ! Estimated return in investment
  SEC: array(TYPES) of set of string ! Sets of shares per industry sector
 end-declarations

 initializations from DATAFILE
  RISK RET LOC SEC
 end-initializations

 declarations
  frac: array(SHARES) of mpvar      ! Fraction of capital used per share
  buy: array(SHARES) of mpvar       ! 1 if asset is in portfolio, 0 otherwise
 end-declarations

! 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) <= MAXRISK

! Limits on geographical distribution
 forall(r in REGIONS) do
  sum(s in LOC(r)) frac(s) >= MINREG
  sum(s in LOC(r)) frac(s) <= MAXREG
 end-do 

! Diversification across industry sectors
 forall(t in TYPES) sum(s in SEC(t)) frac(s) <= MAXSEC

! Spend all the capital
 sum(s in SHARES) frac(s) = 1
 
! Upper bounds on the investment per share
 forall(s in SHARES) frac(s) <= MAXVAL

! Limit the total number of assets
 sum(s in SHARES) buy(s) <= MAXNUM

 forall(s in SHARES) do
  buy(s) is_binary                  ! Turn variables into binaries
  frac(s) <= MAXVAL*buy(s)                 ! Linking the variables
  frac(s) >= MINVAL*buy(s)                 ! Linking the variables
 end-do

! Display Optimizer log
 setparam("XPRS_verbose", true)

! Solve the problem
 maximize(Return)

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

end-model 

foliomemio.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file foliomemio.mos
   ```````````````````
   Modeling a MIP problem 
   to perform portfolio optimization.

   Same model as in foliomip3.mos with
   simplified data structures (replaced arrays of structured types).
   -- Data input/output in memory --
   
   Run modes for this model:
   1. Stand-alone: data I/O to text files
      (run this model from Workbench or from Mosel command line) 
   2. Submodel to another Mosel model: data exchange in memory
      (run model 'runfolio.mos' or 'runfoliopar.mos' to execute this model)
   3a. C: I/O to C program runfolio.c or runfoliod.c
      (compile and run C program 'runfolio.c' or 'runfoliod.c')
   3b. Java: I/O to Java program runfolio.java, runfoliob.java, or
      runfoliod.java
      (compile and run Java program 'runfolio.java', 'runfoliob.java',
      or 'runfoliod.java')
   3c. (Windows only) C#: I/O to C# program runfolio.cs or runfoliob.cs
      (compile and run C# program 'runfolio.cs' or 'runfoliob.cs')
   4. Remote execution from another Mosel model: 
      (run model 'runfoliodistr.mos' or 'runfoliopardistr.mos' to execute 
      this model)   
   5a. Remote execution from C: I/O to C program distfolio.c or distfoliopar.c
      (compile and run C program 'distfolio.c' or 'distfoliopar.c')
   5b. Remote execution from Java: I/O to Java program distfolio.java or
      distfoliopar.java
      (compile and run Java program 'distfolio.java' or 'distfoliopar.java')
   
  (c) 2009 Fair Isaac Corporation
      author: S.Heipcke, Jan. 2009, rev. Oct 2012
*******************************************************!)

model "Portfolio optimization with MIP"
 uses "mmxprs"

 parameters
  MAXRISK = 1/3                      ! Max. investment into high-risk values
  MINREG = 0.2                       ! Min. investment per geogr. region
  MAXREG = 0.5                       ! Max. investment per geogr. region
  MAXSEC = 0.25                      ! Max. investment per ind. sector
  MAXVAL = 0.2                       ! Max. investment per share
  MINVAL = 0.1                       ! Min. investment per share
  MAXNUM = 15                        ! Max. number of different assets

  DATAFILE = "folio10.dat"           ! File with problem data
  OUTPUTFILE = "sol10out.dat"        ! File for solution output
  RISKDATA = "RISK"                  ! Locations of input data
  RETDATA = "RET"
  LOCDATA = "LOCTAB"
  SECDATA = "SECTAB"
  FRACSOL = "FRAC"                   ! Locations for solution output
  BUYSOL = "BUY"
  NUMSHARES = "NUMSHARES"
  RETSOL = "RETSOL"
  SOLSTATUS = "SOLSTATUS"
 end-parameters

 declarations
  SHARES,S: set of string            ! Set of shares
  RISK: set of string                ! Set of high-risk values among shares
  REGIONS: set of string             ! Geographical regions
  TYPES: set of string               ! Share types (ind. sectors)
  LOCTAB: dynamic array(REGIONS,SHARES) of boolean ! Shares per geogr. region
  RET: array(SHARES) of real         ! Estimated return in investment
  SECTAB: dynamic array(TYPES,SHARES) of boolean ! Shares per industry sector
 end-declarations

 initializations from DATAFILE
  RISK as RISKDATA
  RET as RETDATA
  LOCTAB as LOCDATA
  SECTAB as SECDATA
 end-initializations

 declarations
  frac: array(SHARES) of mpvar      ! Fraction of capital used per share
  buy: array(SHARES) of mpvar       ! 1 if asset is in portfolio, 0 otherwise
 end-declarations

! 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) <= MAXRISK

! Limits on geographical distribution
 forall(r in REGIONS) do
  sum(s in SHARES | exists(LOCTAB(r,s))) frac(s) >= MINREG
  sum(s in SHARES | exists(LOCTAB(r,s))) frac(s) <= MAXREG
 end-do 

! Diversification across industry sectors
 forall(t in TYPES) sum(s in SHARES | exists(SECTAB(t,s))) frac(s) <= MAXSEC

! Spend all the capital
 sum(s in SHARES) frac(s) = 1
 
! Upper bounds on the investment per share
 forall(s in SHARES) frac(s) <= MAXVAL

! Limit the total number of assets
 sum(s in SHARES) buy(s) <= MAXNUM

 forall(s in SHARES) do
  buy(s) is_binary                  ! Turn variables into binaries
  frac(s) <= MAXVAL*buy(s)                 ! Linking the variables
  frac(s) >= MINVAL*buy(s)                 ! Linking the variables
 end-do


! Display Optimizer log
 setparam("XPRS_verbose", true)

! Solve the problem
 maximize(Return)


! Adapt Mosel comparison tolerance to Optimizer feasibility tolerance
 setparam("zerotol", getparam("XPRS_feastol")/10)

! Solution output
 function getvalues(v: array(SHARES) of mpvar): array(S) of real
  forall(s in SHARES | v(s).sol<>0) returned(s):= v(s).sol  
 end-function
 
 initializations to OUTPUTFILE
  evaluation of Return.sol as RETSOL
  evaluation of sum(s in SHARES | buy(s).sol<>0) 1 as NUMSHARES
  evaluation of getvalues(frac) as FRACSOL
  evaluation of getvalues(buy) as BUYSOL
  evaluation of getprobstat as SOLSTATUS
 end-initializations

end-model 

foliomemio2.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file foliomemio2.mos
   ````````````````````
   Modeling a MIP problem 
   to perform portfolio optimization.

   Same model as in foliomip3.mos with
   simplified data structures (replaced arrays of structured types).
   -- Data input/output in memory --
   -- Grouping arrays with identical index sets --
   
   Run modes for this model:
   1. Stand-alone: data I/O to text files
      (run this model from Workbench or from Mosel command line) 
   2. Submodel to another Mosel model: data exchange in memory
      (run model 'runfolio2.mos' to execute this model)
   3a. C: I/O to C program folio2.c
      (compile and run C program 'folio2.c')
   3b. Java: I/O to Java program folio2.java
      (compile and run Java program 'folio2.java')
   3c. C# (Windows only): I/O to C# program folio2.cs
      (compile and run C# program 'folio2.cs')
  
  (c) 2009 Fair Isaac Corporation
      author: S.Heipcke, Feb. 2009, rev. Oct 2012
*******************************************************!)

model "Portfolio optimization with MIP"
 uses "mmxprs"

 parameters
  MAXRISK = 1/3                      ! Max. investment into high-risk values
  MINREG = 0.2                       ! Min. investment per geogr. region
  MAXREG = 0.5                       ! Max. investment per geogr. region
  MAXSEC = 0.25                      ! Max. investment per ind. sector
  MAXVAL = 0.2                       ! Max. investment per share
  MINVAL = 0.1                       ! Min. investment per share
  MAXNUM = 15                        ! Max. number of different assets

  DATAFILE = "folio10.dat"           ! File with problem data
  OUTPUTFILE = "sol10out.dat"        ! File for solution output
  RISKDATA = "RISK"                  ! Locations of input data
  RETDATA = "RET"
  LOCDATA = "LOCTAB"
  SECDATA = "SECTAB"
  FRACBUYSOL = "FRACBUY"             ! Locations for solution output
  NUMSHARES = "NUMSHARES"
  RETSOL = "RETSOL"
  SOLSTATUS = "SOLSTATUS"
 end-parameters

 declarations
  SHARES,S: set of string            ! Set of shares
  RISK: set of string                ! Set of high-risk values among shares
  REGIONS: set of string             ! Geographical regions
  TYPES: set of string               ! Share types (ind. sectors)
  LOCTAB: dynamic array(REGIONS,SHARES) of boolean ! Shares per geogr. region
  RET: array(SHARES) of real         ! Estimated return in investment
  SECTAB: dynamic array(TYPES,SHARES) of boolean ! Shares per industry sector
 end-declarations

 initializations from DATAFILE
  RISK as RISKDATA
  RET as RETDATA
  LOCTAB as LOCDATA
  SECTAB as SECDATA
 end-initializations

 declarations
  frac: array(SHARES) of mpvar      ! Fraction of capital used per share
  buy: array(SHARES) of mpvar       ! 1 if asset is in portfolio, 0 otherwise
 end-declarations

! 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) <= MAXRISK

! Limits on geographical distribution
 forall(r in REGIONS) do
  sum(s in SHARES | exists(LOCTAB(r,s))) frac(s) >= MINREG
  sum(s in SHARES | exists(LOCTAB(r,s))) frac(s) <= MAXREG
 end-do 

! Diversification across industry sectors
 forall(t in TYPES) sum(s in SHARES | exists(SECTAB(t,s))) frac(s) <= MAXSEC

! Spend all the capital
 sum(s in SHARES) frac(s) = 1
 
! Upper bounds on the investment per share
 forall(s in SHARES) frac(s) <= MAXVAL

! Limit the total number of assets
 sum(s in SHARES) buy(s) <= MAXNUM

 forall(s in SHARES) do
  buy(s) is_binary                  ! Turn variables into binaries
  frac(s) <= MAXVAL*buy(s)                 ! Linking the variables
  frac(s) >= MINVAL*buy(s)                 ! Linking the variables
 end-do


! Display Optimizer log
 setparam("XPRS_verbose", true)

! Solve the problem
 maximize(Return)


! Adapt Mosel comparison tolerance to Optimizer feasibility tolerance
 setparam("zerotol", getparam("XPRS_feastol")/10)

! Solution output
 function getvalues(v: array(SHARES) of mpvar): array(S) of real
  forall(s in SHARES | v(s).sol<>0) returned(s):= v(s).sol  
 end-function
 
 initializations to OUTPUTFILE
  evaluation of Return.sol as RETSOL
  evaluation of sum(s in SHARES | buy(s).sol<>0) 1 as NUMSHARES
  [evaluation of getvalues(frac) , evaluation of getvalues(buy)] as FRACBUYSOL
  evaluation of getprobstat as SOLSTATUS
 end-initializations

end-model 

foliocbio.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file foliocbio.mos
   ``````````````````
   Modeling a MIP problem 
   to perform portfolio optimization.

   Same model as in foliomip3.mos.
   -- Defining an integer solution callback 
      to write out solution information to external program --
   
  (c) 2011 Fair Isaac Corporation
      author: S.Heipcke, July 2011, rev. Oct. 2012
*******************************************************!)

model "Portfolio optimization with MIP"
 uses "mmxprs"
 uses "mmjobs"

 parameters
  MAXRISK = 1/3                     ! Max. investment into high-risk values
  MINREG = 0.2                      ! Min. investment per geogr. region
  MAXREG = 0.5                      ! Max. investment per geogr. region
  MAXSEC = 0.25                     ! Max. investment per ind. sector
  MAXVAL = 0.2                      ! Max. investment per share
  MINVAL = 0.1                      ! Min. investment per share
  MAXNUM = 15                       ! Max. number of different assets
  DATAFILE = "folio250.dat"         ! File with problem data
  OUTPUTFILE = "sol10out.dat"       ! File for solution output
  FRACSOL = "FRAC"                  ! Locations for solution output
  BUYSOL = "BUY"
  NUMSHARES = "NUMSHARES"
  RETSOL = "RETSOL"
  SOLCOUNT = "SOLCOUNT"
 end-parameters

 forward procedure print_sol

 declarations
  SHARES,S: set of string            ! Set of shares
  RISK: set of string                ! Set of high-risk values among shares
  REGIONS: set of string             ! Geographical regions
  TYPES: set of string               ! Share types (ind. sectors)
  LOC: array(REGIONS) of set of string ! Sets of shares per geogr. region
  RET: array(SHARES) of real         ! Estimated return in investment
  SEC: array(TYPES) of set of string ! Sets of shares per industry sector
 end-declarations

 initializations from DATAFILE
  RISK RET LOC SEC
 end-initializations

 declarations
  frac: array(SHARES) of mpvar      ! Fraction of capital used per share
  buy: array(SHARES) of mpvar       ! 1 if asset is in portfolio, 0 otherwise
 end-declarations

! 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) <= MAXRISK

! Limits on geographical distribution
 forall(r in REGIONS) do
  sum(s in LOC(r)) frac(s) >= MINREG
  sum(s in LOC(r)) frac(s) <= MAXREG
 end-do 

! Diversification across industry sectors
 forall(t in TYPES) sum(s in SEC(t)) frac(s) <= MAXSEC

! Spend all the capital
 sum(s in SHARES) frac(s) = 1
 
! Upper bounds on the investment per share
 forall(s in SHARES) frac(s) <= MAXVAL

! Limit the total number of assets
 sum(s in SHARES) buy(s) <= MAXNUM

 forall(s in SHARES) do
  buy(s) is_binary                  ! Turn variables into binaries
  frac(s) <= MAXVAL*buy(s)                 ! Linking the variables
  frac(s) >= MINVAL*buy(s)                 ! Linking the variables
 end-do


! Display Optimizer log
 setparam("XPRS_verbose", true)

! Adapt Mosel comparison tolerance to Optimizer feasibility tolerance
 setparam("zerotol", getparam("XPRS_feastol")/10)

! Set a MIP solution callback
 setcallback(XPRS_CB_INTSOL, "print_sol")

! Solve the problem
 maximize(Return)

 if getprobstat <> XPRS_OPT then exit(1); end-if 


!******** Solution output********

!**** Auxiliary function creating an array of solution values ****
 function getvalues(v: array(SHARES) of mpvar): array(S) of real
  forall(s in SHARES | v(s).sol<>0) returned(s):= v(s).sol  
 end-function


!**** Definition of the MIP solution callback function ****
 public procedure print_sol
  initializations to OUTPUTFILE
   evaluation of getparam("XPRS_MIPSOLS") as SOLCOUNT
   evaluation of sum(s in SHARES | buy(s).sol<>0) 1 as NUMSHARES
   evaluation of getsol(Return) as RETSOL
   evaluation of getvalues(frac) as FRACSOL
   evaluation of getvalues(buy) as BUYSOL
  end-initializations
 end-procedure

end-model 

foliocb.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file foliocb.mos
   ````````````````
   Modeling a MIP problem 
   to perform portfolio optimization.

   Same model as in foliomip3.mos.
   -- Defining an integer solution callback --
   
  (c) 2008 Fair Isaac Corporation
      author: S.Heipcke, Dec. 2008
*******************************************************!)

model "Portfolio optimization with MIP"
 uses "mmxprs"

 parameters
  MAXRISK = 1/3                     ! Max. investment into high-risk values
  MINREG = 0.2                      ! Min. investment per geogr. region
  MAXREG = 0.5                      ! Max. investment per geogr. region
  MAXSEC = 0.25                     ! Max. investment per ind. sector
  MAXVAL = 0.2                      ! Max. investment per share
  MINVAL = 0.1                      ! Min. investment per share
  MAXNUM = 15                       ! Max. number of different assets
  DATAFILE = "folio250.dat"         ! File with problem data
 end-parameters

 forward procedure print_sol

 declarations
  SHARES: set of string              ! Set of shares
  RISK: set of string                ! Set of high-risk values among shares
  REGIONS: set of string             ! Geographical regions
  TYPES: set of string               ! Share types (ind. sectors)
  LOC: array(REGIONS) of set of string ! Sets of shares per geogr. region
  RET: array(SHARES) of real         ! Estimated return in investment
  SEC: array(TYPES) of set of string ! Sets of shares per industry sector
 end-declarations

 initializations from DATAFILE
  RISK RET LOC SEC
 end-initializations

 declarations
  frac: array(SHARES) of mpvar      ! Fraction of capital used per share
  buy: array(SHARES) of mpvar       ! 1 if asset is in portfolio, 0 otherwise
 end-declarations

! 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) <= MAXRISK

! Limits on geographical distribution
 forall(r in REGIONS) do
  sum(s in LOC(r)) frac(s) >= MINREG
  sum(s in LOC(r)) frac(s) <= MAXREG
 end-do 

! Diversification across industry sectors
 forall(t in TYPES) sum(s in SEC(t)) frac(s) <= MAXSEC

! Spend all the capital
 sum(s in SHARES) frac(s) = 1
 
! Upper bounds on the investment per share
 forall(s in SHARES) frac(s) <= MAXVAL

! Limit the total number of assets
 sum(s in SHARES) buy(s) <= MAXNUM

 forall(s in SHARES) do
  buy(s) is_binary                  ! Turn variables into binaries
  frac(s) <= MAXVAL*buy(s)                 ! Linking the variables
  frac(s) >= MINVAL*buy(s)                 ! Linking the variables
 end-do


! Display Optimizer log
 setparam("XPRS_verbose", true)

! Set a MIP solution callback
 setcallback(XPRS_CB_INTSOL, "print_sol")

! Solve the problem
 maximize(Return)


! Solution printing
 procedure print_sol
  writeln("Solution ", getparam("XPRS_MIPSOLS"))
          ! Attention: 'getobjval' cannot be used during the optimization run
!  writeln("Total return: ", getparam("XPRS_MIPOBJVAL"))
  writeln("Total return: ", getsol(Return))
  forall(s in SHARES | getsol(frac(s))>0)
   writeln(s, ": ", getsol(frac(s))*100, "% (", getsol(buy(s)), ")")
 end-procedure
end-model 

folioenumsol.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file folioenumsol.mos
   `````````````````````
   Modeling a MIP problem 
   to perform portfolio optimization.
   
   Same model as in foliomip3.mos.
   -- Using the solution enumerator --
   
  (c) 2008 Fair Isaac Corporation
      author: S.Heipcke, Dec. 2008, rev. Jan. 2013
*******************************************************!)

model "Portfolio optimization with MIP"
 uses "mmxprs"

 parameters
  MAXRISK = 1/3                     ! Max. investment into high-risk values
  MINREG = 0.2                      ! Min. investment per geogr. region
  MAXREG = 0.5                      ! Max. investment per geogr. region
  MAXSEC = 0.25                     ! Max. investment per ind. sector
  MAXVAL = 0.2                      ! Max. investment per share
  MINVAL = 0.1                      ! Min. investment per share
  MAXNUM = 7                        ! Max. number of different assets
  DATAFILE = "folio10.dat"          ! File with problem data
 end-parameters

 forward procedure print_sol

 declarations
  SHARES: set of string              ! Set of shares
  RISK: set of string                ! Set of high-risk values among shares
  REGIONS: set of string             ! Geographical regions
  TYPES: set of string               ! Share types (ind. sectors)
  LOC: array(REGIONS) of set of string ! Sets of shares per geogr. region
  RET: array(SHARES) of real         ! Estimated return in investment
  SEC: array(TYPES) of set of string ! Sets of shares per industry sector
 end-declarations

 initializations from DATAFILE
  RISK RET LOC SEC
 end-initializations

 declarations
  frac: array(SHARES) of mpvar      ! Fraction of capital used per share
  buy: array(SHARES) of mpvar       ! 1 if asset is in portfolio, 0 otherwise
 end-declarations

! 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) <= MAXRISK

! Limits on geographical distribution
 forall(r in REGIONS) do
  sum(s in LOC(r)) frac(s) >= MINREG
  sum(s in LOC(r)) frac(s) <= MAXREG
 end-do 

! Diversification across industry sectors
 forall(t in TYPES) sum(s in SEC(t)) frac(s) <= MAXSEC

! Spend all the capital
 sum(s in SHARES) frac(s) = 1
 
! Upper bounds on the investment per share
 forall(s in SHARES) frac(s) <= MAXVAL

! Limit the total number of assets
 sum(s in SHARES) buy(s) <= MAXNUM

 forall(s in SHARES) do
  buy(s) is_binary                  ! Turn variables into binaries
  frac(s) <= MAXVAL*buy(s)                 ! Linking the variables
  frac(s) >= MINVAL*buy(s)                 ! Linking the variables
 end-do

! Remove doubles from the solution pool, comparing solutions on their 
! discrete variables only
 setparam("XPRS_ENUMDUPLPOL",3)

! Alternatively: switch off MIP heuristics to avoid generation of doubles
! setparam("XPRS_HEURSTRATEGY", 0)

! Disable presolve operations that attempt to improve the efficiency by 
! cutting off MIP solutions from the feasible region
 presolveops:= getparam("XPRS_PRESOLVEOPS")
 if bittest(presolveops,32)=32 then presolveops-=32; end-if 
                                     ! Disable duplicate column removal  
 if bittest(presolveops,8)=8 then presolveops-=8; end-if     
                                     ! Disable dual reduction operations 
 setparam("XPRS_PRESOLVEOPS", presolveops)  
 presolveops:= getparam("XPRS_MIPPRESOLVE")
 if bittest(presolveops,16)=16 then presolveops-=16; end-if 
                                     ! Disable in-tree dual reductions
 setparam("XPRS_MIPPRESOLVE", presolveops)  
 setparam("XPRS_SYMMETRY", 0)        ! Disable symmetry detection

! Set the max. number of solutions to store (default: 10)
 setparam("XPRS_enummaxsol", 25)

! Display Optimizer log
 setparam("XPRS_verbose", true)

! Solve the problem, enabling the solution enumerator
 maximize(XPRS_ENUM, Return)

! Print out all solutions saved by the enumerator
 forall(i in 1..getparam("XPRS_enumsols")) do
  selectsol(i)                      ! Select a solution from the pool
  writeln("Solution ", i)
  print_sol
 end-do

! Solution printing
 procedure print_sol
  writeln("Total return: ", getobjval)
  forall(s in SHARES | getsol(frac(s))>0)
   writeln(s, ": ", getsol(frac(s))*100, "% (", getsol(buy(s)), ")")
 end-procedure
end-model 

folioinfeas.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file folioinfeas.mos
   ````````````````````
   Modeling an LP problem 
   to perform portfolio optimization.

   Linear version of the model in foliomip3.mos.
   -- Infeasible model parameter values --
   -- Handling infeasibility through auxiliary variables --
   
  (c) 2008 Fair Isaac Corporation
      author: S.Heipcke, Dec. 2008, rev. Mar. 2014
*******************************************************!)

model "Portfolio optimization with MIP"
 uses "mmxprs"

 parameters
  MAXRISK = 1/3                     ! Max. investment into high-risk values
  MINREG = 0.3                      ! Min. investment per geogr. region
  MAXREG = 0.5                      ! Max. investment per geogr. region
  MAXSEC = 0.1                      ! Max. investment per ind. sector
  MAXVAL = 0.2                      ! Max. investment per share
  MINVAL = 0.1                      ! Min. investment per share
  DATAFILE = "folio250.dat"         ! File with problem data
 end-parameters

 forward procedure print_sol

 declarations
  SHARES: set of string              ! Set of shares
  RISK: set of string                ! Set of high-risk values among shares
  REGIONS: set of string             ! Geographical regions
  TYPES: set of string               ! Share types (ind. sectors)
  LOC: array(REGIONS) of set of string ! Sets of shares per geogr. region
  RET: array(SHARES) of real         ! Estimated return in investment
  SEC: array(TYPES) of set of string ! Sets of shares per industry sector
 end-declarations

 initializations from DATAFILE
  RISK RET LOC SEC
 end-initializations

 declarations
  frac: array(SHARES) of mpvar      ! Fraction of capital used per share
 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

! Limits on geographical distribution
 forall(r in REGIONS) do
  LimitMinReg(r):= sum(s in LOC(r)) frac(s) >= MINREG
  LimitMaxReg(r):= sum(s in LOC(r)) frac(s) <= MAXREG
 end-do 

! Diversification across industry sectors
 forall(t in TYPES) LimitSec(t):= sum(s in SEC(t)) frac(s) <= MAXSEC

! Spend all the capital
 sum(s in SHARES) frac(s) = 1
 
! Upper bounds on the investment per share
 forall(s in SHARES) frac(s) <= MAXVAL

! Display Optimizer log
 setparam("XPRS_verbose", true)

! Solve the problem (using primal Simplex to minimize infeasibilities)
 maximize(XPRS_PRI,Return)

 declarations
  mx,mdj: set of mpvar
  mslack,mdual: set of linctr
  devRisk: mpvar
  devMinReg,devMaxReg: array(REGIONS) of mpvar
  devSec: array(TYPES) of mpvar
 end-declarations 

 if getprobstat=XPRS_INF then
 ! Print some details 
  getinfeas(mx, mslack, mdual, mdj)
  writeln("Infeasible variables:")
  forall(v in mx) writeln("  ",getname(v))
  forall(v in mdj) writeln("  ",getname(v))
  writeln("Infeasible constraints:")
  forall(c in mslack) writeln("  ",getname(c))
  forall(c in mdual) writeln("  ",getname(c))
 
  writeln("#### Original problem infeasible. Adding deviation variables ####")

 ! Add deviation variables to make problem solvable
  LimitRisk -= devRisk
  forall(r in REGIONS) do
   LimitMinReg(r) += devMinReg(r)
   LimitMaxReg(r) -= devMaxReg(r)
   devMaxReg(r) <= MAXREG/2  ! Only allow small deviations
  end-do
  forall(t in TYPES) do
   LimitSec(t) -= devSec(t)
   devSec(t)<= MAXSEC/2              ! Only allow small deviations
  end-do 
 
  Penalty:= devRisk + sum(r in REGIONS) (devMinReg(r)+devMaxReg(r)) +
            sum(t in TYPES) devSec(t)
 
 ! Resolve the problem with penalty terms added to the objective 
  maximize(Return - 10*Penalty)

  if getprobstat=XPRS_INF then
   writeln("No solution after relaxation")
   exit(1)
  end-if
  
  writeln("Constraint violations:")
  writeln("  Constraint            Activity  Deviation  Bound(s)")
  writeln("  Risk                  ", 
          strfmt(getsol(sum(s in RISK) frac(s)),-10), 
          strfmt(devRisk.sol,-10), " (", MAXRISK, ")")
  forall(r in REGIONS)
   writeln("  Region ", strfmt(r,-11), "    ", 
           strfmt(getsol(sum(s in LOC(r)) frac(s)),-10), 
           strfmt(devMaxReg(r).sol-devMinReg(r).sol,-10), 
           " (", MINREG, "-",MAXREG,")")
  forall(t in TYPES)
   writeln("  Sector ", strfmt(t,-14), " ", 
           strfmt(getsol(sum(s in SEC(t)) frac(s)),-10),  
           strfmt(devSec(t).sol,-10), " (", MAXSEC, ")")    
 end-if

 print_sol

! Solution printing
 procedure print_sol
  writeln("Solution ", getparam("XPRS_MIPSOLS"))
  writeln("Total return: ", getsol(Return))
  forall(s in SHARES | getsol(frac(s))>0)
   writeln(s, ": ", getsol(frac(s))*100, "%")
 end-procedure
end-model 

folioinfcause.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file folioinfcause.mos
   ``````````````````````
   Modeling a MIP problem 
   to perform portfolio optimization.

   Same model as in foliomip3.mos.
   -- Infeasible model parameter values --
   -- Retrieving infeasible row/column from presolve --

   (c) 2012 Fair Isaac Corporation
       author: S.Heipcke, Oct. 2012, rev. Dec. 2016
*******************************************************!)

model "Portfolio optimization with MIP"
 uses "mmxprs"

 parameters
  MAXRISK = 1/3                     ! Max. investment into high-risk values
  MINREG = 0.1                      ! Min. investment per geogr. region
  MAXREG = 0.2                      ! Max. investment per geogr. region
  MAXSEC = 0.1                      ! Max. investment per ind. sector
  MAXVAL = 0.15                     ! Max. investment per share
  MINVAL = 0.15                     ! Min. investment per share
  MAXNUM = 4                        ! Max. number of different assets
  DATAFILE = "folio10.dat"          ! File with problem data
 end-parameters

 forward procedure print_sol

 declarations
  SHARES: set of string              ! Set of shares
  RISK: set of string                ! Set of high-risk values among shares
  REGIONS: set of string             ! Geographical regions
  TYPES: set of string               ! Share types (ind. sectors)
  LOC: array(REGIONS) of set of string ! Sets of shares per geogr. region
  RET: array(SHARES) of real         ! Estimated return in investment
  SEC: array(TYPES) of set of string ! Sets of shares per industry sector
 end-declarations

 initializations from DATAFILE
  RISK RET LOC SEC
 end-initializations

 declarations
  frac: array(SHARES) of mpvar      ! Fraction of capital used per share
  buy: array(SHARES) of mpvar       ! 1 if asset is in portfolio, 0 otherwise
 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

! Limits on geographical distribution
 forall(r in REGIONS) do
  LimitMinReg(r):= sum(s in LOC(r)) frac(s) >= MINREG
  LimitMaxReg(r):= sum(s in LOC(r)) frac(s) <= MAXREG
 end-do 

! Diversification across industry sectors
 forall(t in TYPES) LimitSec(t):= sum(s in SEC(t)) frac(s) <= MAXSEC

! 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

! Limit the total number of assets
 LimitNum:= sum(s in SHARES) buy(s) <= MAXNUM

 forall(s in SHARES) do
  buy(s) is_binary                  ! Turn variables into binaries
  LinkUB(s):= frac(s) <= MAXVAL*buy(s)     ! Linking the variables
  LinkLB(s):= frac(s) >= MINVAL*buy(s)     ! Linking the variables
 end-do


! Display Optimizer log
 setparam("XPRS_verbose", true)
 setparam("XPRS_LOADNAMES", true)

 setparam("XPRS_TRACE", 1)          ! Show detailed presolve log

! Solve the problem
 maximize(XPRS_LIN,Return)

 declarations
  V: set of mpvar
  C: set of linctr
 end-declarations

 probstat:= getprobstat
 case probstat of
  XPRS_OPT: writeln("Problem solved")
  XPRS_INF: do
              setparam("XPRS_verbose", false)  ! Disable Optimizer output
	      writeln("LP infeasible")
               
              getinfcause(V, C)                ! Retrieve inf. var. or constr.
              forall(v in V) writeln("Infeasible variable: ", getname(v), " ")
              forall(c in C) writeln("Infeasible constraint: ", getname(c), " ")
            end-do
  XPRS_OTH: writeln("Problem unbounded") 
  XPRS_UNF: writeln("Optimization unfinished")
  else writeln("Unknown problem status")
 end-case

! Solution printing
 procedure print_sol
  writeln("Solution ", getparam("XPRS_MIPSOLS"))
  writeln("Total return: ", getsol(Return))
  forall(s in SHARES | getsol(frac(s))>0)
   writeln(s, ": ", getsol(frac(s))*100, "% (", getsol(buy(s)), ")")
 end-procedure
end-model 

folioiis.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file folioiis.mos
   `````````````````
   Modeling a MIP problem 
   to perform portfolio optimization.

   Same model as in foliomip3.mos.
   -- Infeasible model parameter values --
   -- Retrieving IIS --
   
  (c) 2008 Fair Isaac Corporation
      author: S.Heipcke, Dec. 2008, rev. June 2010
*******************************************************!)

model "Portfolio optimization with MIP"
 uses "mmxprs"

 parameters
  MAXRISK = 1/3                     ! Max. investment into high-risk values
  MINREG = 0.1                      ! Min. investment per geogr. region
  MAXREG = 0.2                      ! Max. investment per geogr. region
  MAXSEC = 0.1                     ! Max. investment per ind. sector
  MAXVAL = 0.2                      ! Max. investment per share
  MINVAL = 0.1                      ! Min. investment per share
  MAXNUM = 5                        ! Max. number of different assets
  DATAFILE = "folio250.dat"         ! File with problem data
 end-parameters

 forward procedure print_sol

 declarations
  SHARES: set of string              ! Set of shares
  RISK: set of string                ! Set of high-risk values among shares
  REGIONS: set of string             ! Geographical regions
  TYPES: set of string               ! Share types (ind. sectors)
  LOC: array(REGIONS) of set of string ! Sets of shares per geogr. region
  RET: array(SHARES) of real         ! Estimated return in investment
  SEC: array(TYPES) of set of string ! Sets of shares per industry sector
 end-declarations

 initializations from DATAFILE
  RISK RET LOC SEC
 end-initializations

 declarations
  frac: array(SHARES) of mpvar      ! Fraction of capital used per share
  buy: array(SHARES) of mpvar       ! 1 if asset is in portfolio, 0 otherwise
 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

! Limits on geographical distribution
 forall(r in REGIONS) do
  LimitMinReg(r):= sum(s in LOC(r)) frac(s) >= MINREG
  LimitMaxReg(r):= sum(s in LOC(r)) frac(s) <= MAXREG
 end-do 

! Diversification across industry sectors
 forall(t in TYPES) LimitSec(t):= sum(s in SEC(t)) frac(s) <= MAXSEC

! 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

! Limit the total number of assets
 LimitNum:= sum(s in SHARES) buy(s) <= MAXNUM

 forall(s in SHARES) do
  buy(s) is_binary                  ! Turn variables into binaries
  LinkUB(s):= frac(s) <= MAXVAL*buy(s)     ! Linking the variables
  LinkLB(s):= frac(s) >= MINVAL*buy(s)     ! Linking the variables
 end-do


! Display Optimizer log
 setparam("XPRS_verbose", true)
 setparam("XPRS_LOADNAMES", true)

! Solve the problem
 maximize(XPRS_LIN,Return)

 declarations
  V: set of mpvar
  C: set of linctr
 end-declarations

 probstat:= getprobstat
 case probstat of
  XPRS_OPT: writeln("Problem solved")
  XPRS_INF: do
              setparam("XPRS_verbose", false)  ! Disable Optimizer output
	      writeln("LP infeasible")

              getiis(0, V, C)                  ! Retrieve the IIS approximation
              writeln("IIS approximation")
              write("  variables: "); writeln(getsize(V))
              write("  constraints: "); writeln(getsize(C))

              getiis({},{})                    ! Generate all IIS
              numiis:= getparam("XPRS_NUMIIS") ! Retrieve number of IIS
              writeln("Total IIS:", numiis)
              forall(i in 1..numiis) do
               getiis(i, V, C)                 ! Retrieve the i'th IIS
               writeln("IIS ", i)
               write("  variables: "); writeln(getsize(V))
	       forall(v in V) write(getname(v), " "); writeln
               write("  constraints: "); writeln(getsize(C))
	       forall(c in C) write(getname(c), " "); writeln
              end-do	     
            end-do
  XPRS_OTH: writeln("Problem unbounded") 
  XPRS_UNF: writeln("Optimization unfinished")
  else writeln("Unknown problem status")
 end-case

! Solution printing
 procedure print_sol
  writeln("Solution ", getparam("XPRS_MIPSOLS"))
  writeln("Total return: ", getsol(Return))
  forall(s in SHARES | getsol(frac(s))>0)
   writeln(s, ": ", getsol(frac(s))*100, "% (", getsol(buy(s)), ")")
 end-procedure
end-model 

foliomiis.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file foliomiis.mos
   ``````````````````
   Modeling a MIP problem 
   to perform portfolio optimization.

   Same model as in foliomip3.mos.
   -- Infeasible model parameter values --
   -- Retrieving MIIS --
   
  (c) 2010 Fair Isaac Corporation
      author: S.Heipcke, Oct. 2010
*******************************************************!)

model "Portfolio optimization with MIP"
 uses "mmxprs"

 parameters
  MAXRISK = 1/4                     ! Max. investment into high-risk values
  MINREG = 0.1                      ! Min. investment per geogr. region
  MAXREG = 0.25                     ! Max. investment per geogr. region
  MAXSEC = 0.15                     ! Max. investment per ind. sector
  MAXVAL = 0.225                    ! Max. investment per share
  MINVAL = 0.1                      ! Min. investment per share
  MAXNUM = 5                        ! Max. number of different assets
  DATAFILE = "folio5.dat"           ! File with problem data
 end-parameters

 declarations
  SHARES: set of string              ! Set of shares
  RISK: set of string                ! Set of high-risk values among shares
  REGIONS: set of string             ! Geographical regions
  TYPES: set of string               ! Share types (ind. sectors)
  LOC: array(REGIONS) of set of string ! Sets of shares per geogr. region
  RET: array(SHARES) of real         ! Estimated return in investment
  SEC: array(TYPES) of set of string ! Sets of shares per industry sector
 end-declarations

 initializations from DATAFILE
  RISK RET LOC SEC
 end-initializations

 declarations
  frac: array(SHARES) of mpvar      ! Fraction of capital used per share
  buy: array(SHARES) of mpvar       ! 1 if asset is in portfolio, 0 otherwise
 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

! Limits on geographical distribution
 forall(r in REGIONS) do
  LimitMinReg(r):= sum(s in LOC(r)) frac(s) >= MINREG
  LimitMaxReg(r):= sum(s in LOC(r)) frac(s) <= MAXREG
 end-do 

! Diversification across industry sectors
 forall(t in TYPES) LimitSec(t):= sum(s in SEC(t)) frac(s) <= MAXSEC

! 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

! Limit the total number of assets
 LimitNum:= sum(s in SHARES) buy(s) <= MAXNUM

 forall(s in SHARES) do
  buy(s) is_binary                  ! Turn variables into binaries
  LinkUB(s):= frac(s) <= MAXVAL*buy(s)     ! Linking the variables
  LinkLB(s):= frac(s) >= MINVAL*buy(s)     ! Linking the variables
 end-do


! Display Optimizer log
 setparam("XPRS_verbose", true)
 setparam("XPRS_LOADNAMES", true)

! Uncomment this line to see that the problem is LP-feasible
! maximize(XPRS_LIN,Return)

! Solve the problem
 maximize(Return)

 declarations
  V: set of mpvar
  C: set of linctr
 end-declarations

 probstat:= getprobstat
 case probstat of
  XPRS_OPT: writeln("Problem solved")
  XPRS_INF: do
              setparam("XPRS_verbose", false)  ! Disable Optimizer output
	      writeln("MIP infeasible")

              getiis({},{})                    ! Generate all IIS
              numiis:= getparam("XPRS_NUMIIS") ! Retrieve number of IIS
                                               ! (at most 1 for MIP) 
              writeln("Total IIS:", numiis)
              forall(i in 1..numiis) do
               getiis(i, V, C)                 ! Retrieve the i'th IIS
               writeln("IIS ", i)
               write("  variables: "); writeln(getsize(V))
	       forall(v in V) write(getname(v), " "); writeln
               write("  constraints: "); writeln(getsize(C))
	       forall(c in C) write(getname(c), " "); writeln
              end-do	     
            end-do
  XPRS_OTH: writeln("Problem unbounded") 
  XPRS_UNF: writeln("Optimization unfinished")
  else writeln("Unknown problem status")
 end-case

end-model 

foliorep.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file foliorep.mos
   `````````````````
   Modeling a MIP problem 
   to perform portfolio optimization.

   Same model as in foliomip3.mos.
   -- Infeasible model parameter values --
   -- Repairing infeasibilities --
   
  (c) 2008 Fair Isaac Corporation
      author: S.Heipcke, Dec. 2008, rev. Oct. 2014
*******************************************************!)

model "Portfolio optimization with MIP"
 uses "mmxprs"

 parameters
  MAXRISK = 1/3                     ! Max. investment into high-risk values
  MINREG = 0.3                      ! Min. investment per geogr. region
  MAXREG = 0.5                      ! Max. investment per geogr. region
  MAXSEC = 0.15                     ! Max. investment per ind. sector
  MAXVAL = 0.2                      ! Max. investment per share
  MINVAL = 0.1                      ! Min. investment per share
  MAXNUM = 4                        ! Max. number of different assets
  DATAFILE = "folio10.dat"          ! File with problem data
 end-parameters

 forward procedure print_sol
 forward procedure print_violated

 declarations
  SHARES: set of string              ! Set of shares
  RISK: set of string                ! Set of high-risk values among shares
  REGIONS: set of string             ! Geographical regions
  TYPES: set of string               ! Share types (ind. sectors)
  LOC: array(REGIONS) of set of string ! Sets of shares per geogr. region
  RET: array(SHARES) of real         ! Estimated return in investment
  SEC: array(TYPES) of set of string ! Sets of shares per industry sector
 end-declarations

 initializations from DATAFILE
  RISK RET LOC SEC
 end-initializations

 declarations
  frac: array(SHARES) of mpvar      ! Fraction of capital used per share
  buy: array(SHARES) of mpvar       ! 1 if asset is in portfolio, 0 otherwise
 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

! Limits on geographical distribution
 forall(r in REGIONS) do
  LimitMinReg(r):= sum(s in LOC(r)) frac(s) >= MINREG
  LimitMaxReg(r):= sum(s in LOC(r)) frac(s) <= MAXREG
 end-do 

! Diversification across industry sectors
 forall(t in TYPES) LimitSec(t):= sum(s in SEC(t)) frac(s) <= MAXSEC

! Spend all the capital
 sum(s in SHARES) frac(s) = 1
 
! Upper bounds on the investment per share
 forall(s in SHARES) frac(s) <= MAXVAL

! Limit the total number of assets
 LimitNum:= sum(s in SHARES) buy(s) <= MAXNUM

 forall(s in SHARES) do
  buy(s) is_binary                  ! Turn variables into binaries
  frac(s) <= MAXVAL*buy(s)                 ! Linking the variables
  frac(s) >= MINVAL*buy(s)                 ! Linking the variables
 end-do


! Display Optimizer log
! setparam("XPRS_verbose", true)

! Solve the problem
! maximize(XPRS_LIN,Return)
 maximize(Return)

!**** Infeasibility repair + reporting ****

 declarations
  Alrp,Agrp: array(linctr) of real  ! Selectors for LEG / GEQ constraints
  Albp,Aubp: array(mpvar) of real   ! Selector for lower / upper bounds on vars
  rstat: array(range) of string     ! Status message text
 end-declarations

 probstat:= getprobstat
 case probstat of
  XPRS_OPT: writeln("Problem solved")
  XPRS_INF: do 
             ! Must use the detailed infeasibility repair method since
	     ! only some constraints of each type may be relaxed
              Alrp(LimitRisk):=1
              forall(r in REGIONS) Alrp(LimitMaxReg(r)):=1
	      forall(t in TYPES) Alrp(LimitSec(t)):=1
              Alrp(LimitNum):=1
              forall(r in REGIONS) Agrp(LimitMinReg(r)):=1

              delta:=0.001
              while (delta<10) do
                setparam("XPRS_MAXTIME", -10)
!               setparam("XPRS_VERBOSE", false)

               ! Option 'r': repairinfeas reports the relaxed constraints/bounds
                repairinfeas(Alrp, Agrp, Albp, Aubp, 'r', delta, "")
		repstatus:= getprobstat
                write("delta = ", delta, ": ")
                case probstat of
                  XPRS_OPT: writeln("Relaxed problem solved")
                  XPRS_INF: writeln("Relaxed problem infeasible")
                  XPRS_OTH: writeln("Relaxed problem unbounded") 
                  XPRS_UNF: writeln("Repairinfeas has been terminated")
                  else writeln("Unknown problem status")
                end-case

               ! Display the relaxed solution
                print_sol
		
               ! Programmatic checking of constraint violations
                print_violated
		
                delta:= delta*10
              end-do 
            end-do
  XPRS_OTH: writeln("Problem unbounded") 
  XPRS_UNF: writeln("Optimization unfinished")
  else writeln("Unknown problem status")
 end-case

!**** Solution printing ****
 procedure print_sol
  writeln("  Total return: ", getsol(Return))
  forall(s in SHARES | getsol(frac(s))>0)
   writeln("  ", s, ": ", getsol(frac(s))*100, "% (", getsol(buy(s)), ")")
 end-procedure

!**** Display violated  constraints ****
 procedure print_violated
  declarations
   AllCtr: set of linctr
  end-declarations
 
  EPS:=1e-6
  
  writeln(" Violated (relaxed) constraints:")
  getloadedlinctrs(AllCtr)
  
  forall(c in AllCtr) 
   case gettype(c) of
    CT_EQ:  if abs(getsol(c))>EPS then
              writeln("   = constraint ", getname(c), " by ", c.sol)
            end-if 
    CT_GEQ: if getsol(c)<-EPS then
              writeln("  >= constraint ", getname(c), " by ", c.sol)
            end-if 
    CT_LEQ: if getsol(c)>EPS then
              writeln("  <= constraint ", getname(c), " by ", c.sol)
            end-if 
   end-case
   writeln
 end-procedure

end-model 

foliorep_sol.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file foliorep_sol.mos
   `````````````````````
   Modeling a MIP problem 
   to perform portfolio optimization.

   Same model as in foliomip3.mos.
   -- Infeasible model parameter values --
   -- Repairing infeasibilities --
   -- Storing solutions in an mpsol object --
   
  (c) 2014 Fair Isaac Corporation
      author: S.Heipcke, Sep. 2014
*******************************************************!)

model "Portfolio optimization with MIP"
 uses "mmxprs"

 parameters
  MAXRISK = 1/3                     ! Max. investment into high-risk values
  MINREG = 0.3                      ! Min. investment per geogr. region
  MAXREG = 0.5                      ! Max. investment per geogr. region
  MAXSEC = 0.15                     ! Max. investment per ind. sector
  MAXVAL = 0.2                      ! Max. investment per share
  MINVAL = 0.1                      ! Min. investment per share
  MAXNUM = 4                        ! Max. number of different assets
  DATAFILE = "folio10.dat"          ! File with problem data
 end-parameters

 forward procedure print_sol
 forward procedure print_violated

 declarations
  SHARES: set of string              ! Set of shares
  RISK: set of string                ! Set of high-risk values among shares
  REGIONS: set of string             ! Geographical regions
  TYPES: set of string               ! Share types (ind. sectors)
  LOC: array(REGIONS) of set of string ! Sets of shares per geogr. region
  RET: array(SHARES) of real         ! Estimated return in investment
  SEC: array(TYPES) of set of string ! Sets of shares per industry sector
 end-declarations

 initializations from DATAFILE
  RISK RET LOC SEC
 end-initializations

 declarations
  frac: array(SHARES) of mpvar      ! Fraction of capital used per share
  buy: array(SHARES) of mpvar       ! 1 if asset is in portfolio, 0 otherwise
 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

! Limits on geographical distribution
 forall(r in REGIONS) do
  LimitMinReg(r):= sum(s in LOC(r)) frac(s) >= MINREG
  LimitMaxReg(r):= sum(s in LOC(r)) frac(s) <= MAXREG
 end-do 

! Diversification across industry sectors
 forall(t in TYPES) LimitSec(t):= sum(s in SEC(t)) frac(s) <= MAXSEC

! Spend all the capital
 sum(s in SHARES) frac(s) = 1
 
! Upper bounds on the investment per share
 forall(s in SHARES) frac(s) <= MAXVAL

! Limit the total number of assets
 LimitNum:= sum(s in SHARES) buy(s) <= MAXNUM

 forall(s in SHARES) do
  buy(s) is_binary                  ! Turn variables into binaries
  frac(s) <= MAXVAL*buy(s)                 ! Linking the variables
  frac(s) >= MINVAL*buy(s)                 ! Linking the variables
 end-do


! Display Optimizer log
! setparam("XPRS_verbose", true)

! Solve the problem
! maximize(XPRS_LIN,Return)
 maximize(Return)
 
!**** Infeasibility repair + reporting ****

 declarations
  Alrp,Agrp: array(linctr) of real  ! Selectors for LEG / GEQ constraints
  Albp,Aubp: array(mpvar) of real   ! Selector for lower / upper bounds on vars
  rstat: array(range) of string     ! Status message text
 end-declarations

 probstat:= getprobstat
 case probstat of
  XPRS_OPT: writeln("Problem solved")
  XPRS_INF: do 
             ! Must use the detailed infeasibility repair method since
	     ! only some constraints of each type may be relaxed
              Alrp(LimitRisk):=1
              forall(r in REGIONS) Alrp(LimitMaxReg(r)):=1
	      forall(t in TYPES) Alrp(LimitSec(t)):=1
              Alrp(LimitNum):=1
              forall(r in REGIONS) Agrp(LimitMinReg(r)):=1

	      rstat::(0..5)["relaxed optimum found", 
	        "relaxed problem infeasible", "relaxed problem unbounded", 
                "solution nonoptimal for original objective",
                "error", "numerical instability"]

              delta:=0.001
	      while (delta<10) do
	       setparam("XPRS_MAXTIME", -10)
!	       setparam("XPRS_VERBOSE", false)

               ! Option 'r': repairinfeas reports the relaxed constraints/bounds
                repairinfeas(Alrp, Agrp, Albp, Aubp, 'r', delta, "")
		repstatus:= getprobstat
                write("delta = ", delta, ": ")
                case probstat of
                  XPRS_OPT: writeln("Relaxed problem solved")
                  XPRS_INF: writeln("Relaxed problem infeasible")
                  XPRS_OTH: writeln("Relaxed problem unbounded") 
                  XPRS_UNF: writeln("Repairinfeas has been terminated")
                  else writeln("Unknown problem status")
                end-case

               ! Display the relaxed solution
                print_sol
		
               ! Programmatic checking of constraint violations
                print_violated
		
                delta:= delta*10
	      end-do 
            end-do
  XPRS_OTH: writeln("Problem unbounded") 
  XPRS_UNF: writeln("Optimization unfinished")
  else writeln("Unknown problem status")
 end-case

!**** Solution printing ****
 procedure print_sol
  writeln("  Total return: ", getsol(Return))
  forall(s in SHARES | getsol(frac(s))>0)
   writeln("  ", s, ": ", getsol(frac(s))*100, "% (", getsol(buy(s)), ")")
 end-procedure

!**** Display violated  constraints ****
 procedure print_violated
  declarations
   Solution: mpsol
   AllCtr: set of linctr
  end-declarations
 
  EPS:=1e-6
  
  writeln(" Violated (relaxed) constraints:")
  getloadedlinctrs(AllCtr)
  savesol(Solution)
  
  forall(c in AllCtr) 
   case gettype(c) of
    CT_EQ:  if abs(getsol(Solution,c))>EPS then
             writeln("   = constraint ", getname(c), " by ", getsol(Solution,c))
            end-if 
    CT_GEQ: if getsol(Solution,c)<-EPS then
             writeln("  >= constraint ", getname(c), " by ", getsol(Solution,c))
            end-if 
    CT_LEQ: if getsol(Solution,c)>EPS then
             writeln("  <= constraint ", getname(c), " by ", getsol(Solution,c))
            end-if 
   end-case
   writeln
 end-procedure

end-model 

runfolio.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file runfolio.mos
   `````````````````
   Master model running portfolio optimization model.

   Runs model foliomemio.mos.
   -- Data input/output in memory --
      
  (c) 2009 Fair Isaac Corporation
      author: S.Heipcke, Jan. 2009
*******************************************************!)

model "Run portfolio optimization model"
 uses "mmjobs"                       ! Use multiple model handling
 uses "mmsystem", "mmxprs"

 parameters
  MODELFILE = "foliomemio.mos"       ! Optimization model
  INPUTFILE = "folio10.dat"          ! File with problem data
 
  MAXRISK = 1/3                      ! Max. investment into high-risk values
  MINREG = 0.2                       ! Min. investment per geogr. region
  MAXREG = 0.5                       ! Max. investment per geogr. region
  MAXSEC = 0.25                      ! Max. investment per ind. sector
  MAXVAL = 0.2                       ! Max. investment per share
  MINVAL = 0.1                       ! Min. investment per share
  MAXNUM = 15                        ! Max. number of different assets
 end-parameters
 
 forward procedure write_html_results

 declarations
  SHARES: set of string              ! Set of shares
  RISK: set of string                ! Set of high-risk values among shares
  REGIONS: set of string             ! Geographical regions
  TYPES: set of string               ! Share types (ind. sectors)
  LOCTAB: dynamic array(REGIONS,SHARES) of boolean ! Shares per geogr. region
  RET: array(SHARES) of real         ! Estimated return in investment
  SECTAB: dynamic array(TYPES,SHARES) of boolean ! Shares per industry sector

  returnsol: real                    ! Solution values
  numsharessol,status: integer
  fracsol: array(SHARES) of real     ! Fraction of capital used per share
  buysol: array(SHARES) of real      ! 1 if asset is in portfolio, 0 otherwise

  foliomod: Model
 end-declarations

! Compile and load the optimization model
 if compile("", MODELFILE, "shmem:bim") <> 0 then
  writeln("Error during model compilation")
  exit(1)
 end-if
 load(foliomod, "shmem:bim")
 fdelete("shmem:bim")

! Read in data from file
 initializations from INPUTFILE
  RISK RET LOCTAB SECTAB
 end-initializations

! Save data to memory
 initializations to "raw:"
  RISK as 'shmem:RISK'
  RET as 'shmem:RET'
  LOCTAB as 'shmem:LOCTAB'
  SECTAB as 'shmem:SECTAB'
 end-initializations

 run(foliomod, "MAXRISK=" + MAXRISK + ",MINREG=" + MINREG + 
  ",MAXREG=" + MAXREG + ",MAXSEC=" + MAXSEC +
  ",MAXVAL=" + MAXVAL + ",MINVAL=" + MINVAL +
  ",MAXNUM=" + MAXNUM + ",DATAFILE='raw:',OUTPUTFILE='raw:'," +
  "RISKDATA='shmem:RISK',RETDATA='shmem:RET',LOCDATA='shmem:LOCTAB'," +
  "SECDATA='shmem:SECTAB',FRACSOL='shmem:FRAC',BUYSOL='shmem:BUY'," +
  "NUMSHARES='shmem:NUMSHARES',RETSOL='shmem:RETSOL'," +
  "SOLSTATUS='shmem:SOLSTATUS'")
  wait                              ! Wait for model termination
  dropnextevent                     ! Ignore termination event message

 initializations from  "raw:"
  returnsol as 'shmem:RETSOL'
  numsharessol as 'shmem:NUMSHARES'
  fracsol as 'shmem:FRAC'
  buysol as 'shmem:BUY'
  status as 'shmem:SOLSTATUS'
 end-initializations

 case status of
  XPRS_OPT: writeln("Problem solved to optimality")
  XPRS_UNF: writeln("Problem solving unfinished")
  XPRS_INF: writeln("Problem is infeasible")
  XPRS_UNB,XPRS_OTH:  writeln("No solution available")
 end-case 

 ! Solution printing
 writeln("Total return: ", returnsol)
 writeln("Number of shares: ", numsharessol)
 forall(s in SHARES | fracsol(s)>0)
  writeln(s, ": ", fracsol(s)*100, "% (", buysol(s), ")")
 
 write_html_results

! *********** Writing an HTML result file ***********
 procedure write_html_results
  setparam("datetimefmt", "%0d-%N-%y, %0H:%0M:%0S")

  HTMLFILE:= INPUTFILE + "_sol.html"
  fopen(HTMLFILE, F_OUTPUT)
  writeln("<html>")
  writeln("<head>")
  writeln("<style type='text/css'>")
  writeln("body {font-family: Verdana, Geneva, Helvetica, Arial, sans-serif; color: 000055 }")
  writeln("table td {background-color: ffffaa; text-align: left }")
  writeln("table th {background-color: 053055; color: ffcc88}")
 writeln("</style>")
  writeln("</head>")

  writeln("<body>")
  writeln("<center><h2>Portfolio Optimization Results</h2></center>")
  writeln("<table width='100%' cellpadding='5' cellspacing='0' border=0>")
  writeln("<tr><td width='55%'><font color='#000055'><b>Total return: ",
          returnsol, "</b></font></td><td><font color='#885533'><b>Problem instance: ",
          INPUTFILE,"</b></font></td></tr>")
  writeln("<tr><td><font color='#000055'><b>Number of shares: ", numsharessol, "</b></font></td><td><font color='#885533'><b>Date: ", datetime(SYS_NOW),"</b></font></td></tr>")
  writeln("<tr><td colspan='2'>&nbsp;</td></tr>")
  writeln("</table>")

  writeln("<table cellpadding='2' cellspacing='1' width='100%'>")
  writeln("<tr><th>Value</th><th>Percentage</th></tr>")
 forall(s in SHARES | fracsol(s)>0) 
   writeln("<tr><td>", s, "</td><td>", strfmt(fracsol(s)*100,4,2), 
           "%</td></tr>")
  writeln("</table>")
  writeln("</body>")
  writeln("</html>")
  fclose(F_OUTPUT)
 end-procedure

end-model

runfolio2.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file runfolio2.mos
   ``````````````````
   Master model running portfolio optimization model.

   Runs model foliomemio2.mos.
   -- Data input/output in memory --
   -- Grouping arrays with identical index sets --
      
  (c) 2009 Fair Isaac Corporation
      author: S.Heipcke, Feb. 2009
*******************************************************!)

model "Run portfolio optimization model"
 uses "mmjobs"                       ! Use multiple model handling
 uses "mmsystem", "mmxprs"

 parameters
  MODELFILE = "foliomemio2.mos"      ! Optimization model
  INPUTFILE = "folio10.dat"          ! File with problem data
 
  MAXRISK = 1/3                      ! Max. investment into high-risk values
  MINREG = 0.2                       ! Min. investment per geogr. region
  MAXREG = 0.5                       ! Max. investment per geogr. region
  MAXSEC = 0.25                      ! Max. investment per ind. sector
  MAXVAL = 0.2                       ! Max. investment per share
  MINVAL = 0.1                       ! Min. investment per share
  MAXNUM = 15                        ! Max. number of different assets
 end-parameters
 
 forward procedure write_html_results

 declarations
  SHARES: set of string              ! Set of shares
  RISK: set of string                ! Set of high-risk values among shares
  REGIONS: set of string             ! Geographical regions
  TYPES: set of string               ! Share types (ind. sectors)
  LOCTAB: dynamic array(REGIONS,SHARES) of boolean ! Shares per geogr. region
  RET: array(SHARES) of real         ! Estimated return in investment
  SECTAB: dynamic array(TYPES,SHARES) of boolean ! Shares per industry sector

  returnsol: real                    ! Solution values
  numsharessol,status: integer
  fracsol: array(SHARES) of real     ! Fraction of capital used per share
  buysol: array(SHARES) of real      ! 1 if asset is in portfolio, 0 otherwise

  foliomod: Model
 end-declarations

! Compile and load the optimization model
 if compile("", MODELFILE, "shmem:bim") <> 0 then
  writeln("Error during model compilation")
  exit(1)
 end-if
 load(foliomod, "shmem:bim")
 fdelete("shmem:bim")

! Read in data from file
 initializations from INPUTFILE
  RISK RET LOCTAB SECTAB
 end-initializations

! Save data to memory
 initializations to "raw:"
  RISK as 'shmem:RISK'
  RET as 'shmem:RET'
  LOCTAB as 'shmem:LOCTAB'
  SECTAB as 'shmem:SECTAB'
 end-initializations

 run(foliomod, "MAXRISK=" + MAXRISK + ",MINREG=" + MINREG + 
  ",MAXREG=" + MAXREG + ",MAXSEC=" + MAXSEC +
  ",MAXVAL=" + MAXVAL + ",MINVAL=" + MINVAL +
  ",MAXNUM=" + MAXNUM + ",DATAFILE='raw:',OUTPUTFILE='raw:'," +
  "RISKDATA='shmem:RISK',RETDATA='shmem:RET',LOCDATA='shmem:LOCTAB'," +
  "SECDATA='shmem:SECTAB',FRACBUYSOL='shmem:FRACBUY'," +
  "NUMSHARES='shmem:NUMSHARES',RETSOL='shmem:RETSOL'," +
  "SOLSTATUS='shmem:SOLSTATUS'")
  wait                              ! Wait for model termination
  dropnextevent                     ! Ignore termination event message

 initializations from  "raw:"
  returnsol as 'shmem:RETSOL'
  numsharessol as 'shmem:NUMSHARES'
  [fracsol,buysol] as 'shmem:FRACBUY'
  status as 'shmem:SOLSTATUS'
 end-initializations

 case status of
  XPRS_OPT: writeln("Problem solved to optimality")
  XPRS_UNF: writeln("Problem solving unfinished")
  XPRS_INF: writeln("Problem is infeasible")
  XPRS_UNB,XPRS_OTH:  writeln("No solution available")
 end-case 

 ! Solution printing
 writeln("Total return: ", returnsol)
 writeln("Number of shares: ", numsharessol)
 forall(s in SHARES | fracsol(s)>0)
  writeln(s, ": ", fracsol(s)*100, "% (", buysol(s), ")")
 
 write_html_results

! *********** Writing an HTML result file ***********
 procedure write_html_results
  setparam("datetimefmt", "%0d-%N-%y, %0H:%0M:%0S")

  HTMLFILE:= INPUTFILE + "_sol.html"
  fopen(HTMLFILE, F_OUTPUT)
  writeln("<html>")
  writeln("<head>")
  writeln("<style type='text/css'>")
  writeln("body {font-family: Verdana, Geneva, Helvetica, Arial, sans-serif; color: 000055 }")
  writeln("table td {background-color: ffffaa; text-align: left }")
  writeln("table th {background-color: 053055; color: ffcc88}")
 writeln("</style>")
  writeln("</head>")

  writeln("<body>")
  writeln("<center><h2>Portfolio Optimization Results</h2></center>")
  writeln("<table width='100%' cellpadding='5' cellspacing='0' border=0>")
  writeln("<tr><td width='55%'><font color='#000055'><b>Total return: ",
          returnsol, "</b></font></td><td><font color='#885533'><b>Problem instance: ",
          INPUTFILE,"</b></font></td></tr>")
  writeln("<tr><td><font color='#000055'><b>Number of shares: ", numsharessol, "</b></font></td><td><font color='#885533'><b>Date: ", datetime(SYS_NOW),"</b></font></td></tr>")
  writeln("<tr><td colspan='2'>&nbsp;</td></tr>")
  writeln("</table>")

  writeln("<table cellpadding='2' cellspacing='1' width='100%'>")
  writeln("<tr><th>Value</th><th>Percentage</th></tr>")
 forall(s in SHARES | fracsol(s)>0) 
   writeln("<tr><td>", s, "</td><td>", strfmt(fracsol(s)*100,4,2), 
           "%</td></tr>")
  writeln("</table>")
  writeln("</body>")
  writeln("</html>")
  fclose(F_OUTPUT)
 end-procedure

end-model

runfoliopar.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file runfoliopar.mos
   ````````````````````
   Master model running several instances of the
   portfolio optimization model in parallel.

   Runs model foliomemio.mos.
   -- Data input/output in memory --

   *** ATTENTION: This model will return an error if ***
   *** no more than one Xpress licence is available. ***
   *** With a single license, use setting NUMPAR=1   ***
      
  (c) 2009 Fair Isaac Corporation
      author: S.Heipcke, Feb. 2009, rev. Dec. 2017 
*******************************************************!)

model "Run portfolio optimization model (parallel)"
 uses "mmjobs"                       ! Use multiple model handling
 uses "mmsystem", "mmxprs"

 parameters
  MODELFILE = "foliomemio.mos"       ! Optimization model
  INPUTFILE = "folio10.dat"          ! File with problem data
 
  MAXRISK = 1/3                      ! Max. investment into high-risk values
  MINREG = 0.2                       ! Min. investment per geogr. region
  MAXREG = 0.5                       ! Max. investment per geogr. region
  MAXSEC = 0.25                      ! Max. investment per ind. sector
  MAXVAL = 0.2                       ! Max. investment per share
  MINVAL = 0.1                       ! Min. investment per share
  MAXNUM = 9                         ! Max. number of different assets

  NUMPAR = 5                         ! Number of model instances to run
 end-parameters
 
 forward procedure write_html_header
 forward procedure write_html_line(i:integer)
 forward procedure write_html_line(i:integer,msg:string)
 forward procedure write_html_footer

 declarations
  SHARES: set of string              ! Set of shares
  RISK: set of string                ! Set of high-risk values among shares
  REGIONS: set of string             ! Geographical regions
  TYPES: set of string               ! Share types (ind. sectors)
  LOCTAB: dynamic array(REGIONS,SHARES) of boolean ! Shares per geogr. region
  RET: array(SHARES) of real         ! Estimated return in investment
  SECTAB: dynamic array(TYPES,SHARES) of boolean ! Shares per industry sector

  returnsol,totalreturn: real        ! Solution values
  numsharessol,status,totalnum,totalopt: integer
  fracsol: array(SHARES) of real     ! Fraction of capital used per share
  buysol: array(SHARES) of real      ! 1 if asset is in portfolio, 0 otherwise

  foliomod: dynamic array(Instances:range) of Model
 end-declarations

! Compile the optimization model
 if compile("", MODELFILE, "shmem:bim") <> 0 then
  writeln("Error during model compilation")
  exit(1)
 end-if
! Load several instances of the optimization model
 forall(i in 1..NUMPAR) do
  create(foliomod(i))
  load(foliomod(i), "shmem:bim")
 end-do
 fdelete("shmem:bim")

! Read in data from file
 initializations from INPUTFILE
  RISK RET LOCTAB SECTAB
 end-initializations

! Save data to memory
 initializations to "raw:"
  RISK as 'shmem:RISK'
  RET as 'shmem:RET'
  LOCTAB as 'shmem:LOCTAB'
  SECTAB as 'shmem:SECTAB'
 end-initializations

! Start all instances in parallel, using unique file location names for output
 forall(i in Instances)
  run(foliomod(i), "MAXRISK=" + MAXRISK + ",MINREG=" + MINREG + 
  ",MAXREG=" + MAXREG + ",MAXSEC=" + MAXSEC +
  ",MAXVAL=" + MAXVAL + ",MINVAL=" + MINVAL + 
  ",MAXNUM=" + (MAXNUM-i) + ",DATAFILE='raw:',OUTPUTFILE='raw:'," +
  "RISKDATA='shmem:RISK',RETDATA='shmem:RET',LOCDATA='shmem:LOCTAB'," +
  "SECDATA='shmem:SECTAB',FRACSOL='shmem:FRAC" + i +"',BUYSOL='shmem:BUY" +
  i + "',NUMSHARES='shmem:NUMSHARES" + i + "',RETSOL='shmem:RETSOL" + i + 
  "',SOLSTATUS='shmem:SOLSTATUS" + i + "'" ) 

! Wait until all models have finished 
! (alternatively: could retrieve results as soon as a run finishes)
 forall(i in Instances) do
  wait                              ! Wait for model terminations
  dropnextevent                     ! Ignore termination event message
 end-do

! Output: generate an HTML page with all solutions
 write_html_header

 forall(i in Instances) do
  forall(s in SHARES) do
   fracsol(s):=0; buysol(s):=0
  end-do 

  initializations from  "raw:"
   returnsol as 'shmem:RETSOL'+i
   numsharessol as 'shmem:NUMSHARES'+i
   fracsol as 'shmem:FRAC'+i
   buysol as 'shmem:BUY'+i
   status as 'shmem:SOLSTATUS'+i
  end-initializations

  case status of
   XPRS_OPT: do
              write_html_line(i)
              totalreturn+=returnsol
              totalnum+=numsharessol
              totalopt+=1
             end-do 
   XPRS_UNF: write_html_line(i,"Problem solving unfinished")
   XPRS_INF: write_html_line(i,"Problem is infeasible")
   XPRS_UNB,XPRS_OTH: write_html_line(i,"No solution available")
  end-case 

 end-do
 
 write_html_footer

! *********** Writing an HTML result file ***********
 procedure write_html_header
  setparam("datetimefmt", "%0d-%N-%y, %0H:%0M:%0S")

  HTMLFILE:= INPUTFILE + "_sol.html"
  fopen(HTMLFILE, F_OUTPUT)
  writeln("<html>")
  writeln("<head>")
  writeln("<style type='text/css'>")
  writeln("body {font-family: Verdana, Geneva, Helvetica, Arial, sans-serif; color: 000055 }")
  writeln("table td {background-color: ffffaa; text-align: left }")
  writeln("table th {background-color: 053055; color: ffcc88}")
 writeln("</style>")
  writeln("</head>")

  writeln("<body>")
  writeln("<center><h2>Portfolio Optimization Summary Results</h2></center>")
  writeln("<table width='100%' cellpadding='5' cellspacing='0' border=0>")
  writeln("<tr><td width='55%'><font color='#000055'><b> </b></font></td><td><font color='#885533'><b>Problem data: ",
          INPUTFILE,"</b></font></td></tr>")
  writeln("<tr><td><font color='#000055'><b> </b></font></td><td><font color='#885533'><b>Date: ", datetime(SYS_NOW),"</b></font></td></tr>")
  writeln("<tr><td colspan='2'>&nbsp;</td></tr>")
  writeln("</table>")

  writeln("<table cellpadding='2' cellspacing='1' width='100%'>")
  writeln("<tr><th>Instance</th><th>Return</th><th>No. shares</th><th>Value: Percentage</th></tr>")
 end-procedure

 procedure write_html_line(i:integer)
  write("<tr><td><center>", i, "</center></td><td>", returnsol, "</td><td><center>", numsharessol, "</center></td><td>")
  writeln("<table cellpadding='2' cellspacing='0' width='100%'>")
  ct:=0
  forall(s in SHARES | fracsol(s)>0) do
   ct+=1   
   writeln(if(ct mod 4=1, "<tr>", ""),
           "<td><font size='-1'>", s, ": ", strfmt(fracsol(s)*100,4,2), "%,</font></td>", 
           if(ct mod 4=0, "</tr>", ""))
  end-do  
  writeln(if(ct mod 4<>0, "</tr>", ""), "</table></td></tr>") 
 end-procedure

 procedure write_html_line(i:integer,msg:string)
  writeln("<tr><td><center>", i, "</center></td><td align='left' colspan='3'>", msg, "</td></tr>")
 end-procedure

 procedure write_html_footer
  writeln("<tr><th>Average</th><th>", totalreturn/totalopt, "</th><th>", totalnum/totalopt, "</th><th></th></tr>")
  writeln("</table>")
  writeln("</body>")
  writeln("</html>")
  fclose(F_OUTPUT)
 end-procedure

end-model

runfoliodistr.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file runfoliodistr.mos
   ``````````````````````
   Master model running portfolio optimization model
   on a remote Mosel instance.

   Runs model foliomemio.mos.
 
   *** ATTENTION: This model will return an error if ***
   *** no more than one Xpress licence is available. ***
      
  (c) 2010 Fair Isaac Corporation
      author: S.Heipcke, July 2010
*******************************************************!)

model "Run portfolio optimization model remotely"
 uses "mmjobs"                       ! Use multiple model handling
 uses "mmsystem", "mmxprs"

 parameters
  MODELFILE = "foliomemio"           ! Optimization model
  INPUTFILE = "folio10.dat"          ! File with problem data
  OUTPUTFILE = "solout.dat"          ! File for solution output
 
  MAXRISK = 1/3                      ! Max. investment into high-risk values
  MINREG = 0.2                       ! Min. investment per geogr. region
  MAXREG = 0.5                       ! Max. investment per geogr. region
  MAXSEC = 0.25                      ! Max. investment per ind. sector
  MAXVAL = 0.2                       ! Max. investment per share
  MINVAL = 0.1                       ! Min. investment per share
  MAXNUM = 15                        ! Max. number of different assets
 end-parameters
 
 forward procedure write_html_results

 declarations
  SHARES: set of string              ! Set of shares
  returnsol: real                    ! Solution values
  numsharessol,status: integer
  fracsol: dynamic array(SHARES) of real  ! Fraction of capital used per share
  buysol: dynamic array(SHARES) of real   ! 1 if asset is in portfolio, 0 otherwise

  foliomod: Model                    ! Mosel model
  moselinst: Mosel                   ! Mosel instance
 end-declarations

! Compile the optimization model locally
 if compile(MODELFILE+".mos") <> 0 then
  writeln("Error during model compilation")
  exit(1)
 end-if

! Start a remote Mosel instance: 
! "" stands for the node running this model; try IP addresses or host names
 if connect(moselinst, "")<>0 then exit(2); end-if

! Load the optimization model into the remote instance
 load(moselinst, foliomod, "rmt:"+MODELFILE+".bim")
 fdelete(MODELFILE+".bim")


 run(foliomod, "MAXRISK=" + MAXRISK + ",MINREG=" + MINREG + 
  ",MAXREG=" + MAXREG + ",MAXSEC=" + MAXSEC +
  ",MAXVAL=" + MAXVAL + ",MINVAL=" + MINVAL +
  ",MAXNUM=" + MAXNUM + ",DATAFILE='rmt:" + INPUTFILE +
  "',OUTPUTFILE='rmt:" + OUTPUTFILE + "'")
  wait                              ! Wait for model termination
  dropnextevent                     ! Ignore termination event message

 initializations from OUTPUTFILE
  returnsol as 'RETSOL'
  numsharessol as 'NUMSHARES'
  fracsol as 'FRAC'
  buysol as 'BUY'
  status as 'SOLSTATUS'
 end-initializations

 case status of
  XPRS_OPT: writeln("Problem solved to optimality")
  XPRS_UNF: writeln("Problem solving unfinished")
  XPRS_INF: writeln("Problem is infeasible")
  XPRS_UNB,XPRS_OTH:  writeln("No solution available")
 end-case 

 ! Solution printing
 writeln("Total return: ", returnsol)
 writeln("Number of shares: ", numsharessol)
 forall(s in SHARES | fracsol(s)>0)
  writeln(s, ": ", fracsol(s)*100, "% (", buysol(s), ")")
 
 write_html_results

! *********** Writing an HTML result file ***********
 procedure write_html_results
  setparam("datetimefmt", "%0d-%N-%y, %0H:%0M:%0S")

  HTMLFILE:= INPUTFILE + "_sol.html"
  fopen(HTMLFILE, F_OUTPUT)
  writeln("<html>")
  writeln("<head>")
  writeln("<style type='text/css'>")
  writeln("body {font-family: Verdana, Geneva, Helvetica, Arial, sans-serif; color: 000055 }")
  writeln("table td {background-color: ffffaa; text-align: left }")
  writeln("table th {background-color: 053055; color: ffcc88}")
 writeln("</style>")
  writeln("</head>")

  writeln("<body>")
  writeln("<center><h2>Portfolio Optimization Results</h2></center>")
  writeln("<table width='100%' cellpadding='5' cellspacing='0' border=0>")
  writeln("<tr><td width='55%'><font color='#000055'><b>Total return: ",
          returnsol, "</b></font></td><td><font color='#885533'><b>Problem instance: ",
          INPUTFILE,"</b></font></td></tr>")
  writeln("<tr><td><font color='#000055'><b>Number of shares: ", numsharessol, "</b></font></td><td><font color='#885533'><b>Date: ", datetime(SYS_NOW),"</b></font></td></tr>")
  writeln("<tr><td colspan='2'>&nbsp;</td></tr>")
  writeln("</table>")

  writeln("<table cellpadding='2' cellspacing='1' width='100%'>")
  writeln("<tr><th>Value</th><th>Percentage</th></tr>")
 forall(s in SHARES | fracsol(s)>0) 
   writeln("<tr><td>", s, "</td><td>", strfmt(fracsol(s)*100,4,2), 
           "%</td></tr>")
  writeln("</table>")
  writeln("</body>")
  writeln("</html>")
  fclose(F_OUTPUT)
 end-procedure

end-model

runfoliopardistr.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file runfoliopardistr.mos
   `````````````````````````
   Master model running several instances of the
   portfolio optimization model in parallel using
   several Mosel instances (distribute architecture).

   Runs model foliomemio.mos.

   *** ATTENTION: This model will return an error if ***
   *** no more than one Xpress licence is available. ***
   *** With a single license, use setting NUMPAR=1   ***
      
  (c) 2010 Fair Isaac Corporation
      author: S.Heipcke, July 2010, rev. Dec. 2017
*******************************************************!)

model "Run portfolio optimization model (distributed parallel)"
 uses "mmjobs"                       ! Use multiple model handling
 uses "mmsystem", "mmxprs"

 parameters
  MODELFILE = "foliomemio"           ! Optimization model
  INPUTFILE = "folio10.dat"          ! File with problem data
 
  MAXRISK = 1/3                      ! Max. investment into high-risk values
  MINREG = 0.2                       ! Min. investment per geogr. region
  MAXREG = 0.5                       ! Max. investment per geogr. region
  MAXSEC = 0.25                      ! Max. investment per ind. sector
  MAXVAL = 0.2                       ! Max. investment per share
  MINVAL = 0.1                       ! Min. investment per share
  MAXNUM = 9                         ! Max. number of different assets

  NUMPAR = 5                         ! Number of model instances to run
 end-parameters
 
 forward procedure write_html_header
 forward procedure write_html_line(i:integer)
 forward procedure write_html_line(i:integer,msg:string)
 forward procedure write_html_footer

 declarations
  SHARES: set of string              ! Set of shares
  returnsol,totalreturn: real        ! Solution values
  numsharessol,status,totalnum,totalopt: integer
  fracsol: dynamic array(SHARES) of real  ! Fraction of capital used per share
  buysol: dynamic array(SHARES) of real   ! 1 if asset is in portfolio, 0 otherwise

  foliomod: dynamic array(Instances:range) of Model  ! Mosel models
  moselinst: dynamic array(Instances) of Mosel       ! Mosel instances
 end-declarations

! Compile the optimization model
 if compile(MODELFILE+".mos") <> 0 then
  writeln("Error during model compilation")
  exit(1)
 end-if

! Start remote Mosel instances: 
! "" stands for the node running this model; try IP addresses or host names
 forall(i in 1..NUMPAR) do
  create(moselinst(i))
  if connect(moselinst(i), "")<>0 then exit(2); end-if
 end-do

! Load several instances of the optimization model
 forall(i in 1..NUMPAR) do
  create(foliomod(i))
  load(moselinst(i), foliomod(i), "rmt:"+MODELFILE+".bim")
 end-do
 fdelete(MODELFILE+".bim")

! Start all instances in parallel, using unique file names for output
 forall(i in Instances)
  run(foliomod(i), "MAXRISK=" + MAXRISK + ",MINREG=" + MINREG + 
  ",MAXREG=" + MAXREG + ",MAXSEC=" + MAXSEC +
  ",MAXVAL=" + MAXVAL + ",MINVAL=" + MINVAL + 
  ",MAXNUM=" + (MAXNUM-i) + ",DATAFILE='rmt:" + INPUTFILE +
  "',OUTPUTFILE='rmt:solout" + i + ".dat"+ "',FRACSOL='FRAC" + i +
  "',BUYSOL='BUY" + i + "',NUMSHARES='NUMSHARES" + i + 
  "',RETSOL='RETSOL" + i + "',SOLSTATUS='SOLSTATUS" + i + "'" ) 

! Wait until all models have finished 
! (alternatively: could retrieve results as soon as a run finishes)
 forall(i in Instances) do
  wait                              ! Wait for model terminations
  dropnextevent                     ! Ignore termination event message
 end-do

! Output: generate an HTML page with all solutions
 write_html_header

 forall(i in Instances) do
  forall(s in SHARES) do
   fracsol(s):=0; buysol(s):=0
  end-do 

  OFile:="solout"+i+".dat"

  initializations from OFile
   returnsol as 'RETSOL'+i
   numsharessol as 'NUMSHARES'+i
   fracsol as 'FRAC'+i
   buysol as 'BUY'+i
   status as 'SOLSTATUS'+i
  end-initializations

  fdelete(OFile)

  case status of
   XPRS_OPT: do
              write_html_line(i)
              totalreturn+=returnsol
              totalnum+=numsharessol
              totalopt+=1
             end-do 
   XPRS_UNF: write_html_line(i,"Problem solving unfinished")
   XPRS_INF: write_html_line(i,"Problem is infeasible")
   XPRS_UNB,XPRS_OTH: write_html_line(i,"No solution available")
  end-case 

 end-do
 
 write_html_footer

! *********** Writing an HTML result file ***********
 procedure write_html_header
  setparam("datetimefmt", "%0d-%N-%y, %0H:%0M:%0S")

  HTMLFILE:= INPUTFILE + "_sol.html"
  fopen(HTMLFILE, F_OUTPUT)
  writeln("<html>")
  writeln("<head>")
  writeln("<style type='text/css'>")
  writeln("body {font-family: Verdana, Geneva, Helvetica, Arial, sans-serif; color: 000055 }")
  writeln("table td {background-color: ffffaa; text-align: left }")
  writeln("table th {background-color: 053055; color: ffcc88}")
 writeln("</style>")
  writeln("</head>")

  writeln("<body>")
  writeln("<center><h2>Portfolio Optimization Summary Results</h2></center>")
  writeln("<table width='100%' cellpadding='5' cellspacing='0' border=0>")
  writeln("<tr><td width='55%'><font color='#000055'><b> </b></font></td><td><font color='#885533'><b>Problem data: ",
          INPUTFILE,"</b></font></td></tr>")
  writeln("<tr><td><font color='#000055'><b> </b></font></td><td><font color='#885533'><b>Date: ", datetime(SYS_NOW),"</b></font></td></tr>")
  writeln("<tr><td colspan='2'>&nbsp;</td></tr>")
  writeln("</table>")

  writeln("<table cellpadding='2' cellspacing='1' width='100%'>")
  writeln("<tr><th>Instance</th><th>Return</th><th>No. shares</th><th>Value: Percentage</th></tr>")
 end-procedure

 procedure write_html_line(i:integer)
  write("<tr><td><center>", i, "</center></td><td>", returnsol, "</td><td><center>", numsharessol, "</center></td><td>")
  writeln("<table cellpadding='2' cellspacing='0' width='100%'>")
  ct:=0
  forall(s in SHARES | fracsol(s)>0) do
   ct+=1   
   writeln(if(ct mod 4=1, "<tr>", ""),
           "<td><font size='-1'>", s, ": ", strfmt(fracsol(s)*100,4,2), "%,</font></td>", 
           if(ct mod 4=0, "</tr>", ""))
  end-do  
  writeln(if(ct mod 4<>0, "</tr>", ""), "</table></td></tr>") 
 end-procedure

 procedure write_html_line(i:integer,msg:string)
  writeln("<tr><td><center>", i, "</center></td><td align='left' colspan='3'>", msg, "</td></tr>")
 end-procedure

 procedure write_html_footer
  writeln("<tr><th>Average</th><th>", totalreturn/totalopt, "</th><th>", totalnum/totalopt, "</th><th></th></tr>")
  writeln("</table>")
  writeln("</body>")
  writeln("</html>")
  fclose(F_OUTPUT)
 end-procedure

end-model

folioxml.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file folioxml.mos
   `````````````````
   Modeling a small LP problem 
   to perform portfolio optimization.
   -- Reading/writing data in XML format --
   
  (c) 2010 Fair Isaac Corporation
      author: S.Heipcke, July 2010, rev. July 2013
*******************************************************!)

model "Portfolio optimization with LP"
 uses "mmxprs"
 uses "mmxml"                        ! XML interface functions

 parameters
  DATAFILE= "folio.xml"              ! File with problem data
  OUTFILE= "result.xml"              ! Output file 
  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

 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

  AllData, ResData: xmldoc           ! XML document
  Share,Root,Sol: integer            ! XML nodes
  NodeList: list of integer
 end-declarations

! Reading data from an XML file
 load(AllData, DATAFILE)

 getnodes(AllData, "portfolio/share", NodeList) 
 RISK:= union(l in NodeList | getattr(AllData,l,"risk")="high") 
         {getstrattr(AllData,l,"name")} 
 NA:= union(l in NodeList | getattr(AllData,l,"region")="NA") 
         {getstrattr(AllData,l,"name")} 
 
(! Alternatively:
 getnodes(AllData, "portfolio/share[@risk='high']/attribute::name", NodeList)
 RISK:=union(r in NodeList) {getstrvalue(AllData,r)}
 getnodes(AllData, "portfolio/share[@region='NA']/attribute::name", NodeList)
 NA:=union(r in NodeList) {getstrvalue(AllData,r)}
 getnodes(AllData, "portfolio/share", NodeList) 
!)

 forall(l in NodeList)
   RET(getstrattr(AllData,l,"name")):= getintattr(AllData, l, "ret") 


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

! 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) <= MAXRISK

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

! Spend all the capital
 sum(s in SHARES) frac(s) = 1
 
! Upper bounds on the investment per share
 forall(s in SHARES) frac(s) <= MAXVAL

! Solve the problem
 maximize(Return)

! Solution printing
 writeln("Total return: ", getobjval)
 forall(s in SHARES) 
  writeln(strfmt(s,-12), ": \t", strfmt(getsol(frac(s))*100,5,2), "%")


! Create solution representation in XML format
 Root:=addnode(ResData, 0, XML_ELT, "result")    ! Create root node "result"
 Sol:= addnode(ResData, Root, XML_ELT, "solution") ! Add a "solution" node
 setattr(ResData, Sol, "value", getobjval)       ! ... with attribute "value"
 forall(s in SHARES) do
   Share:=addnode(ResData, Sol, XML_ELT,"share") ! Add a node to "solution"
   setattr(ResData, Share, "name", s)            ! ... with attribute "name"
   setvalue(ResData, Share, frac(s).sol)         ! ... and solution value
 end-do
 
 save(ResData, OUTFILE)        ! Save solution to XML format file
 save(ResData, Sol, "")        ! Display XML format solution on screen

end-model 

folioxmlqp.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file folioxmlqp.mos
   ```````````````````
   Modeling a small QP problem 
   to perform portfolio optimization.
   -- 1. QP: minimize variance
      2. MIQP: limited number of assets ---
   -- Reading/writing data in XML format --
   
  (c) 2010 Fair Isaac Corporation
      author: S.Heipcke, July 2010, rev. Sep. 2017
*******************************************************!)

model "Portfolio optimization with QP/MIQP"
 uses "mmxprs", "mmnl"
 uses "mmxml"                       ! XML interface functions

 parameters
  MAXVAL = 0.3                      ! Max. investment per share
  MINAM = 0.5                       ! Min. investment into N.-American values
  MAXNUM = 4                        ! Max. number of different assets
  TARGET = 9.0                      ! Minimum target yield
 end-parameters

 forward procedure save_solution(num: integer)

 declarations
  SHARES = 1..10                    ! Set of shares
  RISK: set of integer              ! Set of high-risk values among shares
  NA: set of integer                ! Set of shares issued in N.-America
  RET: array(SHARES) of real        ! Estimated return in investment
  VAR: array(SHARES,SHARES) of real ! Variance/covariance matrix of
                                    ! estimated returns

  AllData, Solution: xmldoc         ! XML document
  Share,Root,Sol: integer           ! XML nodes
  NodeList: list of integer
 end-declarations

! Reading data from an XML file
 load(AllData, "folioqp.xml")
 getnodes(AllData, "portfolio/share", NodeList) 
 RISK:= union(l in NodeList | getattr(AllData,l,"risk")="high") 
         {getintattr(AllData,l,"name")} 
 NA:= union(l in NodeList | getattr(AllData,l,"region")="NA") 
         {getintattr(AllData,l,"name")} 
 forall(l in NodeList)
   RET(getintattr(AllData,l,"name")):= getintattr(AllData, l, "ret") 

! Read a second XML file
 reset(AllData)                     ! Empty the "xmldoc" object
 load(AllData, "folioqpvar.xml")
 getnodes(AllData, "variance/var", NodeList) 
 forall(l in NodeList)
   VAR(getintattr(AllData, l, "ind1"),getintattr(AllData, l, "ind2")):=
     getrealvalue(AllData,l)
 reset(AllData)                     ! Free up memory

! Prepare XML structure for solution output
 Root:=addnode(Solution, 0, XML_ELT, "result")    ! Create root node "result"


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

! **** First problem: unlimited number of assets ****

! Objective: mean variance
 Variance:= sum(s,t in SHARES) VAR(s,t)*frac(s)*frac(t) 

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

! Spend all the capital
 sum(s in SHARES) frac(s) = 1
 
! Target yield
 sum(s in SHARES) RET(s)*frac(s) >=  TARGET

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

! Solve the problem
 minimize(Variance)

! Solution printing
 writeln("With a target of ", TARGET, " minimum variance is ", getobjval)
 forall(s in SHARES) writeln(s, ": ", getsol(frac(s))*100, "%")  

 save_solution(1)

! **** Second problem: limit total number of assets ****

 declarations
  buy: array(SHARES) of mpvar       ! 1 if asset is in portfolio, 0 otherwise
 end-declarations

! Limit the total number of assets
 sum(s in SHARES) buy(s) <= MAXNUM

 forall(s in SHARES) do
  buy(s) is_binary
  frac(s) <= buy(s)
 end-do

! Solve the problem
 minimize(Variance)

 writeln("With a target of ", TARGET," and at most ", MAXNUM,
          " assets,\n minimum variance is ", getobjval)
 forall(s in SHARES) writeln(s, ": ", getsol(frac(s))*100, "%") 

 save_solution(2)

! Write solution to a new XML file
 save(Solution, "qpresult.xml")

!*********************************************************************

! Solution printing to a file
 procedure save_solution(num: integer)
   Sol:= addnode(Solution, Root, XML_LASTCHILD, XML_ELT, "solution")
                                       ! Append a "solution" node
   setattr(Solution, Sol, "num", num)  ! ... with attribute "num"
   forall(s in SHARES) do              ! Add node containing solution value
    Share:= addnode(Solution, Sol, "share", frac(s).sol)
    setattr(Solution, Share, "name", s)
   end-do
   save(Solution, Sol, "")             ! Display XML solution on screen
 end-procedure  

 
end-model 

runfolioxml.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file runfolioxml.mos
   ````````````````````
   Master model running portfolio optimization model.

   Runs model foliomemio.mos.
   -- Data input/output in memory --
   -- Using XML module for writing HTML output --
      
  (c) 2010 Fair Isaac Corporation
      author: S.Heipcke, Sep. 2010, rev. Sep. 2012
*******************************************************!)

model "Run portfolio optimization model"
 uses "mmjobs"                       ! Use multiple model handling
 uses "mmsystem", "mmxprs"
 uses "mmxml"

 parameters
  MODELFILE = "foliomemio.mos"       ! Optimization model
  INPUTFILE = "folio10.dat"          ! File with problem data
 
  MAXRISK = 1/3                      ! Max. investment into high-risk values
  MINREG = 0.2                       ! Min. investment per geogr. region
  MAXREG = 0.5                       ! Max. investment per geogr. region
  MAXSEC = 0.25                      ! Max. investment per ind. sector
  MAXVAL = 0.2                       ! Max. investment per share
  MINVAL = 0.1                       ! Min. investment per share
  MAXNUM = 15                        ! Max. number of different assets
 end-parameters
 
 forward procedure write_html_results

 declarations
  SHARES: set of string              ! Set of shares
  RISK: set of string                ! Set of high-risk values among shares
  REGIONS: set of string             ! Geographical regions
  TYPES: set of string               ! Share types (ind. sectors)
  LOCTAB: dynamic array(REGIONS,SHARES) of boolean ! Shares per geogr. region
  RET: array(SHARES) of real         ! Estimated return in investment
  SECTAB: dynamic array(TYPES,SHARES) of boolean ! Shares per industry sector

  returnsol: real                    ! Solution values
  numsharessol,status: integer
  fracsol: array(SHARES) of real     ! Fraction of capital used per share
  buysol: array(SHARES) of real      ! 1 if asset is in portfolio, 0 otherwise

  foliomod: Model
 end-declarations

! Compile and load the optimization model
 if compile("", MODELFILE, "shmem:bim") <> 0 then
  writeln("Error during model compilation")
  exit(1)
 end-if
 load(foliomod, "shmem:bim")
 fdelete("shmem:bim")

! Read in data from file
 initializations from INPUTFILE
  RISK RET LOCTAB SECTAB
 end-initializations

! Save data to memory
 initializations to "raw:"
  RISK as 'shmem:RISK'
  RET as 'shmem:RET'
  LOCTAB as 'shmem:LOCTAB'
  SECTAB as 'shmem:SECTAB'
 end-initializations

 run(foliomod, "MAXRISK=" + MAXRISK + ",MINREG=" + MINREG + 
  ",MAXREG=" + MAXREG + ",MAXSEC=" + MAXSEC +
  ",MAXVAL=" + MAXVAL + ",MINVAL=" + MINVAL +
  ",MAXNUM=" + MAXNUM + ",DATAFILE='raw:',OUTPUTFILE='raw:'," +
  "RISKDATA='shmem:RISK',RETDATA='shmem:RET',LOCDATA='shmem:LOCTAB'," +
  "SECDATA='shmem:SECTAB',FRACSOL='shmem:FRAC',BUYSOL='shmem:BUY'," +
  "NUMSHARES='shmem:NUMSHARES',RETSOL='shmem:RETSOL'," +
  "SOLSTATUS='shmem:SOLSTATUS'")
  wait                              ! Wait for model termination
  dropnextevent                     ! Ignore termination event message

 initializations from  "raw:"
  returnsol as 'shmem:RETSOL'
  numsharessol as 'shmem:NUMSHARES'
  fracsol as 'shmem:FRAC'
  buysol as 'shmem:BUY'
  status as 'shmem:SOLSTATUS'
 end-initializations

 case status of
  XPRS_OPT: writeln("Problem solved to optimality")
  XPRS_UNF: writeln("Problem solving unfinished")
  XPRS_INF: writeln("Problem is infeasible")
  XPRS_UNB,XPRS_OTH:  writeln("No solution available")
 end-case 

 ! Solution printing
 writeln("Total return: ", returnsol)
 writeln("Number of shares: ", numsharessol)
 forall(s in SHARES | fracsol(s)>0)
  writeln(s, ": ", fracsol(s)*100, "% (", buysol(s), ")")
 
 write_html_results

! *********** Writing an HTML result file ***********
 procedure write_html_results
  declarations
   OutputData: xmldoc
   Root, Head, Body, Style, Title, Table, Row, Cell: integer
  end-declarations

  setparam("datetimefmt", "%0d-%N-%y, %0H:%0M:%0S")

  Root:= addnode(OutputData, 0, XML_ELT, "html")
  Head:= addnode(OutputData, Root, XML_ELT, "head")
  Style:= addnode(OutputData, Head, XML_ELT, "style",
    "body {font-family: Verdana, Geneva, Helvetica, Arial, sans-serif; color: 000055 }\n" +
    "table td {background-color: ffffaa; text-align: left }\n" +
    "table th {background-color: 053055; color: ffcc88}")
  setattr(OutputData, Style, "type", "text/css")
 
  Body:= addnode(OutputData, Root, XML_LASTCHILD, XML_ELT, "body")
  TitleCenter:= addnode(OutputData, Body, XML_ELT, "center")
  Title:= addnode(OutputData, TitleCenter, XML_ELT, "h2", 
              "Portfolio Optimization Results")

  Table:= addnode(OutputData, Body, XML_ELT, "table")
    setattr(OutputData, Table, "width", '100%')
    setattr(OutputData, Table, "cellpadding", '5')
    setattr(OutputData, Table, "cellspacing", '0')
    setattr(OutputData, Table, "border", 0)
  Row:= addnode(OutputData, Table, XML_ELT, "tr")
  Cell:= addnode(OutputData, Row, XML_ELT, "td", "Total return: " + returnsol)
    setattr(OutputData, Cell, "width", '55%')
    setattr(OutputData, Cell, "style", 'color: #8B4513; font-weight: bold;')
  Cell:= addnode(OutputData, Row, XML_LASTCHILD, XML_ELT, "td",
              "Problem instance: " + INPUTFILE)
    setattr(OutputData, Cell, "style", 'color: #8B4513; font-weight: bold;')
  Row:= addnode(OutputData, Table, XML_LASTCHILD, XML_ELT, "tr")
  Cell:= addnode(OutputData, Row, XML_ELT, "td",
                     "Number of shares: " + numsharessol)
    setattr(OutputData, Cell, "style", 'color: #000055; font-weight: bold;')
  Cell:= addnode(OutputData, Row, XML_LASTCHILD, XML_ELT, "td",
              "Date: " + datetime(SYS_NOW))
    setattr(OutputData, Cell, "style", 'color: #8B4513; font-weight: bold;')
  Row:= addnode(OutputData, Table, XML_LASTCHILD, XML_ELT, "tr")
  Cell:= addnode(OutputData, Row, XML_ELT, "td")
    setattr(OutputData, Cell, "colspan", 2)
  CellEmpty:= addnode(OutputData, Cell, XML_ELT, "br")

  Table:= addnode(OutputData, Body, XML_LASTCHILD, XML_ELT, "table")
    setattr(OutputData, Table, "width", '100%')
    setattr(OutputData, Table, "cellpadding", '2')
    setattr(OutputData, Table, "cellspacing", '1')
  Row:= addnode(OutputData, Table, XML_ELT, "tr")
  Cell:= addnode(OutputData, Row, XML_ELT, "th", "Value")
  Cell:= addnode(OutputData, Row, XML_LASTCHILD, XML_ELT, "th", "Percentage")
  forall(s in SHARES | fracsol(s)>0) do
    Row:= addnode(OutputData, Table, XML_LASTCHILD, XML_ELT, "tr")
    Cell:= addnode(OutputData, Row, XML_ELT, "td", s)
    Cell:= addnode(OutputData, Row, XML_LASTCHILD, XML_ELT, "td", 
             textfmt(fracsol(s)*100,4,2) + "%")
  end-do

  HTMLFILE:= INPUTFILE + "_sol.html"
  save(OutputData, HTMLFILE)           ! Write the XML file

 end-procedure

end-model

foliojson.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file foliojson.mos
   ``````````````````
   Modeling a small LP problem 
   to perform portfolio optimization.
   -- Reading/writing data in JSON format --
   
  (c) 2014 Fair Isaac Corporation
      author: S.Heipcke, Sep. 2014
*******************************************************!)

model "Portfolio optimization with LP"
 uses "mmxprs"
 uses "mmxml"                        ! XML/JSON interface functions

 parameters
  DATAFILE= "folio.json"             ! File with problem data
  OUTFILE= "result.json"             ! Output file 
  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

 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

  AllData, ResData: xmldoc           ! XML document
  Share,Root,Sol: integer            ! XML nodes
  NodeList: list of integer
 end-declarations

! Reading data from a JSON file
 jsonload(AllData, DATAFILE)


 getnodes(AllData, "jsv/share/jsv", NodeList) 
 RISK:= union(l in NodeList | 
              getvalue(AllData,getnode(AllData,l,"risk"))="high") 
         {getstrvalue(AllData,getnode(AllData,l,"name"))} 

 NA:= union(l in NodeList | 
              getvalue(AllData,getnode(AllData,l,"region"))="NA") 
         {getstrvalue(AllData,getnode(AllData,l,"name"))} 

(! Alternatively:
 getnodes(AllData, "jsv/share/jsv/risk[string()='high']/../name", NodeList)
 RISK:=union(r in NodeList) {getstrvalue(AllData,r)}
 getnodes(AllData, "jsv/share/jsv/region[string()='NA']/../name", NodeList)
 NA:=union(r in NodeList) {getstrvalue(AllData,r)}
 getnodes(AllData, "jsv/share/jsv", NodeList) 
!)

 forall(l in NodeList)
   RET(getstrvalue(AllData,getnode(AllData,l,"name"))):= 
     getintvalue(AllData,getnode(AllData,l,"ret")) 


(! Reading alternative data format 'share2':
 getnodes(AllData, "jsv/share2/jsv/jsv[position()=6 and string()='high']/..",
   NodeList)
 RISK:= union(r in NodeList) 
   {getstrvalue(AllData,getnode(AllData,r,"jsv[position()=1]"))}
 getnodes(AllData, "jsv/share2/jsv/jsv[position()=5 and string()='NA']/..",
   NodeList)
 NA:= union(r in NodeList) 
   {getstrvalue(AllData,getnode(AllData,r,"jsv[position()=1]"))}
 getnodes(AllData, "jsv/share2/jsv", NodeList) 
 forall(l in NodeList)
   RET(getstrvalue(AllData,getnode(AllData,l,"jsv[position()=1]"))):= 
     getintvalue(AllData,getnode(AllData,l,"jsv[position()=2]"))  
!)

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

! 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) <= MAXRISK

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

! Spend all the capital
 sum(s in SHARES) frac(s) = 1
 
! Upper bounds on the investment per share
 forall(s in SHARES) frac(s) <= MAXVAL

! Solve the problem
 maximize(Return)

! Solution printing
 writeln("Total return: ", getobjval)
 forall(s in SHARES) 
  writeln(strfmt(s,-12), ": \t", strfmt(getsol(frac(s))*100,5,2), "%")


! Create solution representation in JSON format
 Root:=addnode(ResData, 0, XML_ELT, "jsv")         ! Create root node
 Sol:= addnode(ResData, Root, XML_ELT, "solution") ! Add a "solution" node
 n:=addnode(ResData, Sol, "value", getobjval)      ! ... with child "value"
 Share:= addnode(ResData, Sol, XML_ELT, "share")   ! Add a node to "solution"
 forall(s in SHARES)
   n:=addnode(ResData, Share, s,frac(s).sol)       ! Add a node to "share"
 
 jsonsave(ResData, OUTFILE)        ! Save solution to JSON format file
 jsonsave(ResData, Sol, "")        ! Display JSON format solution on screen
 save(ResData, Sol, "")            ! Display XML format solution on screen
end-model 

foliohttpsrv.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file foliohttpsrv.mos
   `````````````````````
   HTTP server receiving requests for model runs with
   XML-format data and running instances of model 
   folioxml.mos for every request (on the same Mosel
   instance that is running this http server model).
   
  (c) 2013 Fair Isaac Corporation
      author: S.Heipcke, July 2013, rev. Apr. 2014
*******************************************************!)

model "HTTP server launching portfolio model"
 uses "mmhttp"                       ! Use HTTP functions
 uses "mmjobs"                       ! Use multiple model handling

 parameters
  MODELFILE = "folioxml"             ! Optimization model
 end-parameters 

 declarations
  foliomod = record
   m: Model                          ! Mosel model  
   id: integer                       ! Model index 
   rid: integer                      ! Request index
   tempdir: string                   ! Name of temporary data directory
  end-record
  modqueue: list of foliomod         ! Active models
                       
  DATAFILE, bimfile: string
  MAXRISK, MAXVAL, MINAM: real  
 end-declarations

! Compile the optimization model
 bimfile:=getparam("tmpdir")+"/"+MODELFILE+".bim"
 if compile("g",MODELFILE+".mos",bimfile) <> 0 then
  writeln("Error during model compilation")
  exit(1)
 end-if


!**** Create a new model instance and start running it ****
 function newfoliomod(rid: integer): foliomod
    ! Load the optimization model 
    load(returned.m, bimfile)
    returned.id:= getid(returned.m)
    returned.rid:= rid

    ! Extract the data file from the tar archive
    returned.tempdir:=getparam("tmpdir")+"/tartemp"+rid
    makedir(returned.tempdir)
    untar("zlib.gzip:"+httpreqfile(rid), returned.tempdir)   ! Untar the data
  
    ! The configuration data is held in a fixed-name file
    initializations from returned.tempdir+"/folioconfig.dat"
      MAXRISK
      MAXVAL
      MINAM
      DATAFILE
    end-initializations

    ! Run model, disabling output
    setdefstream(returned.m,F_OUTPUT, "null:") 
    run(returned.m, "MAXRISK=" + MAXRISK + ",MAXVAL=" + MAXVAL + 
        ",MINAM=" + MINAM + ",DATAFILE='" + returned.tempdir+"/"+DATAFILE +
        "',OUTFILE="+httpreqfile(rid))
 end-function

!**** Locate an entry in the queue of active models ****
 function findmodel(mid: integer): integer
   ct:=0
   returned:=-1
   forall(p in modqueue, ct as counter)
    if p.id=mid then
     returned:= p.rid

     ! Delete temporary files
     removefiles(SYS_RECURS, p.tempdir, "*")
     removedir(p.tempdir)

     ! Delete entries from list
     unload(p.m)
     
     break
    end-if
 
   if returned<0 then
    writeln("Queue entry not found")
   elif ct=1 then
    cuthead(modqueue,1)
   elif ct=modqueue.size then
    cuttail(modqueue,1)
   elif ct>1 and ct<modqueue.size then
    tqueue:=splittail(modqueue,-ct+1)
    cuthead(tqueue,1)
    modqueue+=tqueue
   end-if

 end-function

!**** Server: receive optimization requests, start submodel, send back results

! Server configuration
 setparam("http_defport",2533)          ! Set server port (2533)
 setparam("http_maxreq", 4)             ! Max. number of simultaneous requests
 setparam("http_srvconfig",HTTP_POST)   ! Only POST requests
 setparam("workdir",getparam("tmpdir")) ! Move to temporary directory

 httpstartsrv                           ! Start the server

! Handle events received by the server
 repeat
  wait                                  ! Wait for an event
  ev:=getnextevent
  if ev.class=EVENT_HTTPNEW then        ! Request pending
   r:=integer(ev.value)                 ! Get request ID

   if httpreqtype(r)=HTTP_POST and      ! This is redundant (only POST expected)
      httpreqlabel(r)="runmodel" then
   !**** Extract data and start model run **** 
     writeln(time(SYS_NOW), " Request ", r, " received from ", httpreqfrom(r))
     if httpreqstat(r)<>2 then          ! Whether data file exists
      httpreplycode(r,400,"Missing data archive")   ! Reply "Bad request"
     else 
      modqueue += [newfoliomod(r)]
     end-if

   else
    httpreplycode(r,400)                ! "Bad request"             
   end-if

  elif ev.class=EVENT_END then
   !**** Retrieve results file and return it to the client; cleaning up **** 
    ! Retrieve sender model ID
    evmodid:= ev.fromid

    ! Find model in queue and remove it
    rid:=findmodel(evmodid)
   ! fcopy(httpreqfile(rid),"")        ! Display file contents

    ! Reply to client
    writeln(time(SYS_NOW), " Reply to request ", rid)
    if ev.value=RT_OK then
     httpreply(rid,httpreqfile(rid))
    elif ev.value=RT_LICERR then
     httpreplycode(rid, 500, "No license available to run optimization model")
    else
     httpreplycode(rid, 500, "Error during model execution")
    end-if 
  end-if 
 
 until false

end-model

foliohttpclient.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file foliohttpclient.mos
   ````````````````````````
   Sending HTTP requests for model runs with
   XML-format data to a server, retrieving and
   displaying the results.

   *** Before running this model, an HTTP server must be
   *** launched by running the file foliohttpsrv.mos.
   
  (c) 2013 Fair Isaac Corporation
      author: S.Heipcke, July 2013
*******************************************************!)

model "HTTP client launching portfolio model"
 uses "mmhttp"                       ! Use HTTP functions
 uses "mmxml"                        ! Use XML format

 parameters
  DATAFILE= "folio.xml"              ! File with problem data
  OUTFILE= "result.xml"              ! Output file 
  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

  SERVERNAME = "localhost"           ! Configure with the machine name/address
                                     ! that is running foliohttpsrv.mos
 end-parameters 

 declarations
  ResData: xmldoc                    ! XML document
  SList: list of integer             ! XML nodes
 end-declarations

 ! Create a temporary file with the configuration data
 TEMPDIR:=getparam("tmpdir")+"/tartemp"
 makedir(TEMPDIR)
 initializations to TEMPDIR+"/folioconfig.dat"
  MAXRISK
  MAXVAL
  MINAM
  DATAFILE
 end-initializations

 ! Create an archive with the configuration data + XML data file
 fcopy(DATAFILE, TEMPDIR)
 newtar(0, "zlib.gzip:tmp:folio.tgz", TEMPDIR, [DATAFILE, "folioconfig.dat"])

 ! Delete temporary files
 removefiles(SYS_RECURS, TEMPDIR, "*")
 removedir(TEMPDIR)

 ! Post the solving request (synchronous mode => waits for reply from server)
 status:=httppost("http://" + SERVERNAME + ":2533/runmodel", 
                  "tmp:folio.tgz", OUTFILE)

 ! Display the result
 if status/100=2 then
  load(ResData, OUTFILE)             ! Reading data from an XML file
  sol:=getnode(ResData, "result/solution") 
  writeln("Solution with value ", getattr(ResData, sol, "value"), ":")
  getnodes(ResData, sol, "share", SList)
  forall(s in SList)
   writeln("  ", getattr(ResData, s, "name"), ": ", getvalue(ResData, s))
 else
  writeln("Request failed with code: ", status, " (", httpreason(status), ")")
  fcopy(OUTFILE,"")                  ! Display output file contents (error msg)
 end-if
 
end-model