| |||||||||||||||||
Els - An economic lot-sizing problem solved by cut-and-branch and branch-and-cut heuristics Description The version 'xbels' of this example shows how to implement cut-and-branch (= cut
generation at the root node of the MIP search) and 'xbelsc' implements a
branch-and-cut (= cut generation at the MIP search tree nodes)
algorithm using the cut manager.
Source Files By clicking on a file name, a preview is opened at the bottom of this page.
xbelsc.cs /******************************************************** Xpress-BCL C# Example Problems ============================== file xbelsc.cs `````````````` Economic lot sizing, ELS, problem, solved by adding (l,S)-inequalities) in a branch-and-cut heuristic (using the cut manager). ELS considers production planning over a horizon of T periods. In period t, t=1,...,T, there is a given demand DEMAND[t] that must be satisfied by production prod[t] in period t and by inventory carried over from previous periods. There is a set-up up cost SETUPCOST[t] associated with production in period t. The unit production cost in period t is PRODCOST[t]. There is no inventory or stock-holding cost. *** This model cannot be run with a Community Licence *** (c) 2008-2024 Fair Isaac Corporation authors: S.Heipcke, D.Brett. ********************************************************/ using System; using System.Text; using System.IO; using Optimizer; using BCL; namespace Examples { public struct XPRBprobStruct { public XPRBprob prob; public double tol; }; public class TestAdvElsCallback { const int T = 6; /* Number of time periods */ /****DATA****/ int[] DEMAND = { 1, 3, 5, 3, 4, 2}; /* Demand per period */ int[] SETUPCOST = {17,16,11, 6, 9, 6}; /* Setup cost per period */ int[] PRODCOST = { 5, 3, 2, 1, 3, 1}; /* Production cost per period */ int[,] D = new int[T, T]; /* Total demand in periods t1 - t2 */ XPRBvar[] prod = new XPRBvar[T]; /* Production in period t */ XPRBvar[] setup = new XPRBvar[T]; /* Setup in period t */ XPRBprob p = new XPRBprob("ElsC"); /* Initialize a new problem in BCL */ /***********************************************************************/ public void modEls() { int s, t, k; XPRBexpr cobj, le; for (s = 0; s < T; s++) for (t = 0; t < T; t++) for (k = s; k <= t; k++) D[s, t] += DEMAND[k]; /****VARIABLES****/ for (t = 0; t < T; t++) { prod[t] = p.newVar("prod" + (t + 1)); setup[t] = p.newVar("setup" + (t + 1), BCLconstant.XPRB_BV); } /****OBJECTIVE****/ cobj = new XPRBexpr(); for (t = 0; t < T; t++) /* Minimize total cost */ cobj += SETUPCOST[t] * setup[t] + PRODCOST[t] * prod[t]; p.setObj(p.newCtr(cobj)); /****CONSTRAINTS****/ /* Production in period t must not exceed the total demand for the remaining periods; if there is production during t then there is a setup in t */ for (t = 0; t < T; t++) p.newCtr("Production", prod[t] <= D[t, T - 1] * setup[t]); /* Production in periods 0 to t must satisfy the total demand during this period of time */ for (t = 0; t < T; t++) { le = new XPRBexpr(0); for (s = 0; s <= t; s++) le += prod[s]; p.newCtr("Demand", le >= D[0, t]); } } /**************************************************************************/ /* Cut generation loop at the tree node: */ /* get the solution values */ /* identify and set up violated constraints */ /* add cuts to the matrix */ /**************************************************************************/ public int cbNode(XPRSprob xprsp, object mobj) { XPRBprobStruct mo; double objval; /* Objective value */ int t, l; int ncut; /* Counters for cuts */ double[] solprod = new double[T]; double[] solsetup = new double[T]; /* Solution values for var.s prod & setup */ double ds; int depth, node; XPRBcut[] cut = new XPRBcut[T]; XPRBexpr le; mo = (XPRBprobStruct)mobj; ncut = 0; depth = xprsp.NodeDepth; node = xprsp.Nodes; /* Get the solution values */ mo.prob.beginCB(xprsp); mo.prob.sync(BCLconstant.XPRB_XPRS_SOL); for (t = 0; t < T; t++) { solprod[t] = prod[t].getSol(); solsetup[t] = setup[t].getSol(); } /* Search for violated constraints: */ for (l = 0; l < T; l++) { for (ds = 0.0, t = 0; t <= l; t++) { if (solprod[t] < D[t, l] * solsetup[t] + mo.tol) ds += solprod[t]; else ds += D[t, l] * solsetup[t]; } /* Add the violated inequality: the minimum of the actual production prod[t] and the maximum potential production D[t][l]*setup[t] in periods 0 to l must at least equal the total demand in periods 0 to l. sum(t=1:l) min(prod[t], D[t][l]*setup[t]) >= D[0][l] */ if (ds < D[0, l] - mo.tol) { le = new XPRBexpr(0); for (t = 0; t <= l; t++) { if (solprod[t] < D[t, l] * solsetup[t] + mo.tol) le += prod[t]; else le += D[t, l] * setup[t]; } cut[ncut] = mo.prob.newCut(le >= D[0, l]); ncut++; } } /* Add cuts to the problem */ if (ncut > 0) { mo.prob.addCuts(cut, ncut); objval = xprsp.LPObjVal; System.Console.Write("Cuts added : " + ncut + " (depth " + depth + ", node "); System.Console.WriteLine(node + "), obj. " + objval); } mo.prob.endCB(); return 0; } /***********************************************************************/ public void treeCutGen() { IntPtr oprob; XPRBprobStruct mo; double feastol; int starttime, t; CutmgrCallback del = new CutmgrCallback(cbNode); XPRSprob xprsp = p.getXPRSprob(); starttime = XPRB.getTime(); xprsp.LPLog = 0; xprsp.MIPLog = 3; xprsp.CutStrategy = 0; xprsp.Presolve = 0; xprsp.ExtraRows = 5000; feastol = xprsp.FeasTol; feastol *= 10; mo.prob = p; mo.tol = feastol; p.setCutMode(1); xprsp.AddCutmgrCallback(del, (object)mo); p.mipOptimize(); /* Solve the MIP */ System.Console.Write("(" + (XPRB.getTime() - starttime) / 1000.0 + " sec) MIP status "); System.Console.WriteLine(p.getMIPStat() + ", best solution: " + p.getObjVal()); for (t = 0; t < T; t++) { System.Console.Write("Period " + (t + 1) + ": prod " + prod[t].getSol() + " (demand: "); System.Console.Write(DEMAND[t] + ", cost: " + PRODCOST[t] + "), setup "); System.Console.WriteLine(setup[t].getSol() + " (cost: " + SETUPCOST[t] + ")"); } } /***********************************************************************/ public static void Main() { XPRB.init(); TestAdvElsCallback TestInstance = new TestAdvElsCallback(); TestInstance.modEls(); /* Model the problem */ TestInstance.treeCutGen(); /* Solve the problem */ return; } } } | |||||||||||||||||
© Copyright 2024 Fair Isaac Corporation. |