Skip to content

Commit

Permalink
Update routing Python samples
Browse files Browse the repository at this point in the history
  • Loading branch information
lperron committed Jan 29, 2025
1 parent 0ce4b91 commit cedcb51
Show file tree
Hide file tree
Showing 31 changed files with 684 additions and 299 deletions.
1 change: 1 addition & 0 deletions ortools/constraint_solver/samples/cp_is_fun_cp.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"""
# [START import]
from ortools.constraint_solver import pywrapcp

# [END import]


Expand Down
247 changes: 141 additions & 106 deletions ortools/constraint_solver/samples/cvrp_reload.py

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions ortools/constraint_solver/samples/cvrptw_break.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import functools
from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp

# [END import]


Expand Down Expand Up @@ -240,6 +241,8 @@ def print_solution(
capacity_dimension = routing.GetDimensionOrDie("Capacity")
time_dimension = routing.GetDimensionOrDie("Time")
for vehicle_id in range(data["num_vehicles"]):
if not routing.IsVehicleUsed(assignment, vehicle_id):
continue
index = routing.Start(vehicle_id)
plan_output = f"Route for vehicle {vehicle_id}:\n"
distance = 0
Expand Down
1 change: 1 addition & 0 deletions ortools/constraint_solver/samples/nqueens_cp.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
# [START import]
import sys
from ortools.constraint_solver import pywrapcp

# [END import]


Expand Down
1 change: 1 addition & 0 deletions ortools/constraint_solver/samples/simple_cp_program.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

# [START import]
from ortools.constraint_solver import pywrapcp

# [END import]


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# [START import]
from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp

# [END import]


Expand Down
1 change: 1 addition & 0 deletions ortools/constraint_solver/samples/tsp.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
# [START import]
from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp

# [END import]


Expand Down
1 change: 1 addition & 0 deletions ortools/constraint_solver/samples/tsp_circuit_board.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import math
from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp

# [END import]


Expand Down
3 changes: 2 additions & 1 deletion ortools/constraint_solver/samples/tsp_cities.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# [START import]
from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp

# [END import]


Expand Down Expand Up @@ -59,8 +60,8 @@ def print_solution(manager, routing, solution):
index = solution.Value(routing.NextVar(index))
route_distance += routing.GetArcCostForVehicle(previous_index, index, 0)
plan_output += f" {manager.IndexToNode(index)}\n"
print(plan_output)
plan_output += f"Route distance: {route_distance}miles\n"
print(plan_output)
# [END solution_printer]


Expand Down
1 change: 1 addition & 0 deletions ortools/constraint_solver/samples/tsp_distance_matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# [START import]
from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp

# [END import]


Expand Down
11 changes: 7 additions & 4 deletions ortools/constraint_solver/samples/vrp.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
# [START import]
from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp

# [END import]


Expand Down Expand Up @@ -65,16 +66,18 @@ def print_solution(data, manager, routing, solution):
"""Prints solution on console."""
print(f"Objective: {solution.ObjectiveValue()}")
total_distance = 0
for vehicle_id in range(data["num_vehicles"]):
index = routing.Start(vehicle_id)
plan_output = f"Route for vehicle {vehicle_id}:\n"
for vehicle_index in range(manager.GetNumberOfVehicles()):
if not routing.IsVehicleUsed(solution, vehicle_index):
continue
index = routing.Start(vehicle_index)
plan_output = f"Route for vehicle {vehicle_index}:\n"
route_distance = 0
while not routing.IsEnd(index):
plan_output += f" {manager.IndexToNode(index)} ->"
previous_index = index
index = solution.Value(routing.NextVar(index))
route_distance += routing.GetArcCostForVehicle(
previous_index, index, vehicle_id
previous_index, index, vehicle_index
)
plan_output += f" {manager.IndexToNode(index)}\n"
plan_output += f"Distance of the route: {route_distance}m\n"
Expand Down
3 changes: 3 additions & 0 deletions ortools/constraint_solver/samples/vrp_breaks.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
# [START import]
from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp

# [END import]


Expand Down Expand Up @@ -82,6 +83,8 @@ def print_solution(manager, routing, solution):
time_dimension = routing.GetDimensionOrDie("Time")
total_time = 0
for vehicle_id in range(manager.GetNumberOfVehicles()):
if not routing.IsVehicleUsed(solution, vehicle_id):
continue
index = routing.Start(vehicle_id)
plan_output = f"Route for vehicle {vehicle_id}:\n"
while not routing.IsEnd(index):
Expand Down
81 changes: 45 additions & 36 deletions ortools/constraint_solver/samples/vrp_breaks_from_start.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,17 @@
# [START import]
from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp

# [END import]


# [START data_model]
def create_data_model():
"""Stores the data for the problem."""
data = {}
data['num_vehicles'] = 4
data['depot'] = 0
data['time_matrix'] = [
data["num_vehicles"] = 4
data["depot"] = 0
data["time_matrix"] = [
[0, 27, 38, 34, 29, 13, 25, 9, 15, 9, 26, 25, 19, 17, 23, 38, 33],
[27, 0, 34, 15, 9, 25, 36, 17, 34, 37, 54, 29, 24, 33, 50, 43, 60],
[38, 34, 0, 49, 43, 25, 13, 40, 23, 37, 20, 63, 58, 56, 39, 77, 37],
Expand All @@ -55,48 +56,52 @@ def create_data_model():
[33, 60, 37, 67, 62, 35, 24, 42, 25, 23, 17, 42, 36, 26, 9, 39, 0],
]
# 15 min of service time
data['service_time'] = [15] * len(data['time_matrix'])
data['service_time'][data['depot']] = 0
assert len(data['time_matrix']) == len(data['service_time'])
data["service_time"] = [15] * len(data["time_matrix"])
data["service_time"][data["depot"]] = 0
assert len(data["time_matrix"]) == len(data["service_time"])
return data
# [END data_model]


# [START solution_printer]
def print_solution(manager, routing, solution):
"""Prints solution on console."""
print(f'Objective: {solution.ObjectiveValue()}')
print(f"Objective: {solution.ObjectiveValue()}")

print('Breaks:')
print("Breaks:")
intervals = solution.IntervalVarContainer()
for i in range(intervals.Size()):
brk = intervals.Element(i)
if brk.PerformedValue() == 1:
print(f'{brk.Var().Name()}: ' +
f'Start({brk.StartValue()}) Duration({brk.DurationValue()})')
print(
f"{brk.Var().Name()}: "
+ f"Start({brk.StartValue()}) Duration({brk.DurationValue()})"
)
else:
print(f'{brk.Var().Name()}: Unperformed')
print(f"{brk.Var().Name()}: Unperformed")

time_dimension = routing.GetDimensionOrDie('Time')
time_dimension = routing.GetDimensionOrDie("Time")
total_time = 0
for vehicle_id in range(manager.GetNumberOfVehicles()):
if not routing.IsVehicleUsed(solution, vehicle_id):
continue
index = routing.Start(vehicle_id)
plan_output = f'Route for vehicle {vehicle_id}:\n'
plan_output = f"Route for vehicle {vehicle_id}:\n"
while not routing.IsEnd(index):
time_var = time_dimension.CumulVar(index)
if routing.IsStart(index):
start_time = solution.Value(time_var)
plan_output += f'{manager.IndexToNode(index)} '
plan_output += f'Time({solution.Value(time_var)}) -> '
plan_output += f"{manager.IndexToNode(index)} "
plan_output += f"Time({solution.Value(time_var)}) -> "
index = solution.Value(routing.NextVar(index))
time_var = time_dimension.CumulVar(index)
plan_output += f'{manager.IndexToNode(index)} '
plan_output += f'Time({solution.Value(time_var)})'
plan_output += f"{manager.IndexToNode(index)} "
plan_output += f"Time({solution.Value(time_var)})"
print(plan_output)
route_time = solution.Value(time_var) - start_time
print(f'Time of the route: {route_time}min\n')
print(f"Time of the route: {route_time}min\n")
total_time += route_time
print(f'Total time of all routes: {total_time}min')
print(f"Total time of all routes: {total_time}min")
# [END solution_printer]


Expand All @@ -109,24 +114,24 @@ def main():

# Create the routing index manager.
# [START index_manager]
manager = pywrapcp.RoutingIndexManager(len(data['time_matrix']),
data['num_vehicles'], data['depot'])
manager = pywrapcp.RoutingIndexManager(
len(data["time_matrix"]), data["num_vehicles"], data["depot"]
)
# [END index_manager]

# Create Routing Model.
# [START routing_model]
routing = pywrapcp.RoutingModel(manager)
# [END routing_model]


# Create and register a transit callback.
# [START transit_callback]
def time_callback(from_index, to_index):
"""Returns the travel time between the two nodes."""
# Convert from routing variable Index to time matrix NodeIndex.
from_node = manager.IndexToNode(from_index)
to_node = manager.IndexToNode(to_index)
return data['time_matrix'][from_node][to_node]
return data["time_matrix"][from_node][to_node]

transit_callback_index = routing.RegisterTransitCallback(time_callback)
# [END transit_callback]
Expand All @@ -137,13 +142,14 @@ def time_callback(from_index, to_index):
# [END arc_cost]

# Add Time Windows constraint.
time = 'Time'
time = "Time"
routing.AddDimension(
transit_callback_index,
10, # need optional waiting time to place break
180, # maximum time per vehicle
False, # Don't force start cumul to zero.
time)
time,
)
time_dimension = routing.GetDimensionOrDie(time)
time_dimension.SetGlobalSpanCostCoefficient(10)

Expand All @@ -158,29 +164,32 @@ def time_callback(from_index, to_index):
node_visit_transit = [0] * routing.Size()
for index in range(routing.Size()):
node = manager.IndexToNode(index)
node_visit_transit[index] = data['service_time'][node]
node_visit_transit[index] = data["service_time"][node]

# Add a break lasting 5 minutes, start between 25 and 45 minutes after route start
for v in range(manager.GetNumberOfVehicles()):
start_var = time_dimension.CumulVar(routing.Start(v))
break_start = routing.solver().Sum(
[routing.solver().IntVar(25, 45), start_var])
break_start = routing.solver().Sum([routing.solver().IntVar(25, 45), start_var])

break_intervals = [
routing.solver().FixedDurationIntervalVar(break_start, 5,
f'Break for vehicle {v}')
routing.solver().FixedDurationIntervalVar(
break_start, 5, f"Break for vehicle {v}"
)
]
time_dimension.SetBreakIntervalsOfVehicle(break_intervals, v,
node_visit_transit)
time_dimension.SetBreakIntervalsOfVehicle(
break_intervals, v, node_visit_transit
)
# [END break_constraint]

# Setting first solution heuristic.
# [START parameters]
search_parameters = pywrapcp.DefaultRoutingSearchParameters()
search_parameters.first_solution_strategy = (
routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)
routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC
)
search_parameters.local_search_metaheuristic = (
routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)
routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH
)
# search_parameters.log_search = True
search_parameters.time_limit.FromSeconds(2)
# [END parameters]
Expand All @@ -195,10 +204,10 @@ def time_callback(from_index, to_index):
if solution:
print_solution(manager, routing, solution)
else:
print('No solution found !')
print("No solution found !")
# [END print_solution]


if __name__ == '__main__':
if __name__ == "__main__":
main()
# [END program]
3 changes: 3 additions & 0 deletions ortools/constraint_solver/samples/vrp_capacity.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# [START import]
from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp

# [END import]


Expand Down Expand Up @@ -63,6 +64,8 @@ def print_solution(data, manager, routing, solution):
total_distance = 0
total_load = 0
for vehicle_id in range(data["num_vehicles"]):
if not routing.IsVehicleUsed(solution, vehicle_id):
continue
index = routing.Start(vehicle_id)
plan_output = f"Route for vehicle {vehicle_id}:\n"
route_distance = 0
Expand Down
3 changes: 3 additions & 0 deletions ortools/constraint_solver/samples/vrp_drop_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# [START import]
from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp

# [END import]


Expand Down Expand Up @@ -72,6 +73,8 @@ def print_solution(data, manager, routing, assignment):
total_distance = 0
total_load = 0
for vehicle_id in range(data["num_vehicles"]):
if not routing.IsVehicleUsed(assignment, vehicle_id):
continue
index = routing.Start(vehicle_id)
plan_output = f"Route for vehicle {vehicle_id}:\n"
route_distance = 0
Expand Down
4 changes: 4 additions & 0 deletions ortools/constraint_solver/samples/vrp_global_span.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
# [START import]
from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp

# [END import]


Expand Down Expand Up @@ -66,6 +67,8 @@ def print_solution(data, manager, routing, solution):
print(f"Objective: {solution.ObjectiveValue()}")
max_route_distance = 0
for vehicle_id in range(data["num_vehicles"]):
if not routing.IsVehicleUsed(solution, vehicle_id):
continue
index = routing.Start(vehicle_id)
plan_output = f"Route for vehicle {vehicle_id}:\n"
route_distance = 0
Expand All @@ -82,6 +85,7 @@ def print_solution(data, manager, routing, solution):
max_route_distance = max(route_distance, max_route_distance)
print(f"Maximum of the route distances: {max_route_distance}m")


# [END solution_printer]


Expand Down
Loading

0 comments on commit cedcb51

Please sign in to comment.