def _set_capacity_dimension_constraints( self, data: VehicleRoutingProblemInstance, routing: RoutingModel, manager: RoutingIndexManager): if data.courier_capacities is None: return def demand_callback(index): node = manager.IndexToNode(index) return data.node_demands[node] capacity_callback = routing.RegisterUnaryTransitCallback( demand_callback) routing.AddDimensionWithVehicleCapacity( capacity_callback, 0, # waiting time data.courier_capacities, # maximum distance per vehicle False, # Force start cumul to zero. self.CAPACITY_DIMENSION_NAME) capacity_dimension = routing.GetDimensionOrDie( self.CAPACITY_DIMENSION_NAME) for courier_idx, start_utilization in enumerate( data.start_utilizations): node_idx = routing.Start(courier_idx) self._set_constraint_on_var( node_idx, TimeWindowConstraint(node=node_idx, is_hard=True, from_time=start_utilization, to_time=start_utilization), capacity_dimension)
def main() -> None: """ Entry point of the program. """ # Parse command line arguments args = parse_args() # Instantiate the data problem data = load_data_model(args.path) # Create the Routing Index Manager and Routing Model manager = RoutingIndexManager(data["num_locations"], data["num_vehicles"], data["depot"]) routing = RoutingModel(manager) # Define weights of edges weight_callback_index = routing.RegisterTransitCallback( create_weight_callback(manager, data)) routing.SetArcCostEvaluatorOfAllVehicles(weight_callback_index) # Add capacity constraints demand_callback = create_demand_callback(manager, data) demand_callback_index = routing.RegisterUnaryTransitCallback( demand_callback) add_capacity_constraints(routing, manager, data, demand_callback_index) # Add time window constraints time_callback_index = routing.RegisterTransitCallback( create_time_callback(manager, data)) add_time_window_constraints(routing, manager, data, time_callback_index) # Set first solution heuristic (cheapest addition) search_params = DefaultRoutingSearchParameters() search_params.first_solution_strategy = FirstSolutionStrategy.PATH_CHEAPEST_ARC if args.gls: search_params.local_search_metaheuristic = ( LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH) # NOTE: Since Guided Local Search could take a very long time, we set a # reasonable time limit search_params.time_limit.seconds = 30 if args.verbose: search_params.log_search = True # Solve the problem assignment = routing.SolveWithParameters(search_params) if not assignment: print("No solution found.") return # Print the solution print_solution(data, routing, manager, assignment) # Export network and route graphs if args.export_network_graph: draw_network_graph(args.export_network_graph, data) if args.export_route_graph: draw_route_graph(args.export_route_graph, data, routing, manager, assignment)
def add_capacity_constraints(routing: pywrapcp.RoutingModel, data: dict, demand_callback): """ Add capacity constraints. """ demand_callback_index = routing.RegisterUnaryTransitCallback(demand_callback) routing.AddDimensionWithVehicleCapacity( demand_callback_index, slack_max=0, # null slack # vehicle maximum capacities vehicle_capacities=data['vehicle_capacities'], fix_start_cumul_to_zero=True, # start cumul to zero name='Capacity', )
def apply(self, solver: RoutingModel): """Vehicle's occupation is restricted based on demand""" callback_index = solver.RegisterUnaryTransitCallback(self._callback) solver.AddDimensionWithVehicleCapacity( evaluator_index=callback_index, slack_max=0, vehicle_capacities=[ vehicle.capacity for vehicle in self.problem.vehicles.values() ], fix_start_cumul_to_zero=True, name='capacity_constraint' )
def apply(self, manager: pywrapcp.RoutingModel, routing: pywrapcp.RoutingModel, data_model: DataModel): def demand_callback(from_index): """Returns the demand of the node.""" # Convert from routing variable Index to demands NodeIndex. from_node = manager.IndexToNode(from_index) return data_model.demands[from_node] demand_callback_index = routing.RegisterUnaryTransitCallback( demand_callback) routing.AddDimensionWithVehicleCapacity( demand_callback_index, 0, # null capacity slack data_model.vehicle_capacities, True, # start cumul to zero 'Capacity') return routing
def main(): """ Entry point of the program. """ # Parse command line arguments args = parse_args() #Crafted data : coordinates = [[0.848307, 0.32357132], [0.53917086, 0.862489], [0.28499496, 0.7470896], [0.66891015, 0.07388902], [0.6514969, 0.4077109], [0.782356, 0.28167558], [0.2601446, 0.9196638], [0.3402847, 0.62080956], [0.3920853, 0.8653455], [0.79114413, 0.09456837], [0.11343169, 0.73570406]] Distance_matrix = list() for j in range(len(coordinates)): l = list() for i in range(len(coordinates)): l.append(distance(coordinates[j], coordinates[i])) Distance_matrix.append(l) data = dict() data['weights'] = Distance_matrix data['service_times'] = [0, 1, 0.5, 1, 1, 0.5, 2, 2, 2, 0.5, 2] data['demands'] = [ 0, 0.25, 0.2, 0.1, 0.2, 0.35, 0.15, 0.3, 0.15, 0.15, 0.3 ] data['time_windows'] = [[0, 9], [0, 5], [5, 9], [0, 9], [0, 9], [0, 9], [0, 5], [5, 9], [5, 9], [0, 5], [0, 9]] data['vehicle_capacities'] = [1, 1, 1] data['depot'] = 0 data['num_locations'] = 11 data['num_vehicles'] = 3 # Instantiate the data problem #data = load_data_model(args.path) # Create the Routing Index Manager and Routing Model manager = RoutingIndexManager(data['num_locations'], data['num_vehicles'], data['depot']) routing = RoutingModel(manager) # Define weight of each edge weight_callback_index = routing.RegisterTransitCallback( create_weight_callback(manager, data)) routing.SetArcCostEvaluatorOfAllVehicles(weight_callback_index) # Add capacity constraints demand_callback = create_demand_callback(manager, data) demand_callback_index = routing.RegisterUnaryTransitCallback( demand_callback) add_capacity_constraints(routing, manager, data, demand_callback_index) # Add time window constraints time_callback_index = routing.RegisterTransitCallback( create_time_callback(manager, data)) add_time_window_constraints(routing, manager, data, time_callback_index) # Set first solution heuristic (cheapest addition) search_params = DefaultRoutingSearchParameters() # pylint: disable=no-member search_params.first_solution_strategy = FirstSolutionStrategy.PATH_CHEAPEST_ARC if args.gls: # pylint: disable=no-member search_params.local_search_metaheuristic = LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH # NOTE: Since Guided Local Search could take a very long time, we set a reasonable time # limit search_params.time_limit.seconds = 30 if args.verbose: search_params.log_search = True # Solve the problem assignment = routing.SolveWithParameters(search_params) if not assignment: print('No solution found.') return # Print the solution print_solution(Distance_matrix, data, routing, manager, assignment) # Draw network and route graphs """if args.graph:
data['starts'], data['ends']) # Create Routing Model routing = RoutingModel(manager) """ Define weight of each edge https://developers.google.com/optimization/routing/vrp """ distance_callback = create_distance_callback(manager, data) transit_callback_index = routing.RegisterTransitCallback(distance_callback) routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) """ Add capacity constraints https://developers.google.com/optimization/routing/cvrp """ demand_callback = create_demand_callback(manager, data) demand_callback_index = routing.RegisterUnaryTransitCallback( demand_callback) add_capacity_constraints(routing, manager, data, demand_callback_index) """ Add time window constraints https://developers.google.com/optimization/routing/vrptw """ if 'time_windows' in data.keys(): time_callback = create_time_callback(manager, data) time_callback_index = routing.RegisterTransitCallback(time_callback) add_time_window_constraints(routing, manager, data, time_callback_index) """ The code sets the first solution strategy to PATH_CHEAPEST_ARC, which creates an initial route for the solver by repeatedly adding edges with the least weight that don't lead to a previously visited node (other than the depot). For other options, see the link below