FICO
FICO Xpress Optimization Examples Repository
FICO Optimization Community FICO Xpress Optimization Home
Back to examples browserPrevious exampleNext example

Facility location problem - Data as collections

Description
Solve a facility location problem for which data is given as collections.

facloc_dnet.zip[download all files]

Source Files
By clicking on a file name, a preview is opened at the bottom of this page.
FacilityLocationCollection.cs[download]
FacilityLocationCollection.csproj[download]





FacilityLocationCollection.cs

// (c) 2023-2024 Fair Isaac Corporation

using System;
using System.Linq;
using Optimizer;
using static Optimizer.Objects.Utils;
using Variable = Optimizer.Objects.Variable;
using XpressProblem = Optimizer.Objects.XpressProblem;
using Optimizer.Maps;
using System.Collections.Generic;

namespace XPRSexamples
{
    /// <summary>Solve a facility location problem for which data is given as collections.</summary>
    public class FacilityLocationCollection
    {
        /// <summary>Customer descriptor.</summary>
        private sealed class Customer
        {
            /// <summary>Customer name.</summary>
            public readonly String name;
            /// <summary>Demand for this customer.</summary>
            public readonly double demand;
            public Customer(String name, double demand)
            {
                this.demand = demand;
                this.name = name;
            }
        }

        /// <summary>Facility descriptor.</summary>
        private sealed class Facility
        {
            /// <summary>Facility name.</summary>
            public readonly String name;
            /// <summary>Capacity of this facility.</summary>
            public readonly double capacity;
            /// <summary>Cost for opening this facility.</summary>
            public readonly double cost;
            public Facility(String name, double capacity, double cost)
            {
                this.name = name;
                this.capacity = capacity;
                this.cost = cost;
            }
        }

        /// <summary>The customers in this example.</summary>
        private static readonly Customer[] customers = new Customer[]{
            new Customer("Customer 1", 80),
            new Customer("Customer 2", 270),
            new Customer("Customer 3", 250)
        };
        /// <summary>The facilityies in this example.</summary>
        private static readonly Facility[] facilities = new Facility[]{
            new Facility("Facility 1", 500, 1000),
            new Facility("Facility 2", 500, 1000),
            new Facility("Facility 3", 500, 1000)
        };

        /// <summary>Cost for transporting one unit between a customer and a facility.</summary>
        private static readonly HashMap2<Facility, Customer, double> transportCost = new HashMap2<Facility, Customer, double>();
        static FacilityLocationCollection()
        {
            transportCost.Add(facilities[0], customers[0], 4.0);
            transportCost.Add(facilities[0], customers[1], 5.0);
            transportCost.Add(facilities[0], customers[2], 6.0);
            transportCost.Add(facilities[1], customers[0], 6.0);
            transportCost.Add(facilities[1], customers[1], 4.0);
            transportCost.Add(facilities[1], customers[2], 3.0);
            transportCost.Add(facilities[2], customers[0], 9.0);
            transportCost.Add(facilities[2], customers[1], 7.0);
            transportCost.Add(facilities[2], customers[2], 4.0);
        }

        public static void Main(String[] args)
        {
            using (XpressProblem prob = new XpressProblem())
            {
                // Create a 1-dimensional map of y variables, indexed by Facility instances.
                var y = prob.AddVariables(facilities)
                            .WithType(ColumnType.Binary)
                            .WithName(f => f.name)
                            .ToMap();
                // Create a 2-dimensional map of x variables, indexed by (Facility,Customer) pairs
                var x = prob.AddVariables(facilities, customers)
                            .WithType(ColumnType.Binary)
                            .WithName((f, c) => String.Format("x[{0},{1}]", f.name, c.name))
                            .ToMap();

                // for each customer c
                //    sum(f=1..m) x[f,c] = d
                prob.AddConstraints(customers,
                    c => Sum(facilities, (Facility f) => x[f, c]).Eq(c.demand)
                    );

                // for each facility f
                //    sum(c=1..n) x[f,c] <= capacity[j] * y[f]
                prob.AddConstraints(facilities,
                    f => Sum(customers, (Customer c) => x[f, c]).Leq(y[f] * f.capacity)
                    );

                // minimize sum(j=1..m) cost[j] * y[j] +
                //          sum(i=1..n) sum(j=1..m) cost[f,c] * x[f,c]
                prob.SetObjective(Sum(Sum(facilities, (Facility f) => y[f] * f.cost),
                                      Sum(customers,
                                          (Customer c) => Sum(facilities, (Facility f) => x[f, c] * transportCost[f, c]))));


                prob.WriteProb("facilitylocationcollection.lp", "l");

                prob.Optimize("");
                double[] sol = prob.GetSolution();
                foreach (var f in facilities)
                {
                    if (y[f].GetValue(sol) > 0.5)
                    {
                        Console.WriteLine("Facility " + f.name + " is open, serves");
                        foreach (var c in customers)
                        {
                            if (x[f, c].GetValue(sol) > 0.0)
                                Console.WriteLine("  " + c.name + ": " +
                                                   x[f, c].GetValue(sol));
                        }
                    }
                }
            }
        }
    }
}

Back to examples browserPrevious exampleNext example