For completeness, all statements are shown. Statements that are new or changed from Chapter 15 are indicated.
proc optmodel; set PERIODS; num length {PERIODS}; num demand {PERIODS}; read data period_data into PERIODS=[_N_] length demand; set TYPES; num num_avail {TYPES}; num min_level {TYPES}; num max_level {TYPES}; num unit_cost {TYPES}; num excess_cost {TYPES}; num startup_cost {TYPES}; read data type_data into TYPES=[_N_] num_avail min_level max_level unit_cost excess_cost startup_cost; var NumWorking {PERIODS, type in TYPES} >= 0 <= num_avail[type] integer; var Excess {PERIODS, TYPES} >= 0; var NumStartup {PERIODS, type in TYPES} >= 0 <= num_avail[type] integer; impvar Output {period in PERIODS, type in TYPES} = min_level[type] * NumWorking[period,type] + Excess[period,type];
The following statements declare the additional index set and parameters and then read the additional input data:
set <str> HYDROS; num hydro_level {HYDROS}; num hydro_unit_cost {HYDROS}; num hydro_depth_rate {HYDROS}; num hydro_startup_cost {HYDROS}; read data hydro_data into HYDROS=[hydro] hydro_level=level hydro_unit_cost=unit_cost hydro_depth_rate=depth_rate hydro_startup_cost=startup_cost;
The following statements declare additional variables and fix the value of Depth[1]
:
var HydroNumWorking {PERIODS, HYDROS} binary; var HydroNumStartup {PERIODS, HYDROS} binary; var Depth {PERIODS} >= &min_depth <= &max_depth; fix Depth[1] = &midnight_depth; var Pump {PERIODS} >= 0;
The following IMPVAR statement declares HydroOutput
as a new implicit variable:
impvar HydroOutput {period in PERIODS, hydro in HYDROS} = hydro_level[hydro] * HydroNumWorking[period,hydro];
The following MIN statement is a modification of the objective declaration from Chapter 15:
min TotalCost = sum {period in PERIODS, type in TYPES} ( unit_cost[type] * length[period] * NumWorking[period,type] + excess_cost[type] * length[period] * Excess[period,type] + startup_cost[type] * NumStartup[period,type]) + sum {period in PERIODS, hydro in HYDROS} ( hydro_unit_cost[hydro] * length[period] * HydroNumWorking[period,hydro] + hydro_startup_cost[hydro] * HydroNumStartup[period,hydro]);
The following two CON statements are modified from Chapter 15:
con Demand_con {period in PERIODS}: sum {type in TYPES} Output[period,type] + sum {hydro in HYDROS} HydroOutput[period,hydro] - Pump[period] >= demand[period]; con Reserve_con {period in PERIODS}: sum {type in TYPES} max_level[type] * NumWorking[period,type] + sum {hydro in HYDROS} hydro_level[hydro] * HydroNumWorking[period,hydro].ub >= (1 + &reserve) * demand[period]; con Excess_ub {period in PERIODS, type in TYPES}: Excess[period,type] <= (max_level[type] - min_level[type]) * NumWorking[period,type]; con Startup_con {period in PERIODS, type in TYPES}: NumStartup[period,type] >= NumWorking[period,type] - (if period - 1 in PERIODS then NumWorking[period-1,type] else NumWorking[card(PERIODS),type]);
The following two CON statements declare the final two additional constraints:
con Hydro_startup_con {period in PERIODS, hydro in HYDROS}: HydroNumStartup[period,hydro] >= HydroNumWorking[period,hydro] - (if period - 1 in PERIODS then HydroNumWorking[period-1,hydro] else HydroNumWorking[card(PERIODS),hydro]); con Depth_con {period in PERIODS}: (if period + 1 in PERIODS then Depth[period+1] else Depth[1]) = Depth[period] + &meters_per_mwh * length[period] * Pump[period] - sum {hydro in HYDROS} hydro_depth_rate[hydro] * length[period] * HydroNumWorking[period,hydro];
The following statements call the mixed integer linear programming solver, print the optimal solution, and create several data sets that contain various parts of the optimal solution, with variables grouped according to their index sets:
solve; print NumWorking NumStartup Excess Output; print HydroNumWorking HydroNumStartup HydroOutput; print Pump Depth; create data sol_data1 from [period type] NumWorking NumStartup Excess Output; create data sol_data2 from [period hydro] HydroNumWorking HydroNumStartup HydroOutput; create data sol_data3 from [period] Pump Depth; quit;
Figure 16.1 shows the output from the mixed integer linear programming solver.
Figure 16.1: Output from Mixed Integer Linear Programming Solver
Problem Summary | |
---|---|
Objective Sense | Minimization |
Objective Function | TotalCost |
Objective Type | Linear |
Number of Variables | 75 |
Bounded Above | 0 |
Bounded Below | 20 |
Bounded Below and Above | 54 |
Free | 0 |
Fixed | 1 |
Binary | 20 |
Integer | 30 |
Number of Constraints | 55 |
Linear LE (<=) | 15 |
Linear EQ (=) | 5 |
Linear GE (>=) | 35 |
Linear Range | 0 |
Constraint Coefficients | 190 |
Solution Summary | |
---|---|
Solver | MILP |
Algorithm | Branch and Cut |
Objective Function | TotalCost |
Solution Status | Optimal |
Objective Value | 986630 |
Relative Gap | 0 |
Absolute Gap | 0 |
Primal Infeasibility | 1.219944E-15 |
Bound Infeasibility | 0 |
Integer Infeasibility | 0 |
Best Bound | 986630 |
Nodes | 48 |
Iterations | 843 |
Presolve Time | 0.00 |
Solution Time | 0.05 |