1

VRP のいくつかの問題では、車両の総数を通知するときに、すべてが使用され、少なくともノードを訪問することが危うくなります。実際には、これが最善ではないかもしれませんが、ニーズに応じて適応する理由と方法を理解したいと思います。以下の例は、OR Tools による単純な VRP の例に関するもので、距離マトリックスの小さな編集と、ウェブサイト (ブログ) によるいくつかの変更があります - https://activimetrics.com/blog/ortools/counting_dimension/。後者によると、ルートの公平な分配を実行することが可能であり、これは非常に魅力的であると思われます。これは、原則として、ソルバーが最長のルートを最小化し、最終的に使用する車両の数を減らし、それにいくつかのノードを割り当てるためです。重要なニーズは、少なくとも 1 回は使用されるように、車両を機能させるアプローチを使用することでした。しかし、問題を解決するために 5 台の車両が使用された場合、得られたロジックと結果によって、彼はそこにたどり着き、車両ごとにノードを配置します。これは、このエディションなしでは不可能でした。問題は、4 台の車両しか使用していないため、ソルバーが存在せず、ルートを配布することはできますが、常に車両が除外されることです。

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

public class VrpGlobalSpan
{
    class DataModel
    {      
        public long[,] DistanceMatrix = {
        {0, 9777, 10050,7908,10867,16601},
        {9777, 0, 4763, 4855, 19567,31500},
        {10050, 4763,0,2622,11733,35989},
        {7908,4855,2622,0,10966,27877},
        {10867,19567,11733,10966,0,27795},
        {16601,31500,35989,27877,27795,0},
    };
        public int VehicleNumber = 4;
        public int Depot = 0;
    };

    /// <summary>
    ///   Print the solution.
    /// </summary>
    static void PrintSolution(
        in DataModel data,
        in RoutingModel routing,
        in RoutingIndexManager manager,
        in Assignment solution)
    {
        // Inspect solution.
        long maxRouteDistance = 0;
        for (int i = 0; i < data.VehicleNumber; ++i)
        {
            Console.WriteLine("Route for Vehicle {0}:", i);
            long routeDistance = 0;
            var index = routing.Start(i);
            while (routing.IsEnd(index) == false)
            {
                Console.Write("{0} -> ", manager.IndexToNode((int)index));
                var previousIndex = index;
                index = solution.Value(routing.NextVar(index));
                routeDistance += routing.GetArcCostForVehicle(previousIndex, index, 0);
            }
            Console.WriteLine("{0}", manager.IndexToNode((int)index));
            Console.WriteLine("Distance of the route: {0}m", routeDistance);
            maxRouteDistance = Math.Max(routeDistance, maxRouteDistance);
        }
        Console.WriteLine("Maximum distance of the routes: {0}m", maxRouteDistance);
    }

    public static void Main(String[] args)
    {
        // Instantiate the data problem.
        DataModel data = new DataModel();

        // Create Routing Index Manager
        RoutingIndexManager manager = new RoutingIndexManager(
            data.DistanceMatrix.GetLength(0),
            data.VehicleNumber,
            data.Depot);

        // Create Routing Model.
        RoutingModel routing = new RoutingModel(manager);

        // Create and register a transit callback.
        int transitCallbackIndex = routing.RegisterTransitCallback(
            (long fromIndex, long toIndex) => {
            // Convert from routing variable Index to distance matrix NodeIndex.
            var fromNode = manager.IndexToNode(fromIndex);
                var toNode = manager.IndexToNode(toIndex);
                return data.DistanceMatrix[fromNode, toNode];
            }
            );

        // Define cost of each arc.
        routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
        
        double answer = 5/data.VehicleNumber +1;
        //double Math.Ceiling(answer);
        //double floor = (int)Math.Ceiling(answer);
        routing.AddConstantDimension(
            1,
            (int)Math.Ceiling(answer),
            true,  // start cumul to zero
            "Distance") ;
        RoutingDimension distanceDimension = routing.GetDimensionOrDie("Distance");
        //distanceDimension.SetGlobalSpanCostCoefficient(100);
        for (int i = 0; i < data.VehicleNumber; ++i)
        {
            distanceDimension.SetCumulVarSoftLowerBound(routing.End(i), 2, 1000000);
        }
        // Setting first solution heuristic.
        RoutingSearchParameters searchParameters =
          operations_research_constraint_solver.DefaultRoutingSearchParameters();
        //searchParameters.FirstSolutionStrategy =
        //  FirstSolutionStrategy.Types.Value.PathCheapestArc;
        searchParameters.TimeLimit = new Google.Protobuf.WellKnownTypes.Duration { Seconds = 5 }; 
        searchParameters.LocalSearchMetaheuristic = LocalSearchMetaheuristic.Types.Value.Automatic;       

        // Solve the problem.
        Assignment solution = routing.SolveWithParameters(searchParameters);

        // Print solution on console.
        PrintSolution(data, routing, manager, solution);
    }
}

おそらく、それはすでに議論されたトピックだったに違いありませんが、私は、従うべき最善の道とは何か、この例や他の例をより良いアプローチで変換するためにどのような手段を取るべきかを理解し、理解したいと思っていました. ご清聴ありがとうございました。フィードバックをお待ちしております。ありがとうございました。

4

0 に答える 0