Hide navigation sidebar
Hide table of contents sidebar
Back to top
Toggle table of contents sidebar

# facility.m

    function facility()

    % 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?
    %
    % 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

Help and Feedback

Press `/` or click to search this documentation | Gurobi website | Gurobi community forum
Go to other Gurobi documentation | Gurobi download | Contact support