The first several PROC OPTMODEL statements declare index sets and parameters and then read the input data:
proc optmodel; set <str,str> ARCS; num cost {ARCS}; read data arc_data into ARCS=[i j] cost; set <str> FACTORIES; num capacity {FACTORIES}; read data factory_data into FACTORIES=[factory] capacity; set <str> DEPOTS; num throughput {DEPOTS}; num open_cost {DEPOTS}; num close_savings {DEPOTS}; read data depot_data into DEPOTS=[depot] throughput open_cost=cost close_savings=savings; set <str> EXPAND_DEPOTS; num expand_throughput {EXPAND_DEPOTS}; num expand_cost {EXPAND_DEPOTS}; read data expand_depot_data into EXPAND_DEPOTS=[depot] expand_throughput=throughput expand_cost=cost; set <str> CUSTOMERS; num demand {CUSTOMERS}; read data customer_data into CUSTOMERS=[customer] demand;
The following statements are the same as in Chapter 19:
set NODES = FACTORIES union DEPOTS union CUSTOMERS; num supply {NODES} init 0; for {i in FACTORIES} supply[i] = capacity[i]; for {i in CUSTOMERS} supply[i] = -demand[i]; var Flow {ARCS} >= 0; con Flow_balance_con {i in NODES}: sum {<(i),j> in ARCS} Flow[i,j] - sum {<j,(i)> in ARCS} Flow[j,i] <= supply[i];
The following statements declare the additional variables and constraints:
var IsOpen {DEPOTS} binary; var Expand {EXPAND_DEPOTS} binary; con Max_num_depots_con: sum {i in DEPOTS} IsOpen[i] <= &max_num_depots; con Depot_con {i in DEPOTS}: sum {<(i),j> in ARCS} Flow[i,j] <= throughput[i] * IsOpen[i] + (if i in EXPAND_DEPOTS then expand_throughput[i] * Expand[i]); con Expand_con {i in EXPAND_DEPOTS}: Expand[i] <= IsOpen[i];
The following statements fix the IsOpen
variable to 1 for depots that are not eligible to be closed (indicated by a missing value for close_savings in the input data):
for {i in DEPOTS: close_savings[i] = .} do; close_savings[i] = 0; fix IsOpen[i] = 1; end;
The following statements declare FixedCost
and VariableCost
as implicit variables and TotalCost
as the objective:
impvar FixedCost = sum {depot in DEPOTS} (open_cost[depot] * IsOpen[depot] - close_savings[depot] * (1 - IsOpen[depot])) + sum {depot in EXPAND_DEPOTS} expand_cost[depot] * Expand[depot]; impvar VariableCost = sum {<i,j> in ARCS} cost[i,j] * Flow[i,j]; min TotalCost = FixedCost + VariableCost;
The following statements call the mixed integer linear programming solver and then print the various parts of the objective, the positive variables in the resulting optimal solution, and the additional decision variables:
solve; print FixedCost VariableCost TotalCost; print {<i,j> in ARCS: Flow[i,j].sol > 0} Flow; print IsOpen Expand; quit;
Figure 20.1 shows the output from the mixed integer linear programming solver.
Figure 20.1: Output from Mixed Integer Linear Programming Solver
Problem Summary | |
---|---|
Objective Sense | Minimization |
Objective Function | TotalCost |
Objective Type | Linear |
Number of Variables | 49 |
Bounded Above | 0 |
Bounded Below | 42 |
Bounded Below and Above | 5 |
Free | 0 |
Fixed | 2 |
Binary | 7 |
Integer | 0 |
Number of Constraints | 22 |
Linear LE (<=) | 22 |
Linear EQ (=) | 0 |
Linear GE (>=) | 0 |
Linear Range | 0 |
Constraint Coefficients | 125 |
Solution Summary | |
---|---|
Solver | MILP |
Algorithm | Branch and Cut |
Objective Function | TotalCost |
Solution Status | Optimal |
Objective Value | 174000 |
Relative Gap | 0 |
Absolute Gap | 0 |
Primal Infeasibility | 0 |
Bound Infeasibility | 0 |
Integer Infeasibility | 0 |
Best Bound | 174000 |
Nodes | 1 |
Iterations | 20 |
Presolve Time | 0.00 |
Solution Time | 0.02 |