$title A Transportation Problem with Piecewise Linear Functions (TRNSPWLX,SEQ=386)
$onText
This problem finds a least cost shipping schedule that meets
requirements at markets and supplies at factories. This instance
applies economies of scale which results in a non-convex
objective. This is an extension of the trnsport model in the GAMS
Model Library.
The original nonlinear term is "sum((i,j), c(i,j)*sqrt(x(i,j)))". We
use the following discretization f(x) of sqrt(x)
For x <= 50: f(x) = 1/sqrt(50)*x,
for x >= 400: f(x) = 1/(2*sqrt(400))*(x-400) + sqrt(400)
in between we discretize with linear interpolation between points
The model is organized as follows:
1) We set a starting point for the NLP solver so it will get stuck
in local optimum that is not the global optimum.
2) We use the generic pwlfunc.inc batinclude to get a piecewise linear
MIP formulation to get close to the global optimum.
3) We restart the non-convex NLP from the solution of the discretized
model and hope that the NLP solver finds the global solution.
This model is based on the model trnspwl in the GAMS Model Library
Dantzig, G B, Chapter 3.3. In Linear Programming and Extensions.
Princeton University Press, Princeton, New Jersey, 1963.
Keywords: linear programming, transportation problem, scheduling, piecewise
linear functions, linear interpolation
$offText
Set
i 'canning plants' / seattle, san-diego /
j 'markets' / new-york, chicago, topeka /;
Parameter
a(i) 'capacity of plant i in cases'
/ seattle 350
san-diego 600 /
b(j) 'demand at market j in cases'
/ new-york 325
chicago 300
topeka 275 /;
Table d(i,j) 'distance in thousands of miles'
new-york chicago topeka
seattle 2.5 1.7 1.8
san-diego 2.5 1.8 1.4;
Scalar f 'freight in dollars per case per thousand miles' / 90 /;
Parameter c(i,j) 'transport cost in thousands of dollars per case';
c(i,j) = f*d(i,j)/1000;
Variable
x(i,j) 'shipment quantities in cases'
z 'total transportation costs in thousands of dollars';
Positive Variable x;
* Demonstrate how to restrict the model index
Set ij(i,j);ij(i,j) = yes;
Equation
cost 'define objective function with economies of scale'
supply(i) 'observe supply limit at plant i'
demand(j) 'satisfy demand at market j';
cost.. z =e= sum(ij(i,j), c(i,j)*sqrt(x(i,j)));
supply(i).. sum(ij(i,j), x(i,j)) =l= a(i);
demand(j).. sum(ij(i,j), x(i,j)) =g= b(j);
Model transport / all /;
* Start the local NLP solver in a local solution that is not globally optimal
x.l('seattle ','chicago ') = 25;
x.l('seattle ','topeka ') = 275;
x.l('san-diego','new-york') = 325;
x.l('san-diego','chicago ') = 275;
option nlp = conopt;
solve transport using nlp minimizing z;
* The first model (formulation a) implements a piecewise linear
* approximation based on the convex combination of neighboring points
* using SOS2 variables with unbounded segments at the beginning and
* end of the discretization
Set
s 'segments' / s0*s6 /
sl 'segment labels' / x, y 'coordinates', l 'length', g 'slope' /;
Table sqrtp(s,sl) 'piecewise linear function for sqrt'
x y l g
s0 50 [sqrt( 50)] -inf [ sqrt(50)/50]
s1 50 [sqrt( 50)] 70 [(sqrt(120)-sqrt( 50))/70]
s2 120 [sqrt(120)] 70 [(sqrt(190)-sqrt(120))/70]
s3 190 [sqrt(190)] 70 [(sqrt(260)-sqrt(190))/70]
s4 260 [sqrt(260)] 70 [(sqrt(330)-sqrt(260))/70]
s5 330 [sqrt(330)] 70 [(sqrt(400)-sqrt(330))/70]
s6 400 [sqrt(400)] +inf [1/(2*sqrt(400))];
$onText
This following batinclude has a parameter p as first argument that
defines segments of a piecewise linear function. A start point (x,y) of
a segment plus length and slope need to be provided provides by this
parameter. The actual labels for are also provided on the batinclude
call (arguments 3-6) together with the set of segments (arg 2) and an
optional index set (idxp) to define an indexed parameter to define multiple
piecewise linear functions (arg 7). The optional arguments 8 and 9 allow
the use the same function f with different endogenous arguments (idxm).
The batinclude provides a subset of active segments p_Seg(s), i.e. the
parameter must have data before the batinclude call. The batinclude also
provide a couple of macros:
1) p_Func(x[,idxp]) evaluates the function at point x
2) p_x([idxp][,idxm]) expression to assign x(idxm) value
3) p_y([idxp][,idxm]) expression to assign y(idxm) value
The header of pwlfunc.inc describes its use in more detail
$offText
$batInclude pwlfunc.inc sqrtp s x y l g '' 'i,j' 'ij'
Equation defcouplex(i,j), defobjdisc;
defcouplex(ij(i,j)).. x(i,j) =e= sqrtp_x(i,j);
defobjdisc.. z =e= sum(ij(i,j), c(i,j)*sqrtp_y(i,j));
Model trnspwl / supply, demand, defobjdisc, defcouplex, %sqrtp_EquList% /;
option optCr = 0;
solve trnspwl using mip minimizing z;
solve transport using nlp minimizing z;