【问题标题】:Google Or-Tools Vehicle Routing Problem - Solution is nullGoogle Or-Tools 车辆路线问题 - 解决方案为空
【发布时间】:2019-08-01 06:08:53
【问题描述】:

我无法弄清楚为什么解决方案对象总是为空。我正在尝试修改 Google OR-Tools Vehicle Routing Problem 的 C# 示例。该示例使用位置,我正在尝试使用距离矩阵。我的代码与 Python 示例非常相似,因此它应该可以工作。问题似乎出在 AddDistanceDimension 方法上。

using System;
using System.Collections.Generic;
using System.Text;
using Google.OrTools.ConstraintSolver;

namespace ConsoleApp1
{
    /// <summary>
    ///   This is a sample using the routing library .Net wrapper to solve a VRP problem.
    ///   A description of the problem can be found here:
    ///   http://en.wikipedia.org/wiki/Vehicle_routing_problem.
    /// </summary>
    class Program3
    {
        public class DataProblem
        {
            private int[,] distances_;

            // Constructor:
            public DataProblem()
            {
                distances_ = new int[,] {
                            { 0, 6177, 17282, 7866, 25029, 4511, 6120}, 
                            { 8469, 0, 9517, 1018, 17264, 6101, 615}, 
                            { 17504, 9865, 0, 10445, 9319, 15136, 10464}, 
                            { 7533, 1315, 9699, 0, 17446, 5165, 534}, 
                            { 25351, 17712, 10199, 18291, 0, 22983, 18310}, 
                            { 4993, 5221, 16381, 4620, 24128, 0, 4516}, 
                            { 5969, 958, 10309, 762, 18056, 4538, 0}
                    };
             }

            public int GetVehicleNumber() { return 4; }
            public ref readonly int[,] GetLocations() { return ref distances_; }
            public int GetLocationNumber() { return distances_.GetLength(0); }
            public int GetDepot() { return 0; }
        };


        public class DistanceMatrix : NodeEvaluator2
        {
            private int[,] distances;

            public DistanceMatrix(in DataProblem data)
            {
                distances = data.GetLocations();
            }

            public override long Run(int FromNode, int ToNode)
            {
                return distances[FromNode, ToNode];
            }
        };

        /// <summary>
        ///   Add distance Dimension
        /// </summary>
        static void AddDistanceDimension(in DataProblem data, in RoutingModel routing)
        {
            // public bool AddDimension(NodeEvaluator2 evaluator, long slack_max, long capacity, bool fix_start_cumul_to_zero, string name);
            // Returns false if a dimension with the same name has already been created (and doesn't create the new dimension).
            bool bResult = routing.AddDimension(
                new DistanceMatrix(data),
                0,  // null slack
                7000, // maximum distance per vehicle
                true, // start cumul to zero
                "Distance");
            Console.WriteLine("Was dimension dreated? " + bResult);
            RoutingDimension distanceDimension = routing.GetDimensionOrDie("Distance");
            // Try to minimize the max distance among vehicles.
            // /!\ It doesn't mean the standard deviation is minimized
            distanceDimension.SetGlobalSpanCostCoefficient(100);
        }

        /// <summary>
        ///   Print the solution
        /// </summary>
        static void PrintSolution(
            in DataProblem data,
            in RoutingModel routing,
            in Assignment solution)
        {
            Console.WriteLine("Objective: {0}", solution.ObjectiveValue());
            // Inspect solution.
            for (int i = 0; i < data.GetVehicleNumber(); ++i)
            {
                Console.WriteLine("Route for Vehicle " + i + ":");
                long distance = 0;
                var index = routing.Start(i);
                while (routing.IsEnd(index) == false)
                {
                    Console.Write("{0} -> ", routing.IndexToNode(index));
                    var previousIndex = index;
                    index = solution.Value(routing.NextVar(index));
                    distance += routing.GetArcCostForVehicle(previousIndex, index, i);
                }
                Console.WriteLine("{0}", routing.IndexToNode(index));
                Console.WriteLine("Distance of the route: {0}m", distance);
            }
            Console.ReadLine();
        }

        /// <summary>
        ///   Solves the current routing problem.
        /// </summary>
        static void Solve()
        {
            // Instantiate the data problem.
            DataProblem data = new DataProblem();

            // Create Routing Model
            RoutingModel routing = new RoutingModel(
                data.GetLocationNumber(),
                data.GetVehicleNumber(),
                data.GetDepot());

            // Debugging 
            Console.WriteLine("Number of locations: {0}", data.GetLocationNumber());
            Console.WriteLine("Number of vehicles: {0}", data.GetVehicleNumber());
            Console.WriteLine("Get depot: {0}", data.GetDepot());

            // Define weight cost of each edge
            NodeEvaluator2 distanceEvaluator = new DistanceMatrix(data);
            //protect callbacks from the GC
            GC.KeepAlive(distanceEvaluator);
            routing.SetArcCostEvaluatorOfAllVehicles(distanceEvaluator);
            AddDistanceDimension(data, routing);

            // Setting first solution heuristic (cheapest addition).
            RoutingSearchParameters searchParameters = RoutingModel.DefaultSearchParameters();
            searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathCheapestArc;

            Assignment solution = routing.SolveWithParameters(searchParameters);
            PrintSolution(data, routing, solution);
        }

        public static void Main(String[] args)
        {
            Solve();
        }
    }
}

【问题讨论】:

  • 您的 GC.KeepAlive(distanceEvaluator); 必须在 SolveWithParameter() 之后才能使对象保持活动状态。
  • 你的矩阵应该是 long[,] 回调必须返回一个 long...
  • 在master上我们有一个距离矩阵的例子,见github.com/google/or-tools/blob/master/ortools/…
  • 感谢 Mizux。您的建议帮助我解决了问题。我能够得到我期望的解决方案。它与我的 Python 输出相匹配。

标签: c# or-tools


【解决方案1】:

当您构建DistanceDimension 时,您将地平线设置为7000,而您的矩阵包含 25000、10000 等...

您确定您的数据正确吗?尝试增加视野(7000)...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-22
    • 2020-07-01
    • 2020-12-02
    • 2019-10-15
    • 2021-08-06
    • 2021-06-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多