| |||||||||||||||||||||||||
Coco - A full production planning example Description The Coco productional planning problem: multi-item,
multi-period, multi-site production planning. A sequence
of model versions show how the model
was developed, to (a) use more sophisticated modeling features
and (b) to extend the model, taking it from a simple linear model
to one with fixed prices and logical decisions.
Source Files By clicking on a file name, a preview is opened at the bottom of this page.
Data Files xbcoco.cs /******************************************************** Xpress-BCL C# Example Problems ============================== file xbcoco.cs `````````````` Complete Coco Problem. Specify phase by PHASE parameter. Data input in the model, not via data files. (c) 2008-2024 Fair Isaac Corporation authors: S.Heipcke, D.Brett. ********************************************************/ using System; using System.Text; using System.IO; using BCL; namespace Examples { public class TestIntCocoComplete { const int PHASE = 5; /* Phase = 3: Multi-period parameterised model; mines always open * Phase = 4: Mines may open/closed freely; when closed save 20000 per month * Phase = 5: Once closed always closed; larger saving */ const int NP = 2; /* Number of products (p) */ const int NF = 2; /* factories (f) */ const int NR = 2; /* raw materials (r) */ const int NT = 4; /* time periods (t) */ /****DATA****/ double[,] REV = /* Unit selling price of product p in period t */ {{400, 380, 405, 350}, {410, 397, 412, 397}}; double[,] CMAK = /* Unit cost to make product p at factory f */ {{150, 153}, { 75, 68}}; double[,] CBUY = /* Unit cost to buy raw material r in period t */ {{100, 98, 97, 100}, {200, 195, 198, 200}}; double[] COPEN = /* Fixed cost of factory f being open for one period */ {50000, 63000}; double CPSTOCK = 2.0; /* Unit cost to store any product p */ double CRSTOCK = 1.0; /* Unit cost to store any raw material r */ double[,] REQ = /* Requirement by unit of prod. p for raw material r */ {{1.0, 0.5}, {1.3, 0.4}}; double[,] MXSELL = /* Max. amount of p that can be sold in period t */ {{650, 600, 500, 400}, {600, 500, 300, 250}}; double[] MXMAKE = /* Max. amount factory f can make over all products */ {400, 500}; double MXRSTOCK = 300; /* Max. amount of r that can be stored each f and t */ double[,] PSTOCK0 = /* Initial product p stock level at factory f */ {{50, 100}, {50, 50}}; double[,] RSTOCK0 = /* Initial raw material r stock level at factory f*/ {{100, 150}, { 50, 100}}; /***********************************************************************/ public static void Main() { XPRB.init(); XPRBvar[, ,] make = new XPRBvar[NP, NF, NT]; XPRBvar[, ,] sell = new XPRBvar[NP, NF, NT]; XPRBvar[, ,] pstock = new XPRBvar[NP, NF, NT + 1]; XPRBvar[, ,] buy = new XPRBvar[NR, NF, NT]; XPRBvar[, ,] rstock = new XPRBvar[NR, NF, NT + 1]; XPRBvar[,] openm = new XPRBvar[NF, NT]; XPRBexpr lobj, lc; int p, f, r, t; XPRBprob pb = new XPRBprob("Coco"); /* Initialize a new problem in BCL */ TestIntCocoComplete TestInstance = new TestIntCocoComplete(); /****VARIABLES****/ for (p = 0; p < NP; p++) for (f = 0; f < NF; f++) { for (t = 0; t < NT; t++) { make[p,f,t] = pb.newVar("make_p" + (p+1) + "_f" + (f+1)); /* Amount of prod. p to make at factory f in period t */ sell[p, f, t] = pb.newVar("sell_p" + (p + 1) + "_f" + (f + 1)); /* Amount of prod. p sold from factory f in period t */ } for (t = 0; t < NT + 1; t++) pstock[p,f,t] = pb.newVar("pstock_p" + (p+1) + "_f" + (f+1)); /* Stock level of prod. p at factory f at start of period t */ } for (r = 0; r < NR; r++) for (f = 0; f < NF; f++) { for (t = 0; t < NT; t++) buy[r,f,t] = pb.newVar("buy_r" + (r+1) + "_f" + (f+1)); /* Amount of raw material r bought for factory f in period t */ for (t = 0; t < NT + 1; t++) rstock[r,f,t] = pb.newVar("rstock_r" + (r+1) + "_f" + (f+1)); /* Stock level of raw mat. r at factory f at start of per. t */ } for (f = 0; f < NF; f++) for (t = 0; t < NT; t++) openm[f,t] = pb.newVar("open_f" + (f+1), BCLconstant.XPRB_BV); /* 1 if factory f is open in period t, else 0 */ /****OBJECTIVE****/ lobj = new XPRBexpr(); for (f = 0; f < NF; f++) /* Objective: maximize total profit */ { for (p = 0; p < NP; p++) { for (t = 0; t < NT; t++) lobj += TestInstance.REV[p,t] * sell[p,f,t] - TestInstance.CMAK[p,f] * make[p,f,t]; for (t = 1; t < NT + 1; t++) lobj -= TestInstance.CPSTOCK * pstock[p,f,t]; } if (PHASE == 4) for (t = 0; t < NT; t++) lobj += (20000 - TestInstance.COPEN[f]) * openm[f,t]; else if (PHASE == 5) for (t = 0; t < NT; t++) lobj -= TestInstance.COPEN[f] * openm[f,t]; for (r = 0; r < NR; r++) { for (t = 0; t < NT; t++) lobj -= TestInstance.CBUY[r,t] * buy[r,f,t]; for (t = 1; t < NT + 1; t++) lobj -= TestInstance.CRSTOCK * rstock[r,f,t]; } } pb.setObj(pb.newCtr("OBJ", lobj)); /* Set objective function */ /****CONSTRAINTS****/ for (p = 0; p < NP; p++) /* Product stock balance */ for (f = 0; f < NF; f++) for (t = 0; t < NT; t++) pb.newCtr("PBal", pstock[p,f,t] + make[p,f,t] == sell[p,f,t] + pstock[p,f,t + 1]); for (r = 0; r < NR; r++) /* Raw material stock balance */ for (f = 0; f < NF; f++) for (t = 0; t < NT; t++) { lc = new XPRBexpr(0.0); for (p = 0; p < NP; p++) lc += TestInstance.REQ[p, r] * make[p, f, t]; pb.newCtr("RBal", rstock[r,f,t] + buy[r,f,t] == lc + rstock[r,f,t + 1]); } for (p = 0; p < NP; p++) for (t = 0; t < NT; t++) { /* Limit on the amount of product p to be sold */ lc = new XPRBexpr(0.0); for (f = 0; f < NF; f++) lc += sell[p,f,t]; pb.newCtr("MxSell", lc <= TestInstance.MXSELL[p,t]); } for (f = 0; f < NF; f++) for (t = 0; t < NT; t++) { /* Capacity limit at factory f */ lc = new XPRBexpr(0.0); for (p = 0; p < NP; p++) lc += make[p, f, t]; pb.newCtr("MxMake", lc <= TestInstance.MXMAKE[f] * openm[f,t]); } for (f = 0; f < NF; f++) for (t = 1; t < NT + 1; t++) { /* Raw material stock limit */ lc = new XPRBexpr(0.0); for (r = 0; r < NR; r++) lc += rstock[r, f, t]; pb.newCtr("MxRStock", lc <= TestInstance.MXRSTOCK); } if (PHASE == 5) for (f = 0; f < NF; f++) for (t = 0; t < NT - 1; t++) /* Once closed, always closed */ pb.newCtr("Closed", new XPRBexpr(openm[f,t + 1]) <= openm[f,t]); /****BOUNDS****/ for (p = 0; p < NP; p++) for (f = 0; f < NF; f++) pstock[p, f, 0].fix(TestInstance.PSTOCK0[p, f]); /* Initial product levels */ for (r = 0; r < NR; r++) for (f = 0; f < NF; f++) rstock[r, f, 0].fix(TestInstance.RSTOCK0[r, f]); /* Initial raw mat. levels */ if (PHASE <= 3) for (f = 0; f < NF; f++) for (t = 0; t < NT; t++) openm[f,t].fix(1); /****SOLVING + OUTPUT****/ pb.setSense(BCLconstant.XPRB_MAXIM); /* Choose the sense of the optimization */ pb.mipOptimize(); /* Solve the MIP-problem */ System.Console.WriteLine("Objective: " + pb.getObjVal()); /* Get objective value */ /* Uncomment to print out the solution values */ /* for(p=0;p<NP;p++) for(f=0;f<NF;f++) for(t=0;t<NT;t++) cout << make[p][f][t].getName() << ":" << make[p][f][t].getSol() << " " << sell[p][f][t].getName() << ":" << sell[p][f][t].getSol()) << " "; cout << endl; for(p=0;p<NP;p++) for(f=0;f<NF;f++) for(t=0;t<NT+1;t++) cout << pstock[p][f][t].getName() << ":" << pstock[p][f][t].getSol() << " "; cout << endl; for(r=0;r<NR;r++) for(f=0;f<NF;f++) { for(t=0;t<NT;t++) cout << buy[r][f][t].getName() << ":" << buy[r][f][t].getSol() << " "; for(t=0;t<NT+1;t++) cout << rstock[r][f][t].getName() << ":" << rstock[r][f][t].getSol() << " "; } for(f=0;f<NF;f++) for(t=0;t<NT;t++) cout << openm[f][t].getName() << ":" << openm[f][t].getSol() << " "; cout << endl; */ return; } } } | |||||||||||||||||||||||||
© Copyright 2023 Fair Isaac Corporation. |