| 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. Sep. 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.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(0, V, C)                  ! Retrieve the IIS approximation
              writeln("IIS approximation")
              write("  variables: "); writeln(getsize(V))
              write("  constraints: "); writeln(getsize(C))
              getiis({},{})                    ! Generate all IIS
              numiis:= getparam("XPRS_NUMIIS") ! Retrieve number of IIS
              writeln("Total IIS:", numiis)
              forall(i in 1..numiis) do
               getiis(i, V, C)                 ! Retrieve the i'th IIS
               writeln("IIS ", i)
               write("  variables: "); writeln(getsize(V))
	       forall(v in V) write(getname(v), " "); writeln
               write("  constraints: "); writeln(getsize(C))
	       forall(c in C) write(getname(c), " "); writeln
              end-do	     
            end-do
  XPRS_OTH: writeln("Problem unbounded") 
  XPRS_UNF: writeln("Optimization unfinished")
  else writeln("Unknown problem status")
 end-case
! Solution printing
 procedure print_sol
  writeln("Solution ", getparam("XPRS_MIPSOLS"))
  writeln("Total return: ", getsol(Return))
  forall(s in SHARES | getsol(frac(s))>0)
   writeln(s, ": ", getsol(frac(s))*100, "% (", getsol(buy(s)), ")")
 end-procedure
end-model 
 | 
| 
 | 
| foliomiis.mos | 
| (!******************************************************
   Mosel Example Problems
   ======================
   file foliomiis.mos
   ``````````````````
   Modeling a MIP problem 
   to perform portfolio optimization.
   Same model as in foliomip3.mos.
   -- Infeasible model parameter values --
   -- Retrieving MIIS --
   
  (c) 2010 Fair Isaac Corporation
      author: S.Heipcke, Oct. 2010
*******************************************************!)
model "Portfolio optimization with MIP"
 uses "mmxprs"
 parameters
  MAXRISK = 1/4                     ! Max. investment into high-risk values
  MINREG = 0.1                      ! Min. investment per geogr. region
  MAXREG = 0.25                     ! Max. investment per geogr. region
  MAXSEC = 0.15                     ! Max. investment per ind. sector
  MAXVAL = 0.225                    ! Max. investment per share
  MINVAL = 0.1                      ! Min. investment per share
  MAXNUM = 5                        ! Max. number of different assets
  DATAFILE = "folio5.dat"           ! File with problem data
 end-parameters
 declarations
  SHARES: set of string              ! Set of shares
  RISK: set of string                ! Set of high-risk values among shares
  REGIONS: set of string             ! Geographical regions
  TYPES: set of string               ! Share types (ind. sectors)
  LOC: array(REGIONS) of set of string ! Sets of shares per geogr. region
  RET: array(SHARES) of real         ! Estimated return in investment
  SEC: array(TYPES) of set of string ! Sets of shares per industry sector
 end-declarations
 initializations from DATAFILE
  RISK RET LOC SEC
 end-initializations
 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 that the problem is LP-feasible
! maximize(XPRS_LIN,Return)
! Solve the problem
 maximize(Return)
 declarations
  V: set of mpvar
  C: set of linctr
 end-declarations
 probstat:= getprobstat
 case probstat of
  XPRS_OPT: writeln("Problem solved")
  XPRS_INF: do
              setparam("XPRS_verbose", false)  ! Disable Optimizer output
	      writeln("MIP infeasible")
              getiis({},{})                    ! Generate all IIS
              numiis:= getparam("XPRS_NUMIIS") ! Retrieve number of IIS
                                               ! (at most 1 for MIP) 
              writeln("Total IIS:", numiis)
              forall(i in 1..numiis) do
               getiis(i, V, C)                 ! Retrieve the i'th IIS
               writeln("IIS ", i)
               write("  variables: "); writeln(getsize(V))
	       forall(v in V) write(getname(v), " "); writeln
               write("  constraints: "); writeln(getsize(C))
	       forall(c in C) write(getname(c), " "); writeln
              end-do	     
            end-do
  XPRS_OTH: writeln("Problem unbounded") 
  XPRS_UNF: writeln("Optimization unfinished")
  else writeln("Unknown problem status")
 end-case
end-model 
 | 
| 
 | 
| 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'> </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'> </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'> </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'> </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'> </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
 | 
| 
 |