104 lines
3.0 KiB
C#
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()));
|
|
}
|
|
}
|
|
}
|