bidpwl.gms : Bid Evaluation with Piecewise Linear Functions

Description

A company obtains a number of bids from vendors for the supply
of a specified number of units of an item. Most of the submitted
bids have prices that depend on the volume of business. A formulation
with 0/1 variables is shown in the original gamslib model BID, one with
SOS2 sets in gamslib model bidsos. Here we use segments with a point, length,
and slope to define a model.


Small Model of Type : MIP


Category : GAMS Model library


Main file : bidpwl.gms   includes :  pwlfunc.inc

$title Bid Evaluation with Piecewise Linear Functions (BIDPWL,SEQ=385)

$onText
A company obtains a number of bids from vendors for the supply
of a specified number of units of an item. Most of the submitted
bids have prices that depend on the volume of business. A formulation
with 0/1 variables is shown in the original gamslib model BID, one with
SOS2 sets in gamslib model bidsos. Here we use segments with a point, length,
and slope to define a model.


Bracken, J, and McCormick, G P, Chapter 3. In Selected Applications
of Nonlinear Programming. John Wiley and Sons, New York, 1968,
pp. 28-36.

Keywords: mixed integer linear programming, bid evaluation, micro economics,
          piecewise linear functions
$offText

$eolCom //

Set
   v  'vendors'        / a, b, c, d, e /
   cl 'column labels'  / setup, price, q-min, q-max ,cost /
   s  'segements'      / 0*5 /
   sl 'segment labels' / x, y 'coordinates', l 'length', g 'slope' /;

Scalar req 'requirements' / 239600.48 /;

Table bid(v,s,cl) 'bid data'
             setup   price   q-min   q-max
   a.1     3855.84  61.150           33000
   b.1   125804.84  68.099   22000   70000
   b.2              66.049   70000  100000
   b.3              64.099  100000  150000
   b.4              62.119  150000  160000
   c.1    13456.00  62.190          165600
   d.1     6583.98  72.488           12000
   e.1              70.150           42000
   e.2              68.150   42000   77000;

Parameter BidPwl(v,s,sl) 'bid segment definition';
bidpwl(v,  s,'x') = bid(v,s,'q-min');
bidpwl(v,'1','y') = bid(v,'1','setup') + bid(v,'1','q-min')*bid(v,'1','price');
bidpwl(v,  s,'l') = bid(v,s,'q-max') - bid(v,s,'q-min');
bidpwl(v,  s,'g') = bid(v,s,'price');
bidpwl(v,'0','g') = 1; // no deal

$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 BidPwl s x y l g v

* Fill missing y coordinate for s2 and further
loop(BidPwl_Seg(v,s)$(ord(s) > 2),
   BidPwl(v,s,'y') = BidPwl(v,s-1,'y') + BidPwl(v,s-1,'g')*BidPwl(v,s-1,'l');
);

Variable
   c    'total cost'
   x(v) 'vendor units'
   y(v) 'vendor units';

Equation
   defx(v) 'define vendor units'
   demand  'demand constraint'
   defy(v) 'define cost of vendor units'
   costdef 'cost definition';

defx(v).. x(v) =e= BidPwl_x(v);

demand..  req  =e= sum(v, x(v));

defy(v).. y(v) =e= BidPwl_y(v);

costdef.. c    =e= sum(v, y(v));

Model bideval / all /;

option optCr = 0.0;

solve bideval minimizing c using mip;

Parameter rep;
rep(v,'xmodel') = x.l(v);
rep(v,'ymodel') = y.l(v);
rep(v,'yexec')  = BidPwl_Func(x.l(v),v);
rep(v,'diff')   = rep(v,'ymodel') - rep(v,'yexec');
abort$(sum(v, abs(rep(v,'diff'))) > (1e-6)*card(v))'model and execution time disagree', rep;
display rep;