Apply a binary fixing heuristic to an unpresolved MIP problem
|
|
Type: | Programming |
Rating: | 4 (medium-difficult) |
Description: | We take a production plan model and solve its LP relaxation. This heuristic will speed up solution - though may fail to optimse the problem. The results are displayed on screen and the problem statistics stored in a log file. |
File(s): | FixBV.cs |
|
FixBV.cs |
using System; using System.IO; using Optimizer; namespace XPRSExamples { class FixBV { public static void Main(string[] args) { FixBV example = new FixBV(); example.Run(); } private const double TOL=0.0005; // Tolerance on binary variables private void Run() { try { string sProblem=@"..\..\..\Data\coco"; // Problem name string sLogFile="fixbv.log"; // Log file name int nCol; // Number of columns // Global problem information int nGlEnt; // Number of global entities: binary, integer, semi-continuous and partial integer variables int nSet; // Number of S1 and S2 sets int[] pGlInd; // Column indices of the global entities char[] pGlType; // Global entity types // Bound changes int[] pBndInd; // Column indices of the bounds to be changed char[] pBndType; // New bound type double[] pBndVal; // New bound values int nBnd; // Bound counter int i; // Loop counter int j; // Holder for the bound indices // Solution information double[] x; // LP solution values int nGlStatus; // Global status int nNodes; // Number of nodes solved so far in the global search double dObjVal; // Objective value of the best integer solution // Initialise Optimizer XPRS.Init(""); Console.Write(XPRS.GetBanner()); prob = new XPRSprob(); // Delete and define log file // Delete the file if it exists. if (File.Exists(sLogFile)) { File.Delete(sLogFile); } prob.SetLogFile(sLogFile); // Tell Optimizer to call optimizermsg whenever a message is output prob.MessageCallbacks += new MessageCallback(this.OptimizerMsg); // Get and display the Optimizer version number Console.WriteLine("\nXpress Optimiser Subroutine Library Release {0}\n\n", prob.Version/100); // Turn off presolve and permit no cuts - to slow down solution and allow // the effect of the heuristic to be be seen prob.Presolve = 0; prob.CutStrategy = 0; // Read the problem file prob.MPSFormat = -1; prob.ReadProb(sProblem,""); // Solve the LP relaxation // Get the number of columns nCol = prob.Cols; // Allocate memory for solution array and check for memory shortage x= new double[nCol]; // Solve the LP prob.Maxim(""); // Get LP solution values prob.GetSol(x,null,null,null); // Fix the binary variables that are at their bounds // Allocate memory for global entity arrays pGlInd = new int[nCol]; pGlType = new char[nCol]; // Get global entity information prob.GetGlobal(out nGlEnt, out nSet, pGlType, pGlInd, null, null, (int[])null, null, null); // Allocate memory for bound arrays pBndInd = new int[nGlEnt]; pBndVal = new double[nGlEnt]; pBndType = new char[nGlEnt]; // Initialise bound counter nBnd=0; // Go through the global entities for(i=0; i<nGlEnt; i++) { // Test whether each is a binary variable if (pGlType[i] == 'B') { // Hold the index of the BV j=pGlInd[i]; // If the value of the BV is within TOL of zero, store its index, // set its upper bound to 0, and increment the bound counter if (x[j]<=TOL) { pBndInd[nBnd]=j; pBndType[nBnd]='U'; pBndVal[nBnd]=0.0; nBnd++; // If the value of the BV is within TOL of one,store its index, // set its lower bound to 1, and increment the bound counter } else if ((1-x[j])<=TOL) { pBndInd[nBnd]=j; pBndType[nBnd]='L'; pBndVal[nBnd]=1.0; nBnd++; } } } // Instruct Optimizer to change the bounds of the appropriate BVs, // and tell the user how many have been fixed prob.ChgBounds(nBnd,pBndInd,pBndType,pBndVal); Console.WriteLine("Solving problem {0} with a binary fixing heuristic:\n\n",sProblem); Console.WriteLine(" After the LP optimisation {0} binary variables were fixed\n\n",nBnd); // Solve the modified problem as a MIP // Search for an integer solution prob.Global(); // Get the number of nodes solved in the global search nNodes = prob.Nodes; // Get the objective value of the best integer solution dObjVal = prob.MIPObjVal; // Check the global status and display the results of the global search nGlStatus = (int)prob.MIPStatus; switch (nGlStatus) { case 0: Console.WriteLine(" Problem has not been loaded"); break; case 1: Console.WriteLine(" Search has not begun - LP has not been optimised"); break; case 2: Console.WriteLine(" Search has not begun - LP has been optimised"); break; case 3: Console.WriteLine(" Search interrupted - No integer solution was found"); break; case 4: Console.WriteLine(" Search interrupted - Integer solution found: %g",dObjVal); break; case 5: Console.WriteLine(" No integer solution was found"); break; case 6: Console.WriteLine(" Integer solution found: {0}",dObjVal); break; } Console.WriteLine("\n\n The MIP optimisation took {0} nodes\n\n",nNodes); } catch (XPRSException e) { Console.WriteLine(e.ToString()); throw e; } finally { prob.Destroy(); XPRS.Free(); } } public void OptimizerMsg (XPRSprob prob, object data, string message, int len, int msglvl) { switch(msglvl) { case 3: case 4: Console.WriteLine ("{0}" + message, data); break; } } private XPRSprob prob; } } |