Assume that after solving the diet problem in Example 10.3 you need to add a new constraint on sodium intake of no more than 550 mg/day for adults. The updated nutrition data are given in Table 10.7.
Table 10.7: Updated Cost and Nutrition Values
Bread |
Milk |
Cheese |
Potato |
Fish |
Yogurt |
|
---|---|---|---|---|---|---|
Cost |
2.0 |
3.5 |
8.0 |
1.5 |
11.0 |
1.0 |
Protein, g |
4.0 |
8.0 |
7.0 |
1.3 |
8.0 |
9.2 |
Fat, g |
1.0 |
5.0 |
9.0 |
0.1 |
7.0 |
1.0 |
Carbohydrates, g |
15.0 |
11.7 |
0.4 |
22.6 |
0.0 |
17.0 |
Calories, Cal |
90 |
120 |
106 |
97 |
130 |
180 |
sodium, mg |
148 |
122 |
337 |
186 |
56 |
132 |
The input data set ex3
is updated (and the data set is saved as ex6
) as follows:
/* added a new constraint to the diet problem */ data ex6; input field1 $ field2 $ field3 $ field4 field5 $ field6; datalines; NAME . EX6 . . . ROWS . . . . . N diet . . . . G calories . . . . L protein . . . . G fat . . . . G carbs . . . . L sodium . . . . COLUMNS . . . . . . br diet 2 calories 90 . br protein 4 fat 1 . br carbs 15 sodium 148 . mi diet 3.5 calories 120 . mi protein 8 fat 5 . mi carbs 11.7 sodium 122 . ch diet 8 calories 106 . ch protein 7 fat 9 . ch carbs .4 sodium 337 . po diet 1.5 calories 97 . po protein 1.3 fat .1 . po carbs 22.6 sodium 186 . fi diet 11 calories 130 . fi protein 8 fat 7 . fi carbs 0 sodium 56 . yo diet 1 calories 180 . yo protein 9.2 fat 1 . yo carbs 17 sodium 132 RHS . . . . . . . calories 300 protein 10 . . fat 8 carbs 10 . . sodium 550 . . BOUNDS . . . . . UP . mi 1 . . LO . fi .5 . . ENDATA . . . . . ;
For the modified problem you can warm start the primal and dual simplex solvers to get a solution faster. The dual simplex solver is preferred because a dual feasible solution can be readily constructed from the optimal solution to the diet optimization problem.
Since there is a new constraint in the modified problem, you can use the following SAS code to create a new DUALIN= data set
ex6din
with this information:
data ex6newcon; _ROW_='sodium '; _STATUS_='A'; output; run; /* create a new DUALIN= data set to include the new constraint */ data ex6din; set ex3dout ex6newcon; run;
Note that this step is optional. In this example, you can still use the data set ex3dout
as the DUALIN= data set to solve the modified LP problem by using the BASIS=WARMSTART option. PROC OPTLP validates the PRIMALIN=
and DUALIN= data sets against the input model. Any new variable (or constraint) in the model is added to the PRIMALIN= (or
DUALIN=) data set, and its status is assigned to be 'A'. The primal and dual simplex solvers decide its corresponding status
internally. Any variable in the PRIMALIN= and DUALIN= data sets but not in the input model is removed.
The _ROW_ and _STATUS_ columns of the DUALIN= data set ex6din
are shown in Output 10.6.1.
Output 10.6.1: DUALIN= Data Set with a Newly Added Constraint
Obs | _ROW_ | _STATUS_ |
---|---|---|
1 | calories | U |
2 | protein | L |
3 | fat | U |
4 | carbs | B |
5 | sodium | A |
The dual simplex solver is called to solve the modified diet optimization problem more quickly with the following SAS code:
proc optlp data=ex6 objsense=min presolver=none algorithm=ds primalout=ex6pout dualout=ex6dout scale=none logfreq=1 basis=warmstart primalin=ex3pout dualin=ex6din; run;
The optimal primal and dual solutions of the modified problem are displayed in Output 10.6.2.
Output 10.6.2: Primal and Dual Solution Output
Primal Solution |
Obs | Objective Function ID |
RHS ID | Variable Name |
Variable Type |
Objective Coefficient |
Lower Bound | Upper Bound | Variable Value | Variable Status |
Reduced Cost |
---|---|---|---|---|---|---|---|---|---|---|
1 | diet | br | N | 2.0 | 0.0 | 1.7977E308 | 0.00000 | L | 1.19066 | |
2 | diet | mi | D | 3.5 | 0.0 | 1 | 0.05360 | B | 0.00000 | |
3 | diet | ch | N | 8.0 | 0.0 | 1.7977E308 | 0.44950 | B | 0.00000 | |
4 | diet | po | N | 1.5 | 0.0 | 1.7977E308 | 1.86517 | B | 0.00000 | |
5 | diet | fi | O | 11.0 | 0.5 | 1.7977E308 | 0.50000 | L | 5.15641 | |
6 | diet | yo | N | 1.0 | 0.0 | 1.7977E308 | 0.00000 | L | 1.10849 |
Dual Solution |
Obs | Objective Function ID |
RHS ID | Constraint Name | Constraint Type |
Constraint RHS |
Constraint Lower Bound |
Constraint Upper Bound |
Dual Variable Value |
Constraint Status |
Constraint Activity |
---|---|---|---|---|---|---|---|---|---|---|
1 | diet | calories | G | 300 | . | . | 0.02179 | U | 300.000 | |
2 | diet | protein | L | 10 | . | . | -0.55360 | L | 10.000 | |
3 | diet | fat | G | 8 | . | . | 1.06286 | U | 8.000 | |
4 | diet | carbs | G | 10 | . | . | 0.00000 | B | 42.960 | |
5 | diet | sodium | L | 550 | . | . | 0.00000 | B | 532.941 |
The iteration log shown in Output 10.6.3 indicates that it takes the dual simplex solver no more iterations to solve the modified problem by using the BASIS=WARMSTART option, since the optimal solution to the original problem remains optimal after one more constraint is added.
Output 10.6.3: Iteration Log
NOTE: The problem EX6 has 6 variables (0 free, 0 fixed). |
NOTE: The problem has 5 constraints (2 LE, 0 EQ, 3 GE, 0 range). |
NOTE: The problem has 29 constraint coefficients. |
NOTE: The LP presolver value NONE is applied. |
NOTE: The LP solver is called. |
NOTE: The Dual Simplex algorithm is used. |
Objective Entering Leaving |
Phase Iteration Value Time Variable Variable |
D 2 1 1.208134e+01 0 |
NOTE: Optimal. |
NOTE: Objective = 12.0813379. |
NOTE: The Dual Simplex solve time is 0.00 seconds. |
NOTE: The data set WORK.EX6POUT has 6 observations and 10 variables. |
NOTE: The data set WORK.EX6DOUT has 5 observations and 10 variables. |
Both this example and Example 10.4 illustrate the situation in which the optimal solution does not change after some perturbation of the parameters of the LP problem. The simplex solver starts from an optimal solution and quickly verifies the optimality. Usually the optimal solution of the slightly perturbed problem can be obtained after performing relatively small number of iterations if starting with the optimal solution of the original problem. In such cases you can expect a dramatic reduction of computation time, for instance, if you want to solve a large LP problem and a slightly perturbed version of this problem by using the BASIS=WARMSTART option rather than solving both problems from scratch.