The Mixed Integer Linear Programming Solver

Example 14.2 Multicommodity Transshipment Problem with Fixed Charges

The following example has been adapted from the example "A Multicommodity Transshipment Problem with Fixed Charges" in Chapter 4, "The LP Procedure" (SAS/OR User's Guide: Mathematical Programming Legacy Procedures).

This example illustrates the use of PROC OPTMODEL to generate a mixed integer linear program to solve a multicommodity network flow model with fixed charges. Consider a network with nodes N, arcs A, and a set C of commodities to be shipped between the nodes. The commodities are defined in the data set COMMODITY_DATA, as follows:

title 'Multicommodity Transshipment Problem with Fixed Charges';

data commodity_data;
   do c = 1 to 4;
      output;
   end;
run;

Shipping cost s Subscript i j c is for each of the four commodities c across each of the arcs left-parenthesis i comma j right-parenthesis. In addition, there is a fixed charge f Subscript i j for the use of each arc left-parenthesis i comma j right-parenthesis. The shipping costs and fixed charges are defined in the data set ARC_DATA, as follows:

data arc_data;
   input from $ to $ c1 c2 c3 c4 fx;
   datalines;
farm-a  Chicago 20 15 17 22 100
farm-b  Chicago 15 15 15 30  75
farm-c  Chicago 30 30 10 10 100
farm-a  StLouis 30 25 27 22 150
farm-c  StLouis 10 9 11 10   75
Chicago NY      75 75 75 75 200
StLouis NY      80 80 80 80 200
;

The supply (positive numbers) or demand (negative numbers) d Subscript i c at each of the nodes for each commodity c is shown in the data set SUPPLY_DATA, as follows:

data supply_data;
   input node $ sd1 sd2 sd3 sd4;
   datalines;
farm-a  100  100  40   .
farm-b  100  200  50  50
farm-c   40  100  75 100
NY     -150 -200 -50 -75
;

Let x Subscript i j c define the flow of commodity c across arc left-parenthesis i comma j right-parenthesis. Let y Subscript i j Baseline equals 1 if arc left-parenthesis i comma j right-parenthesis is used, and 0 otherwise. Since the total flow on an arc left-parenthesis i comma j right-parenthesis must be at most the total demand across all nodes k element-of upper N, you can define the trivial upper bound u Subscript i j c as

x Subscript i j c Baseline less-than-or-equal-to u Subscript i j c Baseline equals sigma-summation Underscript k element-of upper N vertical-bar d Subscript k c Baseline less-than 0 Endscripts left-parenthesis minus d Subscript k c Baseline right-parenthesis

This model can be represented using the following mixed integer linear program:

StartLayout 1st Row 1st Column min 2nd Column sigma-summation Underscript left-parenthesis i comma j right-parenthesis element-of upper A Endscripts sigma-summation Underscript c element-of upper C Endscripts s Subscript i j c Baseline x Subscript i j c plus sigma-summation Underscript left-parenthesis i comma j right-parenthesis element-of upper A Endscripts f Subscript i j Baseline y Subscript i j 2nd Row 1st Column normal s period normal t period 2nd Column sigma-summation Underscript j element-of upper N vertical-bar left-parenthesis i comma j right-parenthesis element-of upper A Endscripts x Subscript i j c minus sigma-summation Underscript j element-of upper N vertical-bar left-parenthesis j comma i right-parenthesis element-of upper A Endscripts x Subscript j i c 3rd Column less-than-or-equal-to 4th Column d Subscript i c 5th Column for-all i element-of upper N comma c element-of upper C 6th Column left-parenthesis normal b normal a normal l normal a normal n normal c normal e normal bar normal c normal o normal n right-parenthesis 3rd Row 1st Column Blank 2nd Column x Subscript i j c 3rd Column less-than-or-equal-to 4th Column u Subscript i j c Baseline y Subscript i j 5th Column for-all left-parenthesis i comma j right-parenthesis element-of upper A comma c element-of upper C 6th Column left-parenthesis normal f normal i normal x normal e normal d normal bar normal c normal h normal a normal r normal g normal e normal bar normal c normal o normal n right-parenthesis 4th Row 1st Column Blank 2nd Column x Subscript i j c 3rd Column greater-than-or-equal-to 4th Column 0 5th Column for-all left-parenthesis i comma j right-parenthesis element-of upper A comma c element-of upper C 5th Row 1st Column Blank 2nd Column y Subscript i j Baseline element-of StartSet 0 comma 1 EndSet 3rd Column Blank 4th Column Blank 5th Column for-all left-parenthesis i comma j right-parenthesis element-of upper A EndLayout

Constraint (balance_con) ensures conservation of flow for both supply and demand. Constraint (fixed_charge_con) models the fixed charge cost by forcing y Subscript i j Baseline equals 1 if x Subscript i j c Baseline greater-than 0 for some commodity c element-of upper C.

The PROC OPTMODEL statements follow:

proc optmodel;
   set COMMODITIES;
   read data commodity_data into COMMODITIES=[c];

   set <str,str> ARCS;
   num unit_cost {ARCS, COMMODITIES};
   num fixed_charge {ARCS};
   read data arc_data into ARCS=[from to] {c in COMMODITIES}
      <unit_cost[from,to,c]=col('c'||c)> fixed_charge=fx;
   print unit_cost fixed_charge;

   set <str> NODES = union {<i,j> in ARCS} {i,j};
   num supply {NODES, COMMODITIES} init 0;
   read data supply_data nomiss into [node] {c in COMMODITIES}
      <supply[node,c]=col('sd'||c)>;
   print supply;

   var AmountShipped {ARCS, c in COMMODITIES} >= 0 <= sum {i in NODES}
      max(supply[i,c],0);

   /* UseArc[i,j] = 1 if arc (i,j) is used, 0 otherwise */
   var UseArc {ARCS} binary;

   /* TotalCost = variable costs + fixed charges */
   min TotalCost = sum {<i,j> in ARCS, c in COMMODITIES}
      unit_cost[i,j,c] * AmountShipped[i,j,c]
      + sum {<i,j> in ARCS} fixed_charge[i,j] * UseArc[i,j];

   con flow_balance {i in NODES, c in COMMODITIES}:
      sum {<(i),j> in ARCS} AmountShipped[i,j,c] -
      sum {<j,(i)> in ARCS} AmountShipped[j,i,c] <= supply[i,c];

   /* if AmountShipped[i,j,c] > 0 then UseArc[i,j] = 1 */
   con fixed_charge_def {<i,j> in ARCS, c in COMMODITIES}:
      AmountShipped[i,j,c] <= AmountShipped[i,j,c].ub * UseArc[i,j];

   solve;

   print AmountShipped;

   create data solution from [from to commodity]={<i,j> in ARCS,
      c in COMMODITIES: AmountShipped[i,j,c].sol ne 0} amount=AmountShipped;
quit;

Although the PROC LP example used M = 1.0e6 in the FIXED_CHARGE_DEF constraint that links the continuous variable to the binary variable, it is numerically preferable to use a smaller, data-dependent value. Here, the upper bound on AmountShipped[i,j,c] is used instead. This upper bound is calculated in the first VAR statement as the sum of all positive supplies for commodity c. The logical condition AmountShipped[i,j,k].sol ne 0 in the CREATE DATA statement ensures that only the nonzero parts of the solution appear in the SOLUTION data set.

The problem summary, solution summary, and the output from the three PRINT statements are shown in Output 14.2.1.

Output 14.2.1: Multicommodity Transshipment Problem with Fixed Charges Solution Summary

Multicommodity Transshipment Problem with Fixed Charges

The OPTMODEL Procedure

[1][2][3]unit_cost
ChicagoNY175
ChicagoNY275
ChicagoNY375
ChicagoNY475
StLouisNY180
StLouisNY280
StLouisNY380
StLouisNY480
farm-aChicago120
farm-aChicago215
farm-aChicago317
farm-aChicago422
farm-aStLouis130
farm-aStLouis225
farm-aStLouis327
farm-aStLouis422
farm-bChicago115
farm-bChicago215
farm-bChicago315
farm-bChicago430
farm-cChicago130
farm-cChicago230
farm-cChicago310
farm-cChicago410
farm-cStLouis110
farm-cStLouis29
farm-cStLouis311
farm-cStLouis410

[1][2]fixed_charge
ChicagoNY200
StLouisNY200
farm-aChicago100
farm-aStLouis150
farm-bChicago75
farm-cChicago100
farm-cStLouis75

supply
 1234
Chicago0000
NY-150-200-50-75
StLouis0000
farm-a100100400
farm-b1002005050
farm-c4010075100

Problem Summary
Objective SenseMinimization
Objective FunctionTotalCost
Objective TypeLinear
  
Number of Variables35
Bounded Above0
Bounded Below0
Bounded Below and Above35
Free0
Fixed0
Binary7
Integer0
  
Number of Constraints52
Linear LE (<=)52
Linear EQ (=)0
Linear GE (>=)0
Linear Range0
  
Constraint Coefficients112

Solution Summary
SolverMILP
AlgorithmBranch and Cut
Objective FunctionTotalCost
Solution StatusOptimal
Objective Value42825
  
Relative Gap0
Absolute Gap0
Primal Infeasibility0
Bound Infeasibility0
Integer Infeasibility0
  
Best Bound42825
Nodes1
Solutions Found4
Iterations41
Presolve Time0.00
Solution Time0.02

[1][2][3]AmountShipped
ChicagoNY1110
ChicagoNY2100
ChicagoNY350
ChicagoNY475
StLouisNY140
StLouisNY2100
StLouisNY30
StLouisNY40
farm-aChicago110
farm-aChicago20
farm-aChicago30
farm-aChicago40
farm-aStLouis10
farm-aStLouis20
farm-aStLouis30
farm-aStLouis40
farm-bChicago1100
farm-bChicago2100
farm-bChicago30
farm-bChicago40
farm-cChicago10
farm-cChicago20
farm-cChicago350
farm-cChicago475
farm-cStLouis140
farm-cStLouis2100
farm-cStLouis30
farm-cStLouis40


Last updated: March 04, 2026