| |||||||||||||
Purchase - Definition of SOS-2 Description A model for optimal purchasing with price-breaks featuring a
complex MIP model, data input from file and using SOS-2. Further explanation of this example: Quick reference guide 'MIP formulations and linearizations', Section 3.3 Price breaks
Source Files By clicking on a file name, a preview is opened at the bottom of this page.
Data Files xbpurch.cs /******************************************************** Xpress-BCL C# Example Problems ============================== file xbpurch.cs ``````````````` Purchasing problem using SOS-2. (c) 2008-2024 Fair Isaac Corporation authors: S.Heipcke, D.Brett. ********************************************************/ /* WARNING. This model is not for the novice, but it does contain many * * useful ideas. * * The formulation is tricky because the discounts are all-quantity, * * so the graph of cost against quantity purchased is discontinuous. * * To maintain sanity in the special ordered set formulation, we must * * coarsen the discontinuity by stopping purchases just at the break * * point. */ using System; using System.Text; using System.IO; using BCL; namespace Examples { public class TestProduction { //Define XPRBDATAPATH to wherever you have placed the data folder; here we expect it to be same directory as compiled example. static string XPRBDATAPATH = Directory.GetParent(System.Reflection.Assembly.GetExecutingAssembly().Location).FullName + "/Data"; string PARAMSFILE = XPRBDATAPATH + "/purchase/params.dat"; string MAXPERCFILE = XPRBDATAPATH + "/purchase/maxperc.dat"; string REQFILE = XPRBDATAPATH + "/purchase/required.dat"; string PRICEFILE = XPRBDATAPATH + "/purchase/pricebk.dat"; /****TABLES****/ int NS; /* Number of suppliers */ int NB; /* Number of price breaks */ int NB2; /* Useful parameter */ double[,] UC; /* Unit cost */ double[,] BR; /* Breakpoints (quantities at which unit cost changes) */ double[,] X; /* Coarsened break points */ double[,] C; /* Total cost at break points */ double[] DELTA; /* Coarsening factors */ double[] MAXPERC; /* Maximum percentage from each supplier */ double REQ; /* Total quantity required */ double delta = 0.10; /* Base coarsening factor */ /* Initialize a new problem in BCL */ XPRBprob p = new XPRBprob("Purchase"); public static void Main() { System.Console.WriteLine("Started Production Test.\n"); XPRB.init(); TestProduction InitClassInstance = new TestProduction(); /* Data input from file */ InitClassInstance.readData(); /* Formulate and solve the problem */ InitClassInstance.modPurchase(); return; } /*********************************************************************/ public void modPurchase() { XPRBexpr lobj, lc; XPRBexpr[] lr; int s,b; XPRBvar[] x; XPRBvar[,] lam; /****VARIABLES****/ x = new XPRBvar[NS]; /* Quantity to purchase from supplier s */ for(s=0;s<NS;s++) x[s] = p.newVar("x"); lam = new XPRBvar [NS,NB2]; for(s=0;s<NS;s++) { /* Weights at breakpoint b for supplier s */ for(b=0;b<NB2;b++) lam[s,b] = p.newVar(("lam_" + (s+1).ToString())); } /****OBJECTIVE****/ //Init lobj lobj = new XPRBexpr(); /* Minimize the sum of costs*weights */ for(s=0;s<NS;s++) for(b=0;b<NB2;b++) lobj += C[s,b]*lam[s,b]; /* Set objective function */ p.setObj(p.newCtr("OBJ", lobj)); /****CONSTRAINTS****/ /* Define x, also order the lam variables by breakpoint quantities */ lr = new XPRBexpr[NS]; for(s=0;s<NS;s++) { lr[s] = new XPRBexpr(0); for(b=0;b<NB2;b++) lr[s] += X[s,b]*lam[s,b]; p.newCtr("DefX", lr[s] == x[s]); } /* The convexity constraint (lam sum to 1) */ for (s = 0; s < NS; s++) { lc = new XPRBexpr(); for (b = 0; b < NB2; b++) lc += lam[s, b]; p.newCtr("Conv", lc == 1); } /* The minimum quantity that must be bought */ lc = new XPRBexpr(); for(s=0;s<NS;s++) lc += x[s]; p.newCtr("MustBuy", lc >= REQ); /****BOUNDS****/ /* No more than the maximum percentage from each supplier */ for(s=0;s<NS;s++) x[s].setUB(MAXPERC[s]*REQ/100.0); /****SETS****/ /* Define the lam as SOS2 as we can linearly interpolate between the * breakpoints. The weights are the DefX coefficients augmented by 1 because BCL does not accept the weight 0. */ for(s=0;s<NS;s++) { for(b=0;b<NB2;b++) lr[s] += lam[s,b]; p.newSos("SetLam", BCLconstant.XPRB_S2, lr[s]); } /****SOLVING + OUTPUT****/ /* Output to MPS file */ p.exportProb(BCLconstant.XPRB_MPS,"TestResult.matrix"); /* Choose the sense of the optimization */ p.setSense(BCLconstant.XPRB_MINIM); /* Solve the MIP-problem */ p.mipOptimize(); /* Get objective value */ System.Console.WriteLine("Objective: " + p.getObjVal() + "\n"); /* Print out the solution values */ for(s=0;s<NS;s++) System.Console.Write(x[s].getName() + ":" + x[s].getSol() + " "); System.Console.WriteLine("\n"); for(s=0;s<NS;s++) for(b=0;b<NB2;b++) System.Console.Write(lam[s,b].getName() + ":" + lam[s,b].getSol() + " "); System.Console.WriteLine("\n"); } /*********************************************************************/ /**** Read data from files **** * Need to do this via StreamReader as per XPRBreadline C# method ******************************/ public void readData() { //public int XPRBreadline(StreamReader fileStreamIn, int maxlen, // string format, out object[] output) FileStream file = new FileStream(PARAMSFILE, FileMode.Open, FileAccess.Read); StreamReader fileStreamIn = new StreamReader(file); int s,b; /* Read the parameter file */ //Part of XPRBprob: public int XPRBreadline(StreamReader fileStreamIn, //int maxlen, string format, out object[] output) object[] objRead; p.XPRBreadline(fileStreamIn, 200, "{i}", out objRead); NS = (int)objRead[0]; p.XPRBreadline(fileStreamIn, 200, "{i}", out objRead); NB = (int)objRead[0]; fileStreamIn.Close(); file.Close(); NB2 = 2*NB; /* Now define the tables that we will use, using the sizes we have just read. */ UC= new double[NS,NB]; BR = new double[NS,NB]; X=new double[NS,NB2]; C=new double[NS,NB2]; DELTA=new double[NB2]; MAXPERC=new double[NS]; /* Define coarsening factors. */ DELTA[0]=0; DELTA[1] = -1*delta; for(b=2;b<NB2;b++) DELTA[b] = -1*DELTA[b-1]; /* Read the price and breakpoint data file */ for(s=0;s<NS;s++) for(b=0;b<NB;b++) { UC[s,b]=0; BR[s,b]=0; } file = new FileStream(PRICEFILE, FileMode.Open, FileAccess.Read); fileStreamIn = new StreamReader(file); while (p.XPRBreadline(fileStreamIn, 200, "{i}, {i}, {g}, {g}", out objRead)==4) { s = (int)objRead[0]; b = (int)objRead[1]; UC[s - 1, b - 1] = (double)objRead[2]; BR[s - 1, b - 1] = (double)objRead[3]; } fileStreamIn.Close(); file.Close(); /* Read the percentages data file */ file = new FileStream(MAXPERCFILE, FileMode.Open, FileAccess.Read); fileStreamIn = new StreamReader(file); p.XPRBreadarrline(fileStreamIn, 200, "{g}, ", out MAXPERC, NS); fileStreamIn.Close(); file.Close(); /* Read the required amount data file */ file = new FileStream(REQFILE, FileMode.Open, FileAccess.Read); fileStreamIn = new StreamReader(file); p.XPRBreadline(fileStreamIn, 200, "{g}", out objRead); REQ = (double)objRead[0]; fileStreamIn.Close(); file.Close(); /* We now pick out the data from the tables into which they have been read. */ for(s=0;s<NS;s++) { /* First total cost and (new) breakpoint are (0,0) */ C[s,0] = 0; X[s,0] = 0; for(b=1;b<NB2;b++) { /* Rest calculated... */ C[s,b] = UC[s,b/2] * BR[s,(b-1)/2]; /*...unit price*quantity */ X[s,b] = BR[s,(b-1)/2] + DELTA[b]; /*...coarsened grids */ } } } /*********************************************************************/ } } | |||||||||||||
© Copyright 2024 Fair Isaac Corporation. |