FICO Xpress Optimization Examples Repository
FICO Optimization Community FICO Xpress Optimization Home
Back to examples browserPrevious exampleNext example

Cut generation for an economic lot-sizing (ELS) problem

This model implements various forms of cut-and-branch and branch-and-cut algorithms. In its simplest form (looping over LP solving) it illustrates the following features:
  • adding new constraints and resolving the LP-problem (cut-and-branch)
  • basis in- and output
  • if statement
  • repeat-until statement
  • procedure
The model els.mos also implements a configurable cutting plane algorithm:
  • defining the cut manager node callback function,
  • defining and adding cuts during the MIP search (branch-and-cut), and
  • using run-time parameters to configure the solution algorithm.
The version elsglobal.mos shows how to implement global cuts. And the model version elscb.mos defines additional callbacks for extended logging and user stopping criteria based on the MIP gap.

Another implementation (master model: runels.mos, submodel: elsp.mos) parallelizes the execution of several model instances, showing the following features:
  • parallel execution of submodels
  • communication between different models (for bound updates on the objective function)
  • sending and receiving events
  • stopping submodels
The fourth implementation (master model: runelsd.mos, submodel: elsd.mos) is an extension of the parallel version in which the solve of each submodels are distributed to various computing nodes.

Further explanation of this example: elscb.mos, elsglobal.mos, runels.mos: Xpress Whitepaper 'Multiple models and parallel solving with Mosel', Section 'Solving several model instances in parallel'.

Source Files

Data Files


   Mosel Example Problems

   file runelsd.mos
   Run several instances of the model elsd.mos in
   parallel and coordinate the solution update.
   -- Distributed computing version --
   Before running this model, you need to set up the array
   NodeNames with machine names/addresses of your local network.
   All nodes that are used need to have the same version of
   Xpress installed and suitably licensed, and the server 
   "xprmsrv" must have been started on these machines.
   All files are local to the root node, no write access is
   required at remote nodes.

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

   (c) 2010 Fair Isaac Corporation
       author: S. Heipcke, May 2010, rev. Jun. 2015

model "Els main"
 uses "mmjobs", "mmsystem"

  DATAFILE = "els.dat"
  T = 15
  P = 4
  RI = 1..2                                ! Set of (remote) Mosel instances
  RM = 0..5                                ! Range of models
  TIMES = 1..T                             ! Time periods
  PRODUCTS = 1..P                          ! Set of products
  solprod: array(PRODUCTS,TIMES) of real   ! Sol. values for var.s produce
  solsetup: array(PRODUCTS,TIMES) of real  ! Sol. values for var.s setup
  DEMAND: array(PRODUCTS,TIMES) of integer ! Demand per period
  modELS: array(RM) of Model               ! Models
  NEWSOL = 2                               ! Identifier for "sol. found" event
  Msg: Event                               ! Messages sent by models
  params: text                             ! Submodel runtime parameters

  moselInst: array(RI) of Mosel            ! (Remote) Mosel instances
  NodeNames: array(RI) of string           ! Node names for remote connections

! Setting up remote connections
! Use machine names within your local network, IP addresses, or
! empty string for the current node running this model
 NodeNames :: (1..2)["", "localhost"]

! Start the remote Mosel instances
 forall(i in RI) 
  if connect(moselInst(i), NodeNames(i))<>0 then exit(1); end-if

! Compile, load, and run models M1 and M2
 M1:= 1; M2:=3
 res:= compile("elsd.mos")                        ! Compile locally
 load(moselInst(1), modELS(M1), "rmt:elsd.bim")   ! Load on remote nodes
 load(moselInst(2), modELS(M2), "rmt:elsd.bim")
 forall(m in RM) modELS(m).uid:= m
 setmodpar(params, "DATAFILE", DATAFILE)
 setmodpar(params, "T", T); setmodpar(params, "P", P)
                                       ! Start submodel runs
 setmodpar(params, "ALG", M1); run(modELS(M1), params)
 setmodpar(params, "ALG", M2); run(modELS(M2), params)

 objval:= MAX_REAL
 algsol:= -1; algopt:= -1

  wait                                 ! Wait for the next event
  Msg:= getnextevent                   ! Get the event
  if getclass(Msg)=NEWSOL then         ! Get the event class
   if getvalue(Msg) < objval then      ! Value of the event (= obj. value)
    algsol:= Msg.fromuid               ! ID of model sending the event
    objval:= getvalue(Msg)
    writeln("Improved solution ", objval, " found by model ", algsol)
    forall(m in RM | m <> algsol) send(modELS(m), NEWSOL, objval)
    writeln("Solution ", getvalue(Msg), " found by model ", Msg.fromuid)
 until getclass(Msg)=EVENT_END         ! A model has finished
 algopt:= Msg.fromuid                  ! Retrieve ID of terminated model
 forall(m in RM) stop(modELS(m))       ! Stop all running models

 if algsol=-1 then
  writeln("No solution available")
 else                     ! Retrieve the best solution from shared memory
  initializations from "bin:sol_"+algsol
  initializations from DATAFILE
! Solution printing
  writeln("Best solution found by model ", algsol) 
  writeln("Optimality proven by model ", algopt) 
  writeln("Objective value: ", objval) 
  write("Period  setup    ")
  forall(p in PRODUCTS) write(strfmt(p,-7))
  forall(t in TIMES) do
   write("\n ", strfmt(t,2), strfmt(sum(p in PRODUCTS) solsetup(p,t),8), "    ")
   forall(p in PRODUCTS) write(strfmt(solprod(p,t),3), " (",DEMAND(p,t),")")

! Cleaning up temporary files
 forall(m in RM) fdelete("sol_"+m) 


Back to examples browserPrevious exampleNext example