Agricultural Pricing: What Prices to Charge for Dairy Products


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 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

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 1991585587.2
   
Optimality Error 3.8424396E-8
Infeasibility 3.8424396E-8
   
Iterations 48
Presolve Time 0.00
Solution Time 0.25

[1] Price Demand
Butter 667.29 383251
Cheese1 889.84 251708
Cheese2 1066.18 57099
Milk 303.83 4775665

Price_index_con.DUAL
0.61609



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.

Figure 21.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 1991585587.2
   
Optimality Error 0.0024623304
Infeasibility 3.8424396E-8
   
Iterations 50
Presolve Time 0.00
Solution Time 0.04

[1] Price Demand
Butter 667.29 383251
Cheese1 889.84 251708
Cheese2 1066.18 57099
Milk 303.83 4775665

Price_index_con.DUAL
.



The optimal solutions for the two algorithms agree. The dual value is missing for the active set algorithm because the solution status is Best Feasible.

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

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 18

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 1.229285E-16
Dual Infeasibility 0
Bound Infeasibility 0
Duality Gap 3.591388E-16
Complementarity 0
   
Iterations 10
Presolve Time 0.00
Solution Time 0.01

[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 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.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.01

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

Figure 21.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 6.915434E-13
Infeasibility 3.8405415E-7
   
Iterations 12
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.