Initializing help system before first use

LCSP: Labour constrained scheduling problem


Type: Resource constrained scheduling
Rating: 3
Description: Schedule the processing of a set of jobs with resource usage profiles subject to precedence constraints between certain pairs of jobs. The objective is to minimize the makespan (completion time of last job).
  • difficult MIP problem
  • dynamic creation of variables
  • constraint definitions with logical conditions
  • using parameters in the optimization function
  • if-then-else statement
File(s): lscp1.mos


lscp1.mos
(!*******************************************************
  * Mosel Example Problems                              *
  * ======================                              *
  *                                                     *
  * file lscp1.mos                                      *
  * ``````````````                                      *
  * Example for the use of the Mosel language           *
  * (Labour Constrained Scheduling Problem)             *
  *                                                     *
  * (c) 2008 Fair Isaac Corporation                     *
  *     author: S. Heipcke, 2001, rev. Feb. 2010        *
  *******************************************************!)

model Lscp1                        ! Start a new model

uses "mmxprs"                      ! Load the optimizer library
uses "mmsystem"

parameters
 WEAKPREC = true ! Set to false to use formulation with strong precedence
                 ! constraints 
end-parameters

declarations
 NJ     = 25     ! Number of jobs (dummy end job is last and is counted) 
 RJ     = 1..NJ  ! Range of jobs 
 RJT    = 1..5   ! Range of job-types (includes dummy end job type) 
 RJOBL  = 1..9   ! Range of job lengths 
 TT     = 73     ! Time horizon
 RT     = 1..TT  ! Range of time slices 
 RARCS  = 1..26  ! Range of precedence constraints 
 LABOUR = 18     ! Number of workers available per period

 JT: array(RJ) of integer          ! Job-class for jobs 
 P: array(RJT) of integer          ! Processing times of job-classes 
                                   ! (must be positive) 
 TMIN: array(RJ) of integer        ! Earliest start time for jobs 
 TMAX: array(RJ) of integer        ! Latest start time for jobs 
 LABREQ: array(RJT,RJOBL) of integer ! Labour requirement per period of 
                                     ! job-type 
 ARC: array(RARCS,1..2) of integer ! Precendence constraints (TAIL(a),HEAD(a)) 
 TAIL: array(RARCS) of integer     ! Tail of a precedence arc 
 HEAD: array(RARCS) of integer     ! Head of a precedence arc 

 x: dynamic array(RT,RJ) of mpvar  ! 1 if job j starts at time t, else 0
 st: array(RJ) of mpvar            ! Start times of jobs
end-declarations
 
 JT:: [1,1,1,1,1,1,1,2,2,2,2,3,3,3,4,4,4,4,4,4,4,4,4,4,5]
 P::  [7,9,8,5] 
 TMIN:: [1,8,15,22,29,36,43, 
         1,10,19,28, 
         1,9,17, 
         9,14,19,24,29,34,39,44,49,54, 
         59]
 TMAX:: [23,30,37,44,51,58,65, 
         36,45,54,63, 
         14,29,44, 
         22,27,32,37,42,47,52,57,62,67, 
         72]
 LABREQ:: [12,12,6,2,2,2,2,
           12,12,6,2,2,2,2,2,2,
           12,12,3,3,3,3,3,3,
           6,6,6,6,6]
 ARC:: [1,2,
        2,3,
        3,4,
        4,5,
        5,6,
        6,7,
        8,9,
        9,10,
        10,11,
        12,13,
        13,14,
        15,16,
        16,17,
        17,18,
        18,19,
        19,20,
        20,21,
        21,22,
        22,23,
        23,24,
        12,15,
        13,18,
        14,21,
        7,25,
        11,25,
        24,25]

 forall(a in RARCS) do
  TAIL(a):=ARC(a,1)
  HEAD(a):=ARC(a,2)
 end-do   

                                   ! Create the variables
 forall(t in RT,j in RJ | t>=TMIN(j) and t<= TMAX(j))
  create(x(t,j))

                                   ! Link s_j variables with x_jt variables
 forall(j in RJ) Link(j):= st(j) = sum(t in RT|exists(x(t,j))) t * x(t,j)

                                   ! Each job has to start exactly once
 forall(j in RJ) Start(j):= sum(t in RT|exists(x(t,j))) x(t,j) = 1

                                   ! Labour capacity constraints
 forall(t in RT) Labour(t):= sum(i in 1..NJ-1,u in 1..P(JT(i)) | 
   t-u+1>=1 and t-u+1<=TT) LABREQ(JT(i),u) * x(t-u+1,i) <= LABOUR

 if (WEAKPREC) then                ! Weak precedence constraints
  forall(a in RARCS) WPrec(a):= st(HEAD(a)) >= st(TAIL(a)) + P(JT(TAIL(a)))
 else                              ! Strong precedence constraints
  forall(a in RARCS, t in TMIN(HEAD(a))..TMAX(HEAD(a)) |
    t-P(JT(TAIL(a))) >= TMIN(TAIL(a)) and t-P(JT(TAIL(a))) <= TMAX(TAIL(a)))
      SPrec(a,t):= sum(s in 1..t) x(s,HEAD(a)) <=
        sum(s in 1..t-P(JT(TAIL(a)))) x(s,TAIL(a))
 end-if
 
 forall(t in RT,j in RJ|exists(x(t,j)))
  x(t,j) is_binary                 ! Variables x are 0/1
  
! Objective function: minimize the start time of the final (dummy) job
! (it can only start once all other jobs are complete).
 minimize(st(NJ))

                                   ! Print out the solution
 writeln("Solution:\n Objective: ", getobjval)

 forall(j in 1..NJ-1) do
  write(" start(", j,"): ", st(j).sol)
  if JT(j)