PROC OPTMODEL Statements and Output

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 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 22.1 shows the output when you use the (default) NLP interior point algorithm.

Figure 22.1: Output from NLP Interior Point Algorithm

The OPTMODEL Procedure

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

Performance Information
Execution Mode Single-Machine
Number of Threads 4

Solution Summary
Solver NLP
Algorithm Interior Point
Objective Function TotalRevenue
Solution Status Optimal
Objective Value 1991585768.2
   
Optimality Error 7.8630478E-7
Infeasibility 7.8630478E-7
   
Iterations 40
Presolve Time 0.00
Solution Time 0.64

[1] Price Demand
Butter 667.31 383231
Cheese1 889.58 251766
Cheese2 1066.22 57091
Milk 303.84 4775603

Price_index_con.DUAL
0.61421


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 22.2 shows the output when you use the ALGORITHM=ACTIVESET option to invoke the active set algorithm.

Figure 22.2: Output from NLP Active Set 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

Performance Information
Execution Mode Single-Machine
Number of Threads 4

Solution Summary
Solver NLP
Algorithm Active Set
Objective Function TotalRevenue
Solution Status Best Feasible
Objective Value 1991585768.2
   
Optimality Error 0.0024622983
Infeasibility 7.8630478E-7
   
Iterations 93
Presolve Time 0.00
Solution Time 0.28

[1] Price Demand
Butter 667.31 383231
Cheese1 889.58 251766
Cheese2 1066.22 57091
Milk 303.84 4775603

Price_index_con.DUAL
0.61558


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 described on page 299 of Williams:

   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.

Figure 22.3 shows the output when you use the (default) quadratic programming solver on the reformulated problem.

Figure 22.3: Output from Quadratic Programming Solver, Reformulated Problem

The OPTMODEL Procedure

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 16

Performance Information
Execution Mode Single-Machine
Number of Threads 4

Solution Summary
Solver QP
Algorithm Interior Point
Objective Function TotalRevenue
Solution Status Optimal
Objective Value 1991585591.9
   
Primal Infeasibility 4.371373E-17
Dual Infeasibility 1.473482E-16
Bound Infeasibility 5.755324E-17
Duality Gap 1.197129E-16
Complementarity 3.0307127E-8
   
Iterations 11
Presolve Time 0.00
Solution Time 0.02

[1] Price Demand
Butter 667.29 383255
Cheese1 889.89 251695
Cheese2 1066.17 57101
Milk 303.83 4775678

Price_index_con.DUAL
0.6161


Figure 22.4 shows the output when you use the WITH NLP option to invoke the nonlinear programming interior point algorithm on the reformulated problem.

Figure 22.4: Output from NLP Interior Point Algorithm, 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

Performance Information
Execution Mode Single-Machine
Number of Threads 4

Solution Summary
Solver NLP
Algorithm Interior Point
Objective Function TotalRevenue
Solution Status Optimal
Objective Value 1991585591.9
   
Optimality Error 5E-7
Infeasibility 0
   
Iterations 7
Presolve Time 0.00
Solution Time 0.07

[1] Price Demand
Butter 667.29 383255
Cheese1 889.89 251695
Cheese2 1066.17 57101
Milk 303.83 4775678

Price_index_con.DUAL
0.6161


Figure 22.5 shows the output when you use the ALGORITHM=ACTIVESET option to invoke the active set algorithm on the reformulated problem.

Figure 22.5: Output from NLP Active Set Algorithm, 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

Performance Information
Execution Mode Single-Machine
Number of Threads 4

Solution Summary
Solver NLP
Algorithm Active Set
Objective Function TotalRevenue
Solution Status Optimal
Objective Value 1991585591.9
   
Optimality Error 4.052786E-19
Infeasibility 2.3841858E-7
   
Iterations 9
Presolve Time 0.00
Solution Time 0.02

[1] Price Demand
Butter 667.29 383255
Cheese1 889.89 251695
Cheese2 1066.17 57101
Milk 303.83 4775678

Price_index_con.DUAL
0.6161


The optimal solutions and dual values for all three algorithms agree with the previous results.