Initializing help system before first use

E. Ground transport


Description:

Problem name and type, features Difficulty
E‑1 Car rental: Transport problem ***
data preprocessing, set operations, sqrt and ^2, if-then-elif
E‑2 Choosing the mode of transport: Minimum cost flow **
formulation with extra nodes for modes of transport; encoding of arcs, finalize, union of sets, nodes labeled with strings
E‑3 Depot location: Facility location problem ***
modeling flows as fractions, definition of model cuts
E‑4 Heating oil delivery: Vehicle routing problem (VRP) ****
elimination of inadmissible subtours, cuts; selection with `|', definition of model cuts
E‑5 Combining different modes of transport ***
modeling implications, weak and strong formulation of bounding constraints; triple indices
E‑6 Fleet planning for vans ***
maxlist, minlist, max, min


File(s): e1carrent.mos (Mar. 2002), e2minflow.mos (Mar. 2002), e3depot.mos (Mar. 2002), e4deliver.mos (Mar. 2002), e5combine.mos (Mar. 2002), e6vanrent.mos (Mar. 2002)
Data file(s): e1carrent.dat, e2minflow.dat, e3depot.dat, e4deliver.dat, e5combine.dat, e6vanrent.dat

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

   file e1carrent.mos
   ``````````````````
   Fleet management in car rental
   
   (c) 2008 Fair Isaac Corporation
       author: S. Heipcke, Mar. 2002
*******************************************************!)

model "E-1 Car rental"
 uses "mmxprs"

 declarations
  AGENTS = 1..10                     ! Car rental agencies

  REQ: array(AGENTS) of integer      ! Required number of cars
  STOCK: array(AGENTS) of integer    ! Number of cars in stock
  X,Y: array(AGENTS) of integer      ! Coordinates of rental agencies
  COST: real                         ! Cost per km of moving a car
  NEED: set of integer               ! Agencies needing more cars
  EXCESS: set of integer             ! Agencies with too many cars
 end-declarations

 initializations from 'e1carrent.dat'
  REQ STOCK X Y COST
 end-initializations

 if sum(a in AGENTS) (STOCK(a)-REQ(a)) <> 0 then
  writeln("Problem is infeasible")
  exit(0)
 end-if 

! Calculate sets of agencies with excess or deficit of cars
 forall(a in AGENTS)
  if STOCK(a) - REQ(a) < 0 then
   NEED += {a}
  elif STOCK(a) - REQ(a) > 0 then
   EXCESS += {a}
  end-if

 finalize(NEED); finalize(EXCESS)

 declarations
  DIST: array(EXCESS,NEED) of real   ! Distance between agencies
  move: array(EXCESS,NEED) of mpvar  ! Cars exchanged between agencies
 end-declarations

! Calculate distances between agencies
 forall(a in EXCESS,b in NEED) 
  DIST(a,b):= 1.3*sqrt((X(a)-X(b))^2 + (Y(a)-Y(b))^2)

! Objective: total transport cost
 Cost:= sum(a in EXCESS,b in NEED) COST*DIST(a,b)*move(a,b)

! Agencies with excess availability
 forall(a in EXCESS) sum(b in NEED) move(a,b) = STOCK(a) - REQ(a)

! Agencies in need of cars
 forall(b in NEED) sum(a in EXCESS) move(a,b) = REQ(b) - STOCK(b)

 forall(a in EXCESS,b in NEED) move(a,b) is_integer

! Solve the problem
 minimize(Cost)
 
! Solution printing
 writeln("Total cost: ", getobjval)
 write(" ->")
 forall(b in NEED) write(strfmt(b,3))
 writeln
 forall(a in EXCESS) do
  write(a,"  ")
  forall(b in NEED) write(strfmt(getsol(move(a,b)),3))
  writeln
 end-do 

end-model

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

   file e2minflow.mos
   ``````````````````
   Choosing the mode of transport (Minimum cost flow)
   
   (c) 2008 Fair Isaac Corporation
       author: S. Heipcke, Mar. 2002
*******************************************************!)

model "E-2 Minimum cost flow"
 uses "mmxprs"

 declarations
  NODES: set of string                  ! Set of nodes
  MINQ : integer                        ! Total quantity to transport
  A: array(ARCS:range,1..2) of string   ! Arcs
  COST: array(ARCS) of integer          ! Transport cost on arcs
  MINCAP,MAXCAP: array(ARCS) of integer ! Minimum and maximum arc capacities
 end-declarations

 initializations from 'e2minflow.dat'
  A MINQ MINCAP MAXCAP COST
 end-initializations

 finalize(ARCS)

! Calculate the set of nodes
 NODES:=union(a in ARCS) {A(a,1),A(a,2)}

 declarations
  flow: array(ARCS) of mpvar            ! Flow on arcs
 end-declarations

! Objective: total transport cost
 Cost:= sum(a in ARCS) COST(a)*flow(a)

! Flow balance: inflow equals outflow
 forall(n in NODES | n<>"SOURCE" and n<>"SINK")
  sum(a in ARCS | A(a,2)=n) flow(a) = sum(a in ARCS | A(a,1)=n) flow(a)
   
! Min and max flow capacities
 forall(a in ARCS | MAXCAP(a) > 0) do
  flow(a) >= MINCAP(a)
  flow(a) <= MAXCAP(a)
 end-do
  
! Minimum total quantity to transport
 sum(a in ARCS | A(a,1)="SOURCE" ) flow(a) >= MINQ

! Solve the problem
 minimize(Cost)
 
! Solution printing
 writeln("Total cost: ", getobjval)
 forall(a in ARCS)
  write( if(getsol(flow(a))>0, 
         A(a,1) + " -> "+ A(a,2) + ": "+ getsol(flow(a))+"\n", ""))

end-model

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

   file e3depot.mos
   ````````````````
   Depot location
   
   (c) 2008 Fair Isaac Corporation
       author: S. Heipcke, Mar. 2002
*******************************************************!)

model "E-3 Depot location"
 uses "mmxprs"

 declarations
  DEPOTS = 1..12                       ! Set of depots
  CUST = 1..12                         ! Set of customers

  COST: array(DEPOTS,CUST) of integer  ! Delivery cost
  CFIX: array(DEPOTS) of integer       ! Fix cost of depot construction
  CAP: array(DEPOTS) of integer        ! Depot capacity
  DEM: array(CUST) of integer          ! Demand by customers

  fflow: array(DEPOTS,CUST) of mpvar   ! Perc. of demand supplied from depot
  build: array(DEPOTS) of mpvar        ! 1 if depot built, 0 otherwise
 end-declarations

 initializations from 'e3depot.dat'
  COST CFIX CAP DEM
 end-initializations

! Objective: total cost
 TotCost:= sum(d in DEPOTS, c in CUST) COST(d,c)*fflow(d,c) +
            sum(d in DEPOTS) CFIX(d)*build(d)

! Satisfy demands
 forall(c in CUST) sum(d in DEPOTS) fflow(d,c) = 1
   
! Capacity limits at depots
 forall(d in DEPOTS) sum(c in CUST) DEM(c)*fflow(d,c) <= CAP(d)*build(d)

! Additional constraints:
! If there is any delivery from depot d, then this depot must be built
(!
 declarations
  modcut: array(DEPOTS,CUST) of linctr
 end-declarations

 forall(d in DEPOTS, c in CUST) do
  modcut(d,c):= DEM(c) * fflow(d,c) <= CAP(d) * build(d)
  setmodcut(modcut(d,c))
 end-do
!)

 forall(d in DEPOTS) build(d) is_binary
 forall(d in DEPOTS, c in CUST) fflow(d,c) <= 1

! Uncomment the following line to see the Optimizer log
! setparam("XPRS_VERBOSE",true)

! Solve the problem
 minimize(TotCost)
 
! Solution printing
 writeln("Total cost: ", getobjval)
 forall(d in DEPOTS, c in CUST)
  if(getsol(fflow(d,c))>0) then
   writeln(strfmt(d,2), " -> ", strfmt(c,2), ": ", 
           strfmt(getsol(fflow(d,c))*DEM(c),3) )
  end-if

end-model

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

   file e4deliver.mos
   ``````````````````
   Heating oil delivery (Traveling Salesman Problem)
   
   (c) 2008 Fair Isaac Corporation
       author: S. Heipcke, Mar. 2002
*******************************************************!)

model "E-4 Oil delivery"
 uses "mmxprs"

 declarations
  NS = 7
  SITES = 1..NS                       ! Set of locations, 1=refinery
  CLIENTS = 2..NS

  DEM: array(SITES) of integer        ! Demands
  DIST: array(SITES,SITES) of integer ! Distances between locations
  CAP: integer                        ! Lorry capacity

  prec: array(SITES,SITES) of mpvar   ! 1 if i immediately precedes j, 
                                      ! 0 otherwise 
  quant: array(CLIENTS) of mpvar      ! Quantity delivered up to i
 end-declarations

 initializations from 'e4deliver.dat'
  DEM DIST CAP
 end-initializations

! Objective: total distance driven
 Length:= sum(i,j in SITES | i<>j) DIST(i,j)*prec(i,j)

! Enter and leave every city only once (except the depot)
 forall(j in CLIENTS) sum(i in SITES| i<>j) prec(i,j) = 1
 forall(i in CLIENTS) sum(j in SITES| i<>j) prec(i,j) = 1

! If i is the first client of a tour, then quant(i)=DEM(i)
 forall(i in CLIENTS) quant(i) <= CAP + (DEM(i)-CAP)*prec(1,i)

! If j comes just after i in a tour, then quant(j) is greater than the 
! quantity delivered during the tour up to i plus the quantity to be 
! delivered at j (to avoid loops and keep capacity limit of the tanker)
 forall(i,j in CLIENTS| i<>j) quant(j) >= quant(i) + DEM(j) - CAP +
                           CAP*prec(i,j) + (CAP-DEM(j)-DEM(i))*prec(j,i)

! Additional constraints:
! If i is not the first client of a tour, quant(i) is larger than the sum 
! of the quantities to deliver to i and to his predecessor on the tour
(!
 declarations
  modcut: array(CLIENTS) of linctr
 end-declarations

 forall(i in CLIENTS) do
  modcut(i):= quant(i) >= DEM(i) + sum(j in SITES| i<>j) DEM(j)*prec(j,i)
  setmodcut(modcut(i))
 end-do
!)

 forall(i in CLIENTS) do
  quant(i) <= CAP
  quant(i) >= DEM(i)
 end-do
 
 forall(i,j in SITES | i<>j) prec(i,j) is_binary

! Uncomment the following line to see the Optimizer log
! setparam("XPRS_VERBOSE",true)

! Solve the problem
 minimize(Length)

! Solution printing
 writeln("Total distance: ", getobjval)
 forall(i in CLIENTS)
  if(getsol(prec(1,i))>0) then
   ct:=DEM(i)
   writeln(1, " -> ", i)
   p:=i
   while(p<>1) do
    n:= integer(round(sum(j in SITES) j*getsol(prec(p,j))))
    writeln(p, " -> ", n)
    ct+=DEM(n)
    p:=n
   end-do
   writeln("Quantity delivered: ", ct)
  end-if

end-model

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

   file e5combine.mos
   ``````````````````
   Combining different modes of transport
   
   (c) 2008 Fair Isaac Corporation
       author: S. Heipcke, Mar. 2002
*******************************************************!)

model "E-5 Combined transport"
 uses "mmxprs"

 declarations
  NL = 4
  LEGS = 1..NL                          ! Legs of the transport
  MODES: set of string                  ! Modes of transport

  CTRANS: array(MODES,LEGS) of integer  ! Transport cost
  CCHG: array(MODES,MODES) of integer   ! Cost of changing mode of transport
 end-declarations

 initializations from 'e5combine.dat'
  CTRANS CCHG
 end-initializations

 finalize(MODES)

 declarations
  use: array(MODES,LEGS) of mpvar        ! 1 if a mode is used, 0 otherwise 
  change: array(MODES,MODES,1..NL-1) of mpvar  ! 1 if change from mode m to n
                                               ! at end of leg, 0 otherwise
 end-declarations

! Objective: total cost
 Cost:= sum(m in MODES, l in LEGS) CTRANS(m,l)*use(m,l) +
         sum(m,n in MODES,l in 1..NL-1) CCHG(m,n)*change(m,n,l)

! One mode of transport per leg        
 forall(l in LEGS) sum(m in MODES) use(m,l) = 1
 
! Change or maintain mode of transport between every pair of legs 
 forall(l in 1..NL-1) sum(m,n in MODES) change(m,n,l) = 1

! Relation between modes used and changes
 forall(m,n in MODES,l in 1..NL-1) use(m,l) + use(n,l+1) >= 2*change(m,n,l)

 forall(m in MODES, l in LEGS) use(m,l) is_binary
 forall(m,n in MODES,l in 1..NL-1) change(m,n,l) is_binary
 
! Solve the problem
 minimize(Cost)
 
! Solution printing
 writeln("Total cost: ", getobjval)
 forall(l in LEGS) do
  write("  ",l, "-", l+1,": ")
  forall(m in MODES) write(if(getsol(use(m,l))>0 , m, ""))
 end-do 
 writeln

end-model

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

   file e6vanrent.mos
   ``````````````````
   Fleet planning for van rental
   
   (c) 2008 Fair Isaac Corporation
       author: S. Heipcke, Mar. 2002
*******************************************************!)

model "E-6 Van rental"
 uses "mmxprs"

 declarations
  NM = 6
  MONTHS = 1..NM                      ! Months
  CONTR = 3..5                        ! Contract types

  REQ: array(MONTHS) of integer       ! Monthly requirements
  COST: array(CONTR) of integer       ! Cost of contract types
  NINIT: integer                      ! Vans rented at beginning of plan

  rent: array(CONTR,MONTHS) of mpvar  ! New rentals every month
 end-declarations

 initializations from 'e6vanrent.dat'
  REQ COST NINIT
 end-initializations

! Objective: total cost
 Cost:= sum(c in CONTR, m in MONTHS) COST(c)*rent(c,m)

! Fulfill the monthly requirements
 forall(m in MONTHS) 
  if(m<=2, NINIT, 0) + 
   sum(c in CONTR, n in maxlist(1,m-c+1)..minlist(m,NM-c+1)) rent(c,n) >= 
    REQ(m)

! Solve the problem
 minimize(Cost)
 
! Solution printing
 declarations
  NAMES: array(MONTHS) of string
 end-declarations

 initializations from 'e6vanrent.dat'
  NAMES
 end-initializations
 
 writeln("Total cost: ", getobjval)
 write("new rents  ")
 forall(m in MONTHS) write(NAMES(m), "  ")
 writeln
 forall(c in CONTR) do
  write(c, " months ")
  forall(m in MONTHS) write(strfmt(getsol(rent(c,m)),5))
  writeln
 end-do
 write("Total    ")
 forall(m in MONTHS) write(strfmt(getsol(if(m<=2, NINIT, 0) + 
   sum(c in CONTR, n in maxlist(1,m-c+1)..minlist(m,NM-c+1)) rent(c,n)), 5))
 writeln   

end-model