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:
  • Automated solver tuning (foliolptune.mos)
  • Defining an integer solution callback (foliocb.mos, callback specification by name: foliocbm.mos; using an 'mpsol' object: foliocb_sol.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, MIP, NLP infeasible (folioiis.mos, foliomiis.mos, folionliis.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)
    • main 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)
    • main 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, foliocb_sol.mos, foliocbm.mos, folioenumsol.mos, folioinfeas.mos, folioinfcause.mos, folioiis.mos, foliomiis.mos, folionliis.mos, foliolptune.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, folioqp.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 --

  *** This model cannot be run with a Community Licence 
      for the provided data instance ***

  (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. Sep. 2018
*******************************************************!)

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): dynamic 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. Sep. 2018
*******************************************************!)

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): dynamic 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 --

  *** This model cannot be run with a Community Licence 
      for the provided data instance ***

  (c) 2011 Fair Isaac Corporation
      author: S.Heipcke, July 2011, rev. Mar. 2022
*******************************************************!)

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 printsol

 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, ->printsol)

! 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): dynamic 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 ****
 procedure printsol
  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 
      passing the subroutine as a reference --

  *** This model cannot be run with a Community Licence 
      for the provided data instance ***

  (c) 2008 Fair Isaac Corporation
      author: S.Heipcke, Dec. 2008, rev. Mar. 2022
*******************************************************!)

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 printsol

 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, ->printsol)

! Solve the problem
 maximize(Return)


! Solution printing
 procedure printsol
  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 

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

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

   Same model as in foliomip3.mos.
   -- Defining an integer solution callback to
      store solutions into an 'mpsol' entity --

  *** This model cannot be run with a Community Licence 
      for the provided data instance ***

  (c) 2021 Fair Isaac Corporation
      author: S.Heipcke, June 2021, rev. Mar. 2022
*******************************************************!)

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
  MAXSOLS = 2
 end-parameters

 forward procedure storesol

 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
  Sol: dynamic array(SOLS:range) of mpsol
 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, ->storesol)

! Solve the problem
 maximize(Return)

! Solution printing
 forall(i in SOLS | i <= MAXSOLS) do
  writeln("\nSolution ", i)
  writeln("Total return: ", getsol(Sol(i), Return))
  forall(s in SHARES | getsol(Sol(i), frac(s))>0)
   writeln(s, ": ", getsol(Sol(i), frac(s))*100, "% (", getsol(Sol(i), buy(s)), ")")
 end-do

! **** Store intermediate solutions, keeping up to MAXSOLS in total ****
 procedure storesol
  numsol:= getparam("XPRS_MIPSOLS")
  solid:= (numsol-1) mod MAXSOLS + 1
  writeln("Storing solution ", numsol, " (Return=", Return.sol, ")")
  if numsol>MAXSOLS then 
   reset(Sol(solid))
  else
   create(Sol(solid))
  end-if
  savesol(Sol(solid))
 end-procedure
end-model 

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

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

   Same model as in foliomip3.mos.
   -- Defining an integer solution callback 
      specifying the subroutine via its name --

  *** This model cannot be run with a Community Licence 
      for the provided data instance ***

  (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 public procedure printsol

 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, "printsol")

! Solve the problem
 maximize(Return)


! Solution printing
 public procedure printsol
  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. Feb. 2023
*******************************************************!)

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_HEUREMPHASIS", 0)

! Disable presolve operations that attempt to improve the efficiency by 
! cutting off MIP solutions from the feasible region
 setparam("XPRS_MIPDUALREDUCTIONS", 0)

! 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. Sep. 2018
*******************************************************!)

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

 public declarations
  frac: array(SHARES) of mpvar      ! Fraction of capital used per share
  Return: linctr                    ! Total return
  LimitRisk: linctr                 ! Max. percentage of high-risk values
  LimitMinReg,LimitMaxReg: array(REGIONS) of linctr  ! Min/max perc. per region 
  LimitSec: array(TYPES) of linctr  ! Max. percentage per industry sector 
  TotalOne: linctr                  ! Spend all the capital
 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

! 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. May 2018
*******************************************************!)

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

 public 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
  Return: linctr                    ! Total return
  LimitRisk: linctr                 ! Max. percentage of high-risk values
  LimitMinReg,LimitMaxReg: array(REGIONS) of linctr  ! Min/max perc. per region 
  LimitSec: array(TYPES) of linctr  ! Max. percentage per industry sector 
  TotalOne: linctr                  ! Spend all the capital
  LimitNum: linctr                  ! Max. total number of assets
  LinkUB,LinkLB: array(SHARES) of linctr  ! Linking buy+frac variables
 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: do
              writeln("Problem solved")
              print_sol
            end-do
  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 --

  *** This model cannot be run with a Community Licence 
      for the provided data instance ***

  (c) 2008 Fair Isaac Corporation
      author: S.Heipcke, Dec. 2008, rev. Feb. 2024
*******************************************************!)

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

 public 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
  Return: linctr                    ! Total return
  LimitRisk: linctr                 ! Max. percentage of high-risk values
  LimitMinReg,LimitMaxReg: array(REGIONS) of linctr  ! Min/max perc. per region 
  LimitSec: array(TYPES) of linctr  ! Max. percentage per industry sector 
  TotalOne: linctr                  ! Spend all the capital
  LimitNum: linctr                  ! Max. total number of assets
  LinkUB,LinkLB: array(SHARES) of linctr  ! Linking buy+frac variables
 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: do
              writeln("Problem solved")
              print_sol
            end-do
  XPRS_INF: do
              setparam("XPRS_verbose", false)  ! Disable Optimizer output
	      writeln("LP infeasible")

              getiis({},{})                    ! Generate all IIS
              numiis:= getparam("XPRS_NUMIIS") ! Retrieve number of IIS
              writeln("Total IIS:", numiis, " status:", 
                getparam("XPRS_IISSOLSTATUS"))
 ! IIS status: 0: unstarted, 1: feasible (no IIS), 2: completed, 3: unfinished
              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, rev. Mar. 2024
*******************************************************!)

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

 public 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
  Return: linctr                    ! Total return
  LimitRisk: linctr                 ! Max. percentage of high-risk values
  LimitMinReg,LimitMaxReg: array(REGIONS) of linctr  ! Min/max perc. per region 
  LimitSec: array(TYPES) of linctr  ! Max. percentage per industry sector 
  TotalOne: linctr                  ! Spend all the capital
  LimitNum: linctr                  ! Max. total number of assets
  LinkUB,LinkLB: array(SHARES) of linctr  ! Linking buy+frac variables
 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 whether 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, " status:", 
                getparam("XPRS_IISSOLSTATUS"))
 ! IIS status: 0: unstarted, 1: feasible (no IIS), 2: completed, 3: unfinished
              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 

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

   file folionliis.mos
   ```````````````````
   Modeling a small QCQP or MIQCQP problem 
   to perform portfolio optimization.
  
   Same model as in folioqc.mos or foliomiqc.mos.
   -- Infeasible model parameter values --
   -- Retrieving IIS -- 

  (c) 2023 Fair Isaac Corporation
      author: S.Heipcke, June 2023
*******************************************************!)

model "Portfolio optimization with QCQP"
 uses "mmxprs", "mmnl"

 parameters
  MAXVAL = 0.3                      ! Max. investment per share
  MINAM = 0.5                       ! Min. investment into N.-American values
  MAXVAR = 0.5                      ! Max. allowed variance
  MINVAL = 0.2                      ! Min. investment per share
  MAXNUM = 5                        ! Max. number of different assets
  IFMIP=false                       ! Switch between continuous and discrete
 end-parameters

 declarations
  SHARES = 1..10                    ! Set of 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
 end-declarations

 initializations from "folioqp.dat"
  RET NA VAR
 end-initializations

 public 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
  LimitMinAm: linctr                ! Min. amount for geograph. region 
  TotalOne: linctr                  ! Spend all the capital
  LimitVar: nlctr                   ! Max. variance
  LimitNum: linctr                  ! Max. total number of assets
  LinkUB,LinkLB: array(SHARES) of linctr   ! Linking buy+frac variables
 end-declarations

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

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

! Spend all the capital
 TotalOne:= sum(s in SHARES) frac(s) = 1
 
! Limit variance
 LimitVar:= sum(s,t in SHARES) VAR(s,t)*frac(s)*frac(t) <= MAXVAR

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

 if IFMIP then
! 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
 end-if

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

! Solve the problem
 maximize(Return)

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

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

              getiis({},{},{},{})              ! Generate all IIS
              numiis:= getparam("XPRS_NUMIIS") ! Retrieve number of IIS
              writeln("Total IIS:", numiis, " status:", 
                getparam("XPRS_IISSOLSTATUS"))
 ! IIS status: 0: unstarted, 1: feasible (no IIS), 2: completed, 3: unfinished
              forall(i in 1..numiis) do
                getiis(i, V, C, NC, {})        ! Retrieve the i'th IIS
                writeln("IIS ", i, ":")
                writeln(" variables: ", getsize(V))
	        write("  "); forall(v in V) write(getname(v), " "); writeln
                writeln(" linear constraints: ", getsize(C))
	        write("  "); forall(c in C) write(getname(c), " "); writeln
                writeln(" nonlinear constraints: ", getsize(NC))
	        write("  "); forall(c in NC) 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 

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

   file foliolptune.mos
   ````````````````````
   Modeling a small LP problem 
   to perform portfolio optimization.
   -- Added Tuner flags --
   
  (c) 2008 Fair Isaac Corporation
      author: S.Heipcke, Aug. 2003
*******************************************************!)

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

 public declarations
  SHARES = 1..10                     ! Set of shares
  RISK = {2,3,4,9,10}                ! Set of high-risk values among shares
  NA = {1,2,3,4}                     ! Set of shares issued in N.-America
  RET: array(SHARES) of real         ! Estimated return in investment

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

 RET:: [5,17,26,12,8,9,7,6,31,21]
 
! Objective: total return
 Return:= sum(s in SHARES) RET(s)*frac(s) 

! Limit the percentage of high-risk values
 sum(s in RISK) frac(s) <= 1/3

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

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


(! Problem output from Mosel (to check problem definition, not for tuning):
  exportprob(EP_MAX,'foliomos.lp', Return);
  exportprob(EP_MPS,'foliomos.mat', Return);

! Problem output from the solver (for tuning):
  setparam('XPRS_LOADNAMES',true)
  loadprob(Return);
  writeprob('folioopt.mat', 'x');
!)

! Display progress log 
 setparam('XPRS_VERBOSE',true)

! Solve the problem
 setparam("XPRS_TUNERMAXTIME", 60)
 setparam("XPRS_TUNEROUTPUTPATH", string(expandpath("TuneOut")))
 maximize(XPRS_TUNE, Return)

(!
 declarations
  status:array({XPRS_OPT,XPRS_UNF,XPRS_INF,XPRS_UNB,XPRS_OTH}) of string
 end-declarations

 status::([XPRS_OPT,XPRS_UNF,XPRS_INF,XPRS_UNB,XPRS_OTH])[
          "Optimum found","Unfinished","Infeasible","Unbounded","Failed"]
 
 writeln("Problem status: ", status(getprobstat))
!)
 
! Solution printing
 writeln("Total return: ", getobjval)
 forall(s in SHARES) writeln(s, ": ", getsol(frac(s))*100, "%")  

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. Sep. 2022
*******************************************************!)

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

 public 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
  Return: linctr                    ! Total return
  LimitRisk: linctr                 ! Max. percentage of high-risk values
  LimitMinReg,LimitMaxReg: array(REGIONS) of linctr  ! Min/max perc. per region 
  LimitSec: array(TYPES) of linctr  ! Max. percentage per industry sector 
  LimitNum: linctr                  ! Max. total number of assets
 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_TIMELIMIT", 10)
!               setparam("XPRS_VERBOSE", false)

               ! Option 'r': repairinfeas reports the relaxed constraints/bounds
                repairinfeas(Alrp, Agrp, Albp, Aubp, 'r', delta, "")
		probstat:= 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, rev. Sep. 2022
*******************************************************!)

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

 public 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
  Return: linctr                    ! Total return
  LimitRisk: linctr                 ! Max. percentage of high-risk values
  LimitMinReg,LimitMaxReg: array(REGIONS) of linctr  ! Min/max perc. per region 
  LimitSec: array(TYPES) of linctr  ! Max. percentage per industry sector 
  LimitNum: linctr                  ! Max. total number of assets
 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_TIMELIMIT", 10)
!	       setparam("XPRS_VERBOSE", false)

               ! Option 'r': repairinfeas reports the relaxed constraints/bounds
                repairinfeas(Alrp, Agrp, Albp, Aubp, 'r', delta, "")
		probstat:= 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
   `````````````````
   Main model running portfolio optimization model as submodel.

   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
   ``````````````````
   Main model running portfolio optimization model as submodel.

   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
   ````````````````````
   Main 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
   ``````````````````````
   Main model running portfolio optimization model as submodel
   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
   `````````````````````````
   Main 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
   ````````````````````
   Main model running portfolio optimization model as submodel.

   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

© 2001-2024 Fair Isaac Corporation. All rights reserved. This documentation is the property of Fair Isaac Corporation (“FICO”). Receipt or possession of this documentation does not convey rights to disclose, reproduce, make derivative works, use, or allow others to use it except solely for internal evaluation purposes to determine whether to purchase a license to the software described in this documentation, or as otherwise set forth in a written software license agreement between you and FICO (or a FICO affiliate). Use of this documentation and the software described in it must conform strictly to the foregoing permitted uses, and no other use is permitted.