Пример #1
0
        public RoutingSolver(DataModel data)
        {
            if (this.Data.GetTimeWindows().GetLength(0) != this.Data.GetTimeMatrix().GetLength(0))
            {
                throw new System.ComponentModel.DataAnnotations.ValidationException("Travel Time Matrix and Time Windows Matrix must have the same length.");
            }

            this.Data = data;

            // Create Routing Index Manager
            // [START index_manager]
            this.manager = new RoutingIndexManager(
                this.Data.GetTimeMatrix().GetLength(0), // Total Number of Sites
                this.Data.GetVehicleNumber(),
                this.Data.GetDepot());
            // [END index_manager]

            this.timeCallback = new TimeCallback(this.Data, manager);
        }
Пример #2
0
    /// <summary>
    ///   Solves the current routing problem.
    /// </summary>
    private void Solve(int number_of_orders, int number_of_vehicles)
    {
        Console.WriteLine("Creating model with " + number_of_orders +
                          " orders and " + number_of_vehicles + " vehicles.");
        // Finalizing model
        int number_of_locations = locations_.Length;

        RoutingIndexManager manager =
            new RoutingIndexManager(number_of_locations, number_of_vehicles,
                                    vehicle_starts_, vehicle_ends_);
        RoutingModel model = new RoutingModel(manager);

        // Setting up dimensions
        const int      big_number         = 100000;
        LongLongToLong manhattan_callback = new Manhattan(manager, locations_, 1);

        model.AddDimension(
            model.RegisterTransitCallback(manhattan_callback),
            big_number, big_number, false, "time");
        RoutingDimension time_dimension = model.GetDimensionOrDie("time");

        LongToLong demand_callback = new Demand(order_demands_);

        model.AddDimension(model.RegisterUnaryTransitCallback(demand_callback),
                           0, vehicle_capacity_, true, "capacity");
        RoutingDimension capacity_dimension = model.GetDimensionOrDie("capacity");

        // Setting up vehicles
        LongLongToLong[] cost_callbacks = new LongLongToLong[number_of_vehicles];
        for (int vehicle = 0; vehicle < number_of_vehicles; ++vehicle)
        {
            int            cost_coefficient        = vehicle_cost_coefficients_[vehicle];
            LongLongToLong manhattan_cost_callback =
                new Manhattan(manager, locations_, cost_coefficient);
            cost_callbacks[vehicle] = manhattan_cost_callback;
            int manhattan_cost_index =
                model.RegisterTransitCallback(manhattan_cost_callback);
            model.SetArcCostEvaluatorOfVehicle(manhattan_cost_index, vehicle);
            time_dimension.CumulVar(model.End(vehicle)).SetMax(
                vehicle_end_time_[vehicle]);
        }

        // Setting up orders
        for (int order = 0; order < number_of_orders; ++order)
        {
            time_dimension.CumulVar(order).SetRange(order_time_windows_[order].start_,
                                                    order_time_windows_[order].end_);
            long[] orders = { manager.NodeToIndex(order) };
            model.AddDisjunction(orders, order_penalties_[order]);
        }

        // Solving
        RoutingSearchParameters search_parameters =
            operations_research_constraint_solver.DefaultRoutingSearchParameters();

        search_parameters.FirstSolutionStrategy =
            FirstSolutionStrategy.Types.Value.AllUnperformed;

        Console.WriteLine("Search");
        Assignment solution = model.SolveWithParameters(search_parameters);

        //protect callbacks from the GC
        GC.KeepAlive(manhattan_callback);
        GC.KeepAlive(demand_callback);
        for (int cost_callback_index = 0; cost_callback_index < cost_callbacks.Length; cost_callback_index++)
        {
            GC.KeepAlive(cost_callbacks[cost_callback_index]);
        }

        if (solution != null)
        {
            String output = "Total cost: " + solution.ObjectiveValue() + "\n";
            // Dropped orders
            String dropped = "";
            for (int order = 0; order < number_of_orders; ++order)
            {
                if (solution.Value(model.NextVar(order)) == order)
                {
                    dropped += " " + order;
                }
            }
            if (dropped.Length > 0)
            {
                output += "Dropped orders:" + dropped + "\n";
            }
            // Routes
            for (int vehicle = 0; vehicle < number_of_vehicles; ++vehicle)
            {
                String route = "Vehicle " + vehicle + ": ";
                long   order = model.Start(vehicle);
                if (model.IsEnd(solution.Value(model.NextVar(order))))
                {
                    route += "Empty";
                }
                else
                {
                    for (;
                         !model.IsEnd(order);
                         order = solution.Value(model.NextVar(order)))
                    {
                        IntVar local_load = capacity_dimension.CumulVar(order);
                        IntVar local_time = time_dimension.CumulVar(order);
                        route += order + " Load(" + solution.Value(local_load) + ") " +
                                 "Time(" + solution.Min(local_time) + ", " +
                                 solution.Max(local_time) + ") -> ";
                    }
                    IntVar load = capacity_dimension.CumulVar(order);
                    IntVar time = time_dimension.CumulVar(order);
                    route += order + " Load(" + solution.Value(load) + ") " +
                             "Time(" + solution.Min(time) + ", " + solution.Max(time) + ")";
                }
                output += route + "\n";
            }
            Console.WriteLine(output);
        }
    }