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

[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 Optimal
Objective Value 1991585605.1
   
Optimality Error 3.228403E-22
Infeasibility 1.7034844E-8
   
Iterations 69
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



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

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

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

[1] Price Demand
Butter 667.29 383255
Cheese1 889.89 251696
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 5.702343E-10
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.61608



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