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

Loading and cutting problems

Description
Problem name and type, featuresDifficultyRelated examples
D‑1 Wagon load balancing: Nonpreemptive scheduling on parallel machines ****
heuristic solution requiring sorting algorithm, formulation of maximin objective; nested subroutines: function returning heuristic solution value and sorting procedure, ceil, getsize, if-then, break, exit, all loop types (forall-do, repeat-until, while-do), setparam, qsort, cutoff value, loading a MIP start solution
D‑2 Barge loading: Knapsack problem ** burglar1.mos, knapsack_graph.mos
incremental problem definition with 3 different objectives, procedure for solution printing
D‑3 Tank loading: Loading problem ***
2 objectives; data preprocessing, as, dynamic creation of variables, procedure for solution printing, if-then-else
D‑4 Backing up files: Bin-packing problem ** binpacking_graph.mos
2 versions of mathematical model, symmetry breaking; data preprocessing, ceil, range
D‑5 Cutting sheet metal: Covering problem * g6transmit.mos, j2bigbro.mos
D‑6 Cutting steel bars for desk legs: Cutting-stock problem ** cutstock_graph.mos
set operation(s) on range sets, set of integer (data as set contents)


Further explanation of this example: 'Applications of optimization with Xpress-MP', Chapter 9: Loading and cutting stock problems

mosel_app_4.zip[download all files]

Source Files

Data Files





d3tanks.mos

(!******************************************************
   Mosel Example Problems
   ======================

   file d3tanks.mos
   ````````````````
   Loading of liquid chemicals into tanks

   Five tanker ships filled with liquids must be unloaded
   into storage tanks. The 5 liquids must not be mixed.
   (1) How should the ships be unloaded to maximize the capacity
   of unused tanks? (2) How should they be unloaded to maximize
   the number of unused tanks?

   The storage tanks are defined as a range of consecutive  
   integers whereas the liquids are identified by their names. 
   Entries of the decision variable array 'load' are created
   dynamically depending on the initial configuration data. 
   This problem calls the custom 'printsol' procedure after 
   minimizing each objective.   

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

model "D-3 Tank loading"
 uses "mmxprs"

 forward procedure printsol

 declarations   
  TANKS: range                       ! Set of tanks
  LIQ: set of string                 ! Set of liquids

  CAP: array(TANKS) of integer       ! Tank capacities
  TINIT: array(TANKS) of string      ! Initial tank contents type
  QINIT: array(TANKS) of integer     ! Quantity of initial contents
  ARR: array(LIQ) of integer         ! Arriving quantities of chemicals
  REST: array(LIQ) of integer        ! Rest after filling part. filled tanks
 
  ifload: dynamic array(LIQ,TANKS) of mpvar  ! 1 if liquid loaded into tank,
                                     ! 0 otherwise
 end-declarations

 initializations from 'd3tanks.dat'
  CAP ARR
  [TINIT, QINIT] as 'FILLED'
 end-initializations

 finalize(LIQ)

 forall(t in TANKS | QINIT(t)=0, l in LIQ) do
  create(ifload(l,t))
  ifload(l,t) is_binary
 end-do 

! Complete the initially partially filled tanks and calculate the remaining
! quantities of liquids
 forall(l in LIQ) 
  REST(l):= ARR(l) - sum(t in TANKS | TINIT(t)=l) (CAP(t)-QINIT(t))
 
! Objective 1: total tank capacity used
 TankUse:= sum(l in LIQ, t in TANKS) CAP(t)*ifload(l,t)

! Objective 2: number of tanks used
 TankNum:= sum(l in LIQ, t in TANKS) ifload(l,t)

! Do not mix different liquids
 forall(t in TANKS) sum(l in LIQ) ifload(l,t) <= 1

! Load the empty tanks within their capacity limits
 forall(l in LIQ) sum(t in TANKS) CAP(t)*ifload(l,t) >= REST(l)

! Solve the problem with objective 1
 minimize(TankUse)
 
! Solution printing
 printsol

! Solve the problem with objective 2
 minimize(TankNum)
 
! Solution printing
 printsol
  
!-----------------------------------------------------------------

! Solution printing
 procedure printsol
  writeln("Used capacity: ", getsol(TankUse) + 
                             sum(t in TANKS | QINIT(t)>0) CAP(t),
         " Capacity of empty tanks: ", sum(t in TANKS) CAP(t) - 
                                       getsol(TankUse) - 
                                       sum(t in TANKS | QINIT(t)>0) CAP(t))
  writeln("Number of tanks used: ", getsol(TankNum) + 
                                    sum(t in TANKS | QINIT(t)>0) 1) 
  forall(t in TANKS)
   if(QINIT(t)=0) then
    write(t, ": ")
    forall(l in LIQ) write( if(getsol(ifload(l,t))>0 , l, ""))
    writeln
   else
    writeln(t, ": ", TINIT(t))
   end-if
 end-procedure
    
end-model

Back to examples browserPrevious exampleNext example