google / or-tools

Google's Operations Research tools:
https://developers.google.com/optimization/
Apache License 2.0
11.27k stars 2.13k forks source link

TSP with pickups and deliveries: Error when upgrading to version ^7.1 #1302

Closed conorato closed 5 years ago

conorato commented 5 years ago

When upgrading from v 7.0.6546 to v 7.1.6720, I am getting a System.AccessViolationException when trying to solve a problem that has a node marked as a pickup and as a delivery. The same code works fine in v 7.0, and both packages are from NuGet.

The model is the same as the one presented in the Vehicle Routing with Pickups and Deliveries guide, and the data is:

public long[,] DistanceMatrix =
{     
    { 0,   100, 100,  80, 100 },      
    { 100,   0, 80,  100, 100 },     
    { 100, 100, 0,   100,  80 },  
    { 100,  80, 100,   0, 100 },  
    { 100, 100, 100, 100,   0 },  
};  
public int[][] PickupsDeliveries =
{
    new int[] {1, 2},
    new int[] {3, 4},
    new int[] {4, 1},
};

The same error occurs when I set the PickupsDeliveries this way:

public int[][] PickupsDeliveries =
{
    new int[] {1, 2},
    new int[] {2, 3},
    new int[] {3, 4},
};

Here's the full code:

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

/// <summary>
///   Minimal Pickup & Delivery Problem (PDP).
/// </summary>
public class VrpPickupDelivery
{
    class DataModel
    {
        public long[, ] DistanceMatrix = {
            { 0, 100, 100, 80, 100 },
            { 100, 0, 80, 100, 100 },
            { 100, 100, 0, 100, 80 },
            { 100, 80, 100, 0, 100 },
            { 100, 100, 100, 100, 0 },
        };
        public int[][] PickupsDeliveries = {
            new int[] { 1, 2 },
            new int[] { 3, 4 },
            new int[] { 4, 1 },
        };

        //public int[][] PickupsDeliveries = {
        //   new int[] {1, 2},
        //   new int[] {2, 3},
        //   new int[] {3, 4},
        // };

        public int VehicleNumber = 1;
        public int Depot = 0;
    };

    /// <summary>
    ///   Print the solution.
    /// </summary>
    static void PrintSolution(in DataModel data, in RoutingModel routing, in RoutingIndexManager manager, in Assignment solution)
    {
        long totalDistance = 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);
            totalDistance += routeDistance;
        }
        Console.WriteLine("Total Distance of all routes: {0}m", totalDistance);
    }

    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);

        // Add Distance constraint.
        routing.AddDimension(
            transitCallbackIndex,
            0,
            3000,
            true, // start cumul to zero
            "Distance");
        RoutingDimension distanceDimension = routing.GetMutableDimension("Distance");
        distanceDimension.SetGlobalSpanCostCoefficient(100);

        // Define Transportation Requests.
        Solver solver = routing.solver();
        for (int i = 0; i < data.PickupsDeliveries.GetLength(0); i++)
        {
            long pickupIndex = manager.NodeToIndex(data.PickupsDeliveries[i][0]);
            long deliveryIndex = manager.NodeToIndex(data.PickupsDeliveries[i][1]);
            routing.AddPickupAndDelivery(pickupIndex, deliveryIndex);
            solver.Add(solver.MakeEquality(
                routing.VehicleVar(pickupIndex),
                routing.VehicleVar(deliveryIndex)));
            solver.Add(solver.MakeLessOrEqual(
                distanceDimension.CumulVar(pickupIndex),
                distanceDimension.CumulVar(deliveryIndex)));
        }

        // Setting first solution heuristic.
        RoutingSearchParameters searchParameters =
            operations_research_constraint_solver.DefaultRoutingSearchParameters();
        searchParameters.FirstSolutionStrategy =
            FirstSolutionStrategy.Types.Value.PathCheapestArc;

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

        // Print solution on console.
        PrintSolution(data, routing, manager, solution);
    }
}
Mizux commented 5 years ago

seems related to #1294

lperron commented 5 years ago

Works fine on 7.3

lperron commented 5 years ago

Route for Vehicle 0: 0 -> 3 -> 4 -> 1 -> 2 -> 0 Distance of the route: 460m Total Distance of all routes: 460m