FICO
FICO Xpress Optimization Examples Repository
FICO Optimization Community FICO Xpress Optimization Home
Back to examples browserPrevious exampleNext example

Purchasing with price breaks

Description
There are three suppliers of a good, and they have quoted various prices for various quantities of product. We want to buy at least total cost, yet not buy too much from any one supplier. Each supplier offers decreasing prices for increased lot size, in the form of incremental discounts. We wish to buy 600 items in total.
  • complex MIP model
  • data input from file, including parameters for dimensioning
  • splitting the declaration section to read first the parameters that are used to declare the data arrays
  • using SOS-2
Further explanation of this example: 'Xpress teaching material', Section 2.4 'SOS-2: Purchasing with price breaks'; 'Applications of optimization with Xpress-MP', Section 3.4.5 'Special Ordered Sets of type 2'

purchasegr.zip[download all files]

Source Files
By clicking on a file name, a preview is opened at the bottom of this page.
purchase_graph.mos[download]
purchase_pwl.mos[download]
purchase_pwl_graph.mos[download]

Data Files





purchase_pwl_graph.mos

(!******************************************************
   Mosel Example Problems
   ======================

   file purchase_pwl_graph.mos
   ```````````````````````````
   TYPE:         Purchasing with price breaks
   DIFFICULTY:   3
   FEATURES:     MIP problem, using 'pwlin' for piecewise linear function,
                 graphical representation of data
   DESCRIPTION:  There are three suppliers of a good, and they have quoted 
                 various prices for various quantities of product. We want 
                 to buy at least total cost, yet not buy too much from any 
                 one supplier. Each supplier offers decreasing prices for
                 increased lot size, in the form of incremental discounts.
                 We wish to buy 600 items in total.     
   FURTHER INFO: `Applications of optimization with Xpress-MP teaching 
                 material', Section 2.4 `SOS-2: Purchasing with price breaks';
                 `Applications of optimization with Xpress-MP', 
                 Section 3.4.5 `Special Ordered Sets of type 2'

   (c) 2020 Fair Isaac Corporation
       author: S. Heipcke, July 2020
*******************************************************!)

model "Purchase pwl graph"
 uses "mmxnlp", "mmsvg"

 declarations
  NB = 3
  BREAK1 = 1..NB                     ! Price breaks
  BREAK0 = 0..NB                     ! Price breaks including 0
  SUPPL = 1..3                       ! Suppliers
 
  COST: array(SUPPL,BREAK1) of real  ! Unit cost
  B: array(SUPPL,BREAK0) of real    ! Breakpoints (quantities at which unit
                                     ! cost changes)
  CB: array(SUPPL,BREAK0) of real   ! Total cost at break points
  MAXPERC: array(SUPPL) of real      ! Maximum percentages for each supplier
  REQ: real                          ! Total quantity required

  buy: array(SUPPL) of mpvar         ! Quantity to purchase from supplier s
  pay: array(SUPPL) of mpvar         ! Cost incurred from supplier s
 end-declarations

 initializations from 'purchase.dat'
  COST B MAXPERC REQ
 end-initializations

! **** Graphical representation of data ****

! Calculate total cost at breakpoints
 forall(s in SUPPL) do
  CB(s,0):= 0
  forall(b in BREAK1) CB(s,b):= CB(s,b-1) + COST(s,b)*(B(s,b)-B(s,b-1))
 end-do

 FACT:=100
 svgsetgraphviewbox(0, 0, max(s in SUPPL) B(s,NB), 2*FACT*max(s in SUPPL,b in BREAK1) COST(s,b)+1)
 svgsetgraphlabels("Units","Cost per unit")
 svgsetgraphstyle(SVG_STROKEWIDTH,5)
 forall(s in SUPPL) do
  svgaddgroup("SG"+s, "Supplier "+s)
  ! Unit cost graph per supplier
  svgaddline(union(b in BREAK1) [B(s,b-1), FACT*COST(s,b), B(s,b), FACT*COST(s,b)]) 
  ! Total cost scaled to fit into unit cost graph
!  svgaddline(union(b in BREAK1) [B(s,b-1), CB(s,b-1)/5, B(s,b), CB(s,b)/5])
 end-do

! Objective: sum of costs*weights
 MinCost:= sum(s in SUPPL) pay(s)

! Define relation between bought quantities and price paid per supplier
 forall(s in SUPPL) 
 ! Formulation of pwlin via breakpoint coordinates
!   pay(s) = pwlin(buy(s), union(b in BREAK0) [B(s,b),CB(s,b)])
 ! Formulation of pwlin via slopes
!   pay(s) = pwlin(buy(s), union(b in 1..(NB-1)) [B(s,b)], union(b in BREAK1) [COST(s,b)])
 ! Formulation of pwlin via segments
   pay(s) = pwlin(union(b in 0..(NB-1)) [pws(B(s,b),CB(s,b)+COST(s,b+1)*(buy(s)-B(s,b)))]) 

! The minimum quantity that must be bought
 Demand:= sum(s in SUPPL) buy(s) >= REQ

! No more than the maximum percentage from each supplier
 forall(s in SUPPL) buy(s) <= MAXPERC(s)*REQ/100.0

 minimize(MinCost)              ! Solve the MIP-problem

 writeln("Minimum total cost: ", getobjval)
 forall(s in SUPPL) writeln(" buy(",s,"): ", getsol(buy(s)), " cost: ", pay(s).sol)

 svgsave("purchase.svg")
 svgrefresh
 svgwaitclose("Close browser window to terminate model execution.", 1)
end-model

Back to examples browserPrevious exampleNext example