Apply a binary fixing heuristic to an unpresolved MIP problem
|
|
|
| Type: | Production planning |
| Rating: | 3 (intermediate) |
| 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.vb |
| Data file(s): | coco.mat |
|
|
|
| FixBV.vb |
Imports System
Imports Microsoft.VisualBasic
Imports Optimizer
Imports System.IO
Module FixBV
Private Const TOL As Double = 0.0005 ' Tolerance on binary variables
Public Sub RunFixBV(ByRef Log As TextWriter)
Try
Const sProblem As String = "..\Data\coco" ' Problem name
Const sLogFile As String = "fixbv.log" ' Log file name
Dim nCol As Integer ' Number of columns
' Global problem information
Dim nGlEnt As Integer ' Number of global entities: binary, integer,
' semi-continuous and partial integer variables
Dim nSet As Integer ' Number of S1 and S2 sets
Dim pGlInd() As Integer ' Column indices of the global entities
Dim pGlType() As Char ' Global entity types
' Bound changes
Dim pBndInd() As Integer ' Column indices of the bounds to be changed
Dim pBndType() As Char ' New bound type
Dim pBndVal() As Double ' New bound values
Dim nBnd As Integer ' Bound counter
Dim i As Integer ' Loop counter
Dim j As Integer ' Holder for the bound indices
' Solution information
Dim x() As Double ' LP solution values
Dim nGlStatus As Integer ' Global status
Dim nNodes As Integer ' Number of nodes solves so far in global search
Dim dObjVal As Double ' Objective value of the best integer solution
' Initialise Optimizer
XPRS.Init("")
Log.WriteLine(XPRS.GetBanner())
Dim prob As XPRSprob
prob = New XPRSprob
' Delete and define log file
If (File.Exists(sLogFile)) Then
File.Delete(sLogFile)
End If
prob.SetLogFile(sLogFile)
' Tell Optimizer to call HandleOptimizerMessage whenever a message is output
prob.AddMessageCallback(New Optimizer.MessageCallback(AddressOf HandleOptimizerMessage), Log)
' Get and display the Optimizer version number
Log.WriteLine( _
vbCrLf & "Xpress Optimizer Subroutine Library Release {0}" & vbCrLf & vbCrLf, _
prob.Version / 100 _
)
' Turn off presolve and permit no cuts - to slow down solution and allow
' the effect of the heuristic to be seen
prob.Presolve = 0
prob.CutStrategy = 0
' Read the problem file
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
ReDim x(nCol - 1)
' Solve the LP
prob.Maxim("")
' Get the LP solution values
prob.GetSol(x, Nothing, Nothing, Nothing)
' Fix the binary variables that are at their bounds
' Allocate memory for gloval entity arrays
ReDim pGlInd(nCol - 1)
ReDim pGlType(nCol - 1)
' Get global entity information
prob.GetGlobal(nGlEnt, nSet, pGlType, pGlInd, Nothing, Nothing, DirectCast(Nothing, Long()), Nothing, Nothing)
' Allocate memory for bound arrays
ReDim pBndInd(nGlEnt - 1)
ReDim pBndVal(nGlEnt - 1)
ReDim pBndType(nGlEnt - 1)
' Initialise the bound counter
nBnd = 0
' Go through the gloval entities
For i = 0 To nGlEnt - 1
' Test whether each is a binary variable
If (pGlType(i) = "B") Then
' 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) Then
pBndInd(nBnd) = j
pBndType(nBnd) = "U"
pBndVal(nBnd) = 0.0
nBnd = nBnd + 1
' 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
ElseIf ((1 - x(j)) <= TOL) Then
pBndInd(nBnd) = j
pBndType(nBnd) = "L"
pBndVal(nBnd) = 1.0
nBnd = nBnd + 1
End If
End If
Next
' Instruct the Optimizer to change the bounds of the appropriate BVs,
' and tell the user how many have been fixed
prob.ChgBounds(nBnd, pBndInd, pBndType, pBndVal)
Log.WriteLine("Solving problem {0} with a binary fixing heuristic" & _
vbCrLf & vbCrLf, sProblem)
Log.WriteLine(" After the LP optiziation {0} binary variables were fixed" & _
vbCrLf & vbCrLf, nBnd)
' Solve the modified problem as a MIP
' Search for an integer solution
prob.[Global]()
' Get th enumber 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 = prob.MIPStatus
Select Case nGlStatus
Case 0
Log.WriteLine(" Problem has not been loaded")
Case 1
Log.WriteLine(" Search has not begun - LP has not been optimised")
Case 2
Log.WriteLine(" Search has not begun - LP has been optimised")
Case 3
Log.WriteLine(" Search interrupted - No integer solution was found")
Case 4
Log.WriteLine(" Search interrupted - Integer solution found: %g", dObjVal)
Case 5
Log.WriteLine(" No integer solution was found")
Case 6
Log.WriteLine(" Integer solution found: {0}", dObjVal)
End Select
Log.WriteLine(vbCrLf & vbCrLf & "The MIP optimisation took {0} nodes" & vbCrLf & vbCrLf, nNodes)
' Destroy the problem and free the optimizer
prob.Destroy()
XPRS.Free()
Catch ex As Exception
Log.WriteLine(ex.ToString)
End Try
End Sub
Private Sub HandleOptimizerMessage(ByVal prob As Optimizer.XPRSprob, ByVal data As Object, _
ByVal message As String, ByVal len As Integer, _
ByVal msglvl As Integer)
Dim log As TextWriter
log = data
If (msglvl = 3 Or msglvl = 4) Then
log.WriteLine(message)
End If
End Sub
End Module
|
