【问题标题】:OR Tools - VRP - Handling cases where no optimal solution can be found或工具 - VRP - 处理无法找到最佳解决方案的案例
【发布时间】:2020-08-13 09:57:18
【问题描述】:

我正在基于 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;
} 

附:如果有人可以帮助我了解“Slack”的实际用途,我将不胜感激。我最初假设它是每辆车的容差(即 10 公里的松弛允许该车辆在其最大路线距离上行驶 10 公里)。但现在我不确定

【问题讨论】:

  • Slack 是为司机准备的,因此司机不会违反交通规则,司机的工作时间不会超过允许的时间或考虑天气条件。
  • 谢谢!那么你将如何使用它呢?我想那么我在这里错误地使用了 Slack?你如何解释公差?
  • 这种情况下的公差是多少?公差是为了确保司机在不违反任何规则或规定的情况下到达目的地。
  • Slack 是指货物可能需要多长时间/多短的时间,这些因素包括:天气、卡车抛锚、上一站装载/卸载需要很长时间。
  • 通常模型有两个维度,一个是距离,一个是时间。沿着路径,每个节点都与一个累积变量相关联。公式为cumul(next(I)) = cumul(I) + transit(I, next(I)) + slack(I)。对于距离,slack 很可能总是 0。对于时间,它可以不为零,然后它对应于节点之前的等待时间。

标签: c# or-tools


【解决方案1】:

如果您的位置在 600 公里,最大允许距离为 500 公里,那么您的问题基本上是不可行的......

但是您可以允许求解器使用 AddDisjunction() 删除此位置,从而使您的问题可行...

请查看文档站点上的示例:https://developers.google.com/optimization/routing/penalties

【讨论】:

  • 谢谢,这很好用。您对如何推导出罚分有任何指导吗?
猜你喜欢
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
  • 2011-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-11
相关资源
最近更新 更多