Facility Examples#
This section includes source code for all of the Gurobi facility examples.
The same source code can be found in the examples
directory of the
Gurobi distribution.
/* Copyright 2024, 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "gurobi_c.h"
#define opencol(p) p
#define transportcol(w,p) nPlants*(w+1)+p
#define MAXSTR 128
int
main(int argc,
char *argv[])
{
GRBenv *env = NULL;
GRBmodel *model = NULL;
int error = 0;
int p, w, col;
int *cbeg = NULL;
int *cind = NULL;
int idx, rowct;
double *cval = NULL;
double *rhs = NULL;
char *sense = NULL;
char vname[MAXSTR];
int cnamect = 0;
char **cname = NULL;
double maxFixed = -GRB_INFINITY, sol, obj;
/* Number of plants and warehouses */
const int nPlants = 5;
const int nWarehouses = 4;
/* Warehouse demand in thousands of units */
double Demand[] = { 15, 18, 14, 20 };
/* Plant capacity in thousands of units */
double Capacity[] = { 20, 22, 17, 19, 18 };
/* Fixed costs for each plant */
double FixedCosts[] =
{ 12000, 15000, 17000, 13000, 16000 };
/* Transportation costs per thousand units */
double TransCosts[4][5] = {
{ 4000, 2000, 3000, 2500, 4500 },
{ 2500, 2600, 3400, 3000, 4000 },
{ 1200, 1800, 2600, 4100, 3000 },
{ 2200, 2600, 3100, 3700, 3200 }
};
/* Create environment */
error = GRBloadenv(&env, "facility.log");
if (error) goto QUIT;
/* Create initial model */
error = GRBnewmodel(env, &model, "facility", nPlants * (nWarehouses + 1),
NULL, NULL, NULL, NULL, NULL);
if (error) goto QUIT;
/* Initialize decision variables for plant open variables */
for (p = 0; p < nPlants; ++p)
{
col = opencol(p);
error = GRBsetcharattrelement(model, "VType", col, GRB_BINARY);
if (error) goto QUIT;
error = GRBsetdblattrelement(model, "Obj", col, FixedCosts[p]);
if (error) goto QUIT;
sprintf(vname, "Open%i", p);
error = GRBsetstrattrelement(model, "VarName", col, vname);
if (error) goto QUIT;
}
/* Initialize decision variables for transportation decision variables:
how much to transport from a plant p to a warehouse w */
for (w = 0; w < nWarehouses; ++w)
{
for (p = 0; p < nPlants; ++p)
{
col = transportcol(w, p);
error = GRBsetdblattrelement(model, "Obj", col, TransCosts[w][p]);
if (error) goto QUIT;
sprintf(vname, "Trans%i.%i", p, w);
error = GRBsetstrattrelement(model, "VarName", col, vname);
if (error) goto QUIT;
}
}
/* The objective is to minimize the total fixed and variable costs */
error = GRBsetintattr(model, "ModelSense", GRB_MINIMIZE);
if (error) goto QUIT;
/* Make space for constraint data */
rowct = (nPlants > nWarehouses) ? nPlants : nWarehouses;
cbeg = malloc(sizeof(int) * rowct);
if (!cbeg) goto QUIT;
cind = malloc(sizeof(int) * (nPlants * (nWarehouses + 1)));
if (!cind) goto QUIT;
cval = malloc(sizeof(double) * (nPlants * (nWarehouses + 1)));
if (!cval) goto QUIT;
rhs = malloc(sizeof(double) * rowct);
if (!rhs) goto QUIT;
sense = malloc(sizeof(char) * rowct);
if (!sense) goto QUIT;
cname = calloc(rowct, sizeof(char*));
if (!cname) goto QUIT;
/* Production constraints
Note that the limit sets the production to zero if
the plant is closed */
idx = 0;
for (p = 0; p < nPlants; ++p)
{
cbeg[p] = idx;
rhs[p] = 0.0;
sense[p] = GRB_LESS_EQUAL;
cname[p] = malloc(sizeof(char) * MAXSTR);
if (!cname[p]) goto QUIT;
cnamect++;
sprintf(cname[p], "Capacity%i", p);
for (w = 0; w < nWarehouses; ++w)
{
cind[idx] = transportcol(w, p);
cval[idx++] = 1.0;
}
cind[idx] = opencol(p);
cval[idx++] = -Capacity[p];
}
error = GRBaddconstrs(model, nPlants, idx, cbeg, cind, cval, sense,
rhs, cname);
if (error) goto QUIT;
/* Demand constraints */
idx = 0;
for (w = 0; w < nWarehouses; ++w)
{
cbeg[w] = idx;
sense[w] = GRB_EQUAL;
sprintf(cname[w], "Demand%i", w);
for (p = 0; p < nPlants; ++p)
{
cind[idx] = transportcol(w, p);
cval[idx++] = 1.0;
}
}
error = GRBaddconstrs(model, nWarehouses, idx, cbeg, cind, cval, sense,
Demand, cname);
if (error) goto QUIT;
/* Guess at the starting point: close the plant with the highest
fixed costs; open all others */
/* First, open all plants */
for (p = 0; p < nPlants; ++p)
{
error = GRBsetdblattrelement(model, "Start", opencol(p), 1.0);
if (error) goto QUIT;
}
/* Now close the plant with the highest fixed cost */
printf("Initial guess:\n");
for (p = 0; p < nPlants; ++p)
{
if (FixedCosts[p] > maxFixed)
{
maxFixed = FixedCosts[p];
}
}
for (p = 0; p < nPlants; ++p)
{
if (FixedCosts[p] == maxFixed)
{
error = GRBsetdblattrelement(model, "Start", opencol(p), 0.0);
if (error) goto QUIT;
printf("Closing plant %i\n\n", p);
break;
}
}
/* Use barrier to solve root relaxation */
error = GRBsetintparam(GRBgetenv(model),
GRB_INT_PAR_METHOD,
GRB_METHOD_BARRIER);
if (error) goto QUIT;
/* Solve */
error = GRBoptimize(model);
if (error) goto QUIT;
/* Print solution */
error = GRBgetdblattr(model, "ObjVal", &obj);
if (error) goto QUIT;
printf("\nTOTAL COSTS: %f\n", obj);
printf("SOLUTION:\n");
for (p = 0; p < nPlants; ++p)
{
error = GRBgetdblattrelement(model, "X", opencol(p), &sol);
if (error) goto QUIT;
if (sol > 0.99)
{
printf("Plant %i open:\n", p);
for (w = 0; w < nWarehouses; ++w)
{
error = GRBgetdblattrelement(model, "X", transportcol(w, p), &sol);
if (error) goto QUIT;
if (sol > 0.0001)
{
printf(" Transport %f units to warehouse %i\n", sol, w);
}
}
}
else
{
printf("Plant %i closed!\n", p);
}
}
QUIT:
/* Error reporting */
if (error)
{
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free data */
free(cbeg);
free(cind);
free(cval);
free(rhs);
free(sense);
for (p = 0; p < cnamect; ++p) {
free(cname[p]);
}
free(cname);
/* Free model */
GRBfreemodel(model);
/* Free environment */
GRBfreeenv(env);
return 0;
}
/* Copyright 2024, 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.
*/
#include "gurobi_c++.h"
#include <sstream>
using namespace std;
int
main(int argc,
char *argv[])
{
GRBEnv* env = 0;
GRBVar* open = 0;
GRBVar** transport = 0;
int transportCt = 0;
try
{
// Number of plants and warehouses
const int nPlants = 5;
const int nWarehouses = 4;
// Warehouse demand in thousands of units
double Demand[] = { 15, 18, 14, 20 };
// Plant capacity in thousands of units
double Capacity[] = { 20, 22, 17, 19, 18 };
// Fixed costs for each plant
double FixedCosts[] =
{ 12000, 15000, 17000, 13000, 16000 };
// Transportation costs per thousand units
double TransCosts[][nPlants] = {
{ 4000, 2000, 3000, 2500, 4500 },
{ 2500, 2600, 3400, 3000, 4000 },
{ 1200, 1800, 2600, 4100, 3000 },
{ 2200, 2600, 3100, 3700, 3200 }
};
// Model
env = new GRBEnv();
GRBModel model = GRBModel(*env);
model.set(GRB_StringAttr_ModelName, "facility");
// Plant open decision variables: open[p] == 1 if plant p is open.
open = model.addVars(nPlants, GRB_BINARY);
int p;
for (p = 0; p < nPlants; ++p)
{
ostringstream vname;
vname << "Open" << p;
open[p].set(GRB_DoubleAttr_Obj, FixedCosts[p]);
open[p].set(GRB_StringAttr_VarName, vname.str());
}
// Transportation decision variables: how much to transport from
// a plant p to a warehouse w
transport = new GRBVar* [nWarehouses];
int w;
for (w = 0; w < nWarehouses; ++w)
{
transport[w] = model.addVars(nPlants);
transportCt++;
for (p = 0; p < nPlants; ++p)
{
ostringstream vname;
vname << "Trans" << p << "." << w;
transport[w][p].set(GRB_DoubleAttr_Obj, TransCosts[w][p]);
transport[w][p].set(GRB_StringAttr_VarName, vname.str());
}
}
// The objective is to minimize the total fixed and variable costs
model.set(GRB_IntAttr_ModelSense, GRB_MINIMIZE);
// Production constraints
// Note that the right-hand limit sets the production to zero if
// the plant is closed
for (p = 0; p < nPlants; ++p)
{
GRBLinExpr ptot = 0;
for (w = 0; w < nWarehouses; ++w)
{
ptot += transport[w][p];
}
ostringstream cname;
cname << "Capacity" << p;
model.addConstr(ptot <= Capacity[p] * open[p], cname.str());
}
// Demand constraints
for (w = 0; w < nWarehouses; ++w)
{
GRBLinExpr dtot = 0;
for (p = 0; p < nPlants; ++p)
{
dtot += transport[w][p];
}
ostringstream cname;
cname << "Demand" << w;
model.addConstr(dtot == Demand[w], cname.str());
}
// Guess at the starting point: close the plant with the highest
// fixed costs; open all others
// First, open all plants
for (p = 0; p < nPlants; ++p)
{
open[p].set(GRB_DoubleAttr_Start, 1.0);
}
// Now close the plant with the highest fixed cost
cout << "Initial guess:" << endl;
double maxFixed = -GRB_INFINITY;
for (p = 0; p < nPlants; ++p)
{
if (FixedCosts[p] > maxFixed)
{
maxFixed = FixedCosts[p];
}
}
for (p = 0; p < nPlants; ++p)
{
if (FixedCosts[p] == maxFixed)
{
open[p].set(GRB_DoubleAttr_Start, 0.0);
cout << "Closing plant " << p << endl << endl;
break;
}
}
// Use barrier to solve root relaxation
model.set(GRB_IntParam_Method, GRB_METHOD_BARRIER);
// Solve
model.optimize();
// Print solution
cout << "\nTOTAL COSTS: " << model.get(GRB_DoubleAttr_ObjVal) << endl;
cout << "SOLUTION:" << endl;
for (p = 0; p < nPlants; ++p)
{
if (open[p].get(GRB_DoubleAttr_X) > 0.99)
{
cout << "Plant " << p << " open:" << endl;
for (w = 0; w < nWarehouses; ++w)
{
if (transport[w][p].get(GRB_DoubleAttr_X) > 0.0001)
{
cout << " Transport " <<
transport[w][p].get(GRB_DoubleAttr_X) <<
" units to warehouse " << w << endl;
}
}
}
else
{
cout << "Plant " << p << " closed!" << endl;
}
}
}
catch (GRBException e)
{
cout << "Error code = " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
}
catch (...)
{
cout << "Exception during optimization" << endl;
}
delete[] open;
for (int i = 0; i < transportCt; ++i) {
delete[] transport[i];
}
delete[] transport;
delete env;
return 0;
}
/* Copyright 2024, 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.
*/
using System;
using Gurobi;
class facility_cs
{
static void Main()
{
try {
// Warehouse demand in thousands of units
double[] Demand = new double[] { 15, 18, 14, 20 };
// Plant capacity in thousands of units
double[] Capacity = new double[] { 20, 22, 17, 19, 18 };
// Fixed costs for each plant
double[] FixedCosts =
new double[] { 12000, 15000, 17000, 13000, 16000 };
// Transportation costs per thousand units
double[,] TransCosts =
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
int nPlants = Capacity.Length;
int nWarehouses = Demand.Length;
// Model
GRBEnv env = new GRBEnv();
GRBModel model = new GRBModel(env);
model.ModelName = "facility";
// Plant open decision variables: open[p] == 1 if plant p is open.
GRBVar[] open = new GRBVar[nPlants];
for (int p = 0; p < nPlants; ++p) {
open[p] = model.AddVar(0, 1, FixedCosts[p], GRB.BINARY, "Open" + p);
}
// Transportation decision variables: how much to transport from
// a plant p to a warehouse w
GRBVar[,] transport = new GRBVar[nWarehouses,nPlants];
for (int w = 0; w < nWarehouses; ++w) {
for (int p = 0; p < nPlants; ++p) {
transport[w,p] =
model.AddVar(0, GRB.INFINITY, TransCosts[w,p], GRB.CONTINUOUS,
"Trans" + p + "." + w);
}
}
// 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 (int p = 0; p < nPlants; ++p) {
GRBLinExpr ptot = 0.0;
for (int w = 0; w < nWarehouses; ++w)
ptot.AddTerm(1.0, transport[w,p]);
model.AddConstr(ptot <= Capacity[p] * open[p], "Capacity" + p);
}
// Demand constraints
for (int w = 0; w < nWarehouses; ++w) {
GRBLinExpr dtot = 0.0;
for (int p = 0; p < nPlants; ++p)
dtot.AddTerm(1.0, transport[w,p]);
model.AddConstr(dtot == Demand[w], "Demand" + w);
}
// Guess at the starting point: close the plant with the highest
// fixed costs; open all others
// First, open all plants
for (int p = 0; p < nPlants; ++p) {
open[p].Start = 1.0;
}
// Now close the plant with the highest fixed cost
Console.WriteLine("Initial guess:");
double maxFixed = -GRB.INFINITY;
for (int p = 0; p < nPlants; ++p) {
if (FixedCosts[p] > maxFixed) {
maxFixed = FixedCosts[p];
}
}
for (int p = 0; p < nPlants; ++p) {
if (FixedCosts[p] == maxFixed) {
open[p].Start = 0.0;
Console.WriteLine("Closing plant " + p + "\n");
break;
}
}
// Use barrier to solve root relaxation
model.Parameters.Method = GRB.METHOD_BARRIER;
// Solve
model.Optimize();
// Print solution
Console.WriteLine("\nTOTAL COSTS: " + model.ObjVal);
Console.WriteLine("SOLUTION:");
for (int p = 0; p < nPlants; ++p) {
if (open[p].X > 0.99) {
Console.WriteLine("Plant " + p + " open:");
for (int w = 0; w < nWarehouses; ++w) {
if (transport[w,p].X > 0.0001) {
Console.WriteLine(" Transport " +
transport[w,p].X + " units to warehouse " + w);
}
}
} else {
Console.WriteLine("Plant " + p + " closed!");
}
}
// Dispose of model and env
model.Dispose();
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
}
}
}
/* Copyright 2024, 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.
*/
import com.gurobi.gurobi.*;
public class Facility {
public static void main(String[] args) {
try {
// Warehouse demand in thousands of units
double Demand[] = new double[] { 15, 18, 14, 20 };
// Plant capacity in thousands of units
double Capacity[] = new double[] { 20, 22, 17, 19, 18 };
// Fixed costs for each plant
double FixedCosts[] =
new double[] { 12000, 15000, 17000, 13000, 16000 };
// Transportation costs per thousand units
double TransCosts[][] =
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
int nPlants = Capacity.length;
int nWarehouses = Demand.length;
// Model
GRBEnv env = new GRBEnv();
GRBModel model = new GRBModel(env);
model.set(GRB.StringAttr.ModelName, "facility");
// Plant open decision variables: open[p] == 1 if plant p is open.
GRBVar[] open = new GRBVar[nPlants];
for (int p = 0; p < nPlants; ++p) {
open[p] = model.addVar(0, 1, FixedCosts[p], GRB.BINARY, "Open" + p);
}
// Transportation decision variables: how much to transport from
// a plant p to a warehouse w
GRBVar[][] transport = new GRBVar[nWarehouses][nPlants];
for (int w = 0; w < nWarehouses; ++w) {
for (int p = 0; p < nPlants; ++p) {
transport[w][p] =
model.addVar(0, GRB.INFINITY, TransCosts[w][p], GRB.CONTINUOUS,
"Trans" + p + "." + w);
}
}
// The objective is to minimize the total fixed and variable costs
model.set(GRB.IntAttr.ModelSense, GRB.MINIMIZE);
// Production constraints
// Note that the right-hand limit sets the production to zero if
// the plant is closed
for (int p = 0; p < nPlants; ++p) {
GRBLinExpr ptot = new GRBLinExpr();
for (int w = 0; w < nWarehouses; ++w) {
ptot.addTerm(1.0, transport[w][p]);
}
GRBLinExpr limit = new GRBLinExpr();
limit.addTerm(Capacity[p], open[p]);
model.addConstr(ptot, GRB.LESS_EQUAL, limit, "Capacity" + p);
}
// Demand constraints
for (int w = 0; w < nWarehouses; ++w) {
GRBLinExpr dtot = new GRBLinExpr();
for (int p = 0; p < nPlants; ++p) {
dtot.addTerm(1.0, transport[w][p]);
}
model.addConstr(dtot, GRB.EQUAL, Demand[w], "Demand" + w);
}
// Guess at the starting point: close the plant with the highest
// fixed costs; open all others
// First, open all plants
for (int p = 0; p < nPlants; ++p) {
open[p].set(GRB.DoubleAttr.Start, 1.0);
}
// Now close the plant with the highest fixed cost
System.out.println("Initial guess:");
double maxFixed = -GRB.INFINITY;
for (int p = 0; p < nPlants; ++p) {
if (FixedCosts[p] > maxFixed) {
maxFixed = FixedCosts[p];
}
}
for (int p = 0; p < nPlants; ++p) {
if (FixedCosts[p] == maxFixed) {
open[p].set(GRB.DoubleAttr.Start, 0.0);
System.out.println("Closing plant " + p + "\n");
break;
}
}
// Use barrier to solve root relaxation
model.set(GRB.IntParam.Method, GRB.METHOD_BARRIER);
// Solve
model.optimize();
// Print solution
System.out.println("\nTOTAL COSTS: " + model.get(GRB.DoubleAttr.ObjVal));
System.out.println("SOLUTION:");
for (int p = 0; p < nPlants; ++p) {
if (open[p].get(GRB.DoubleAttr.X) > 0.99) {
System.out.println("Plant " + p + " open:");
for (int w = 0; w < nWarehouses; ++w) {
if (transport[w][p].get(GRB.DoubleAttr.X) > 0.0001) {
System.out.println(" Transport " +
transport[w][p].get(GRB.DoubleAttr.X) +
" units to warehouse " + w);
}
}
} else {
System.out.println("Plant " + p + " closed!");
}
}
// Dispose of model and environment
model.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
}
}
}
function facility()
% Copyright 2024, 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?
%
% Note that this example uses lists instead of dictionaries. Since
% it does not work with sparse data, lists are a reasonable option.
%
% Based on an example from Frontline Systems:
% http://www.solver.com/disfacility.htm
% Used with permission.
% define primitive data
nPlants = 5;
nWarehouses = 4;
% Warehouse demand in thousands of units
Demand = [15; 18; 14; 20];
% Plant capacity in thousands of units
Capacity = [20; 22; 17; 19; 18];
% Fixed costs for each plant
FixedCosts = [12000; 15000; 17000; 13000; 16000];
% Transportation costs per thousand units
TransCosts = [
4000; 2000; 3000; 2500; 4500;
2500; 2600; 3400; 3000; 4000;
1200; 1800; 2600; 4100; 3000;
2200; 2600; 3100; 3700; 3200];
% Index helper function
flowidx = @(w, p) nPlants * w + p;
% Build model
model.modelname = 'facility';
model.modelsense = 'min';
% Set data for variables
ncol = nPlants + nPlants * nWarehouses;
model.lb = zeros(ncol, 1);
model.ub = [ones(nPlants, 1); inf(nPlants * nWarehouses, 1)];
model.obj = [FixedCosts; TransCosts];
model.vtype = [repmat('B', nPlants, 1); repmat('C', nPlants * nWarehouses, 1)];
for p = 1:nPlants
model.varnames{p} = sprintf('Open%d', p);
end
for w = 1:nWarehouses
for p = 1:nPlants
v = flowidx(w, p);
model.varnames{v} = sprintf('Trans%d,%d', w, p);
end
end
% Set data for constraints and matrix
nrow = nPlants + nWarehouses;
model.A = sparse(nrow, ncol);
model.rhs = [zeros(nPlants, 1); Demand];
model.sense = [repmat('<', nPlants, 1); repmat('=', nWarehouses, 1)];
% Production constraints
for p = 1:nPlants
for w = 1:nWarehouses
model.A(p, p) = -Capacity(p);
model.A(p, flowidx(w, p)) = 1.0;
end
model.constrnames{p} = sprintf('Capacity%d', p);
end
% Demand constraints
for w = 1:nWarehouses
for p = 1:nPlants
model.A(nPlants+w, flowidx(w, p)) = 1.0;
end
model.constrnames{nPlants+w} = sprintf('Demand%d', w);
end
% Save model
gurobi_write(model,'facility_m.lp');
% Guess at the starting point: close the plant with the highest fixed
% costs; open all others first open all plants
model.start = [ones(nPlants, 1); inf(nPlants * nWarehouses, 1)];
[~, idx] = max(FixedCosts);
model.start(idx) = 0;
% Set parameters
params.method = 2;
% Optimize
res = gurobi(model, params);
% Print solution
if strcmp(res.status, 'OPTIMAL')
fprintf('\nTotal Costs: %g\n', res.objval);
fprintf('solution:\n');
for p = 1:nPlants
if res.x(p) > 0.99
fprintf('Plant %d open:\n', p);
end
for w = 1:nWarehouses
if res.x(flowidx(w, p)) > 0.0001
fprintf(' Transport %g units to warehouse %d\n', res.x(flowidx(w, p)), w);
end
end
end
else
fprintf('\n No solution\n');
end
end
#!/usr/bin/env python3.11
# Copyright 2024, 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?
#
# Note that this example uses lists instead of dictionaries. Since
# it does not work with sparse data, lists are a reasonable option.
#
# Based on an example from Frontline Systems:
# http://www.solver.com/disfacility.htm
# Used with permission.
import gurobipy as gp
from gurobipy import GRB
# Warehouse demand in thousands of units
demand = [15, 18, 14, 20]
# Plant capacity in thousands of units
capacity = [20, 22, 17, 19, 18]
# Fixed costs for each plant
fixedCosts = [12000, 15000, 17000, 13000, 16000]
# Transportation costs per thousand units
transCosts = [
[4000, 2000, 3000, 2500, 4500],
[2500, 2600, 3400, 3000, 4000],
[1200, 1800, 2600, 4100, 3000],
[2200, 2600, 3100, 3700, 3200],
]
# Range of plants and warehouses
plants = range(len(capacity))
warehouses = range(len(demand))
# Model
m = gp.Model("facility")
# Plant open decision variables: open[p] == 1 if plant p is open.
open = m.addVars(plants, vtype=GRB.BINARY, obj=fixedCosts, name="open")
# Transportation decision variables: transport[w,p] captures the
# optimal quantity to transport to warehouse w from plant p
transport = m.addVars(warehouses, plants, obj=transCosts, name="trans")
# You could use Python looping constructs and m.addVar() to create
# these decision variables instead. The following would be equivalent
# to the preceding two statements...
#
# open = []
# for p in plants:
# open.append(m.addVar(vtype=GRB.BINARY,
# obj=fixedCosts[p],
# name="open[%d]" % p))
#
# transport = []
# for w in warehouses:
# transport.append([])
# for p in plants:
# transport[w].append(m.addVar(obj=transCosts[w][p],
# name="trans[%d,%d]" % (w, p)))
# The objective is to minimize the total fixed and variable costs
m.ModelSense = GRB.MINIMIZE
# Production constraints
# Note that the right-hand limit sets the production to zero if the plant
# is closed
m.addConstrs(
(transport.sum("*", p) <= capacity[p] * open[p] for p in plants), "Capacity"
)
# Using Python looping constructs, the preceding would be...
#
# for p in plants:
# m.addConstr(sum(transport[w][p] for w in warehouses)
# <= capacity[p] * open[p], "Capacity[%d]" % p)
# Demand constraints
m.addConstrs((transport.sum(w) == demand[w] for w in warehouses), "Demand")
# ... and the preceding would be ...
# for w in warehouses:
# m.addConstr(sum(transport[w][p] for p in plants) == demand[w],
# "Demand[%d]" % w)
# Save model
m.write("facilityPY.lp")
# Guess at the starting point: close the plant with the highest fixed costs;
# open all others
# First open all plants
for p in plants:
open[p].Start = 1.0
# Now close the plant with the highest fixed cost
print("Initial guess:")
maxFixed = max(fixedCosts)
for p in plants:
if fixedCosts[p] == maxFixed:
open[p].Start = 0.0
print(f"Closing plant {p}")
break
print("")
# Use barrier to solve root relaxation
m.Params.Method = 2
# Solve
m.optimize()
# Print solution
print(f"\nTOTAL COSTS: {m.ObjVal:g}")
print("SOLUTION:")
for p in plants:
if open[p].X > 0.99:
print(f"Plant {p} open")
for w in warehouses:
if transport[w, p].X > 0:
print(f" Transport {transport[w, p].X:g} units to warehouse {w}")
else:
print(f"Plant {p} closed!")
# Copyright 2024, 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?
#
# Note that this example uses lists instead of dictionaries. Since
# it does not work with sparse data, lists are a reasonable option.
#
# Based on an example from Frontline Systems:
# http://www.solver.com/disfacility.htm
# Used with permission.
library(Matrix)
library(gurobi)
# define primitive data
nPlants <- 5
nWarehouses <- 4
# Warehouse demand in thousands of units
Demand <- c(15, 18, 14, 20)
# Plant capacity in thousands of units
Capacity <- c(20, 22, 17, 19, 18)
# Fixed costs for each plant
FixedCosts <- c( 12000, 15000, 17000, 13000, 16000)
# Transportation costs per thousand units
TransCosts <- c(4000, 2000, 3000, 2500, 4500,
2500, 2600, 3400, 3000, 4000,
1200, 1800, 2600, 4100, 3000,
2200, 2600, 3100, 3700, 3200 )
flowidx <- function(w, p) {nPlants * (w-1) + p}
# Build model
model <- list()
model$modelname <- 'facility'
model$modelsense <- 'min'
# initialize data for variables
model$lb <- 0
model$ub <- c(rep(1, nPlants), rep(Inf, nPlants * nWarehouses))
model$vtype <- c(rep('B', nPlants), rep('C', nPlants * nWarehouses))
model$obj <- c(FixedCosts, TransCosts)
model$varnames <- c(paste0(rep('Open',nPlants),1:nPlants),
sprintf('Trans%d,%d',
c(mapply(rep,1:nWarehouses,nPlants)),
1:nPlants))
# build production constraint matrix
A1 <- spMatrix(nPlants, nPlants, i = c(1:nPlants), j = (1:nPlants), x = -Capacity)
A2 <- spMatrix(nPlants, nPlants * nWarehouses,
i = c(mapply(rep, 1:nPlants, nWarehouses)),
j = mapply(flowidx,1:nWarehouses,c(mapply(rep,1:nPlants,nWarehouses))),
x = rep(1, nWarehouses * nPlants))
A3 <- spMatrix(nWarehouses, nPlants)
A4 <- spMatrix(nWarehouses, nPlants * nWarehouses,
i = c(mapply(rep, 1:nWarehouses, nPlants)),
j = mapply(flowidx,c(mapply(rep,1:nWarehouses,nPlants)),1:nPlants),
x = rep(1, nPlants * nWarehouses))
model$A <- rbind(cbind(A1, A2), cbind(A3, A4))
model$rhs <- c(rep(0, nPlants), Demand)
model$sense <- c(rep('<', nPlants), rep('=', nWarehouses))
model$constrnames <- c(sprintf('Capacity%d',1:nPlants),
sprintf('Demand%d',1:nWarehouses))
# Save model
gurobi_write(model,'facilityR.lp')
# Guess at the starting point: close the plant with the highest fixed
# costs; open all others first open all plants
model$start <- c(rep(1,nPlants),rep(NA, nPlants * nWarehouses))
# find most expensive plant, and close it in mipstart
cat('Initial guess:\n')
worstidx <- which.max(FixedCosts)
model$start[worstidx] <- 0
cat('Closing plant',worstidx,'\n')
# set parameters
params <- list()
params$method <- 2
# Optimize
res <- gurobi(model, params)
# Print solution
if (res$status == 'OPTIMAL') {
cat('\nTotal Costs:',res$objval,'\nsolution:\n')
cat('Facilities:', model$varnames[which(res$x[1:nPlants]>1e-5)], '\n')
active <- nPlants + which(res$x[(nPlants+1):(nPlants*(nWarehouses+1))] > 1e-5)
cat('Flows: ')
cat(sprintf('%s=%g ',model$varnames[active], res$x[active]), '\n')
rm(active)
} else {
cat('No solution\n')
}
# Clear space
rm(res, model, params, A1, A2, A3, A4)
' Copyright 2024, 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