Files
discrete-optimization-coursera/warehouse/warehouse/MIPSolver.cs
T
2025-08-03 20:24:38 -07:00

104 lines
3.0 KiB
C#

using System;
using System.Collections.Generic;
using Google.OrTools.LinearSolver;
namespace warehouse
{
public class MIPSolver
{
private readonly Warehouse _data;
private TimeSpan _timeLimit;
public MIPSolver(Warehouse data, TimeSpan timeLimit)
{
_timeLimit = timeLimit;
_data = data;
}
public Tuple<double, Assignment> Solve()
{
//"GLPK_MIXED_INTEGER_PROGRAMMING"
//"CBC_MIXED_INTEGER_PROGRAMMING"
//"SCIP_MIXED_INTEGER_PROGRAMMING"
var solver = Solver.CreateSolver("IntegerProgramming", "CBC_MIXED_INTEGER_PROGRAMMING");
// decision variables
var warehouses = new Variable[_data.WarehouseCount];
var customerWarehouses = new Variable[_data.CustomerCount, _data.WarehouseCount];
for (var n = 0; n < _data.WarehouseCount; n++)
{
warehouses[n] = solver.MakeIntVar(0.0, 1.0, "w" + n);
for (var m = 0; m < _data.CustomerCount; m++)
{
customerWarehouses[m, n] = solver.MakeIntVar(0.0, 1.0, "c" + m + "w" + n);
}
}
// minimize cost
solver.SetMinimization();
for (var n = 0; n < _data.WarehouseCount; n++)
{
solver.SetObjectiveCoefficient(warehouses[n], _data.WarehouseSetupCost(n));
for (var m = 0; m < _data.CustomerCount; m++)
{
solver.SetObjectiveCoefficient(customerWarehouses[m, n], _data.CustomerWarehouseCost(m, n));
}
}
// warehouses are on which have at least one customer
for (var n = 0; n < _data.WarehouseCount; n++)
{
for (var m = 0; m < _data.CustomerCount; m++)
{
solver.Add(customerWarehouses[m, n] <= warehouses[n]);
}
}
// customers must have exactly one warehouse
var customerOneWarehouseConstraints = new Constraint[_data.CustomerCount];
for (var m = 0; m < _data.CustomerCount; m++)
{
var customerOneWarehouseConstraint = solver.MakeConstraint(1, 1, "customerServedByOneWarehouse" + m);
customerOneWarehouseConstraints[m] = customerOneWarehouseConstraint;
for (var n = 0; n < _data.WarehouseCount; n++)
{
customerOneWarehouseConstraint.SetCoefficient(customerWarehouses[m, n], 1);
}
}
// capacity constraint
var capacityConstraints = new Constraint[_data.WarehouseCount];
for (var n = 0; n < _data.WarehouseCount; n++)
{
var capacityConstraint = solver.MakeConstraint(0, _data.WarehouseCapacity(n), "cap" + n);
capacityConstraints[n] = capacityConstraint;
for (var m = 0; m < _data.CustomerCount; m++)
{
capacityConstraint.SetCoefficient(customerWarehouses[m, n], _data.CustomerDemand(m));
}
}
//solver.EnableOutput();
solver.SetTimeLimit(Convert.ToInt64(_timeLimit.TotalMilliseconds));
solver.Solve();
var objectiveValue = solver.ObjectiveValue();
var assignments = new List<int>();
for (var m = 0; m < _data.CustomerCount; m++)
{
for (var n = 0; n < _data.WarehouseCount; n++)
{
if (customerWarehouses[m, n].SolutionValue() > 0)
{
assignments.Add(n);
}
}
}
return Tuple.Create(objectiveValue, new Assignment(assignments.ToArray()));
}
}
}