| |||||||||||||||||||
| |||||||||||||||||||
|
Facility location problem - Data as collections Description Solve a facility location problem for which data is given as collections.
Source Files By clicking on a file name, a preview is opened at the bottom of this page.
FacilityLocationArray.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Optimizer;
using Optimizer.Objects;
using static Optimizer.Objects.Utils;
namespace XPRSexamples
{
/// <summary>This example demonstrates some modeling devices.</summary>
/// <remarks>
/// We model a very simple facility location problem: We have customers
/// and facilities. The constraints are:
/// - each customer must be served from exactly one facility
/// - customers can only be served from open facilities
/// - customer demand must be satisfied
/// - facility capacity must not be exceeded
///
/// We minimize the sum of transport cost (between customer and facility)
/// and the cost for opening a facility.
/// In this example data is kept in arrays.
/// </remarks>
internal class FacilityLocationArray
{
/// <summary>Customer description.</summary>
private sealed class Customer
{
/// <summary>Name of customer.</summary>
public readonly string Name;
/// <summary>Demand for 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>Name of facility.</summary>
public readonly string Name;
/// <summary>Capacity of 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>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>Facilities 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 customer and facility.</summary>
private static readonly double[][] transportCost = new double[][] { new double[] { 4, 5, 6 }, new double[] { 6, 4, 3 },
new double[] { 9, 7, 4 } };
public static void Main(string[] args)
{
using (XpressProblem prob = new XpressProblem())
{
Variable[] y = prob.AddVariables(facilities.Length)
.WithType(ColumnType.Binary)
.WithName(f => facilities[f].Name)
.ToArray();
Variable[,] x = prob.AddVariables(facilities.Length, customers.Length)
.WithUB(Double.PositiveInfinity)
.WithName((f, c) => $"x[{facilities[f].Name},{customers[c].Name}")
.ToArray();
// for each customer c
// sum(f=1..m) x[f,c] = d
prob.AddConstraints(customers.Length, c => Sum(facilities.Length, f => x[f, c]) == customers[c].Demand);
// for each facility f
// sum(c=1..n) x[f,c] <= capacity[j] * y[f]
prob.AddConstraints(facilities.Length, f => Sum(customers.Length, c => x[f, c]) <= y[f] * facilities[f].Capacity);
// minimize sum(f=1..m) cost[f] * y[f] +
// sum(c=1..n) sum(f=1..m) cost[f,c] * x[f,c]
prob.SetObjective(Sum(Sum(facilities.Length, f => y[f] * facilities[f].Cost),
Sum(customers.Length, c => Sum(facilities.Length, f => x[f, c] * transportCost[f][c]))));
prob.WriteProb("facilitylocationarray.lp");
prob.Optimize();
if (prob.SolStatus != SolStatus.Optimal)
throw new Exception($"failed to optimize with status {prob.SolStatus}");
double[] sol = prob.GetSolution();
for (int f = 0; f < facilities.Length; ++f)
{
if (y[f].GetValue(sol) > 0.5)
{
Console.WriteLine($"Facility {facilities[f].Name} is open, serves");
for (int c = 0; c < customers.Length; ++c)
{
if (x[f, c].GetValue(sol) > 0.0)
Console.WriteLine($" {customers[c].Name}: {x[f, c].GetValue(sol)}");
}
}
}
}
}
}
}
| |||||||||||||||||||
| © Copyright 2025 Fair Isaac Corporation. |