Проблема маршрута транспортного средства с ограничениями как по расстоянию, так и по времени Ortools - PullRequest
0 голосов
/ 29 мая 2020

Я хотел сделать простой VRP с минимизацией расстояния, сохраняя при этом ограничения по времени для каждого узла. Проблема в том, что со временем я сделал то, что было сказано в руководстве по VRP, но это просто не работает. Выходные данные дают мне:

Day: 0, ((0, 7)) Item: 3
Day: 1, ((0, 4)) Item: 3
Day: 2, ((0, 7)) Item: 0
Day: 3, ((0, 1)) Item: 2
Day: 4, ((0, 7)) Item: 2
Day: 5, ((0, 7)) Item: 0
Day: 6, ((0, 3)) Item: 1

((x, y)) значения - это значения временного диапазона для узлов (они правильно читаются), но не используются должным образом, например, узел 2 находится в день 3, даже если он имеет предел от 0 до 1.

from __future__ import print_function
from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp

def create_data_model():
    """Stores the data for the problem."""
    data = {}
    data['distance_matrix'] = [
        [0, 0, 0, 0, 0, 0, 0, 0], 
        [0, 0, 0, 0, 0, 0, 0, 0], 
        [0, 0, 0, 1, 1, 1, 1, 1], 
        [0, 0, 0, 0, 20, 20, 30, 30],
        [0, 0, 0, 10, 0, 0, 30, 30],
        [0, 0, 0, 10, 0, 0, 30, 30],
        [0, 0, 0, 10, 20, 20, 0, 0],
        [0, 0, 0, 10, 20, 20, 0, 0],
    ]
    data['deadlines'] = [
        (0, 7), # 0 - 1
        (0, 7), # 0 - 2
        (0, 3), # 1 - 3
        (0, 7), # 2 - 4
        (0, 1), # 2 - 5
        (0, 4), # 3 - 6
        (0, 7), # 3 - 7
    ]
    data['num_items'] = 5
    data['num_days'] = 7
    data['types'] = [0,0,1,2,2,3,3]
    data['num_vehicles'] = 1
    data['depot'] = 0
    data['storage_cost'] = 10
    return data


def print_solution(data, manager, routing, solution):
    """Prints solution on console."""
    time_dimension = routing.GetDimensionOrDie('Time')
    print(routing.status())
    max_route_distance = 0
    for vehicle_id in range(data['num_vehicles']):
        index = routing.Start(vehicle_id)
        plan_output = 'Schedule: \n'
        route_distance = 0
        previous_index = index
        index = solution.Value(routing.NextVar(index))
        day = 0
        while not routing.IsEnd(index):
            time_var = time_dimension.CumulVar(index)
            print(time_var)
            plan_output += 'Day: {0}, ({1}) Item: {2} \n'.format(day, data['deadlines'][index-1], data['types'][manager.IndexToNode(index)-1])
            previous_index = index
            index = solution.Value(routing.NextVar(index))
            print(index)
            route_distance += routing.GetArcCostForVehicle(previous_index, index, vehicle_id)
            day += 1
        plan_output += 'Cost : {}\n'.format(route_distance)
        print(plan_output)
        max_route_distance = max(route_distance, max_route_distance)
        #total_time += solution.Min(time_var)
    #print('Total time of all routes: {} days'.format(total_time))
    print('Minimum cost: {}'.format(max_route_distance))




def main():
    """Solve the CVRP problem."""
    # Instantiate the data problem.
    data = create_data_model()

    # Create the routing index manager.
    manager = pywrapcp.RoutingIndexManager(data['num_days']+1,
                                           data['num_vehicles'], data['depot'])

    # Create Routing Model.
    routing = pywrapcp.RoutingModel(manager)

    # --- DISTANCE ---
    # Create and register a transit callback.
    def distance_callback(from_index, to_index):
        """Returns the distance between the two nodes."""
        from_node = manager.IndexToNode(from_index)
        to_node = manager.IndexToNode(to_index)
       # storage = (7 - day)*data['storage_cost']
        return data['distance_matrix'][from_node][to_node]

    transit_callback_index = routing.RegisterTransitCallback(distance_callback)
    routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)


    # --- TIME ---
    #Add Time Windows constraint.
     def time_callback(index):
         return 1
     transit_callback_index = routing.RegisterPositiveUnaryTransitCallback(time_callback)
     time = 'Time'
     routing.AddDimension(
         transit_callback_index,
         0,  # allow waiting time
         data['num_days'],  # maximum time per vehicle
         True,
         time)
    time_dimension = routing.GetDimensionOrDie(time)
    # Add time window constraints for each location except depot.
    for location_idx, time_window in enumerate(data['deadlines']):
        index = manager.NodeToIndex(location_idx)
        time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1])
    # Add time window constraints for each vehicle start node.
    time_dimension.CumulVar(routing.Start(0)).SetRange(data['deadlines'][0][0], data['deadlines'][0][1])


    # Instantiate route start and end times to produce feasible times.
    #routing.AddVariableMinimizedByFinalizer(time_dimension.CumulVar(routing.Start(0)))
    #routing.AddVariableMinimizedByFinalizer(time_dimension.CumulVar(routing.End(0)))



    # Setting first solution heuristic.
    search_parameters = pywrapcp.DefaultRoutingSearchParameters()
    search_parameters.first_solution_strategy = (
        routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)

    # Solve the problem.
    solution = routing.SolveWithParameters(search_parameters)

    # Print solution on console.
    if solution:
        print_solution(data, manager, routing, solution)
    else:
        print('No solution')


if __name__ == '__main__':
    main()
...