|*FORM FIELD Results*|Results|Using transshipment.mod , and the data and script files defined in Computational Model we can solve the American Steel Transshipment Problem to get the optimal Flow variables:
If the total supply is greater than the total demand, the transshipment problem will solve, but flow may be left in the network (in this case at the Pittsburgh node). In transshipment.mod we check that sum {n in NODES} NetDemand[n] <= 0 to ensure a problem is feasible before solving.
If total supply is less than demand (hence the problem is infeasible) we can add a dummy supply node with arcs to all the demand nodes. ??? Up to here??? The optimal solution will show which nodes are "best" to get extra supply for to find the "best" nodes to t to get extrato see where we should , then the problem becomes infeasible! Even in the case of infeasibility, it is preferable to solve the transshipment problem using a dummy supply node so that we can analyse where there is a shortfall in demand. We can balance the problem by either adding a dummy supply node with arcs to all the demand nodes or adding a dummy demand node with arcs from all the supply nodes:
balance_transshipment.mod
# The following parameters are needed to use balance_transshipment.run
param difference;
param dummyDemandCost {NODES};
param dummySupplyCost {NODES};
balance_transshipment.run
let difference := (sum {s in NODES} Supply[s])
- (sum {d in NODES} Demand[d]);
let NODES := NODES union {'Dummy'};
if difference > 0 then
{
print "Total Supply > Total Demand";
print "Solving with dummy supply node...";
let Demand['Dummy'] := difference;
for {n in NODES : Supply[n] > 0} {
let ARCS := ARCS union {(n, 'Dummy')};
let Cost[n, 'Dummy'] := dummyDemandCost[n];
}
}
else if difference < 0 then
{
print "WARNING: Total Supply < Total Demand, problem is infeasible!";
print "Solving with dummy demand node...";
let Demand['Dummy'] := - difference;
for {n in NODES : Demand[n] > 0} {
let ARCS := ARCS union {('Dummy', n)};
let Cost['Dummy', n] := dummySupplyCost[n];
}
}; # else the problem is balanced
steel.run
# steel.run
#
# Written by Mike O'Sullivan & Cameron Walker 2004
#
# This file contains a script for sensitivity analysis
# of the American Steel transshipment model.
#
# Last modified: 27/2/2004
reset;
model transshipment.mod;
model balance_transshipment.mod;
data steel.dat;
let {(m, n) in ARCS} Cost[m, n] := Cost[m, n] / 1000;
for {n in NODES} {
let dummyDemandCost[n] := 0;
let dummySupplyCost[n] := 0;
}
include balance_transshipment.run;
option solver cplex;
solve;
display Flow;
Note We also add a ???LINK??? check statement to our model file to ensure the problem is balanced:
check : sum {n in NODES} Supply[n] = sum {n in NODES} Demand[n];
Our solution now shows that there is 5000 ton of steel remaining at the Pittsburgh Mill, i.e., the flow from Pittsburgh to Dummy is 5000.
POST-OPTIMAL ANALYSIS
Validation
For our solution to be valid we need it to be integer. Observing the Flow values shows that it is in fact integer. Moreover, no branch-and-bound nodes were required to make it integer. The transshipment problem is also naturally integer (like the transportation problem), so solving it as a linear programme will give integer solutions. In fact, any network flow problem with integer supplies, demands and arc capacities has naturally integer solutions.
Parametric Analysis
If ???LINK??? sensitivity analysis shows that improvements to the objective
function may be achieved by changing problem data, then we may use ???LINK??? parametric analysis to see the effect of these changes.
.
.
.
include balance_transshipment.run;
option presolve 0;
option solver cplex;
option cplex_options 'presolve 0 sensitivity';
solve;
display Flow;
display _varname, _var.down, _var.current, _var.up, _var.rc;
display _conname, _con.down, _con.current, _con.up, _con.dual;
The sensitivity analysis shows that the solution is very sensitive to any changes in the constraint right-hand sides, with one exception ConserverFlow at Pittsburgh . However, we have variables on both sides of our constraints so we should expand our constraints to see what the right-hand side is:
For the supply nodes the right-hand side is the negative of the supply, for the demand nodes the right-hand side is the demand and for the transshipment nodes the right-hand side is 0. Thus, any changes we make to the supply or demand at the nodes will affect our optimal solution. The only exception is that the right-hand side of the ConserveFlow['Pittsburgh'] can decrease without affecting our solution. Since Pittsburgh is a supply node (so the right-hand side is the negative of the supply) this means we can increase the supply at Pittsburgh without affecting our solution. This makes sense as Pittsburgh already has excess supply.
However, it seems like we can improve our objective the most by decreasing the demand at Tempe (the shadow price is 1.125), but the Allowable Minimum is such that we cannot discern what the change will be (the solution will change immediately). We can see the effect by using an ???LINK??? AMPL loop :
.
.
.
display TotalCost;
set CHANGES;
param Objective {CHANGES};
param OldDemand;
let OldDemand := Demand['Tempe'];
let CHANGES := {100..1000 by 100};
for {i in CHANGES} {
let Demand['Tempe'] := OldDemand - i;
display Demand['Tempe'];
# Rebalance the problem
include balance_transshipment.run;
solve;
let Objective[i] := TotalCost;
}
Note that we had to alter balance_transshipment.run to consider problems that have been balanced previously:
balance_transshipment.run
let difference := (sum {s in NODES : s <> 'Dummy'} Supply[s])
- (sum {d in NODES : d <> 'Dummy'} Demand[d]);
if 'Dummy' not in NODES then
let NODES := NODES union {'Dummy'};
if difference > 0 then
{
print "Total Supply > Total Demand";
print "Solving with dummy supply node...";
let Demand['Dummy'] := difference;
for {n in NODES : Supply[n] > 0} {
let ARCS := ARCS union {(n, 'Dummy')};
let Cost[n, 'Dummy'] := dummyDemandCost[n];
}
}
else if difference < 0 then
{
print "WARNING: Total Supply < Total Demand, problem is infeasible!";
print "Solving with dummy demand node...";
let Demand['Dummy'] := - difference;
for {n in NODES : Demand[n] > 0} {
let ARCS := ARCS union {('Dummy', n)};
let Cost['Dummy', n] := dummySupplyCost[n];
}
}; # else the problem is balanced
The AMPL parametric analysis shows that, by decreasing the demand for steel at Tempe, we can get a consistent reduction in our objective function, even though this was not clear from our initial sensitivity analysis.
When we consider the sensitvity analysis for variable costs, we see that the only costs that affect our solution are the transportation costs from Pittsburgh and Youngstown to Chicago (all the other costs have Allowable Min and Allowable Max such that no "sensible" change would have any effect). Suppose American Steel are negotiating a new contract with the shipping company that takes their steel from Pittsburgh to Chicago. They estimate that they can get a reduction of around \$25/1000 ton of steel (taking the price from \$400/1000 ton to \$375/1000 ton), but want to know if they should negotiate for a lower price. The sensitivity analysis shows that below \$375/1000 ton the solution will change, so let's use parametric analysis to see what happens:
.
.
.
display TotalCost;
set CHANGES;
param Objective {CHANGES};
param OldCost;
let OldCost := Cost['Pittsburgh', 'Chicago'];
let CHANGES := {0..0.05 by 0.005};
for {i in CHANGES} {
let Cost['Pittsburgh', 'Chicago'] := OldCost - i;
display Cost['Pittsburgh', 'Chicago'];
# Rebalance the problem
include balance_transshipment.run;
solve;
let Objective[i] := TotalCost;
}
The parametric analysis shows that the objective function decreases at a greater rate if the price drops below $375/1000 ton, so American Steel should try and negotiate the price down even further.
|
|*FORM FIELD Conclusions*|Conclusions|There is quite a bit of information to summarise and many ways to present it. Some suggestions include:
- Summarise the problem as usual and list the shipments that American Steel should make (similar to the transportation problem);
- Summarise the problem as usual and present a table of shipments that American Steel should make;
- Draw the network formulation for the problem (being sure to specify what the labels mean). Then draw the actual solution on top of the network formulation. You could colour code flows long arcs to show if they are at their bounds.
Implementation and Ongoing Monitoring
Given that the solution is very sensitive to the supply and demand amounts, careful consideration of the accuracy of these figures is important. Making sure that the bounds on the arcs are reliable is another concern.
Ongoing monitoring of the supply, demand and bounds will help American Steel to keep making good decisions. As shown in the parametric analysis, ongoing negotiation of transportation prices along important routes will help American Steel reduce their expenditure.| |