Skip to content

Commit 7950e22

Browse files
committed
Rewrite python routing layer to use pybind11; port samples
1 parent ff5a2c1 commit 7950e22

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+4577
-2459
lines changed

ortools/constraint_solver/python/constraint_solver.cc

Lines changed: 140 additions & 95 deletions
Large diffs are not rendered by default.

ortools/routing/docs/ROUTING.md

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ int main(int argc, char* argv[]) {
103103
"""Vehicle Routing example."""
104104
105105
from ortools.routing import enums_pb2
106-
from ortools.routing import pywraprouting
106+
from ortools.routing import parameters_pb2
107+
from ortools.routing.python import routing
107108
108109
109110
def main():
@@ -114,46 +115,50 @@ def main():
114115
depot = 0
115116
116117
# Create the routing index manager.
117-
manager = pywraprouting.IndexManager(
118-
num_locations, num_vehicles, depot
119-
)
118+
manager = routing.IndexManager(num_locations, num_vehicles, depot)
120119
121-
# Create Routing Model.
122-
routing = pywraprouting.Model(manager)
120+
# Create Routing routing.
121+
routing_model = routing.Model(manager)
123122
124123
# Create and register a transit callback.
125124
def distance_callback(from_index, to_index):
126125
"""Returns the absolute difference between the two nodes."""
127126
# Convert from routing variable Index to user NodeIndex.
128-
from_node = int(manager.IndexToNode(from_index))
129-
to_node = int(manager.IndexToNode(to_index))
127+
from_node = int(manager.index_to_node(from_index))
128+
to_node = int(manager.index_to_node(to_index))
130129
return abs(to_node - from_node)
131130
132-
transit_callback_index = routing.RegisterTransitCallback(distance_callback)
131+
transit_callback_index = routing_model.register_transit_callback(
132+
distance_callback
133+
)
133134
134135
# Define cost of each arc.
135-
routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
136+
routing_model.set_arc_cost_evaluator_of_all_vehicles(transit_callback_index)
136137
137138
# Setting first solution heuristic.
138-
search_parameters = pywraprouting.DefaultRoutingSearchParameters()
139+
search_parameters: parameters_pb2.RoutingSearchParameters = (
140+
routing.default_routing_search_parameters()
141+
)
139142
search_parameters.first_solution_strategy = (
140143
enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC
141144
) # pylint: disable=no-member
142145
143146
# Solve the problem.
144-
assignment = routing.SolveWithParameters(search_parameters)
147+
assignment = routing_model.solve_with_parameters(search_parameters)
145148
146149
# Print solution on console.
147-
print(f"Objective: {assignment.ObjectiveValue()}")
148-
index = routing.Start(0)
150+
print(f"Objective: {assignment.objective_value()}")
151+
index = routing_model.start(0)
149152
plan_output = "Route for vehicle 0:\n"
150153
route_distance = 0
151-
while not routing.IsEnd(index):
152-
plan_output += f"{manager.IndexToNode(index)} -> "
154+
while not routing_model.is_end(index):
155+
plan_output += f"{manager.index_to_node(index)} -> "
153156
previous_index = index
154-
index = assignment.Value(routing.NextVar(index))
155-
route_distance += routing.GetArcCostForVehicle(previous_index, index, 0)
156-
plan_output += f"{manager.IndexToNode(index)}\n"
157+
index = assignment.value(routing_model.next_var(index))
158+
route_distance += routing_model.get_arc_cost_for_vehicle(
159+
previous_index, index, 0
160+
)
161+
plan_output += f"{manager.index_to_node(index)}\n"
157162
plan_output += f"Distance of the route: {route_distance}m\n"
158163
print(plan_output)
159164

ortools/routing/python/BUILD.bazel

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Copyright 2010-2025 Google LLC
2+
# Licensed under the Apache License, Version 2.0 (the "License");
3+
# you may not use this file except in compliance with the License.
4+
# You may obtain a copy of the License at
5+
#
6+
# http://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS,
10+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
# See the License for the specific language governing permissions and
12+
# limitations under the License.
13+
14+
# Description: python wrapping of the C++ code of the routing library.
15+
16+
load("@pip_deps//:requirements.bzl", "requirement")
17+
load("@pybind11_bazel//:build_defs.bzl", "pybind_extension")
18+
load("@rules_cc//cc:cc_library.bzl", "cc_library")
19+
load("@rules_python//python:py_test.bzl", "py_test")
20+
21+
cc_library(
22+
name = "doc",
23+
hdrs = [
24+
"doc.h",
25+
"index_manager_doc.h",
26+
"parameters_doc.h",
27+
],
28+
)
29+
30+
pybind_extension(
31+
name = "routing",
32+
srcs = ["routing.cc"],
33+
visibility = ["//visibility:public"],
34+
deps = [
35+
":doc",
36+
"//ortools/constraint_solver:cp",
37+
"//ortools/constraint_solver:solver_parameters_cc_proto",
38+
"//ortools/constraint_solver/python:constraint_solver",
39+
"//ortools/routing",
40+
"//ortools/routing:index_manager",
41+
"//ortools/routing:parameters",
42+
"//ortools/routing:types",
43+
"//ortools/util:sorted_interval_list",
44+
"//ortools/util/python:sorted_interval_list",
45+
"@abseil-cpp//absl/algorithm:container",
46+
"@abseil-cpp//absl/container:flat_hash_set",
47+
"@pybind11_abseil//pybind11_abseil:absl_casters",
48+
"@pybind11_protobuf//pybind11_protobuf:native_proto_caster",
49+
],
50+
)
51+
52+
py_test(
53+
name = "routing_test",
54+
size = "small",
55+
srcs = ["routing_test.py"],
56+
deps = [
57+
":routing",
58+
requirement("absl-py"),
59+
"//ortools/constraint_solver/python:constraint_solver",
60+
"//ortools/routing:enums_py_pb2",
61+
"//ortools/routing:parameters_py_pb2",
62+
],
63+
)

ortools/routing/python/CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
# limitations under the License.
1313

1414
# routing
15-
pybind11_add_module(routing_pybind11 MODULE model.cc)
15+
pybind11_add_module(routing_pybind11 MODULE routing.cc)
1616
set_target_properties(routing_pybind11 PROPERTIES
17-
LIBRARY_OUTPUT_NAME "model")
17+
LIBRARY_OUTPUT_NAME "routing")
1818

1919
# note: macOS is APPLE and also UNIX !
2020
if(APPLE)
@@ -29,6 +29,7 @@ endif()
2929
target_link_libraries(routing_pybind11 PRIVATE
3030
${PROJECT_NAMESPACE}::ortools
3131
pybind11_native_proto_caster
32+
pybind11_abseil::absl_casters
3233
)
3334
add_library(${PROJECT_NAMESPACE}::routing_pybind11 ALIAS routing_pybind11)
3435

0 commit comments

Comments
 (0)