我正在基于Google的ORTools为车辆路径问题构建求解器。
对于简单的问题或大容量的问题,它可以很好地工作,但是对于大多数“真实”数据集,我最终都会获得无限期运行或超时的解决方案。
经过一些思考,我意识到并不是所有现实世界的问题都可以解决或达到最佳。例如。我可能希望大多数车辆每天行驶不超过500公里。但是,如果我必须将货物运送给600公里以外的人,则整个解决方案将失败。
如何处理这些情况?现在看来,这是二进制的通过或失败。对于某些情况被忽略或返回次优解决方案,我感到非常高兴。
这是我的解决方案的代码
public List<OptimisedVehicleRoute> Start(Location depot, List<Location> locations, int numVehicles = 1, float maxDistanceKmPerVehicle = 1000f, float maxDistanceKmSlack = 5f)
{
// Create Routing Index Manager
var depotIndex = locations.IndexOf(depot);
var manager = new RoutingIndexManager(locations.Count, numVehicles, depotIndex);
Console.WriteLine($"Depot at {depot.Postcode}");
var routing = new RoutingModel(manager);
var numCalls = 0l;
int transitCallbackIndex = routing.RegisterTransitCallback((long fromIndex, long toIndex) =>
{
numCalls++;
// Convert from routing variable Index to distance matrix NodeIndex.
var fromNode = manager.IndexToNode(fromIndex);
var toNode = manager.IndexToNode(toIndex);
var fromLocation = locations[fromNode];
var toLocation = locations[toNode];
var mDistance = fromLocation.DistanceTo(toLocation);
return mDistance;
});
// The arc cost evaluator tells the solver how to calculate the cost of travel between any two locations
routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
long maxVehicleDistanceSlack = (long)Math.Round(maxDistanceKmSlack * 1000); // slack per day
long maxVehicleDistance = (long)Math.Round(maxDistanceKmPerVehicle * 1000); // 1000km max distance per day
routing.AddDimension(transitCallbackIndex, maxVehicleDistanceSlack, maxVehicleDistance, true, "Distance");
RoutingDimension distanceDimension = routing.GetMutableDimension("Distance");
distanceDimension.SetGlobalSpanCostCoefficient(100);
var searchParameters = operations_research_constraint_solver.DefaultRoutingSearchParameters();
searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathCheapestArc;
var timer = new Stopwatch();
timer.Start();
searchParameters.LogSearch = true;
var solution = routing.SolveWithParameters(searchParameters);
timer.Stop();
Console.WriteLine(timer.Elapsed.TotalSeconds);
var optimisedVehicleRoutes = this.CreateOptimisedVehicleLocations(locations, numVehicles, routing, manager, solution);
this.OptimisedDistanceKm = optimisedVehicleRoutes.Sum(r => r.TotalDistanceKm);
routing.Dispose();
return optimisedVehicleRoutes;
}
P.s。如果有人可以帮助我了解“ Slack”实际上是用于什么的,我将不胜感激。我最初假设这是每辆车的公差(即10 km的松弛度可使该车辆在其最大路线距离上行驶10 km)。但是现在我不确定
答案 0 :(得分:1)
如果您的位置在600公里,最大允许距离为500公里,那么您的问题基本上是不可行的...
但是您可以使用AddDisjunction()
允许求解器放置该位置,从而使问题变得可行...
请在文档站点上查看我们的示例:https://developers.google.com/optimization/routing/penalties