! Given a set of desired flights, figure out how to
route planes to cover these flights.
Repositioning flights are allowed at a cost.
This model illustrate two features:
1) Calendar routines for coordinating the times of
flights involving different locations and time zones,
2) The @INSERT( ) function for creating a derived set
according to fairly arbitrary rules;
! Keywords:
Airline Routing, Fleet Routing,
Airline Scheduling, Fleet Scheduling;
SETS:
CITY: INITA, GMTOFF;
LEG;
CXC( CITY, CITY): TRVTIM;
LODPAIR( LEG, CITY, CITY): Year, Month, Day, Hour, Minute,
DLTIME, Y, PLFLAG;
RLEG;
RPAIR( RLEG, CITY, CITY): DRTIME, U;
DOW /MON..SUN/;
ENDSETS DATA:
City, GMTOFF = ! Cities and their offset in hours from GMT;
Chicago -6 ! Chicago is 6 hours behind Greenwich Mean Time;
Salt_Lake_City -7
Los_Angeles -8
Phoenix -7
Las_Vegas -8
Tucson -7;
LEG = 1..7; ! Get data on each loaded candidate OD pair;
LODPAIR, Year, Month, Day, Hour, Minute =
! Origin Destination Departure time
LEG City City Year Month Day Hour Minute ;
1 Los_Angeles Salt_Lake_City 2012 10 20 11 0
2 Salt_Lake_City Phoenix 2012 10 24 16 20
3 Salt_Lake_City Los_Angeles 2012 10 25 16 0
4 Salt_Lake_City Las_Vegas 2012 10 26 16 0
5 Las_Vegas Salt_Lake_City 2012 10 28 12 0
6 Tucson Salt_Lake_City 2012 10 28 13 0
7 Chicago Las_Vegas 2012 10 22 10 30
;
! Get travel time matrix in minutes;
TRVTIM =
0 190 240 205 215 195 ! Chicago;
190 0 110 100 85 120 ! Salt_Lake_City;
240 110 0 120 120 120 ! Los_Angeles;
205 100 120 0 85 60 ! Phoenix;
215 85 120 85 0 95 ! Las_Vegas;
195 120 120 60 95 0 ;! Tucson;
RLEG = 1..1000; ! Possible number of repositioning legs;
VL = 1; ! Relative value of covering a loaded flight;
RP = .01; ! Relative cost of a repositioning flight;
RA = .95; ! Relative cost of an aircraft;
ENDDATA
SUBMODEL ROUTEM:
! Maximize number of requested flights flown
- cost of repositioning flights
- cost of aircraft;
MAX = VL*@SUM( LODPAIR( n, d, a): Y(n,d,a)) ! Loaded flights;
- RP*@SUM( RPAIR( n, d, a): U(n,d,a)) ! Repositions;
- RA*@SUM( CITY(i): INITA(i)); ! Initial AC at city i;
! You either fly it or you do not;
@FOR( LODPAIR( n, d, a): @BIN(Y(n,d,a)));
@FOR( RPAIR( n, d, a): @BIN(U(n,d,a)));
! For every departing loaded flight from d to a at time DLTIME,
the number of earlier arrivals - earlier departures must be >= Y(n,d,a);
@FOR( LODPAIR( n, d, a):
[LFLO] INITA(d)
+ @SUM( LODPAIR( n1, d1, d) | DLTIME(n1,d1,d) + TRVTIM(d1,d)/60 #LE# DLTIME(n,d,a):
Y(n1,d1,d))
+ @SUM( RPAIR( n1, d1, d) | DRTIME(n1,d1,d) + TRVTIM(D1,d)/60 #LE# DLTIME(n,d,a):
U(n1,d1,d))
- @SUM(LODPAIR(n1,d,a1) | DLTIME(n1,d,a1) #LT# DLTIME(n,d,a):
Y(n1,d,a1))
- @SUM( RPAIR(n1,d,a1) | DRTIME(n1,d,a1) #LE# DLTIME(n,d,a):
U(n1,d,a1))
>= Y(n,d,a);
);
! For every departing repositioning flight from d to a at time DRTIME,
the number of earlier arrivals - earlier departures must be >= U(n,d,a);
@FOR( RPAIR( n, d, a):
[RFLO] INITA(d)
+ @SUM( LODPAIR( n1, d1, d) | DLTIME(n1,d1,d) + TRVTIM(d1,d)/60 #LE# DRTIME(n,d,a):
Y(n1,d1,d))
+ @SUM( RPAIR( n1, d1, d) | DRTIME(n1,d1,d) + TRVTIM(d1,d)/60 #LE# DRTIME(n,d,a):
U(n1,d1,d))
- @SUM(LODPAIR(n1,d,a1) | DLTIME(n1,d,a1) #LE# DRTIME(n,d,a):
Y(n1,d,a1))
- @SUM( RPAIR(n1,d,a1) | a1 #NE# a #AND# (DRTIME(n1,d,a1) #LE# DRTIME(n,d,a)):
U(n1,d,a1))
>= U(n,d,a);
);
ENDSUBMODEL
CALC:
! Begin code to ..
! Convert Year, Month, Day, Hour, Minute(n,d,a) to a scalar DLTIME(n,d,a)
so we can do simple comparisons and arithmetic;
! Compute departure time in scalar GMT time for each loaded flight;
@FOR( LODPAIR( n, d, a):
DLTIME(n,d,a) = @YMD2STM( Year(n,d,a), Month(n,d,a), Day(n,d,a) , Hour(n,d,a), Minute(n,d,a), 0)
- GMTOFF(d); ! Take into account local time;
);
! End of code to convert to scalar time;
! Construct the set of candidate repositioning legs. For each departing
flight from city j, we add a candidate repositioning leg from every
other city j, j #NE# i, at TRVTIM(i,j) minutes earlier ;
k = 0;
@FOR( LODPAIR( n, j, a):
@FOR( CITY(i) | i #NE# j:
k = k+1;
@INSERT( RPAIR, k, i, j);
! Note, travel times are in minutes, scalar time in hours;
DRTIME(k,i,j) = DLTIME(n,j,a) - TRVTIM(i,j)/60;
);
);
! @GEN( ROUTEM); @SOLVE( ROUTEM);
@WRITE(' Value/flight covered= ',VL,@NEWLINE(1),
' Relative cost/repositioning= ',RP,@NEWLINE(1),' Relative cost/aircraft= ',RA,@NEWLINE(1));
@WRITE(@NEWLINE(1),' Number flights covered= ',
@SUM(LODPAIR(n,d,a)| Y(n,d,a) #GT# 0.5 :1),
' (of ',@SUM(LODPAIR(n,d,a) :1),')',@NEWLINE(1));
@WRITE(' Number aircraft used= ',@SUM(CITY(i):INITA(I)),@NEWLINE(1));
@WRITE(@NEWLINE(1),' Initial Aircraft Positions:',@NEWLINE(1),
' # Aircraft City', @NEWLINE(1));
@FOR( CITY(i)| INITA(i) #GT# 0.5:
@WRITE(' ', @FORMAT(INITA(i),'3.0f'), ' ', CITY(i),@NEWLINE(1));
);
@WRITE(@NEWLINE(1),' Trips flown: Depart at(local time)',@NEWLINE(1));
@WRITE(' Origin Destination yyyy mm dd hh mm dwk',@NEWLINE(1));
! A while loop to print the legs used, sorted by DLTIME;
@FOR( LODPAIR( n, d, a): PLFLAG(n,d,a) = 1); ! PLFLAG = 0 if already printed;
MORE = 1;
@WHILE(MORE:
MORE = 0;
CTIME = 9999999999;
@FOR( LODPAIR( n, d, a) | PLFLAG(n,d,a) #AND# (Y(n,d,a) #GT# 0.5):
CTEMP = DLTIME(n,d,a);
@IFC( CTEMP #LT# CTIME:
MORE = 1;
CTIME = CTEMP;
nsv=n; dsv=d; asv=a;
);
);
@IFC( MORE:
PLFLAG(nsv,dsv,asv) = 0;!
Begin code to ... Convert DLTIME(n,d,a) back to year month, day, hour minute;
CTIME = CTIME + GMTOFF(dsv); ! Take into account local time;
IYR = @STM2YR( CTIME); ! Get the year;
IMON = @STM2MON( CTIME); ! Get the month of the year;
IDAY = @STM2DAY( CTIME); ! Get day of month;
IHR = @STM2HR( CTIME); ! Get the hour of the day;
IMIN = @STM2MIN( CTIME); ! Get the minute of the hour;
IWKD = @STM2DWK( CTIME); ! Get the day of the week;
! End of code to convert to year, month,...;
@WRITE( @FORMAT(CITY(dsv),'18s'),' ',@FORMAT(CITY(asv),'18s'),' ',IYR,' ',
IMON,' ',@FORMAT(IDAY,'2.0F'),' ',@FORMAT(IHR,'2.0F'),' ',@FORMAT(IMIN,'2.0F'),' ',DOW(IWKD),@NEWLINE(1));
);
);
@WRITE(@NEWLINE(1),' Repositioning Flights:',@NEWLINE(1));
@WRITE(' Origin Destination yyyy mm dd hh mm dwk',@NEWLINE(1));
@FOR( RPAIR( n, d, a) | U(n,d,a) #GT# 0.5:
! Begin code to ... ;
! Convert DRTIME(n,d,a) back to year month, day, hour minute;
CTIME = DRTIME(n,d,a)+ GMTOFF(d); ! Take into account local time;
IYR = @STM2YR( CTIME); ! Get the year;
IMON = @STM2MON( CTIME); ! Get the month of the year;
IDAY = @STM2DAY( CTIME); ! Get day of month;
IHR = @STM2HR( CTIME); ! Get the hour of the day;
IMIN = @STM2MIN( CTIME); ! Get the minute of the hour;
IWKD = @STM2DWK( CTIME); ! Get the day of the week;
! End of convert code;
@WRITE( @FORMAT(CITY(d),'18s'),' ',@FORMAT(CITY(a),'18s'),' ',IYR,' ',
IMON,' ',@FORMAT(IDAY,'2.0F'),' ',@FORMAT(IHR,'2.0F'),' ',@FORMAT(IMIN,'2.0F'),' ',DOW(IWKD),@NEWLINE(1));
);
ENDCALC
|