| (!*******************************************************
   Mosel Example Problems
   ======================
   file lexgoalprog.mos
   ````````````````````
   An example of lexicographic goal programming using the 
   Xpress multi-objective functionality
   Problem description:
   A company produces two electrical products, A and B. Both require
   two stages of production: wiring and assembly. 
   The production plan must meet several goals:
   1. A profit of $200
   2. A contractual requirement of 40 units of product B
   3. To fully utilize the available wiring department hours
   4. To avoid overtime in the assembly department
   (c) 2022 Fair Isaac Corporation
       author: S. Heipcke, June 2022
  *******************************************************!)
model "lexGP" 
 uses "mmxprs"
 public declarations
  ! Decision variables for the number of products to make of each type
   produceA,produceB: mpvar
  ! Deviational variables:
  ! There is a penalty for both under- and over-utilizing each department
   surfeit_wiring, deficit_wiring: mpvar
   surfeit_assembly, deficit_assembly: mpvar
  ! There is no penalty for surfeit in profit or in production of product B, 
  ! only for deficits
   deficit_profit, deficit_productB: mpvar
   Goals: list of linctr or mpvar    ! or also:  list of any
 end-declarations
 produceA is_integer; produceB is_integer
 ! **** Production constraints:
 ! Meet or exceed profit goal of $200
 ! Profit for products A and B are $7 and $6 respectively
 Profit:= 7 * produceA + 6 * produceB 
 Profit + deficit_profit >= 200
 ! Meet or exceed production goal for product B
 produceB + deficit_productB >= 40
 ! Utilize wiring department:
 ! Products A and B require 2 and 3 hours of wiring, 120 hours are available
 2 * produceA + 3 * produceB - surfeit_wiring + deficit_wiring = 120
 ! Utilize assembly department:
 ! Products A and B require 6 and 5 hours of assembly, 300 hours are available
 6 * produceA + 5 * produceB - surfeit_assembly + deficit_assembly = 300
 ! Objective configuration
 Goals:=[deficit_profit, deficit_productB, surfeit_wiring + deficit_wiring,
         surfeit_assembly + deficit_assembly]
(!  Cfg:= [objconfig("priority=4 abstol=0 reltol=0"),
         objconfig("priority=3 abstol=0 reltol=0"),
         objconfig("priority=2 abstol=0 reltol=0"),
         objconfig("priority=1 abstol=0 reltol=0")] !)
 ! Same as:
 forall(i in 1..4) Cfg+=[objconfig(5-i,1,0,0)]
 ! Uncomment this line to try out the effect of inversing priority order:
 ! forall(i in 1..4) Cfg(i).priority:=i
 
! setparam("XPRS_VERBOSE", true)
 ! Minimize deviations, in priority order
 minimize(Goals,Cfg)
 ! **** Solution reporting
 declarations
   SolStat,SolvStat: array(integer) of string    ! Status messages
 end-declarations
 SolvStat:: ([XPRS_SOLVESTATUS_UNSTARTED, XPRS_SOLVESTATUS_STOPPED, 
   XPRS_SOLVESTATUS_FAILED, XPRS_SOLVESTATUS_COMPLETED])  
  ["The solve has not been started.", "Optimization has been interrupted.",
   "Optimization has run into a nonrecoverable problem and failed.",
   "Search completed."] 
 SolStat:: ([XPRS_SOLSTATUS_NOTFOUND, XPRS_SOLSTATUS_OPTIMAL, 
   XPRS_SOLSTATUS_FEASIBLE, XPRS_SOLSTATUS_INFEASIBLE, XPRS_SOLSTATUS_UNBOUNDED])
  ["No solution available.", "An optimal solution has been found.",
   "A solution that is not proven optimal is found.",
   "No solution exists.", "The problem is unbounded, if feasible."]
 writeln("Problem solve status: ", SolvStat(getparam("XPRS_SOLVESTATUS")), 
         " Solution status: ", SolStat(getparam("XPRS_SOLSTATUS")), 
         " Objectives solved: ", getparam("XPRS_SOLVEDOBJS"))
 if getparam("XPRS_SOLVESTATUS")=XPRS_SOLVESTATUS_COMPLETED and
    getparam("XPRS_SOLSTATUS")=XPRS_SOLSTATUS_OPTIMAL and
    getparam("XPRS_SOLVEDOBJS")=4 then
   writeln('Production plan:')
   writeln('Product A: ', produceA.sol, ' units')
   writeln('Product B: ', produceB.sol, ' units')
   writeln('Profit: $', Profit.sol)
   if deficit_profit.sol > 0: 
     writeln('Profit goal missed by $', deficit_profit.sol)
   if deficit_profit.sol > 0:
     writeln('Profit goal missed by $', deficit_profit.sol)
   if deficit_productB.sol > 0:
     writeln('Contractual goal for product B missed by ', deficit_productB.sol, ' units')
   if surfeit_wiring.sol > 0:
     writeln('Unused wiring department hours: ', surfeit_wiring.sol)
   if deficit_wiring.sol > 0:
     writeln('Wiring department overtime: ', deficit_wiring.sol)
   if surfeit_assembly.sol > 0:
     writeln('Unused assembly department hours: ', surfeit_assembly.sol)
   if deficit_assembly.sol > 0:
     writeln('Assembly department overtime: ', deficit_assembly.sol)
 else
   writeln('Problem could not be solved')
 end-if
end-model  
 | 
| (!*******************************************************
   Mosel Example Problems
   ======================
   file markowitzmo.mos
   ````````````````````
    Markowitz portfolio optimization
    A multi-objective quadratic programming example
    -- Display of the optimal frontier as SVG graph --
    In Markowitz portfolio optimization there are two objectives: 
    to maximize reward while minimizing risk (i.e. variance). 
    This example plots several points on the optimal frontier using 
    a blended multi-objective approach, and shows that a point
    computed using a lexicographic approach also lies on this frontier.
   (c) 2022 Fair Isaac Corporation
       author: S. Heipcke, June 2022
  *******************************************************!)
model "markowitzmo (SVG)"
 uses "mmxnlp", "mmsvg"
 declarations
  STOCKS = 1..5                      ! Set of 5 stocks
  RET: array(STOCKS) of real         ! Historical mean return on investment 
  COV: array(STOCKS,STOCKS) of real  ! Historical covariances of the stocks
  x: array(STOCKS) of mpvar          ! Percentage of capital to invest in stocks
  Goals: list of linctr or nlctr     ! Objective functions
  ObjCfg: list of objconfig          ! Configuration of objectives 
 end-declarations
 RET::[0.31, 0.87, 0.31, 0.66, 0.24]
 COV::[0.32,  0.70,  0.19,  0.52,  0.16,
       0.70,  4.35, -0.48, -0.06, -0.03,
       0.19, -0.48,  0.98,  1.10,  0.10,
       0.52, -0.6,   1.10,  2.48,  0.37,
       0.16, -0.3,   0.10,  0.37,  0.31]
! Constraints:
! Must invest 100% of capital
 sum(i in STOCKS) x(i) = 1
! Objectives:
! Total expected return
 Return:= sum(i in STOCKS) RET(i)*x(i)
 Variance:= sum(i,j in STOCKS) x(i)*x(j)*COV(i,j)
! List of objectives
 Goals:=[Return, Variance]
! setparam("XPRS_VERBOSE", true)
! Vary the objective weights to explore the optimal frontier
 declarations
   POINTS: range
   SOLMEAN: array(POINTS) of real
   SOLVAR: array(POINTS) of real
 end-declarations
 SCALEX:=10
 forall(p in 0..20, w=p/20.0+if(p=0,0.0001,if(p=20,-0.0001,0))) do
  ! Negative weight to minimize variance
  ! maximize(Goals,[objconfig(0,w),objconfig(0,w-1)])
 ! Same as:
   maximize(Goals,[objconfig("weight",w),objconfig("weight",w-1)])
   if getprobstat=XPRS_OPT then
     SOLMEAN(p):=Return.sol
     SOLVAR(p):=Variance.sol
     writeln("Solution for w=", w, ": ", SOLMEAN(p), " / ", SOLVAR(p))
   else
     writeln("No solution for w=", w)
   end-if
 end-do
! Now we will maximize profit alone, and then minimize variance while not
! sacrificing more than 10% of the maximum profit
 ObjCfg:=[objconfig("priority=1 weight=1 reltol=0.1"), 
          objconfig("priority=0 weight=-1")]
! Same as:
! ObjCfg:=[objconfig(1,1,0.001,0.1), objconfig(0,-1)]
! or:
! ObjCfg:=[objconfig(1,1,0.001,0.1), objconfig("weight",-1)]
!)
 maximize(Goals,ObjCfg)
 m0:=Return.sol
 v0:=Variance.sol
 writeln("Solution for config=", ObjCfg, ":\n", strfmt("",20), m0, " / ", v0)
! Plot the optimal frontier and mark the individual point that we calculated
 svgaddgroup("GrS", "Variance vs mean return", 'grey')
 svgsetstyle(SVG_STROKEWIDTH, 0.25)
 svgaddgroup("GrM", "Max profit, then variance", 'darkred')
 forall(p in POINTS) svgaddpoint("GrS", SOLMEAN(p)*SCALEX, SOLVAR(p))
 svgaddline("GrS", sum(p in POINTS) [SOLMEAN(p)*SCALEX, SOLVAR(p)])
 svgaddpoint("GrM", m0*SCALEX,v0)
 svgaddtext("GrS",0.5,8, 'Return on investment vs variance')
 svgsetstyle(svggetlastobj, SVG_COLOR, SVG_BLACK)
 svgsetstyle(svggetlastobj, SVG_FONTSIZE, "5px")
 svgsetgraphscale(10)
 svgsetgraphviewbox(0,0,9,9)
 svgsetgraphpointsize(0.5)
 svgsetgraphlabels('Expected return', 'Variance')
! Optionally save graphic to file
 svgsave("markowitz.svg")
! Display the graph and wait for window to be closed by the user 
 svgrefresh
 svgwaitclose("Close browser window to terminate model execution.", 1)
end-model
 | 
| (!*******************************************************
   Mosel Example Problems
   ======================
   file multiobjknapsack.mos
   `````````````````````````
   Multi-objective knapsack example
   (c) 2022 Fair Isaac Corporation
       author: S. Heipcke, June 2022
  *******************************************************!)
model "multiobjknapsack"
 uses "random", "mmxprs"
 
 parameters
   N = 15            ! Number of items
   NOBJ = 2          ! Number of goals
   MAXW = 10         ! Maximum weight that can be carried
 end-parameters
 declarations
   R=1..N                              ! Set of items
   WEIGHT: array(R) of real            ! Weight per item
   OBJS = 1..NOBJ                      ! Set of objectives
   VALUE: array(OBJS,R) of real        ! Value of items for each objective
   take: array(R) of mpvar             ! Whether to select an item
   TotValue: array(OBJS) of linctr     ! Objective functions (goals)
   ObjCfg: array(OBJS) of objconfig    ! Configuration of objectives
 end-declarations
! Generate random weights and two random value metrics
 setmtrandseed(123)
 forall(i in R) WEIGHT(i):= mtrand_int(1, 4)
 forall(o in OBJS, i in R) VALUE(o,i):= mtrand_int(1, 6)
! Decision variables for each item
 forall(i in R) take(i) is_binary
! Total weight cannot exceed maximum weight
 WLimit:= sum(i in R) WEIGHT(i)*take(i) <= MAXW
! Define the objectives
 forall(o in OBJS) TotValue(o):= sum(i in R) VALUE(o,i)*take(i)
! Configuration of multiple objectives: 
! * Distinct priority values: solved as pre-emptive multi-obj problem where
!   a higher value indicates higher priority, that is, to be treated earlier 
! * Equal priority values: solved as Archimedian multi-obj problem
 ObjCfg(1).priority:=2
 ObjCfg(2).priority:=1
! Solve the problem
 setparam("XPRS_VERBOSE", true)         ! Enable solver logging
 setparam("XPRS_MULTIOBJLOG", 1)        ! Configure multi-objective logging: 
                                        ! 0=none, 1=summary, 2=detailed
 maximise(TotValue,ObjCfg)
! Solution reporting
! if getprobstat=XPRS_OPT and getparam("XPRS_SOLVEDOBJS")=NOBJ then
 if getparam("XPRS_SOLVESTATUS")=XPRS_SOLVESTATUS_COMPLETED and
    getparam("XPRS_SOLSTATUS")=XPRS_SOLSTATUS_OPTIMAL then
   writeln('Problem was solved to optimality.')
   write('Items selected:')
   forall(i in R | take(i).sol=1) write(i, ' ')
   writeln("\nTotal weight:", WLimit.act)
   writeln('First objective:', TotValue(1).sol)
   writeln('Second objective:', TotValue(2).act)
 elif getprobstat=XPRS_INF and getparam("XPRS_SOLVEDOBJS")=1 then
   writeln('Failed to solve first objective.')
 else
   writeln('Solved first objective but failed to solve second objective.')
 end-if
end-model
 |