Lindo Systems

! Job to Machine Assignment and Sequencing. (MachAsgSeq)
A number of jobs (trucks, airplanes...)
arrive over time at a facility (terminal...).
A job cannot be started before its arrival time.
Each job has a due date by which its processing must be finished.
The facility has a number of docks or machines.
Each machine can handle at most one job at a time.
For each job and machine combination, there is a
value of this assignment, as well as a
processing time of the job on the specific machine.
   We would like to assign jobs to machines, and
 a sequence of jobs on the machine so that
 at most one job is assigned to a specific machine
 at a specific instance, and
 there is very little delay, and
 the value of the assignments is maximized;
! Examples are: Assigning airplanes to gates at an airport,
assigning trucks to docks at a freight terminal, and
assigning manufacturing jobs to machines in a factory.
  An extension, not considered here, is to allow a
job to finish after its due date (be tardy), at a penalty;

! Keywords: Assignment, Gate assignment, Dock assignment, 
  Sequencing, Machine Assignment, Task assignment;

SETS:
  JOB: ARVT, DD;
  MACH;
  TSLOT;
  MXJ( MACH, JOB) : PT, VAL;
  MXT( MACH, TSLOT): IDLE;
ENDSETS

! Parameters:
   ARVT(j) = arrival or available time of job j, the first
             period in which j can be processed,
   PT(m,j) = processing time/number periods needed on machine m of job j,
   VAL(m,j) = value or profit of assigning job j to machine m,
   DD(j) = due date for job j;
!    This formulation assumes ARVT, DD, and PT are integers;
! Variables:
   Z(m,t,j) = 1 if job j is assigned to machine m starting during time slot t,
   IDLE(m,t) = 1 if machine m is idle during period t;

DATA:
 TSLOT = 1..30; ! Assume at most 30 minutes in horizon, should be >= max DD;
 DWGT = 0.001;  ! Weight applied to minimizing sum of completion times;

 JOB = J1..J12;
 MACH = A  B  C ;
! Arrival time or first period in which task can be started;
ARVT =  2  1  2  1  1  4  6  7  8 11  8  9;
! Task must be finished at end of this period;
  DD = 13 15 11 11 15 14 17 20 18 17 19 24;
! Processing time of tasks on machines;
  PT =  4  8  5  6  4  3  2  3  5  4  6  5 ! Mach 1;
        5  9  7  7  5  5  1  3  5  5  7  6 ! Mach 2;
        6  9  8  7  5  6  3  3  6  5  7  7;! Mach 3;
! Value of doing a specific job on a specific machine;
  VAL = 5  8  7  7  6  5  2  2  9  6  4  3 ! Mach 1;
        5  9  7  7  5  5  2  3  9  7  6  5 ! Mach 2;
        6  9  7  8  6  5  2  3  9  8  7  5;! Mach 3;
ENDDATA
SETS:
! Key observation:  job j can be assigned to/started in time slot t only if
   ( DD(j) - PT(m,j) #GE# t ) #AND# (ARVT( j) #LE# t);
   MXTXJ( MACH, TSLOT, JOB) |
       ( DD(&3) - PT(&1,&3)+1 #GE# &2) #AND# ( ARVT( &3) #LE# &2) : Z, FLAG;
ENDSETS

SUBMODEL ASGSEQ:
! Maximize the value of the assignments;
 MAX = OBJVALA - DWGT* DELAYA;
 OBJVALA = @SUM( MXTXJ(m,t,j) : VAL(m,j)*Z(m,t,j));
! Compute delay amount, if delayed;
 DELAYA = @SUM( MXTXJ(m,t,j): (t- ARVT(j))*Z(m,t,j));

! Each job must be assigned to at most one machine;
 @FOR( JOB( j):
  [CANDO] @SUM( MXTXJ(m,t,j): Z(m,t,j)) <= 1;
     );

! At most one job can be at a machine m at timeslot t, for t not
    in an obviously idle period;
! Every machine starts idle before 1st period and remains idle or gets some work;
  @FOR( MACH( m):
     [JUST1] 1 = IDLE(m,TSTRT) + @SUM( MXTXJ(m,t,j) | t #EQ# TSTRT: Z(m,t,j)) ;
      );

! For subsequent periods, in period t-1 (the LHS), if the machine is either:
    a)idle, or b)not idle but some job finishes, then
  in period t (the RHS) the machine will be either:
    a) idle, or  b) starts a new task;
  @FOR( TSLOT(t) | t #GT# TSTRT #AND# t #LE# TENDT :
    @FOR( MACH( m):
     [JUSTN] IDLE(m,t-1) 
              + @SUM( JOB(j) | t-PT(m,j) #GE# ARVT(j) #AND# t #LE# DD(j)+1: Z(m,t-PT(m,j),j))
           = IDLE(m,t)  
              + @SUM( JOB(j) | (DD(j) - PT(m,j) + 1 #GE# t) #AND# ( ARVT( j) #LE# t) : Z(m,t,j));
       );  !@FOR( MACH;
     );  ! @FOR(TSLOT;

! The 0/1 variables;
 @FOR( MXTXJ(m,t,j):
   @BIN( Z(m,t,j));
    );
ENDSUBMODEL

CALC:
 @SET( "TERSEO", 2);
! Get the start and end of the interesting periods;
 TSTRT = @MIN( JOB(j): ARVT(j));
 TENDT = @MAX( JOB(j): DD(j));
 @SOLVE( ASGSEQ); ! Solve assignment and sequencing problem;

! Display a short report;
!  Sort the report by MACH, Start time;
!   Set FLAG(m,t,j) = 1 for items still needed to print;
 @FOR( MXTXJ(m,t,j):
   @IFC(  Z(m,t,j) #GT# 0.5:
      FLAG(m,t,j) = 1;
    @ELSE
      FLAG(m,t,j) = 0;
     );
    );
 @WRITE('  Mach-      Ready Start Finish   Due',@NEWLINE(1));
 @WRITE('   ine   Job  time  time   time   time', @NEWLINE(1));

 MORE = 1; ! = 0 when no more lines to print;
 @WHILE( MORE:
! Find the lexico smallest (machine, Start time) remaining to print;
   ms = 1 + @SIZE( JOB);
   ts = 1 + @SIZE(TSLOT);
   MORE = 0;
   @FOR( MXTXJ(m,t,j) | FLAG(m,t,j):
    @IFC( m #EQ# ms #AND# t #LT# ts:
       ts = t; ! New smaller start time, same machine;
       js = j;
       MORE = 1;
        );
    @IFC( m #LT# ms:
       ms = m; ! New smaller machine;
       ts = t;
       js = j;
       MORE = 1;
        );
      );
   @IFC( MORE: ! Did we find another line to print?;
     @WRITE( ' ', @FORMAT( MACH(ms), '5s'));
      @WRITE( ' ',@FORMAT( JOB(js), '5s'),' ', @FORMAT(ARVT(js),'4.0F'), '  ', @FORMAT(ts,'4.0f'), '   ',
         @FORMAT(ts+PT(ms,js)-1,'4.0F'), '   ', @FORMAT(DD(js),'4.0F'), @NEWLINE(1));
     FLAG( ms, ts, js) = 0; ! This line is done;
      );
    );
ENDCALC