' Copyright 2025, Gurobi Optimization, LLC
'
' Facility location: a company currently ships its product from 5 plants
' to 4 warehouses. It is considering closing some plants to reduce
' costs. What plant(s) should the company close, in order to minimize
' transportation and fixed costs?
'
' Based on an example from Frontline Systems:
' http://www.solver.com/disfacility.htm
' Used with permission.
Imports System
Imports Gurobi
Class facility_vb
Shared Sub Main()
Try
' Warehouse demand in thousands of units
Dim Demand As Double() = New Double() {15, 18, 14, 20}
' Plant capacity in thousands of units
Dim Capacity As Double() = New Double() {20, 22, 17, 19, 18}
' Fixed costs for each plant
Dim FixedCosts As Double() = New Double() {12000, 15000, 17000, 13000, _
16000}
' Transportation costs per thousand units
Dim TransCosts As Double(,) = New Double(,) {{4000, 2000, 3000, 2500, 4500}, _
{2500, 2600, 3400, 3000, 4000}, _
{1200, 1800, 2600, 4100, 3000}, _
{2200, 2600, 3100, 3700, 3200}}
' Number of plants and warehouses
Dim nPlants As Integer = Capacity.Length
Dim nWarehouses As Integer = Demand.Length
' Model
Dim env As New GRBEnv()
Dim model As New GRBModel(env)
model.ModelName = "facility"
' Plant open decision variables: open(p) == 1 if plant p is open.
Dim open As GRBVar() = New GRBVar(nPlants - 1) {}
For p As Integer = 0 To nPlants - 1
open(p) = model.AddVar(0, 1, FixedCosts(p), GRB.BINARY, "Open" & p)
Next
' Transportation decision variables: how much to transport from
' a plant p to a warehouse w
Dim transport As GRBVar(,) = New GRBVar(nWarehouses - 1, nPlants - 1) {}
For w As Integer = 0 To nWarehouses - 1
For p As Integer = 0 To nPlants - 1
transport(w, p) = model.AddVar(0, GRB.INFINITY, _
TransCosts(w, p), GRB.CONTINUOUS, _
"Trans" & p & "." & w)
Next
Next
' The objective is to minimize the total fixed and variable costs
model.ModelSense = GRB.MINIMIZE
' Production constraints
' Note that the right-hand limit sets the production to zero if
' the plant is closed
For p As Integer = 0 To nPlants - 1
Dim ptot As GRBLinExpr = 0
For w As Integer = 0 To nWarehouses - 1
ptot.AddTerm(1.0, transport(w, p))
Next
model.AddConstr(ptot <= Capacity(p) * open(p), "Capacity" & p)
Next
' Demand constraints
For w As Integer = 0 To nWarehouses - 1
Dim dtot As GRBLinExpr = 0
For p As Integer = 0 To nPlants - 1
dtot.AddTerm(1.0, transport(w, p))
Next
model.AddConstr(dtot = Demand(w), "Demand" & w)
Next
' Guess at the starting point: close the plant with the highest
' fixed costs; open all others
' First, open all plants
For p As Integer = 0 To nPlants - 1
open(p).Start = 1.0
Next
' Now close the plant with the highest fixed cost
Console.WriteLine("Initial guess:")
Dim maxFixed As Double = -GRB.INFINITY
For p As Integer = 0 To nPlants - 1
If FixedCosts(p) > maxFixed Then
maxFixed = FixedCosts(p)
End If
Next
For p As Integer = 0 To nPlants - 1
If FixedCosts(p) = maxFixed Then
open(p).Start = 0.0
Console.WriteLine("Closing plant " & p & vbLf)
Exit For
End If
Next
' Use barrier to solve root relaxation
model.Parameters.Method = GRB.METHOD_BARRIER
' Solve
model.Optimize()
' Print solution
Console.WriteLine(vbLf & "TOTAL COSTS: " & model.ObjVal)
Console.WriteLine("SOLUTION:")
For p As Integer = 0 To nPlants - 1
If open(p).X > 0.99 Then
Console.WriteLine("Plant " & p & " open:")
For w As Integer = 0 To nWarehouses - 1
If transport(w, p).X > 0.0001 Then
Console.WriteLine(" Transport " & _
transport(w, p).X & _
" units to warehouse " & w)
End If
Next
Else
Console.WriteLine("Plant " & p & " closed!")
End If
Next
' Dispose of model and env
model.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
End Try
End Sub
End Class