$OFFSYMXREF OFFSYMLIST * To: SPIELBERG1 * ORSA Meeting Phoenix AZ Oct 30, 31, Nov 1 SETS I inbound trains / R396, R501, X567 / J time periods / 1*4 / K blocks / Balto, Willard, Pittsbg / L tracks / 1*2 / KL(K,L) Allowed Block to Track Assignments / Balto.2 Willard.(1*2) Pittsbg.(1*2) / M Pullout Leads / 1*2 / LM(L,M) Track to Lead Connections / 1.1 2.2 / N Outbound Trains / R776, R872 / KN(K,N) Outbound Block to Outbound Train Associations / Balto.R776 Willard.R776 Pittsbg.R872 / ; ALIAS (K,KP); ALIAS (L,LP); ALIAS (J,JP); ALIAS (M,MP); SCALARS PROCRATE Processing Minutes per car / .25 / MAXTIME Used for Time Axis reversal MAXTRAX Max # Trks to which block can be simul assigned / 1 / MAXBLOCK Maximum Blocks to a Track / 2 / INFEAS Price Per Car Missing Connection / 1000 / BIGM Big M Used to Force Unused Time Pds to Rear / 999 / ; PARAMETERS TOTCARS(I) Total number of cars on Train I TOTBLK(K) Total number of cars in Block K TOTTRN(N) Total Cars on Outbound Train N SWRHS1(K,L,LP) First Capy Constraint RHS for Reswitch Links SWRHS2(K,L) Second Capy Constraint RHS for Reswitch Links INITBLK(K,L) Initial Matrix Track to Block Assignments in Time Pd 1 INITONE(L) Initial One-to-One Flag Assignments in Time Pd 1 CUTOFF(I) Latest processing for trn I based on blocks carried CUTOFFM(I) Cutoff Times in Reversed Time Axis CAPY(L) capacity of track l in cars / 1 36 2 31 / EPT(I) earliest processing time for train I / R396 20 R501 0 X567 0 / SCHPULL(K) Scheduled Pull Time for Block K TRNPULL(N) Scheduled Pull Time for Train N / R776 35 R872 10 / SCHPULLM(K) Scheduled Pull Times in Reverse Time Axis MAXMISS(K) Max No Cars Block K Allowed to Miss Connection /Balto 0 Willard 0 Pittsbg 0 / SUREMISS(K) Those cars which are certain to miss their connection LEADTOT(N) Sum of All Switching Leads Cost by Train (For Zero Test); TABLE LEADCOST(M,N) Cost of Each Switching Lead by Train R776 R872 1 10 10 2 5 10 TABLE CARBLK(I,K) Outbound Composition of Each Train Balto Willard Pittsbg R396 25 2 R501 5 2 5 X567 15 25 ; * Sum Total Cost for Switching Leads by Train. If any are zero, * those equations dont have to be generated LEADTOT(N) = SUM(M, LEADCOST(M,N)); * Compute Block Pull Times from Train Pull Times SCHPULL(K) = SMIN(N $ KN(K,N), TRNPULL(N)); DISPLAY SCHPULL; * Compute Number of Cars certain to miss connections SUREMISS(K)= SUM(I $ (EPT(I) GT SCHPULL(K)), CARBLK(I,K)); DISPLAY SUREMISS; * Reverse Time Axis for Pull Times MAXTIME = CARD(J) * BIGM; SCHPULLM(K) = MAXTIME - SCHPULL(K); * Calculate Cutoff time for processing train I. This is the earliest * scheduled pull time for any of the blocks carried on the train CUTOFF(I) = SMIN(K $ (CARBLK(I,K) GT 0), SCHPULL(K)); DISPLAY CUTOFF; * Reverse Time Axis for Cutoff Times CUTOFFM(I) = MAXTIME - CUTOFF(I); * Add Up CARBLK to get TOTCARS for each inbound train, and TOTBLK for * each block, and TOTTRN for each outbound train TOTCARS(I) = SUM(K, CARBLK(I,K)) ; TOTBLK(K) = SUM(I, CARBLK(I,K)) ; TOTTRN(N) = SUM(K $ KN(K,N), TOTBLK(K)); DISPLAY TOTCARS, TOTBLK, TOTTRN; * Determine Reswitch Link Capy RHS SWRHS1(K,L,LP) $ KL(K,L) = MIN( CAPY(L), CAPY(LP), TOTBLK(K)); SWRHS2(K,L) $ KL(K,L) = MIN( CAPY(L), TOTBLK(K)); * Set up Initial Block Assignments INITBLK(K,L) = 0; INITBLK("Balto","2") = 1; * Set up initial One-to-One Flags for model testing only INITONE(L) = 0; POSITIVE VARIABLES FLOW(I,J,K,L) cars from train i block k routed to track l in time pd j TRNINV(I,J,K) cars from train i block k held in inventory from j to j+1 TRKINV(J,K,L) cars on track l block k held in inventory from j to j+1 RSWINV(J,K,L) Reswitch Cars put back on same track FINALFLO(J,K,L,M,N) cars pulled from track l block k during time pd J LEFTOVER(K,L) Cars of Block K Leftover on Track L at End of Run LEADFLO(M,N) Cars on Lead M for Train N DURATION(J) minutes duration of activity in time period J SLACK(J) minutes slack time at beginning of time period J START(J) start time of period J in minutes first one always zero STARTM(J) start time of period J reversed time axis RESWIT(J,K,L,LP) cars from track L reswitch to track LP of block K time J ; BINARY VARIABLES MATRIX(J,K,L) Block K assigned to track L during Time Pd J PROCTRN(I,J) Process Train I during Time Period J PROCTRK(J,L) Reswitch Track L during Time Period J PULLBLK(J,K) Pull Block K during Time Period J ONEFLAG(J,L) One-to-One assignment in effect Track L Time J USELEAD(M,N) Train N uses Switching Lead N and must pay for it; FREE VARIABLES Z Objective Function to be minimized; * FITTRAC2(J,L) Optional "Lifted" FITTRACK and HOLDMTX combo EQUATIONS COST define objective function TRNFIRS(I,J,K) Train node flow cons time pd 1 TRNINTM(I,J,K) Train node flow cons time pd 2 to N-1 TRNLAST(I,J,K) Train node flow cons last time pd TRKFIRS(J,K,L) Track node flow cons time pd 1 TRKINTM(J,K,L) Track node flow cons time pd 2 to N-1 TRKLAST(J,K,L) Track node flow cons last time pd LEADFLOW(M,N) Switching Lead and Train Flow Conservation BUYLEAD(M,N) Capy Constraint Forces Buy Switching Lead M ADJACENT(M,MP,N) Must also buy any fouled (intersected) pullout leads FITTRACK(J,L) Sum of Cars must fit the track ONETRN(J) Max One Train per time period can be switched ONETIME(I) Train must be switched during 1 time pd only ONCEMANY(J,L) Once Many-to-One Track must be Reswitched ONETOONE(J,L) Max Blocks to One Track MAXTRACK(J,K) Max # tracks at one time for a block BLKSETUP(K,L) Setup Initial Track-Block Assignments FIXONE(L) Setup Initial One-to-One Flags SETMTX(J,K,L,LP) Clean block with suff track capy dont open another trk NOCHANGE(J,K,L) Allows Change only when track has been pulled FLOWOK1A(I,J,K,L) Flow Link Capy constrained by Matrix Assignmt FLOWOK2A(I,J,K) Flow Link Capy constrained by one train per time period FLOWOK1B(J,K,L,LP) Resw Link Capy constrained by Matrix Assignmt FLOWOK2B(J,K,L) Resw Link Capy constrained by one train per time period FLOWOK2C(J,K,L) Force use of RSWINV Link during reswitch event FLOWOK2D(J,L) Optional Set PROCTRK to Zero if no Reswitch Flow OLDOK2A(I,J,K,L) Old Version of FLOWOK2A OLDOK2B(J,K,L,LP) Old Version of FLOWOK2B First Part OLDOK2C(J,K,L) Old Version of FLOWOK2C Second Part HOLDMTX(J,K,L) Inv Link Capy constrained by Matrix Assignmt HOLDMTX1(J,K,L) Holdmtx Constraint for Last Time Period MINTIME(J) Calculate duration of Time Period J STARTIM1(J) Set Start time of Period 1 equal to zero STARTIM2(J) Calculate Start time of Period J STARTIM3(J) Start Time of Period J in Reversed Time Axis EARSTART(I,J) Processing cannot start before train arrival LATSTART(I,J) Processing cannot start after cutoff time PTIME1(J,K) Dont Pull Earlier than Scheduled Time PTIME2(J,K) Dont Pull Later than Scheduled Time PULLONCE(K) Pull Block only One Time - Eliminate 2 Pulls @Boundary PULLFLO(J,K,L) Pull Blocks only during Schedule Times CLEANPUL(J,K,L) Only Pull Blocks having One-to-One In Effect NORESW(J,L) Dont Reswitch Blks having One-to-One (Optional) FIXPROC1(L) No Purpose to reswitching trks in First Time Pd SHUTOFFT(I,J,K) Optional Shutoff PROCTRN after any block on trn pulled SHUTOFFM(J,K,L) Optional ShutOff Matrix after block has been pulled XMATRIX(J,K,L) Shut Down Matrix in Unused Time Periods XPULLBLK(J,K) Shut Down PullBlk in Unused Time Periods XONEFLAG(J,L) Shut Down OneFlag in Unused Time Periods MAXINFS(K) Maximum No of Cars allowed to Miss Connection; * CUMPROC(J,K) Optional Constrain Inventory Links to #Cars in System * Here, consider alternative objective function of minimizing the * infeasibility (or delay) in being able to pull blocks from the * far end of the yard. Current plan is to minimize the number of * cars rehandled. * Minimize Cars Reswitched (Including Cars Left on Same Track ) * Plus Cost of "Buying" Required Switching Leads * Plus Infeasibility cost of Leftover Cars - Note - * Obj Funct should be refined to not charge cost of Leftover Cars * that cannot possibly make their connections COST .. Z =E= SUM((J,K,L,LP) $ (KL(K,L) $ (KL(K,LP) $ (ORD(L) NE ORD(LP)))),RESWIT(J,K,L,LP)) +SUM((J,K,L) $ ((ORD(J) NE CARD(J)) $ (KL(K,L))) ,RSWINV(J,K,L)) + SUM((M,N) $ (LEADCOST(M,N) GT 0), LEADCOST(M,N)*USELEAD(M,N)) + INFEAS* SUM((K,L) $ KL(K,L), LEFTOVER(K,L)); * Flow Conserv Constraint for the first time period of train nodes TRNFIRS(I,J,K) $ (CARBLK(I,K) NE 0 AND ORD(J) EQ 1) .. SUM(L $ KL(K,L), FLOW(I,J,K,L)) + TRNINV(I,J,K) =E= CARBLK(I,K) ; * Constraint for intermediate time period of train nodes TRNINTM(I,J,K) $ (CARBLK(I,K) NE 0 AND ORD(J) NE 1 AND ORD(J) NE CARD(J)) .. SUM(L $ KL(K,L), FLOW(I,J,K,L)) + TRNINV(I,J,K) =E= TRNINV(I,J-1,K) ; * Constraint for last time period of train nodes TRNLAST(I,J,K) $ (CARBLK(I,K) NE 0 AND ORD(J) EQ CARD(J)) .. SUM(L $ KL(K,L), FLOW(I,J,K,L)) =E= TRNINV(I,J-1,K) ; * Constraint for first time period of track nodes Initial Inventory is Zero TRKFIRS(J,K,L) $ (KL(K,L) $ (ORD(J) EQ 1)) .. SUM(I $ (CARBLK(I,K) NE 0), FLOW(I,J,K,L)) + SUM(LP $ (KL(K,LP) $ (ORD(LP) NE ORD(L))), RESWIT(J,K,LP,L)) =E= TRKINV(J,K,L) + RSWINV(J,K,L) + SUM((M,N) $ (LM(L,M) $ (KN(K,N))) , FINALFLO(J,K,L,M,N)) + SUM(LP $ (KL(K,LP) $ (ORD(LP) NE ORD(L))), RESWIT(J,K,L,LP)); * Constraint for intermediate time period of track nodes TRKINTM(J,K,L) $ (KL(K,L) $ (ORD(J) NE 1 AND ORD(J) NE CARD(J))) .. TRKINV(J-1,K,L) + SUM(I $ (CARBLK(I,K) NE 0), FLOW(I,J,K,L)) + SUM(LP $ (KL(K,LP) $ (ORD(LP) NE ORD(L))), RESWIT(J,K,LP,L)) + RSWINV(J-1,K,L) =E= TRKINV(J,K,L) + RSWINV(J,K,L) + SUM((M,N) $ (LM(L,M) $ (KN(K,N))), FINALFLO(J,K,L,M,N)) + SUM(LP $ (KL(K,LP) $ (ORD(LP) NE ORD(L))), RESWIT(J,K,L,LP)); * Constraints for last time period of track nodes: * Includes Leftover Cars TRKLAST(J,K,L) $ (KL(K,L) $ (ORD(J) EQ CARD(J))) .. TRKINV(J-1,K,L) + RSWINV(J-1,K,L) + SUM(I $ (CARBLK(I,K) NE 0), FLOW(I,J,K,L)) + SUM(LP $ (KL(K,LP) $ (ORD(LP) NE ORD(L))), RESWIT(J,K,LP,L)) =E= SUM((M,N) $ (LM(L,M) $ (KN(K,N))), FINALFLO(J,K,L,M,N)) + SUM(LP $ (KL(K,LP) $ (ORD(LP) NE ORD(L))), RESWIT(J,K,L,LP)) + LEFTOVER(K,L); * Flow Conservation for Switching Lead and Train Nodes LEADFLOW(M,N) .. SUM((J,K,L) $ (KL(K,L) $ (LM(L,M) $ (KN(K,N)))), FINALFLO(J,K,L,M,N)) =E= LEADFLO(M,N); * Model must "buy" any switching leads utilized by the train BUYLEAD(M,N) $ (LEADTOT(N) GT 0) .. LEADFLO(M,N) =L= USELEAD(M,N) * TOTTRN(N); * "Adjacency" constraint here to forces buying intermediate * switching leads which are blocked out by pullout activity, as * well as the leads which are actually used by the track itself ADJACENT(M,MP,N) $ (ORD(M) LT ORD(MP)-1) .. USELEAD(MP-1,N) =G= USELEAD(M,N) + USELEAD(MP,N) - 1; * Calculate Cumulative Number of Cars processed for each block K * by the end of Time Period J. Limit Inventory Link Flows Accordingly * This is an Optional Constraint to Help Fix PROCTRN * Not sure this constraint is doing anything thats not already there * CUMPROC(J,K) .. SUM(L,TRKINV(J,K,L)) + SUM(L,FINALFLO(J,K,L)) + RSWINV =E= * SUM((I,JP) $ (ORD(JP) LE ORD(J)), (CARBLK(I,K) * PROCTRN(I,JP))) * - SUM((JP,L) $ (ORD(JP) LT ORD(J)), FINALFLO(JP,K,L)); * Determine the amount of processing time for Time Pd J * BIGM used to force excess unused time periods to the rear MINTIME(J) .. DURATION(J) =E= PROCRATE * ( SUM((I,K,L) $ ((CARBLK(I,K) NE 0) $ KL(K,L)), FLOW(I,J,K,L)) + SUM((K,L,LP) $ (KL(K,L) $ ( KL(K,LP) $ (ORD(L) NE ORD(LP)))), RESWIT(J,K,L,LP)) + SUM((K,L) $ KL(K,L), RSWINV(J,K,L))) + BIGM * (1- SUM(I, PROCTRN(I,J)) - SUM(L, PROCTRK(J,L))); * Set the Start Time of the First Time Period = 0 by definition STARTIM1(J) $ (ORD(J) EQ 1) .. START(J) =E= 0 ; * Compute Start Times of subsequent time periods STARTIM2(J) $ (ORD(J) GT 1) .. START(J) =E= START(J-1) + SLACK(J-1) + DURATION(J-1) ; * Reversed Time Axis is necessary to avoid nonlinear constraint * on latest block pull time STARTIM3(J) .. STARTM(J) =E= MAXTIME - START(J); * Coupling Constraint prevents more cars than the track can hold FITTRACK(J,L) .. SUM(K $ ((ORD(J) NE CARD(J)) $ (KL(K,L))), TRKINV(J,K,L) + RSWINV(J,K,L)) + SUM((K,M,N) $ (KL(K,L) $ (LM(L,M) $ (KN(K,N)))), FINALFLO(J,K,L,M,N)) =L= CAPY(L) ; * Optional Coupling Constraint is tighter than FITTRACK because it limits * track capacity based on the actual blocks currently assigned to the * track. It is a "lifted" version of HOLDMTX, having both sides summed * over all Blocks K. But since there is usually only one, and never * more than MAXBLOCKs assigned to a track, this constraint will be * stronger than either FITTRACK or HOLDMTX alone * But this one actually seems to increase execution time * FITTRAC2(J,L) .. SUM(K, TRKINV(J,K,L)) + SUM(K, FINALFLO(J,K,L)) * + SUM(K, RSWINV(J,K,L)) =L= SUM(K, (TOTBLK(K) * MATRIX(J,K,L))) ; * Set Up Initial Track to Block Assignments for Time Pd 1 * This is an optional constraint only if desired BLKSETUP(K,L) $ (KL(K,L) $ (INITBLK(K,L) NE 0)) .. MATRIX("1",K,L) =E= INITBLK(K,L) ; * Set Up Initial One-to-One Flags (Only if provided by user) FIXONE(L) $ (INITONE(L) NE 0) .. ONEFLAG("1",L) =E= INITONE(L); * "Lock" Matrix Assignment for Initialized Blocks: That is, for * blocks having initial assignments, where the capacity of the * assigned track is sufficient to hold all the cars in the block, * prohibit moving these cars to another track. This is an optional * constraint for efficiency purposes only to take advantage of * initial conditions only and it may not result in a strictly optimal * solution. To activate, set INITONE(.) for track to a one. * Could be generalized for multiple time periods by using MATRIX * in place of INITBLK and ONEFLAG in place of INITONE, but would * generate a large number of constraints. Efficiency impact * must be tested. Upgraded to standard constraint 5/25/93 SETMTX(J,K,L,LP) $ (KL(K,L) $ ((TOTBLK(K) LE CAPY(L)) AND (ORD(L) NE ORD(LP)))) .. MATRIX(J,K,LP) =L= 2- ONEFLAG(J,L)- MATRIX(J,K,L); * A new block can be added to a track only if: 1) the track does * not have a one-to-one assignment, or 2) the track was pulled or * reswitched in the previous time period NOCHANGE(J,K,L) $ (KL(K,L) $ (ORD(J) GT 1)) .. MATRIX(J-1,K,L) - MATRIX(J,K,L) + 1 =G= ONEFLAG(J,L) - SUM((KP,M,N) $ (KL(KP,L) $ (LM(L,M) $ (KN(KP,N)))), FINALFLO(J-1,KP,L,M,N)) - PROCTRK(J-1,L); * Once a track has been contaminated with more than one block, it * cannot be restored to a one-to-one assignment until it is reswitched ONCEMANY(J,L) $ (ORD(J) GT 1) .. ONEFLAG(J,L) =L= ONEFLAG(J-1,L) + PROCTRK(J,L) ; * This limits the number of blocks which can be assigned to a track. * If One-to-One assignment is in effect, only one block can be assigned. * If Many-to-One assignment in effect, only MAXBLOCK can be assigned. ONETOONE(J,L) .. SUM(K $ KL(K,L), MATRIX(J,K,L)) =L= MAXBLOCK - (MAXBLOCK-1) * ONEFLAG(J,L); * This limits the number of tracks to which one block can be assigned. * This is an optional constraint primarily for efficiency purposes. If * not desired then MAXTRAX can be set to a large number MAXTRACK(J,K) .. SUM(L $ KL(K,L), MATRIX(J,K,L)) =L= MAXTRAX; * Shuts off Classification flows which are not in accordance with current * block to track assignments FLOWOK1A(I,J,K,L) $ (KL(K,L) $ (CARBLK(I,K) NE 0)) .. FLOW(I,J,K,L) =L= CARBLK(I,K) * MATRIX(J,K,L); * Shuts off Reswitch flows not in accordance with block to track assignments FLOWOK1B(J,K,L,LP) $ (KL(K,L) $ (KL(K,LP) $ (ORD(L) NE ORD(LP)))) .. RESWIT(J,K,L,LP) =L= MATRIX(J,K,LP) * SWRHS1(K,L,LP); * Only one train or one reswitch track can be processed during any * one time period ONETRN(J) .. SUM(I, PROCTRN(I,J)) + SUM(L, PROCTRK(J,L)) =L= 1; * Each train must be completely processed during a single time period ONETIME(I) .. SUM(J, PROCTRN(I,J)) =E= 1; * A train cannot be processed before its scheduled availability time * This prevents processing in any earlier time periods J EARSTART(I,J) .. START(J) - EPT(I) * PROCTRN(I,J) =G= 0 ; * In order for all connections to be made, a train cannot be processed * later than its computed cutoff time. This comparison is made on * reversed time axis to avoid nonlinear constraint. Purpose of constraint * is to fix values of PROCTRN to improve efficiency. This constraint * would generate an infeasible problem if CUTOFF < Earliest * Processing Time, so it is not generated if that event occurs LATSTART(I,J) $ (CUTOFF(I) GE EPT(I)) .. STARTM(J) - CUTOFFM(I) * PROCTRN(I,J) =G= 0; * Two constraints "Lifted" by Summation with Equality - they were * formerly separate inequality constraints FLOWOK2A(I,J,K,L) and * FLOWOK2B(J,K,L,LP) * This shuts off all flows originating from train I except during * the time period when train I is being processed FLOWOK2A(I,J,K) $ (CARBLK(I,K) NE 0) .. SUM(L $ KL(K,L), FLOW(I,J,K,L)) =E= CARBLK(I,K) * PROCTRN(I,J); * Original UnLifted Version of FLOWOK2A constraint OLDOK2A(I,J,K,L) $ ((CARBLK(I,K) NE 0) $ KL(K,L)) .. FLOW(I,J,K,L) =L= CARBLK(I,K) * PROCTRN(I,J); * Shuts off all reswitch flows originating from track L except during * the time period when track L is being processed FLOWOK2B(J,K,L) $ KL(K,L) .. SUM(LP $ (KL(K,LP) $ (ORD(L) NE ORD(LP))), RESWIT(J,K,L,LP)) + RSWINV(J,K,L) =L= PROCTRK(J,L) * SWRHS2(K,L); * Original Unlifted Version of FLOWOK2B constraint -First Part * (Although Right Hand side has been tightened using SWRHS2) OLDOK2B(J,K,L,LP) $ (KL(K,L) $ KL(K,LP)) .. RESWIT(J,K,L,LP) =L= PROCTRK(J,L) * SWRHS2(K,L); * Original Unlifted Version of FLOWOK2B constraint - Second Part OLDOK2C(J,K,L) $ KL(K,L) .. RSWINV(J,K,L) =L= PROCTRK(J,L) * SWRHS2(K,L); * Shuts off normal track Inventory Link during reswitch event, to * force the use of RSWINV link FLOWOK2C(J,K,L) $ ((ORD(J) NE CARD(J)) $ (KL(K,L))) .. TRKINV(J,K,L) =L= (1 - PROCTRK(J,L)) * CAPY(L); * Optional Shut Off PROCTRK if there is no flow over the Reswitch links * during that time period. Primary purpose is to properly label excess * time periods, force them all to the end, and fix Binary Variables FLOWOK2D(J,L) .. PROCTRK(J,L) =L= SUM((K,LP) $ (KL(K,L) $ (KL(K,LP) $ (ORD(L) NE ORD(LP)))), RESWIT(J,K,L,LP)); * + SUM(K $ ((ORD(J) NE CARD(J)) $ (KL(K,L))), RSWINV(J,K,L)); * Requires that Block to Track assignment must be maintained at all * times when there are physically cars on Track K from Block K * Does this need special version for last time period ? HOLDMTX(J,K,L) $ ((ORD(J) NE CARD(J)) $ (KL(K,L))) .. TRKINV(J,K,L) + RSWINV(J,K,L) + SUM((M,N) $ (LM(L,M) $ (KN(K,N))), FINALFLO(J,K,L,M,N)) =L= MATRIX(J,K,L)* SWRHS2(K,L); * Holdmtx version for last time period using Leftover links instead * of inventory links HOLDMTX1(J,K,L) $ (KL(K,L) $ (ORD(J) EQ CARD(J))) .. LEFTOVER(K,L) + SUM((M,N) $ (LM(L,M) $ (KN(K,N))), FINALFLO(J,K,L,M,N)) =L= MATRIX(J,K,L)* SWRHS2(K,L); * Efficiency Constraint to Shut Off Matrix after block has been pulled * This along with SHUTOFFT have a very noticeable effect on efficiency SHUTOFFM(J,K,L) $ (KL(K,L) $ (ORD(J) NE 1)) .. MATRIX(J,K,L) =L= 1 - SUM(JP $ (ORD(JP) LT ORD(J)), PULLBLK(JP,K)) + LEFTOVER(K,L); * Shut off PROCTRN after any cars of any block on that train have been pulled SHUTOFFT(I,J,K) $ ((ORD(J) NE 1) AND (CARBLK(I,K) NE 0)) .. PROCTRN(I,J) =L= 1 - SUM((JP,L,M,N) $ (LM(L,M) $ (KN(K,N) $ (KL(K,L) $ (ORD(JP) LT ORD(J))))), FINALFLO(JP,K,L,M,N)/TOTBLK(K)); * This constraint, assuming that the departure yard is full, prevents * early pulling of classification tracks PTIME1(J,K) $ (ORD(J) NE CARD(J)) .. START(J+1) -SCHPULL(K)*PULLBLK(J,K) =G= 0; * This constraint prevents late pulling of classification tracks. Note * it uses reversed time axis to avoid nonlinear constraint. If desired * a similar constraint can be introduced to force processing of inbound * trains prior to their cutoff times. Cutoff times can be computed based * on what blocks are carried on the inbound train. PTIME2(J,K) $ (ORD(J) NE 1) .. STARTM(J) - SCHPULLM(K)*PULLBLK(J,K) =G= 0; * It is possible for above two constraints to be satisfied for two * different time periods, if Scheduled Pull Time = Start(J) precisely * This equation limits model to precisely one pull for each block PULLONCE(K) .. SUM(J, PULLBLK(J,K)) =E= 1; * Optional Efficiency Constraint to Shut Down MATRIX after the * block has been pulled. A similar constraint could be added to * shut down MATRIX until the first car in the block arrives in Yard * Redundant with ShutoffM * PTIME3(J,K,L) $ (ORD(J) NE 1) .. STARTM(J) - SCHPULLM(K)*MATRIX(J,K,L) =G= 0; * Permits flow on FINALFLO pull links only during the time period J * when the block is scheduled to be pulled PULLFLO(J,K,L) $ KL(K,L) .. SUM((M,N) $ (LM(L,M) $ (KN(K,N))), FINALFLO(J,K,L,M,N)) =L= PULLBLK(J,K) * TOTBLK(K); * Permits flow on FINALFLO only if the block is a "Clean" classification, * That is reswitch tracks may not be pulled CLEANPUL(J,K,L) $ KL(K,L) .. SUM((M,N) $ (LM(L,M) $ (KN(K,N))), FINALFLO(J,K,L,M,N)) =L= ONEFLAG(J,L) * TOTBLK(K); * The opposite of CLEANPUL. Tracks having One-to-One assignment may * not be reswitched. The purpose is to help fix 0-1 variables. This * constraint doesnt prevent the model from reswitching any track, just * forces it to set ONEFLAG equal to zero first NORESW(J,L) $ (ORD(J) NE 1).. PROCTRK(J,L) + ONEFLAG(J-1,L) =L= 1; * For model testing it doesnt make sense to reswitch a track during * the first time period FIXPROC1(L) .. PROCTRK("1",L) =E= 0; * Optional Constraint. Once a clean classification has been established, * keep it clean (Dont contaminate) until track has been pulled. In normal * use, this constraint doesnt prevent establishment of reswitch tracks, * it only requires consistency in the ONEFLAG between time periods. When * One to One assignment has been established by user in initial conditions * however, this constraint forces all subsequent vars to one to one and * prevents any additional blocks being added until after the first block * has been pulled. * * This constraint actually degrades efficiency slightly with a * few number of time periods. However I am keeping it in because I * suspect the impact will grow with a larger model. Remember to * audit this one later. * KEEPONE(J,L) $ (ORD(J) NE 1) .. ONEFLAG(J,L) =G= ONEFLAG(J-1,L) * - SUM((K,M,N) $ (LM(L,M) $ (KN(K,N) $ (KL(K,L)))), FINALFLO(J-1,K,L,M,N)); * Shut down Matrix in Unused Time Periods XMATRIX(J,K,L) $ (ORD(J) NE 1) .. MATRIX(J,K,L) =L= SUM(I, PROCTRN(I,J)) + SUM(LP, PROCTRK(J,LP)); * Shut down Pullblk in Unused Time Periods XPULLBLK(J,K) $ (ORD(J) NE 1) .. PULLBLK(J,K) =L= SUM(I, PROCTRN(I,J)) + SUM(LP, PROCTRK(J,LP)); * Shut down OneFlag in Unused Time Periods XONEFLAG(J,L) $ (ORD(J) NE 1) .. ONEFLAG(J,L) =L= SUM(I, PROCTRN(I,J)) + SUM(LP, PROCTRK(J,LP)); * Maximum number of cars allowed to miss connection * Note: The addition of SUREMISS cars does not guarantee feasibility * It may still be necessary for the user to provide a margin of * Infeasibility using the MAXMISS parameter MAXINFS(K) .. SUM(L $ KL(K,L), LEFTOVER(K,L)) =L= MAXMISS(K) + SUREMISS(K); * YARD1 is the Bare Bones Model without any Lifting or Add'l Constraints MODEL YARD1 / COST, TRNFIRS, TRNINTM, TRNLAST, TRKFIRS, TRKINTM, TRKLAST, FITTRACK, ONETRN, ONETIME, ONCEMANY, ONETOONE, BLKSETUP, FIXONE, NOCHANGE, FLOWOK1A, OLDOK2A, FLOWOK1B, OLDOK2B, OLDOK2C, FLOWOK2C, HOLDMTX, HOLDMTX1, MINTIME, STARTIM1, STARTIM2, STARTIM3, EARSTART, PTIME1, PTIME2, PULLONCE, PULLFLO, CLEANPUL, FIXPROC1, MAXINFS /; * YARD2 is a Reduced Model not including Pullout Leads. MODEL YARD2 / COST, TRNFIRS, TRNINTM, TRNLAST, TRKFIRS, TRKINTM, TRKLAST, FITTRACK, ONETRN, ONETIME, ONCEMANY, ONETOONE, MAXTRACK, BLKSETUP, FIXONE, SETMTX, NOCHANGE, FLOWOK1A, FLOWOK2A, FLOWOK1B, FLOWOK2B, FLOWOK2C, FLOWOK2D, HOLDMTX, HOLDMTX1, MINTIME, STARTIM1, STARTIM2, STARTIM3, EARSTART, LATSTART, PTIME1, PTIME2, PULLONCE, PULLFLO, CLEANPUL, NORESW, FIXPROC1, SHUTOFFT, SHUTOFFM, XMATRIX, XPULLBLK, XONEFLAG, MAXINFS /; * YARD3 is the Full Model including additional constraints * and pullout lead features. It includes all constraints except * OLDOK2A, OLDOK2B, OLDOK2C MODEL YARD3 / COST, TRNFIRS, TRNINTM, TRNLAST, TRKFIRS, TRKINTM, TRKLAST, LEADFLOW, BUYLEAD, ADJACENT, FITTRACK, ONETRN, ONETIME, ONCEMANY, ONETOONE, MAXTRACK, BLKSETUP, FIXONE, SETMTX, NOCHANGE, FLOWOK1A, FLOWOK2A, FLOWOK1B, FLOWOK2B, FLOWOK2C, FLOWOK2D, HOLDMTX, HOLDMTX1, MINTIME, STARTIM1, STARTIM2, STARTIM3, EARSTART, LATSTART, PTIME1, PTIME2, PULLONCE, PULLFLO, CLEANPUL, NORESW, FIXPROC1, SHUTOFFT, SHUTOFFM, XMATRIX, XPULLBLK, XONEFLAG, MAXINFS /; * Branching Priorities are not working on the VAX, but here is how they * should be implemented on the IBM Workstation * YARD1.PRIOROPT=1; * YARD2.PRIOROPT=1; * YARD3.PRIOROPT=1; PROCTRN.PRIOR(I,J)=10; PULLBLK.PRIOR(J,K)=20; PROCTRK.PRIOR(J,L)=30; ONEFLAG.PRIOR(J,L)=40; MATRIX.PRIOR(J,K,L) $ KL(K,L) =50; USELEAD.PRIOR(M,N)=25; OPTION LIMROW=0, LIMCOL=0, SOLPRINT=OFF; OPTION MIP=LAMPS, ITERLIM = 35000, OPTCR=0; * Solve 3 Models Using LAMPS without Priorities SOLVE YARD1 USING MIP MINIMIZING Z ; DISPLAY MATRIX.L, ONEFLAG.L, PROCTRN.L, PROCTRK.L, SLACK.L, DURATION.L, START.L, FLOW.L, PULLBLK.L, RESWIT.L, RSWINV.L, FINALFLO.L, LEFTOVER.L; SOLVE YARD2 USING MIP MINIMIZING Z ; DISPLAY MATRIX.L, ONEFLAG.L, PROCTRN.L, PROCTRK.L, SLACK.L, DURATION.L, START.L, FLOW.L, PULLBLK.L, RESWIT.L, RSWINV.L, FINALFLO.L, LEFTOVER.L; SOLVE YARD3 USING MIP MINIMIZING Z ; DISPLAY MATRIX.L, ONEFLAG.L, PROCTRN.L, PROCTRK.L, SLACK.L, DURATION.L, START.L, FLOW.L, PULLBLK.L, RESWIT.L, RSWINV.L, FINALFLO.L, LEADFLO.L, USELEAD.L, LEFTOVER.L; * Solve 3 Models Using OSL Without Priorities OPTION MIP=OSL, ITERLIM=35000, OPTCR=0; SOLVE YARD1 USING MIP MINIMIZING Z; DISPLAY MATRIX.L, ONEFLAG.L, PROCTRN.L, PROCTRK.L, SLACK.L, DURATION.L, START.L, FLOW.L, PULLBLK.L, RESWIT.L, RSWINV.L, FINALFLO.L, LEFTOVER.L; SOLVE YARD2 USING MIP MINIMIZING Z; DISPLAY MATRIX.L, ONEFLAG.L, PROCTRN.L, PROCTRK.L, SLACK.L, DURATION.L, START.L, FLOW.L, PULLBLK.L, RESWIT.L, RSWINV.L, FINALFLO.L, LEFTOVER.L; SOLVE YARD3 USING MIP MINIMIZING Z; DISPLAY MATRIX.L, ONEFLAG.L, PROCTRN.L, PROCTRK.L, SLACK.L, DURATION.L, START.L, FLOW.L, PULLBLK.L, RESWIT.L, RSWINV.L, FINALFLO.L, LEADFLO.L, USELEAD.L, LEFTOVER.L; * Turn On Branching Priorities YARD1.PRIOROPT=1; YARD2.PRIOROPT=1; YARD3.PRIOROPT=1; OPTION MIP=LAMPS, ITERLIM=35000, OPTCR=0; * Solve 3 models using LAMPS with priorities SOLVE YARD1 USING MIP MINIMIZING Z ; DISPLAY MATRIX.L, ONEFLAG.L, PROCTRN.L, PROCTRK.L, SLACK.L, DURATION.L, START.L, FLOW.L, PULLBLK.L, RESWIT.L, RSWINV.L, FINALFLO.L, LEFTOVER.L; SOLVE YARD2 USING MIP MINIMIZING Z ; DISPLAY MATRIX.L, ONEFLAG.L, PROCTRN.L, PROCTRK.L, SLACK.L, DURATION.L, START.L, FLOW.L, PULLBLK.L, RESWIT.L, RSWINV.L, FINALFLO.L, LEFTOVER.L; SOLVE YARD3 USING MIP MINIMIZING Z ; DISPLAY MATRIX.L, ONEFLAG.L, PROCTRN.L, PROCTRK.L, SLACK.L, DURATION.L, START.L, FLOW.L, PULLBLK.L, RESWIT.L, RSWINV.L, FINALFLO.L, LEADFLO.L, USELEAD.L, LEFTOVER.L; OPTION MIP=OSL, ITERLIM=35000, OPTCR=0; * Solve 3 Models using OSL with Priorities SOLVE YARD1 USING MIP MINIMIZING Z; DISPLAY MATRIX.L, ONEFLAG.L, PROCTRN.L, PROCTRK.L, SLACK.L, DURATION.L, START.L, FLOW.L, PULLBLK.L, RESWIT.L, RSWINV.L, FINALFLO.L, LEFTOVER.L; SOLVE YARD2 USING MIP MINIMIZING Z ; DISPLAY MATRIX.L, ONEFLAG.L, PROCTRN.L, PROCTRK.L, SLACK.L, DURATION.L, START.L, FLOW.L, PULLBLK.L, RESWIT.L, RSWINV.L, FINALFLO.L, LEFTOVER.L; SOLVE YARD3 USING MIP MINIMIZING Z ; DISPLAY MATRIX.L, ONEFLAG.L, PROCTRN.L, PROCTRK.L, SLACK.L, DURATION.L, START.L, FLOW.L, PULLBLK.L, RESWIT.L, RSWINV.L, FINALFLO.L, LEADFLO.L, USELEAD.L, LEFTOVER.L;