The first several PROC OPTMODEL statements declare index sets and parameters and then read the input data:
proc optmodel; set <str> RAWS; num supply {RAWS}; read data raw_material_data into RAWS=[raw] supply; set <str> PRODUCTS; num prev_demand {PRODUCTS}; num prev_price {PRODUCTS}; num percent {PRODUCTS, RAWS}; read data product_data into PRODUCTS=[product] {raw in RAWS} <percent[product,raw]=col(raw)> prev_demand prev_price; num elasticity {PRODUCTS, PRODUCTS} init 0; read data elasticity_data into [i j] elasticity;
The following model declaration statements correspond directly to the mathematical programming formulation that is described earlier:
var Price {PRODUCTS} >= 0; var Demand {PRODUCTS} >= 0; max TotalRevenue = sum {product in PRODUCTS} Price[product] * Demand[product]; con Demand_con {i in PRODUCTS}: (Demand[i] - prev_demand[i]) / prev_demand[i] = sum {j in PRODUCTS} elasticity[i,j] * (Price[j] - prev_price[j]) / prev_price[j]; con Supply_con {raw in RAWS: supply[raw] ne .}: sum {product in PRODUCTS} (percent[product,raw]/100) * Demand[product] <= supply[raw]; con Price_index_con: sum {product in PRODUCTS} prev_demand[product] * Price[product] <= sum {product in PRODUCTS} prev_demand[product] * prev_price[product];
In this example, all variables are real, the objective function is quadratic, and all constraints are linear. So PROC OPTMODEL automatically recognizes that this model is a quadratic programming problem, and the first SOLVE statement calls the quadratic programming solver. In this case, the QP solver detects that this maximization problem has a nonconcave objective, and PROC OPTMODEL instead calls the default nonlinear programming algorithm, which is the interior point algorithm.
solve; print Price Demand; print Price_index_con.dual;
Figure 21.1 shows the output when you use the (default) NLP interior point algorithm.
Figure 21.1: Output from NLP Interior Point Algorithm
Problem Summary | |
---|---|
Objective Sense | Maximization |
Objective Function | TotalRevenue |
Objective Type | Quadratic |
Number of Variables | 8 |
Bounded Above | 0 |
Bounded Below | 8 |
Bounded Below and Above | 0 |
Free | 0 |
Fixed | 0 |
Number of Constraints | 7 |
Linear LE (<=) | 3 |
Linear EQ (=) | 4 |
Linear GE (>=) | 0 |
Linear Range | 0 |
Constraint Coefficients | 22 |
To invoke the active set algorithm (which is not the default NLP algorithm), you can use the ALGORITHM= option in the SOLVE
WITH NLP statement:
solve with NLP / algorithm=activeset; print Price Demand; print Price_index_con.dual; quit;
Figure 21.2 shows the output when you use the ALGORITHM=ACTIVESET option to invoke the active set algorithm.
The optimal solutions and dual values for the two algorithms agree.
You can also replace the Demand
and Demand_con declarations with the following IMPVAR and CON statements to perform the substitutions that are described
on page 299 of Williams (1999):
impvar Demand {i in PRODUCTS} = prev_demand[i] * (1 + sum {j in PRODUCTS} elasticity[i,j] * (Price[j] - prev_price[j]) / prev_price[j]); con Demand_nonnegative {i in PRODUCTS}: Demand[i] >= 0;
The resulting formulation is mathematically equivalent but yields a concave objective function, as shown in Williams (1999).
Figure 21.3 shows the output when you use the (default) quadratic programming solver on the reformulated problem.
Figure 21.3: Output from Quadratic Programming Solver, Reformulated Problem
Problem Summary | |
---|---|
Objective Sense | Maximization |
Objective Function | TotalRevenue |
Objective Type | Quadratic |
Number of Variables | 4 |
Bounded Above | 0 |
Bounded Below | 4 |
Bounded Below and Above | 0 |
Free | 0 |
Fixed | 0 |
Number of Constraints | 7 |
Linear LE (<=) | 3 |
Linear EQ (=) | 0 |
Linear GE (>=) | 4 |
Linear Range | 0 |
Constraint Coefficients | 18 |
Solution Summary | |
---|---|
Solver | QP |
Algorithm | Interior Point |
Objective Function | TotalRevenue |
Solution Status | Optimal |
Objective Value | 1991585591.9 |
Primal Infeasibility | 0 |
Dual Infeasibility | 3.407224E-17 |
Bound Infeasibility | 0 |
Duality Gap | 2.394259E-16 |
Complementarity | 0 |
Iterations | 10 |
Presolve Time | 0.00 |
Solution Time | 0.01 |
Figure 21.4 shows the output when you use the WITH NLP option to invoke the nonlinear programming interior point algorithm on the reformulated problem.
Figure 21.5 shows the output when you use the ALGORITHM=ACTIVESET option to invoke the active set algorithm on the reformulated problem.
The optimal solutions and dual values for all three algorithms agree with the previous results.