Lindo Systems
MODEL: ! (PieceLinearSOS2.lng);
! Demonstrates the SOS2 feature of LINGO for representing
arbitrary, piecewise-linear cost curves.
We have two suppliers. Each with his
own piecewise-linear cost curve.
How much should we buy from each to
buy a given total amount at minimum cost? ;
! Keywords: Linearization, Non-convex function,
Piecewise linear, Purchasing, Quantity discount, SOS2;
SETS:
! Suppliers with ...;
SPLR: TCOST, TVOL;
POINT; ! Price schedules with breakpoints;
SXP( SPLR, POINT): WP, VOLP, COSTP;
ENDSETS
DATA:
POINT = 1..8; ! Up to 5 break points;
SPLR = V1 V2; ! Two vendors;
! Total cost at each breakpoint,
linear interpolate between adjacent breakpoints;
! Volume & total cost at each breakpoint;
SXP VOLP COSTP =
V1 1 0 0 ! Supplier 1;
V1 2 999 5994 ! $6/unit up this interval;
V1 3 1000 5000 ! $5/unit starting here;
V1 4 9999 49995 ! $5/unit up to here;
V1 5 10000 45000 ! $4.5/unit starting here;
V1 6 19999 89995.5 ! $4.5/unit up to here;
V1 7 20000 80000 ! $4/unit starting here;
V1 8 50000 200000 ! $4/unit up to here;
V2 1 0 0 ! Supplier 2;
V2 2 999 5994 ! $6/unit up this interval;
V2 3 1000 5000 ! $5/unit starting here;
V2 4 9999 49995 ! $5/unit up to here;
V2 5 10000 45000 ! $4.5/unit starting here;
V2 6 19999 89995.5 ! $4.5/unit up to here;
V2 7 20000 80000 ! $4/unit starting here;
V2 8 50000 200000 ; ! $4/unit up to here;
NEED = 18000; ! Total units needed;
ENDDATA
! To see the scalar version of the model, click on:
Solver | Generate | Display model;
! Minimize total cost of purchases from all suppliers;
MIN = @SUM( SPLR(i): TCOST(i));
! Volume we need. For some price schedules,
it might be cheaper to buy more than needed;
[NC] @SUM( SPLR(i): TVOL(i)) >= NEED;
! For each supplier i;
@FOR( SPLR(i):
! Calculate weighted cost;
[WCOST] TCOST(i) = @SUM( SXP( i, p): COSTP( i, p) * WP( i,p));
! Calculate weighted volume;
[WVOL] TVOL(i) = @SUM( SXP( i,p): VOLP( i,p) * WP( i,p));
! Weights must sum to 1 for each supplier i;
[SUM21] 1 = @SUM( SXP( i,p): WP( i,p));
! Weights must satisfy SOS2 condition:
at most 2 weights > 0, and must be adjacent.
Exploit fact that in LINGO,
string concatenation operator is "+", and
member names are text strings;
@FOR( SXP( i,p): @SOS2( 'SOS2'+SPLR(i), WP( i,p)));
);
END