![]() | |||||||||||||||
| |||||||||||||||
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.
Source Files By clicking on a file name, a preview is opened at the bottom of this page.
Data Files purchase_graph.mos (!****************************************************** Mosel Example Problems ====================== file purchase.mos ````````````````` TYPE: Purchasing with price breaks DIFFICULTY: 3 FEATURES: MIP problem, modeling a piecewise linear function with SOS-2, 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) 2008 Fair Isaac Corporation author: S. Heipcke, Jan. 2001, rev. July 2020 *******************************************************!) model "Purchase" uses "mmxprs", "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 w: array(SUPPL,BREAK0) of mpvar ! Weights at breakpoint k for supplier s end-declarations initializations from 'purchase.dat' COST B MAXPERC REQ end-initializations ! Graphical representation of data FACT:=100 svgsetgraphviewbox(0, 0, max(s in SUPPL) B(s,NB), 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) svgaddline(sum(b in BREAK1) [B(s,b-1), FACT*COST(s,b), B(s,b), FACT*COST(s,b)]) end-do ! 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 ! Objective: sum of costs*weights MinCost:= sum(s in SUPPL, b in BREAK0) CB(s,b) * w(s,b) ! Define buy and also order the weight variables by breakpoint quantities forall(s in SUPPL) Buy(s):= sum(b in BREAK0) B(s,b) * w(s,b) = buy(s) ! The convexity row (w sum to 1) forall(s in SUPPL) OneW(s):= sum(b in BREAK0) w(s,b) = 1 ! 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 ! Define the w as SOS-2 as we can linearly interpolate between the ! breakpoints. forall(s in SUPPL) makesos2(union(b in BREAK0) {w(s,b)}, sum(b in BREAK0) B(s,b)*w(s,b)) ! Alternative formulation: ! The weight coefficients B are all augmented by EPS ! since Mosel does not accept 0-valued weights with `is_sos2'. ! forall(s in SUPPL) sum(b in BREAK0) (B(s,b)+10E-20) * w(s,b) is_sos2 minimize(MinCost) ! Solve the MIP-problem writeln("Minimum cost: ", getobjval) forall(s in SUPPL) writeln(" buy(",s,"): ", getsol(buy(s))) svgsave("purchase.svg") svgrefresh svgwaitclose("Close browser window to terminate model execution.", 1) end-model
| |||||||||||||||
© Copyright 2024 Fair Isaac Corporation. |