diff --git a/cmake/cpp.cmake b/cmake/cpp.cmake index 8f50835a51..3fd61420aa 100644 --- a/cmake/cpp.cmake +++ b/cmake/cpp.cmake @@ -343,6 +343,7 @@ foreach(SUBPROJECT IN ITEMS xpress lp_data packing + routing scheduling port util) @@ -520,6 +521,10 @@ install(DIRECTORY ortools/constraint_solver/docs/ DESTINATION "${CMAKE_INSTALL_DOCDIR}/constraint_solver" FILES_MATCHING PATTERN "*.md") +install(DIRECTORY ortools/routing/docs/ + DESTINATION "${CMAKE_INSTALL_DOCDIR}/routing" + FILES_MATCHING + PATTERN "*.md") endif() ################ diff --git a/cmake/python.cmake b/cmake/python.cmake index 7aff051df0..32494c7a58 100644 --- a/cmake/python.cmake +++ b/cmake/python.cmake @@ -475,6 +475,8 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E $,copy,true> $<$:$> ${PYTHON_PROJECT}/pdlp/python + COMMAND ${CMAKE_COMMAND} -E copy + $ ${PYTHON_PROJECT}/routing COMMAND ${CMAKE_COMMAND} -E copy $ ${PYTHON_PROJECT}/routing/python COMMAND ${CMAKE_COMMAND} -E copy @@ -494,6 +496,7 @@ add_custom_command( min_cost_flow_pybind11 pywrapcp constraint_solver_pybind11 + pywraprouting routing_pybind11 pywraplp model_builder_helper_pybind11 @@ -536,6 +539,7 @@ add_custom_command( COMMAND ${stubgen_EXECUTABLE} -p pybind11_abseil.status --output . COMMAND ${stubgen_EXECUTABLE} -p ortools.math_opt.core.python.solver --output . COMMAND ${stubgen_EXECUTABLE} -p ortools.pdlp.python.pdlp --output . + COMMAND ${stubgen_EXECUTABLE} -p ortools.routing.pywraprouting --output . COMMAND ${stubgen_EXECUTABLE} -p ortools.routing.python.routing --output . COMMAND ${stubgen_EXECUTABLE} -p ortools.sat.python.swig_helper --output . COMMAND ${stubgen_EXECUTABLE} -p ortools.scheduling.python.rcpsp --output . diff --git a/examples/cpp/BUILD.bazel b/examples/cpp/BUILD.bazel index d77d27b996..a9ec6e9f3c 100644 --- a/examples/cpp/BUILD.bazel +++ b/examples/cpp/BUILD.bazel @@ -604,7 +604,7 @@ cc_binary( srcs = ["random_tsp.cc"], deps = [ "//ortools/base", - "//ortools/constraint_solver:routing", + "//ortools/routing", "//ortools/util:random_engine", "@com_google_absl//absl/strings", "@com_google_protobuf//:protobuf", @@ -618,7 +618,7 @@ cc_binary( "//ortools/base", "//ortools/base:file", "//ortools/base:mathutil", - "//ortools/constraint_solver:routing", + "//ortools/routing", "//ortools/routing/parsers:lilim_parser", "@com_google_absl//absl/flags:flag", "@com_google_absl//absl/strings", @@ -1012,6 +1012,7 @@ cc_binary( "//ortools/pdlp:solvers_cc_proto", "//ortools/port:proto_utils", "//ortools/util:file_util", + "//ortools/util:fp_roundtrip_conv", "//ortools/util:sigint", "@com_google_absl//absl/flags:flag", "@com_google_absl//absl/log:check", diff --git a/examples/cpp/max_flow.cc b/examples/cpp/max_flow.cc index a7d1529849..a99e9b4983 100644 --- a/examples/cpp/max_flow.cc +++ b/examples/cpp/max_flow.cc @@ -16,6 +16,7 @@ #include #include +#include "absl/flags/flag.h" #include "ortools/base/init_google.h" #include "ortools/base/logging.h" diff --git a/examples/cpp/min_cost_flow.cc b/examples/cpp/min_cost_flow.cc index 8119bbbf68..7c4dbef571 100644 --- a/examples/cpp/min_cost_flow.cc +++ b/examples/cpp/min_cost_flow.cc @@ -16,6 +16,7 @@ #include #include +#include "absl/flags/flag.h" #include "ortools/base/init_google.h" #include "ortools/base/logging.h" diff --git a/examples/cpp/pdlp_solve.cc b/examples/cpp/pdlp_solve.cc index b0fb360943..1a86d85eb9 100644 --- a/examples/cpp/pdlp_solve.cc +++ b/examples/cpp/pdlp_solve.cc @@ -39,6 +39,7 @@ #include "ortools/pdlp/solvers.pb.h" #include "ortools/port/proto_utils.h" #include "ortools/util/file_util.h" +#include "ortools/util/fp_roundtrip_conv.h" #include "ortools/util/sigint.h" // TODO: .mps.gz files aren't working. As a workaround, use .mps. @@ -108,8 +109,9 @@ void Solve(const std::string& input, absl::string_view params_str, // TODO: In what format should we write the dual solution? if (!sol_file.empty() && convergence_information.has_value()) { std::string sol_string; - absl::StrAppend(&sol_string, - "=obj= ", convergence_information->primal_objective(), + absl::StrAppend( + &sol_string, "=obj= ", + RoundTripDoubleFormat(convergence_information->primal_objective()), "\n"); for (int64_t i = 0; i < result.primal_solution.size(); ++i) { std::string name; @@ -118,7 +120,8 @@ void Solve(const std::string& input, absl::string_view params_str, } else { name = absl::StrCat("var", i); } - absl::StrAppend(&sol_string, name, " ", result.primal_solution(i), "\n"); + absl::StrAppend(&sol_string, name, " ", + RoundTripDoubleFormat(result.primal_solution(i)), "\n"); } LOG(INFO) << "Writing .sol solution to '" << sol_file << "'.\n"; CHECK_OK(file::SetContents(sol_file, sol_string, file::Defaults())); diff --git a/examples/cpp/pdptw.cc b/examples/cpp/pdptw.cc index 5ad9b72dbe..1e28a98700 100644 --- a/examples/cpp/pdptw.cc +++ b/examples/cpp/pdptw.cc @@ -57,14 +57,14 @@ #include "ortools/base/mathutil.h" #include "ortools/base/timer.h" #include "ortools/constraint_solver/constraint_solver.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" -#include "ortools/constraint_solver/routing_types.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" #include "ortools/routing/parameters.pb.h" #include "ortools/routing/parsers/lilim_parser.h" #include "ortools/routing/parsers/simple_graph.h" +#include "ortools/routing/routing.h" +#include "ortools/routing/types.h" ABSL_FLAG(std::string, pdp_file, "", "File containing the Pickup and Delivery Problem to solve."); diff --git a/examples/cpp/random_tsp.cc b/examples/cpp/random_tsp.cc index 5412243325..9dae715f68 100644 --- a/examples/cpp/random_tsp.cc +++ b/examples/cpp/random_tsp.cc @@ -33,10 +33,10 @@ #include "absl/strings/str_cat.h" #include "google/protobuf/text_format.h" #include "ortools/base/logging.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" -#include "ortools//routing/parameters.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/parameters.pb.h" +#include "ortools/routing/routing.h" #include "ortools/util/random_engine.h" ABSL_FLAG(int, tsp_size, 10, "Size of Traveling Salesman Problem instance."); diff --git a/examples/cpp/uncapacitated_facility_location.cc b/examples/cpp/uncapacitated_facility_location.cc index e738ce2417..e91707e0c4 100644 --- a/examples/cpp/uncapacitated_facility_location.cc +++ b/examples/cpp/uncapacitated_facility_location.cc @@ -25,6 +25,7 @@ #include #include +#include "absl/flags/flag.h" #include "absl/flags/parse.h" #include "absl/flags/usage.h" #include "absl/log/initialize.h" diff --git a/ortools/constraint_solver/BUILD.bazel b/ortools/constraint_solver/BUILD.bazel index f9852061d8..8c208c3b00 100644 --- a/ortools/constraint_solver/BUILD.bazel +++ b/ortools/constraint_solver/BUILD.bazel @@ -205,164 +205,3 @@ cc_library( "@com_google_absl//absl/random", ], ) - -# ----- Routing and ArcRouting ----- - -cc_library( - name = "routing_parameters", - srcs = ["routing_parameters.cc"], - hdrs = ["routing_parameters.h"], - deps = [ - ":cp", - ":solver_parameters_cc_proto", - "//ortools/base", - "//ortools/base:protoutil", - "//ortools/port:proto_utils", - "//ortools/routing:enums_cc_proto", - "//ortools/routing:parameters_cc_proto", - "//ortools/util:optional_boolean_cc_proto", - "//ortools/util:testing_utils", - "@com_google_absl//absl/status:statusor", - "@com_google_absl//absl/strings", - "@com_google_absl//absl/time", - "@com_google_protobuf//:protobuf", - ], -) - -cc_library( - name = "routing_types", - hdrs = ["routing_types.h"], - deps = [ - "//ortools/base", - "//ortools/base:intops", - ], -) - -cc_library( - name = "routing_utils", - srcs = ["routing_utils.cc"], - hdrs = ["routing_utils.h"], - visibility = ["//visibility:public"], - deps = [ - "//ortools/base", - "//ortools/util:saturated_arithmetic", - ], -) - -cc_library( - name = "routing_neighborhoods", - srcs = ["routing_neighborhoods.cc"], - hdrs = ["routing_neighborhoods.h"], - visibility = ["//visibility:public"], - deps = [ - ":cp", - ":routing_types", - ":routing_utils", - "//ortools/base", - ], -) - -cc_library( - name = "routing_index_manager", - srcs = ["routing_index_manager.cc"], - hdrs = ["routing_index_manager.h"], - deps = [ - ":routing_types", - "//ortools/base", - "//ortools/base:map_util", - "//ortools/base:strong_vector", - "@com_google_absl//absl/container:flat_hash_set", - ], -) - -cc_library( - name = "routing", - srcs = [ - "routing.cc", - "routing_breaks.cc", - "routing_constraints.cc", - "routing_decision_builders.cc", - "routing_filters.cc", - "routing_flow.cc", - "routing_ils.cc", - "routing_insertion_lns.cc", - "routing_lp_scheduling.cc", - "routing_sat.cc", - "routing_search.cc", - ], - hdrs = [ - "routing.h", - "routing_constraints.h", - "routing_decision_builders.h", - "routing_filters.h", - "routing_ils.h", - "routing_insertion_lns.h", - "routing_lp_scheduling.h", - "routing_search.h", - ], - copts = select({ - "on_linux": [], - "on_macos": [], - "on_windows": ["/Zc:preprocessor"], - "//conditions:default": [], - }), - deps = [ - ":cp", - ":routing_index_manager", - ":routing_neighborhoods", - ":routing_parameters", - ":routing_types", - ":routing_utils", - "//ortools/base", - "//ortools/base:adjustable_priority_queue", - "//ortools/base:dump_vars", - "//ortools/base:hash", - "//ortools/base:map_util", - "//ortools/base:murmur", - "//ortools/base:protoutil", - "//ortools/base:small_map", - "//ortools/base:stl_util", - "//ortools/base:strong_vector", - "//ortools/glop:lp_solver", - "//ortools/graph", - "//ortools/graph:christofides", - "//ortools/graph:connected_components", - "//ortools/graph:linear_assignment", - "//ortools/graph:min_cost_flow", - "//ortools/graph:topologicalsorter", - "//ortools/lp_data", - "//ortools/lp_data:base", - "//ortools/routing:enums_cc_proto", - "//ortools/routing:parameters_cc_proto", - "//ortools/sat:boolean_problem", - "//ortools/sat:cp_constraints", - "//ortools/sat:cp_model", - "//ortools/sat:cp_model_cc_proto", - "//ortools/sat:cp_model_checker", - "//ortools/sat:cp_model_solver", - "//ortools/sat:cp_model_utils", - "//ortools/sat:integer", - "//ortools/sat:integer_expr", - "//ortools/sat:model", - "//ortools/sat:optimization", - "//ortools/sat:theta_tree", - "//ortools/util:bitset", - "//ortools/util:flat_matrix", - "//ortools/util:optional_boolean_cc_proto", - "//ortools/util:range_query_function", - "//ortools/util:saturated_arithmetic", - "//ortools/util:sorted_interval_list", - "@com_google_absl//absl/container:btree", - "@com_google_absl//absl/container:flat_hash_map", - "@com_google_absl//absl/container:flat_hash_set", - "@com_google_absl//absl/container:inlined_vector", - "@com_google_absl//absl/functional:bind_front", - "@com_google_absl//absl/hash", - "@com_google_absl//absl/memory", - "@com_google_absl//absl/strings", - "@com_google_absl//absl/strings:str_format", - "@com_google_absl//absl/time", - "@com_google_absl//absl/types:span", - "@com_google_protobuf//:protobuf", - ], -) diff --git a/ortools/constraint_solver/CMakeLists.txt b/ortools/constraint_solver/CMakeLists.txt index 4f2924766a..f782d2f067 100644 --- a/ortools/constraint_solver/CMakeLists.txt +++ b/ortools/constraint_solver/CMakeLists.txt @@ -30,6 +30,5 @@ target_link_libraries(${NAME} PRIVATE absl::strings absl::str_format protobuf::libprotobuf - ${PROJECT_NAMESPACE}::ortools_proto - ${PROJECT_NAMESPACE}::routing_proto) + ${PROJECT_NAMESPACE}::ortools_proto) #add_library(${PROJECT_NAMESPACE}::constraint_solver ALIAS ${NAME}) diff --git a/ortools/constraint_solver/README.md b/ortools/constraint_solver/README.md index 0a6688c814..70a560091c 100644 --- a/ortools/constraint_solver/README.md +++ b/ortools/constraint_solver/README.md @@ -34,26 +34,8 @@ important for performance. ## Routing solver [Vehicle Routing](http://en.wikipedia.org/wiki/Vehicle_routing) is a useful -extension that is implemented on top of the CP solver library. - -To begin, skim: - -* [routing.h](../constraint_solver/routing.h): -The vehicle routing library lets one model and solve generic vehicle routing -problems ranging from the Traveling Salesman Problem to more complex problems -such as the Capacitated Vehicle Routing Problem with Time Windows. - -### Parameters - -* [routing_parameters.proto](../constraint_solver/routing_parameters.proto): -The Vehicle Routing solver parameters. -* [routing_enums.proto](../constraint_solver/routing_enums.proto): -Enums used to define routing parameters. - -### Solution - -* [assignment.proto](assignment.proto): -Holds the solution of a Routing problem. +extension that is implemented on top of the CP solver library. It is now +available as [a separate module](../routing/README.md). ## Recipes diff --git a/ortools/constraint_solver/constraint_solver.h b/ortools/constraint_solver/constraint_solver.h index 10aa2c9412..250c6fc40c 100644 --- a/ortools/constraint_solver/constraint_solver.h +++ b/ortools/constraint_solver/constraint_solver.h @@ -1074,6 +1074,16 @@ class Solver { optimization_direction_ = direction; } + // An internal method called by Guided Local Search to share current + // penalties with the solver. + void SetGuidedLocalSearchPenaltyCallback( + std::function penalty_callback) { + penalty_callback_ = std::move(penalty_callback); + } + // Returns the current (Guided Local Search)penalty of the given arc tuple. + int64_t GetGuidedLocalSearchPenalty(int64_t i, int64_t j, int64_t k) const { + return (penalty_callback_ == nullptr) ? 0 : penalty_callback_(i, j, k); + } // All factories (MakeXXX methods) encapsulate creation of objects // through RevAlloc(). Hence, the Solver used for allocating the // returned object will retain ownership of the allocated memory. @@ -2329,15 +2339,21 @@ class Solver { /// Creates a Guided Local Search monitor. /// Description here: http://en.wikipedia.org/wiki/Guided_Local_Search +#ifndef SWIG ObjectiveMonitor* MakeGuidedLocalSearch( bool maximize, IntVar* objective, IndexEvaluator2 objective_function, int64_t step, const std::vector& vars, double penalty_factor, + std::function>(int64_t, int64_t)> + get_equivalent_pairs = nullptr, bool reset_penalties_on_new_best_solution = false); ObjectiveMonitor* MakeGuidedLocalSearch( bool maximize, IntVar* objective, IndexEvaluator3 objective_function, int64_t step, const std::vector& vars, const std::vector& secondary_vars, double penalty_factor, + std::function>(int64_t, int64_t)> + get_equivalent_pairs = nullptr, bool reset_penalties_on_new_best_solution = false); +#endif /// This search monitor will restart the search periodically. /// At the iteration n, it will restart after scale_factor * Luby(n) failures @@ -3305,6 +3321,7 @@ class Solver { std::unique_ptr local_search_monitor_; int anonymous_variable_index_; bool should_fail_; + std::function penalty_callback_; }; std::ostream& operator<<(std::ostream& out, const Solver* const s); /// NOLINT diff --git a/ortools/constraint_solver/docs/README.md b/ortools/constraint_solver/docs/README.md index c7f136dd2a..8ce4e8294b 100644 --- a/ortools/constraint_solver/docs/README.md +++ b/ortools/constraint_solver/docs/README.md @@ -1,18 +1,18 @@ # Overview -You can find here, the documentation for the two following Or-Tools components. +You can find here the documentation for the two following OR-Tools components. -* [CP Solver](CP.md) +* [CP Solver](CP.md) - Constraint programming (CP), is the name given to identifying feasible - solutions out of a very large set of candidates, where the problem can be - modeled in terms of arbitrary constraints. + Constraint programming (CP) is the name given to identifying feasible + solutions out of a very large set of candidates, where the problem can be + modeled in terms of arbitrary constraints. - **note:** We **strongly recommend** using the [CP-SAT solver](../../sat) - rather than the original CP solver. + **note:** We **strongly recommend** using the [CP-SAT solver](../../sat) + rather than the original CP solver. -* [Routing Solver](ROUTING.md) +* [Routing Solver](../../routing/docs/ROUTING.md) - A specialized library for identifying best vehicle routes given constraints. + A specialized library for identifying best vehicle routes given constraints. - This library extensiond is implemented on top of the CP Solver library. + This library extension is implemented on top of the CP Solver library. diff --git a/ortools/constraint_solver/local_search.cc b/ortools/constraint_solver/local_search.cc index 2d11813cdd..44731b3c04 100644 --- a/ortools/constraint_solver/local_search.cc +++ b/ortools/constraint_solver/local_search.cc @@ -1735,36 +1735,30 @@ class NearestNeighbors { NearestNeighbors& operator=(const NearestNeighbors&) = delete; virtual ~NearestNeighbors() {} - void Initialize(); + void Initialize(const std::vector& path); const std::vector& Neighbors(int index) const; virtual std::string DebugString() const { return "NearestNeighbors"; } private: - void ComputeNearest(int row); + void ComputeNearest(int row, const std::vector& path); std::vector> neighbors_; Solver::IndexEvaluator3 evaluator_; const PathOperator& path_operator_; const int size_; - bool initialized_; }; NearestNeighbors::NearestNeighbors(Solver::IndexEvaluator3 evaluator, const PathOperator& path_operator, int size) - : evaluator_(std::move(evaluator)), + : neighbors_(path_operator.number_of_nexts()), + evaluator_(std::move(evaluator)), path_operator_(path_operator), - size_(size), - initialized_(false) {} + size_(size) {} -void NearestNeighbors::Initialize() { - // TODO(user): recompute if node changes path ? - if (!initialized_) { - initialized_ = true; - for (int i = 0; i < path_operator_.number_of_nexts(); ++i) { - neighbors_.push_back(std::vector()); - ComputeNearest(i); - } +void NearestNeighbors::Initialize(const std::vector& path) { + for (int node : path) { + if (node < path_operator_.number_of_nexts()) ComputeNearest(node, path); } } @@ -1772,25 +1766,26 @@ const std::vector& NearestNeighbors::Neighbors(int index) const { return neighbors_[index]; } -void NearestNeighbors::ComputeNearest(int row) { +void NearestNeighbors::ComputeNearest(int row, + const std::vector& path_nodes) { // Find size_ nearest neighbors for row of index 'row'. const int path = path_operator_.Path(row); const IntVar* var = path_operator_.Var(row); - const int64_t var_min = var->Min(); - const int var_size = var->Max() - var_min + 1; using ValuedIndex = std::pair; - std::vector neighbors(var_size); - for (int i = 0; i < var_size; ++i) { - const int index = i + var_min; - neighbors[i] = std::make_pair(evaluator_(row, index, path), index); + std::vector neighbors; + for (int index : path_nodes) { + if (!var->Contains(index)) continue; + neighbors.push_back({evaluator_(row, index, path), index}); } - if (var_size > size_) { + const int neighbors_size = neighbors.size(); + if (neighbors_size > size_) { std::nth_element(neighbors.begin(), neighbors.begin() + size_ - 1, neighbors.end()); } // Setup global neighbor matrix for row row_index - for (int i = 0; i < std::min(size_, var_size); ++i) { + neighbors_[row].clear(); + for (int i = 0; i < std::min(size_, neighbors_size); ++i) { neighbors_[row].push_back(neighbors[i].second); } std::sort(neighbors_[row].begin(), neighbors_[row].end()); @@ -1811,12 +1806,13 @@ class LinKernighan : public PathOperator { static const int kNeighbors; - bool InFromOut(int64_t in_i, int64_t in_j, int64_t* out, int64_t* gain); + bool GetBestOut(int64_t in_i, int64_t in_j, int64_t* out, int64_t* gain); Solver::IndexEvaluator3 const evaluator_; NearestNeighbors neighbors_; absl::flat_hash_set marked_; const bool topt_; + std::vector old_path_starts_; }; // While the accumulated local gain is positive, perform a 2opt or a 3opt move @@ -1829,11 +1825,40 @@ LinKernighan::LinKernighan(const std::vector& vars, : PathOperator(vars, secondary_vars, 1, true, false, nullptr, nullptr), evaluator_(evaluator), neighbors_(evaluator, *this, kNeighbors), - topt_(topt) {} + topt_(topt) { + old_path_starts_.resize(number_of_nexts(), -1); +} LinKernighan::~LinKernighan() {} -void LinKernighan::OnNodeInitialization() { neighbors_.Initialize(); } +void LinKernighan::OnNodeInitialization() { + absl::flat_hash_set touched_paths; + for (int i = 0; i < number_of_nexts(); ++i) { + if (IsPathStart(i)) { + for (int node = i; !IsPathEnd(node); node = Next(node)) { + if (i != old_path_starts_[node]) { + touched_paths.insert(old_path_starts_[node]); + touched_paths.insert(i); + old_path_starts_[node] = i; + } + } + } else if (Next(i) == i) { + touched_paths.insert(old_path_starts_[i]); + old_path_starts_[i] = -1; + } + } + for (int touched_path_start : touched_paths) { + if (touched_path_start == -1) continue; + std::vector path; + int node = touched_path_start; + while (!IsPathEnd(node)) { + path.push_back(node); + node = Next(node); + } + path.push_back(node); + neighbors_.Initialize(path); + } +} bool LinKernighan::MakeNeighbor() { marked_.clear(); @@ -1846,14 +1871,14 @@ bool LinKernighan::MakeNeighbor() { int64_t gain = 0; marked_.insert(node); if (topt_) { // Try a 3opt first - if (!InFromOut(node, next, &out, &gain)) return false; + if (!GetBestOut(node, next, &out, &gain)) return false; marked_.insert(next); marked_.insert(out); const int64_t node1 = out; if (IsPathEnd(node1)) return false; const int64_t next1 = Next(node1); if (IsPathEnd(next1)) return false; - if (!InFromOut(node1, next1, &out, &gain)) return false; + if (!GetBestOut(node1, next1, &out, &gain)) return false; marked_.insert(next1); marked_.insert(out); if (!CheckChainValidity(out, node1, node) || !MoveChain(out, node1, node)) { @@ -1869,23 +1894,35 @@ bool LinKernighan::MakeNeighbor() { if (IsPathEnd(next)) return false; } // Try 2opts - while (InFromOut(node, next, &out, &gain)) { + while (GetBestOut(node, next, &out, &gain)) { marked_.insert(next); marked_.insert(out); int64_t chain_last; - if (!ReverseChain(node, out, &chain_last)) { + if (Next(base) == out || (!IsPathEnd(out) && Next(out) == base)) { return false; } - int64_t in_cost = evaluator_(base, chain_last, path); - int64_t out_cost = evaluator_(chain_last, out, path); + const bool success = ReverseChain(base, out, &chain_last) || + ReverseChain(out, base, &chain_last); + if (!success) { +#ifndef NDEBUG + LOG(ERROR) << "ReverseChain failed: " << base << " " << out; + for (int node = StartNode(0); !IsPathEnd(node); node = Next(node)) { + LOG(ERROR) << "node: " << node; + } + LOG(ERROR) << "node: " << node; + DCHECK(false); +#endif + } + const int64_t in_cost = evaluator_(base, chain_last, path); + const int64_t out_cost = evaluator_(chain_last, out, path); if (CapAdd(CapSub(gain, in_cost), out_cost) > 0) { return true; } - node = chain_last; + node = out; if (IsPathEnd(node)) { return false; } - next = out; + next = chain_last; if (IsPathEnd(next)) { return false; } @@ -1895,24 +1932,20 @@ bool LinKernighan::MakeNeighbor() { const int LinKernighan::kNeighbors = 5 + 1; -bool LinKernighan::InFromOut(int64_t in_i, int64_t in_j, int64_t* out, +bool LinKernighan::GetBestOut(int64_t in_i, int64_t in_j, int64_t* out, int64_t* gain) { - const std::vector& nexts = neighbors_.Neighbors(in_j); int64_t best_gain = std::numeric_limits::min(); - int64_t path = Path(in_i); - int64_t out_cost = evaluator_(in_i, in_j, path); + const int64_t path = Path(in_i); + const int64_t out_cost = evaluator_(in_i, in_j, path); const int64_t current_gain = CapAdd(*gain, out_cost); - for (int k = 0; k < nexts.size(); ++k) { - const int64_t next = nexts[k]; - if (next != in_j) { - int64_t in_cost = evaluator_(in_j, next, path); - int64_t new_gain = CapSub(current_gain, in_cost); - if (new_gain > 0 && next != Next(in_j) && marked_.count(in_j) == 0 && - marked_.count(next) == 0) { - if (best_gain < new_gain) { + for (int next : neighbors_.Neighbors(in_j)) { + if (next != in_j && next != Next(in_j) && !marked_.contains(in_j) && + !marked_.contains(next)) { + const int64_t in_cost = evaluator_(in_j, next, path); + const int64_t new_gain = CapSub(current_gain, in_cost); + if (new_gain > 0 && best_gain < new_gain) { *out = next; best_gain = new_gain; - } } } } diff --git a/ortools/constraint_solver/python/CMakeLists.txt b/ortools/constraint_solver/python/CMakeLists.txt index 2c120893a5..a9b9569b64 100644 --- a/ortools/constraint_solver/python/CMakeLists.txt +++ b/ortools/constraint_solver/python/CMakeLists.txt @@ -11,43 +11,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# pywrapcp -set_property(SOURCE routing.i PROPERTY CPLUSPLUS ON) -set_property(SOURCE routing.i PROPERTY SWIG_MODULE_NAME pywrapcp) -set_property(SOURCE routing.i PROPERTY COMPILE_DEFINITIONS - ${OR_TOOLS_COMPILE_DEFINITIONS} ABSL_MUST_USE_RESULT=) -set_property(SOURCE routing.i PROPERTY COMPILE_OPTIONS -nofastunpack) -swig_add_library(pywrapcp - TYPE MODULE - LANGUAGE python - OUTPUT_DIR ${PYTHON_PROJECT_DIR}/constraint_solver - SOURCES routing.i) - -target_include_directories(pywrapcp PRIVATE ${Python3_INCLUDE_DIRS}) -set_property(TARGET pywrapcp PROPERTY SWIG_USE_TARGET_INCLUDE_DIRECTORIES ON) -target_compile_definitions(pywrapcp PUBLIC "PY3") - -# note: macOS is APPLE and also UNIX ! -if(APPLE) - set_target_properties(pywrapcp PROPERTIES - SUFFIX ".so" - INSTALL_RPATH "@loader_path;@loader_path/../../${PROJECT_NAME}/.libs") - set_property(TARGET pywrapcp APPEND PROPERTY - LINK_FLAGS "-flat_namespace -undefined suppress") -elseif(UNIX) - set_target_properties(pywrapcp PROPERTIES - INSTALL_RPATH "$ORIGIN:$ORIGIN/../../${PROJECT_NAME}/.libs") -endif() -target_link_libraries(pywrapcp PRIVATE ortools::ortools) - -# Variable PYTHON_LIBRARIES can contains keyword `optimized` -# which won't be interpreted inside a generator expression. -# i.e. we can't use: $<$:${PYTHON_LIBRARIES}> -# see: https://cmake.org/cmake/help/git-stage/command/target_link_libraries.html#command:target_link_libraries -if(MSVC) - target_link_libraries(pywrapcp PRIVATE ${Python3_LIBRARIES}) -endif() - # constraint_solver pybind11_add_module(constraint_solver_pybind11 MODULE constraint_solver.cc) set_target_properties(constraint_solver_pybind11 PROPERTIES @@ -74,6 +37,43 @@ target_link_libraries(constraint_solver_pybind11 PRIVATE ) add_library(${PROJECT_NAMESPACE}::constraint_solver_pybind11 ALIAS constraint_solver_pybind11) +# legacy pywrapcp +set_property(SOURCE constraint_solver.i PROPERTY CPLUSPLUS ON) +set_property(SOURCE constraint_solver.i PROPERTY SWIG_MODULE_NAME pywrapcp) +set_property(SOURCE constraint_solver.i PROPERTY COMPILE_DEFINITIONS + ${OR_TOOLS_COMPILE_DEFINITIONS} ABSL_MUST_USE_RESULT=) +set_property(SOURCE constraint_solver.i PROPERTY COMPILE_OPTIONS -nofastunpack) +swig_add_library(pywrapcp + TYPE MODULE + LANGUAGE python + OUTPUT_DIR ${PYTHON_PROJECT_DIR}/constraint_solver + SOURCES constraint_solver.i) + +target_include_directories(pywrapcp PRIVATE ${Python3_INCLUDE_DIRS}) +set_property(TARGET pywrapcp PROPERTY SWIG_USE_TARGET_INCLUDE_DIRECTORIES ON) +target_compile_definitions(pywrapcp PUBLIC "PY3") + +# note: macOS is APPLE and also UNIX ! +if(APPLE) + set_target_properties(pywrapcp PROPERTIES + SUFFIX ".so" + INSTALL_RPATH "@loader_path;@loader_path/../../${PROJECT_NAME}/.libs") + set_property(TARGET pywrapcp APPEND PROPERTY + LINK_FLAGS "-flat_namespace -undefined suppress") +elseif(UNIX) + set_target_properties(pywrapcp PROPERTIES + INSTALL_RPATH "$ORIGIN:$ORIGIN/../../${PROJECT_NAME}/.libs") +endif() +target_link_libraries(pywrapcp PRIVATE ortools::ortools) + +# Variable PYTHON_LIBRARIES can contains keyword `optimized` +# which won't be interpreted inside a generator expression. +# i.e. we can't use: $<$:${PYTHON_LIBRARIES}> +# see: https://cmake.org/cmake/help/git-stage/command/target_link_libraries.html#command:target_link_libraries +if(MSVC) + target_link_libraries(pywrapcp PRIVATE ${Python3_LIBRARIES}) +endif() + # Test if(BUILD_TESTING) file(GLOB PYTHON_SRCS "*_test.py") diff --git a/ortools/constraint_solver/samples/BUILD.bazel b/ortools/constraint_solver/samples/BUILD.bazel index 5214884b26..f12ce07a75 100644 --- a/ortools/constraint_solver/samples/BUILD.bazel +++ b/ortools/constraint_solver/samples/BUILD.bazel @@ -24,39 +24,3 @@ code_sample_cc(name="rabbits_and_pheasants_cp") code_sample_cc(name="simple_cp_program") code_sample_cc(name="simple_ls_program") - -code_sample_cc(name="simple_routing_program") - -code_sample_cc(name="tsp") - -code_sample_cc(name="tsp_circuit_board") - -code_sample_cc(name="tsp_cities") - -code_sample_cc(name="tsp_distance_matrix") - -code_sample_cc(name="vrp") - -code_sample_cc(name="vrp_breaks") - -code_sample_cc(name="vrp_capacity") - -code_sample_cc(name="vrp_drop_nodes") - -code_sample_cc(name="vrp_global_span") - -code_sample_cc(name="vrp_initial_routes") - -code_sample_cc(name="vrp_pickup_delivery") - -code_sample_cc(name="vrp_pickup_delivery_fifo") - -code_sample_cc(name="vrp_pickup_delivery_lifo") - -code_sample_cc(name="vrp_resources") - -code_sample_cc(name="vrp_starts_ends") - -code_sample_cc(name="vrp_time_windows") - -code_sample_cc(name="vrp_with_time_limit") diff --git a/ortools/constraint_solver/samples/code_samples.bzl b/ortools/constraint_solver/samples/code_samples.bzl index 3eacc96df9..7a78d8a8f1 100644 --- a/ortools/constraint_solver/samples/code_samples.bzl +++ b/ortools/constraint_solver/samples/code_samples.bzl @@ -20,8 +20,6 @@ def code_sample_cc(name): deps=[ "//ortools/base", "//ortools/constraint_solver:cp", - "//ortools/constraint_solver:routing", - "//ortools/routing:enums_cc_proto", ], ) @@ -33,7 +31,5 @@ def code_sample_cc(name): ":" + name + "_cc", "//ortools/base", "//ortools/constraint_solver:cp", - "//ortools/constraint_solver:routing", - "//ortools/routing:enums_cc_proto", ], ) diff --git a/ortools/constraint_solver/search.cc b/ortools/constraint_solver/search.cc index cf21d85a13..19800f46c2 100644 --- a/ortools/constraint_solver/search.cc +++ b/ortools/constraint_solver/search.cc @@ -3778,9 +3778,11 @@ int64_t GuidedLocalSearchPenaltiesMap::GetPenalty( template class GuidedLocalSearch : public Metaheuristic { public: - GuidedLocalSearch(Solver* solver, IntVar* objective, bool maximize, - int64_t step, const std::vector& vars, - double penalty_factor, + GuidedLocalSearch( + Solver* solver, IntVar* objective, bool maximize, int64_t step, + const std::vector& vars, double penalty_factor, + std::function>(int64_t, int64_t)> + get_equivalent_pairs, bool reset_penalties_on_new_best_solution); ~GuidedLocalSearch() override {} bool AcceptDelta(Assignment* delta, Assignment* deltadelta) override; @@ -3871,6 +3873,8 @@ class GuidedLocalSearch : public Metaheuristic { P penalties_; DirtyArray penalized_values_; bool incremental_; + std::function>(int64_t, int64_t)> + get_equivalent_pairs_; const bool reset_penalties_on_new_best_solution_; }; @@ -3878,6 +3882,8 @@ template GuidedLocalSearch

::GuidedLocalSearch( Solver* solver, IntVar* objective, bool maximize, int64_t step, const std::vector& vars, double penalty_factor, + std::function>(int64_t, int64_t)> + get_equivalent_pairs, bool reset_penalties_on_new_best_solution) : Metaheuristic(solver, {maximize}, {objective}, {step}), penalized_objective_(nullptr), @@ -3888,6 +3894,7 @@ GuidedLocalSearch

::GuidedLocalSearch( penalties_(vars.size()), penalized_values_(vars.size()), incremental_(false), + get_equivalent_pairs_(std::move(get_equivalent_pairs)), reset_penalties_on_new_best_solution_( reset_penalties_on_new_best_solution) { AddVars(vars); @@ -4071,7 +4078,15 @@ bool GuidedLocalSearch

::LocalOptimum() { if (utilities[var] == max_utility) { const IntVarElement& element = assignment_.Element(var); DCHECK(element.Bound()); - penalties_.IncrementPenalty({var, element.Value()}); + const int64_t value = element.Value(); + if (get_equivalent_pairs_ == nullptr) { + penalties_.IncrementPenalty({var, value}); + } else { + for (const auto [other_var, other_value] : + get_equivalent_pairs_(var, value)) { + penalties_.IncrementPenalty({other_var, other_value}); + } + } } } SetCurrentInternalValue(0, std::numeric_limits::max()); @@ -4085,7 +4100,10 @@ class BinaryGuidedLocalSearch : public GuidedLocalSearch

{ Solver* solver, IntVar* objective, std::function objective_function, bool maximize, int64_t step, const std::vector& vars, - double penalty_factor, bool reset_penalties_on_new_best_solution); + double penalty_factor, + std::function>(int64_t, int64_t)> + get_equivalent_pairs, + bool reset_penalties_on_new_best_solution); ~BinaryGuidedLocalSearch() override {} IntExpr* MakeElementPenalty(int index) override; int64_t AssignmentElementPenalty(int index) const override; @@ -4103,11 +4121,16 @@ BinaryGuidedLocalSearch

::BinaryGuidedLocalSearch( Solver* const solver, IntVar* const objective, std::function objective_function, bool maximize, int64_t step, const std::vector& vars, double penalty_factor, + std::function>(int64_t, int64_t)> + get_equivalent_pairs, bool reset_penalties_on_new_best_solution) : GuidedLocalSearch

(solver, objective, maximize, step, vars, - penalty_factor, + penalty_factor, std::move(get_equivalent_pairs), reset_penalties_on_new_best_solution), - objective_function_(std::move(objective_function)) {} + objective_function_(std::move(objective_function)) { + solver->SetGuidedLocalSearchPenaltyCallback( + [this](int64_t i, int64_t j, int64_t k) { return PenalizedValue(i, j); }); +} template IntExpr* BinaryGuidedLocalSearch

::MakeElementPenalty(int index) { @@ -4171,6 +4194,8 @@ class TernaryGuidedLocalSearch : public GuidedLocalSearch

{ std::function objective_function, bool maximize, int64_t step, const std::vector& vars, const std::vector& secondary_vars, double penalty_factor, + std::function>(int64_t, int64_t)> + get_equivalent_pairs, bool reset_penalties_on_new_best_solution); ~TernaryGuidedLocalSearch() override {} IntExpr* MakeElementPenalty(int index) override; @@ -4192,13 +4217,19 @@ TernaryGuidedLocalSearch

::TernaryGuidedLocalSearch( std::function objective_function, bool maximize, int64_t step, const std::vector& vars, const std::vector& secondary_vars, double penalty_factor, + std::function>(int64_t, int64_t)> + get_equivalent_pairs, bool reset_penalties_on_new_best_solution) : GuidedLocalSearch

(solver, objective, maximize, step, vars, - penalty_factor, + penalty_factor, std::move(get_equivalent_pairs), reset_penalties_on_new_best_solution), objective_function_(std::move(objective_function)), secondary_values_(this->NumPrimaryVars(), -1) { this->AddVars(secondary_vars); + solver->SetGuidedLocalSearchPenaltyCallback( + [this](int64_t i, int64_t j, int64_t k) { + return PenalizedValue(i, j, k); + }); } template @@ -4289,16 +4320,20 @@ ObjectiveMonitor* Solver::MakeGuidedLocalSearch( bool maximize, IntVar* const objective, Solver::IndexEvaluator2 objective_function, int64_t step, const std::vector& vars, double penalty_factor, + std::function>(int64_t, int64_t)> + get_equivalent_pairs, bool reset_penalties_on_new_best_solution) { if (absl::GetFlag(FLAGS_cp_use_sparse_gls_penalties)) { return RevAlloc(new BinaryGuidedLocalSearch( this, objective, std::move(objective_function), maximize, step, vars, - penalty_factor, reset_penalties_on_new_best_solution)); + penalty_factor, std::move(get_equivalent_pairs), + reset_penalties_on_new_best_solution)); } else { return RevAlloc( new BinaryGuidedLocalSearch( this, objective, std::move(objective_function), maximize, step, - vars, penalty_factor, reset_penalties_on_new_best_solution)); + vars, penalty_factor, std::move(get_equivalent_pairs), + reset_penalties_on_new_best_solution)); } } @@ -4307,16 +4342,20 @@ ObjectiveMonitor* Solver::MakeGuidedLocalSearch( Solver::IndexEvaluator3 objective_function, int64_t step, const std::vector& vars, const std::vector& secondary_vars, double penalty_factor, + std::function>(int64_t, int64_t)> + get_equivalent_pairs, bool reset_penalties_on_new_best_solution) { if (absl::GetFlag(FLAGS_cp_use_sparse_gls_penalties)) { return RevAlloc(new TernaryGuidedLocalSearch( this, objective, std::move(objective_function), maximize, step, vars, - secondary_vars, penalty_factor, reset_penalties_on_new_best_solution)); + secondary_vars, penalty_factor, std::move(get_equivalent_pairs), + reset_penalties_on_new_best_solution)); } else { return RevAlloc( new TernaryGuidedLocalSearch( this, objective, std::move(objective_function), maximize, step, vars, secondary_vars, penalty_factor, + std::move(get_equivalent_pairs), reset_penalties_on_new_best_solution)); } } diff --git a/ortools/routing/BUILD.bazel b/ortools/routing/BUILD.bazel index ad3a31a992..02f2e514b8 100644 --- a/ortools/routing/BUILD.bazel +++ b/ortools/routing/BUILD.bazel @@ -16,6 +16,21 @@ load("@rules_proto//proto:defs.bzl", "proto_library") package(default_visibility = ["//visibility:public"]) +config_setting( + name = "on_linux", + constraint_values = ["@platforms//os:linux"], +) + +config_setting( + name = "on_macos", + constraint_values = ["@platforms//os:macos"], +) + +config_setting( + name = "on_windows", + constraint_values = ["@platforms//os:windows"], +) + proto_library( name = "ils_proto", srcs = ["ils.proto"], @@ -69,3 +84,162 @@ cc_proto_library( # name = "parameters_py_pb2", # deps = [":parameters_proto"], #) + +cc_library( + name = "parameters", + srcs = ["parameters.cc"], + hdrs = ["parameters.h"], + deps = [ + "//ortools/base", + "//ortools/base:protoutil", + "//ortools/constraint_solver:cp", + "//ortools/constraint_solver:solver_parameters_cc_proto", + "//ortools/port:proto_utils", + "//ortools/routing:enums_cc_proto", + "//ortools/routing:parameters_cc_proto", + "//ortools/util:optional_boolean_cc_proto", + "//ortools/util:testing_utils", + "@com_google_absl//absl/status:statusor", + "@com_google_absl//absl/strings", + "@com_google_absl//absl/time", + "@com_google_protobuf//:protobuf", + ], +) + +cc_library( + name = "types", + hdrs = ["types.h"], + deps = [ + "//ortools/base", + "//ortools/base:intops", + ], +) + +cc_library( + name = "utils", + srcs = ["utils.cc"], + hdrs = ["utils.h"], + visibility = ["//visibility:public"], + deps = [ + "//ortools/base", + "//ortools/util:saturated_arithmetic", + ], +) + +cc_library( + name = "neighborhoods", + srcs = ["neighborhoods.cc"], + hdrs = ["neighborhoods.h"], + visibility = ["//visibility:public"], + deps = [ + ":types", + ":utils", + "//ortools/base", + "//ortools/constraint_solver:cp", + ], +) + +cc_library( + name = "index_manager", + srcs = ["index_manager.cc"], + hdrs = ["index_manager.h"], + deps = [ + ":types", + "//ortools/base", + "//ortools/base:map_util", + "//ortools/base:strong_vector", + "@com_google_absl//absl/container:flat_hash_set", + ], +) + +cc_library( + name = "routing", + srcs = [ + "breaks.cc", + "constraints.cc", + "decision_builders.cc", + "filters.cc", + "flow.cc", + "ils.cc", + "insertion_lns.cc", + "lp_scheduling.cc", + "routing.cc", + "sat.cc", + "search.cc", + ], + hdrs = [ + "constraints.h", + "decision_builders.h", + "filters.h", + "ils.h", + "insertion_lns.h", + "lp_scheduling.h", + "routing.h", + "search.h", + ], + copts = select({ + "on_linux": [], + "on_macos": [], + "on_windows": ["/Zc:preprocessor"], + "//conditions:default": [], + }), + deps = [ + ":index_manager", + ":neighborhoods", + ":parameters", + ":types", + ":utils", + "//ortools/base", + "//ortools/base:adjustable_priority_queue", + "//ortools/base:dump_vars", + "//ortools/base:hash", + "//ortools/base:map_util", + "//ortools/base:murmur", + "//ortools/base:protoutil", + "//ortools/base:small_map", + "//ortools/base:stl_util", + "//ortools/base:strong_vector", + "//ortools/constraint_solver:cp", + "//ortools/glop:lp_solver", + "//ortools/graph", + "//ortools/graph:christofides", + "//ortools/graph:connected_components", + "//ortools/graph:linear_assignment", + "//ortools/graph:min_cost_flow", + "//ortools/graph:topologicalsorter", + "//ortools/lp_data", + "//ortools/lp_data:base", + "//ortools/routing:enums_cc_proto", + "//ortools/routing:parameters_cc_proto", + "//ortools/sat:boolean_problem", + "//ortools/sat:cp_constraints", + "//ortools/sat:cp_model", + "//ortools/sat:cp_model_cc_proto", + "//ortools/sat:cp_model_checker", + "//ortools/sat:cp_model_solver", + "//ortools/sat:cp_model_utils", + "//ortools/sat:integer", + "//ortools/sat:integer_expr", + "//ortools/sat:model", + "//ortools/sat:optimization", + "//ortools/sat:theta_tree", + "//ortools/util:bitset", + "//ortools/util:flat_matrix", + "//ortools/util:optional_boolean_cc_proto", + "//ortools/util:range_query_function", + "//ortools/util:saturated_arithmetic", + "//ortools/util:sorted_interval_list", + "@com_google_absl//absl/container:btree", + "@com_google_absl//absl/container:flat_hash_map", + "@com_google_absl//absl/container:flat_hash_set", + "@com_google_absl//absl/container:inlined_vector", + "@com_google_absl//absl/functional:bind_front", + "@com_google_absl//absl/hash", + "@com_google_absl//absl/memory", + "@com_google_absl//absl/strings", + "@com_google_absl//absl/strings:str_format", + "@com_google_absl//absl/time", + "@com_google_absl//absl/types:span", + "@com_google_protobuf//:protobuf", + ], +) diff --git a/ortools/routing/CMakeLists.txt b/ortools/routing/CMakeLists.txt new file mode 100644 index 0000000000..3278bca04e --- /dev/null +++ b/ortools/routing/CMakeLists.txt @@ -0,0 +1,35 @@ +# Copyright 2010-2024 Google LLC +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +file(GLOB _SRCS "*.h" "*.cc") +set(NAME ${PROJECT_NAME}_routing) + +# Will be merge in libortools.so +#add_library(${NAME} STATIC ${_SRCS}) +add_library(${NAME} OBJECT ${_SRCS}) +set_target_properties(${NAME} PROPERTIES + POSITION_INDEPENDENT_CODE ON + ) +target_include_directories(${NAME} PRIVATE + ${PROJECT_SOURCE_DIR} + ${PROJECT_BINARY_DIR}) +target_link_libraries(${NAME} PRIVATE + ZLIB::ZLIB + absl::base + absl::memory + absl::strings + absl::str_format + protobuf::libprotobuf + ${PROJECT_NAMESPACE}::ortools_proto + ${PROJECT_NAMESPACE}::routing_proto) +#add_library(${PROJECT_NAMESPACE}::routing ALIAS ${NAME}) diff --git a/ortools/routing/README.md b/ortools/routing/README.md index 3fa3de7a65..7042779ffd 100644 --- a/ortools/routing/README.md +++ b/ortools/routing/README.md @@ -1,6 +1,30 @@ # Routing -This folder contains utilities related to routing problems, currently only -utilities for file formats in the -[`parsers`](../routing/parsers) -subfolder. +[Vehicle Routing](http://en.wikipedia.org/wiki/Vehicle_routing) is a useful +extension that is implemented on top of the CP solver library. + +## Routing solver + +To begin, skim: + +* [routing.h](../routing/routing.h): The + vehicle routing library lets one model and solve generic vehicle routing + problems ranging from the Traveling Salesman Problem to more complex + problems such as the Capacitated Vehicle Routing Problem with Time Windows. + +### Parameters + +* [routing_parameters.proto](../routing/parameters.proto): + The Vehicle Routing solver parameters. +* [routing_enums.proto](../routing/enums.proto): + Enums used to define routing parameters. + +### Solution + +* [assignment.proto](../constraint_solver/assignment.proto): + Holds the solution of a Routing problem (as a special case of a CS problem). + +## Parsers + +Utilities for file formats are in the +[`parsers`](../routing/parsers) subfolder. diff --git a/ortools/constraint_solver/routing_breaks.cc b/ortools/routing/breaks.cc similarity index 99% rename from ortools/constraint_solver/routing_breaks.cc rename to ortools/routing/breaks.cc index 0eb20cd723..a6b165e1c7 100644 --- a/ortools/constraint_solver/routing_breaks.cc +++ b/ortools/routing/breaks.cc @@ -27,8 +27,8 @@ #include "ortools/base/types.h" #include "ortools/constraint_solver/constraint_solver.h" #include "ortools/constraint_solver/constraint_solveri.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_filters.h" +#include "ortools/routing/filters.h" +#include "ortools/routing/routing.h" #include "ortools/sat/theta_tree.h" #include "ortools/util/saturated_arithmetic.h" #include "ortools/util/sorted_interval_list.h" diff --git a/ortools/constraint_solver/routing_constraints.cc b/ortools/routing/constraints.cc similarity index 90% rename from ortools/constraint_solver/routing_constraints.cc rename to ortools/routing/constraints.cc index 33f6c8d1ae..ae360c7948 100644 --- a/ortools/constraint_solver/routing_constraints.cc +++ b/ortools/routing/constraints.cc @@ -11,12 +11,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "ortools/constraint_solver/routing_constraints.h" +#include "ortools/routing/constraints.h" #include #include #include #include +#include #include #include #include @@ -26,9 +27,9 @@ #include "ortools/base/strong_vector.h" #include "ortools/constraint_solver/constraint_solver.h" #include "ortools/constraint_solver/constraint_solveri.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_lp_scheduling.h" -#include "ortools/constraint_solver/routing_search.h" +#include "ortools/routing/lp_scheduling.h" +#include "ortools/routing/routing.h" +#include "ortools/routing/search.h" #include "ortools/util/saturated_arithmetic.h" namespace operations_research { @@ -705,5 +706,90 @@ std::string LightRangeLessOrEqual::DebugString() const { return left_->DebugString() + " < " + right_->DebugString(); } } // namespace +namespace { + +class RouteConstraint : public Constraint { + public: + RouteConstraint( + RoutingModel* model, std::vector route_cost_vars, + std::function(const std::vector&)> + route_evaluator) + : Constraint(model->solver()), + model_(model), + route_cost_vars_(std::move(route_cost_vars)), + route_evaluator_(std::move(route_evaluator)), + starts_(model->Size() + model->vehicles(), -1), + ends_(model->Size() + model->vehicles(), -1) { + const int size = model_->Size() + model_->vehicles(); + for (int i = 0; i < size; ++i) { + starts_.SetValue(solver(), i, i); + ends_.SetValue(solver(), i, i); + } + } + ~RouteConstraint() override {} + void Post() override { + const std::vector nexts = model_->Nexts(); + for (int i = 0; i < nexts.size(); ++i) { + if (!nexts[i]->Bound()) { + auto* demon = MakeConstraintDemon2( + model_->solver(), this, &RouteConstraint::AddLink, + "RouteConstraint::AddLink", i, nexts[i]); + nexts[i]->WhenBound(demon); + } + } + } + void InitialPropagate() override { + const std::vector nexts = model_->Nexts(); + for (int i = 0; i < nexts.size(); ++i) { + if (nexts[i]->Bound()) { + AddLink(i, nexts[i]); + } + } + } + std::string DebugString() const override { return "RouteConstraint"; } + + private: + void AddLink(int index, IntVar* next) { + DCHECK(next->Bound()); + const int64_t chain_start = starts_.Value(index); + const int64_t index_next = next->Min(); + const int64_t chain_end = ends_.Value(index_next); + starts_.SetValue(solver(), chain_end, chain_start); + ends_.SetValue(solver(), chain_start, chain_end); + if (model_->IsStart(chain_start) && model_->IsEnd(chain_end)) { + CheckRoute(chain_start, chain_end); + } + } + void CheckRoute(int64_t start, int64_t end) { + route_.clear(); + for (int64_t node = start; node != end; + node = model_->NextVar(node)->Min()) { + route_.push_back(node); + } + route_.push_back(end); + std::optional cost = route_evaluator_(route_); + if (!cost.has_value()) { + solver()->Fail(); + } + route_cost_vars_[model_->VehicleIndex(start)]->SetValue(cost.value()); + } + + RoutingModel* const model_; + std::vector route_cost_vars_; + std::function(const std::vector&)> + route_evaluator_; + RevArray starts_; + RevArray ends_; + std::vector route_; +}; +} // namespace + +Constraint* MakeRouteConstraint( + RoutingModel* model, std::vector route_cost_vars, + std::function(const std::vector&)> + route_evaluator) { + return model->solver()->RevAlloc(new RouteConstraint( + model, std::move(route_cost_vars), std::move(route_evaluator))); +} } // namespace operations_research diff --git a/ortools/constraint_solver/routing_constraints.h b/ortools/routing/constraints.h similarity index 81% rename from ortools/constraint_solver/routing_constraints.h rename to ortools/routing/constraints.h index a861b9cff2..db3626cce0 100644 --- a/ortools/constraint_solver/routing_constraints.h +++ b/ortools/routing/constraints.h @@ -11,14 +11,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_CONSTRAINTS_H_ -#define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_CONSTRAINTS_H_ +#ifndef OR_TOOLS_ROUTING_CONSTRAINTS_H_ +#define OR_TOOLS_ROUTING_CONSTRAINTS_H_ #include +#include +#include #include #include "ortools/constraint_solver/constraint_solver.h" -#include "ortools/constraint_solver/routing.h" +#include "ortools/routing/routing.h" namespace operations_research { @@ -42,6 +44,11 @@ Constraint* MakePathSpansAndTotalSlacks(const RoutingDimension* dimension, std::vector spans, std::vector total_slacks); +Constraint* MakeRouteConstraint( + RoutingModel* model, std::vector route_cost_vars, + std::function(const std::vector&)> + route_evaluator); + } // namespace operations_research -#endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_CONSTRAINTS_H_ +#endif // OR_TOOLS_ROUTING_CONSTRAINTS_H_ diff --git a/ortools/routing/csharp/routing_index_manager.i b/ortools/routing/csharp/index_manager.i similarity index 90% rename from ortools/routing/csharp/routing_index_manager.i rename to ortools/routing/csharp/index_manager.i index 950381b4a6..70c1af7548 100644 --- a/ortools/routing/csharp/routing_index_manager.i +++ b/ortools/routing/csharp/index_manager.i @@ -13,10 +13,10 @@ // Wrapper for RoutingIndexManager. -%include "ortools/routing/csharp/routing_types.i" +%include "ortools/routing/csharp/types.i" %{ -#include "ortools/constraint_solver/routing_index_manager.h" +#include "ortools/routing/index_manager.h" %} DEFINE_INDEX_TYPE_TYPEDEF(operations_research::RoutingNodeIndex, @@ -47,6 +47,6 @@ namespace operations_research { } // namespace operations_research -%include "ortools/constraint_solver/routing_index_manager.h" +%include "ortools/routing/index_manager.h" %unignoreall diff --git a/ortools/routing/csharp/routing.i b/ortools/routing/csharp/routing.i index 6dbd1b9c14..44d6bcd780 100644 --- a/ortools/routing/csharp/routing.i +++ b/ortools/routing/csharp/routing.i @@ -43,7 +43,7 @@ JAGGED_MATRIX_AS_CSHARP_ARRAY(int64_t, int64_t, long, Int64VectorVector); %import "ortools/constraint_solver/csharp/constraint_solver.i" %import "ortools/util/csharp/sorted_interval_list.i" // Domain -%include "ortools/routing/csharp/routing_index_manager.i" +%include "ortools/routing/csharp/index_manager.i" // We need to forward-declare the proto here, so that PROTO_INPUT involving it // works correctly. The order matters very much: this declaration needs to be @@ -58,12 +58,12 @@ class RoutingSearchStatus; // Include the file we want to wrap a first time. %{ -#include "ortools/constraint_solver/routing_types.h" -#include "ortools/constraint_solver/routing_parameters.h" +#include "ortools/routing/types.h" +#include "ortools/routing/parameters.h" #include "ortools/routing/enums.pb.h" #include "ortools/routing/parameters.pb.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/routing.h" %} // RoutingModel methods. @@ -252,5 +252,5 @@ using Google.OrTools.ConstraintSolver; // Wrap routing includes // TODO(user): Replace with %ignoreall/%unignoreall //swiglint: disable include-h-allglobals -%include "ortools/constraint_solver/routing_parameters.h" -%include "ortools/constraint_solver/routing.h" +%include "ortools/routing/parameters.h" +%include "ortools/routing/routing.h" diff --git a/ortools/routing/csharp/routing_types.i b/ortools/routing/csharp/types.i similarity index 96% rename from ortools/routing/csharp/routing_types.i rename to ortools/routing/csharp/types.i index f2556e5e7d..22c2c95a29 100644 --- a/ortools/routing/csharp/routing_types.i +++ b/ortools/routing/csharp/types.i @@ -20,7 +20,7 @@ %import "ortools/util/csharp/vector.i" %{ -#include "ortools/constraint_solver/routing_types.h" +#include "ortools/routing/types.h" %} // This macro defines typemaps for IndexT, std::vector and @@ -87,6 +87,6 @@ namespace operations_research { } // namespace operations_research -%include "ortools/constraint_solver/routing_types.h" +%include "ortools/routing/types.h" %unignoreall diff --git a/ortools/constraint_solver/routing_decision_builders.cc b/ortools/routing/decision_builders.cc similarity index 99% rename from ortools/constraint_solver/routing_decision_builders.cc rename to ortools/routing/decision_builders.cc index 21f317c9d7..766f253545 100644 --- a/ortools/constraint_solver/routing_decision_builders.cc +++ b/ortools/routing/decision_builders.cc @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "ortools/constraint_solver/routing_decision_builders.h" +#include "ortools/routing/decision_builders.h" #include #include @@ -27,8 +27,8 @@ #include "ortools/base/map_util.h" #include "ortools/base/strong_vector.h" #include "ortools/constraint_solver/constraint_solver.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_lp_scheduling.h" +#include "ortools/routing/lp_scheduling.h" +#include "ortools/routing/routing.h" #include "ortools/util/saturated_arithmetic.h" namespace operations_research { diff --git a/ortools/constraint_solver/routing_decision_builders.h b/ortools/routing/decision_builders.h similarity index 94% rename from ortools/constraint_solver/routing_decision_builders.h rename to ortools/routing/decision_builders.h index 9817abbf36..5b511acb3d 100644 --- a/ortools/constraint_solver/routing_decision_builders.h +++ b/ortools/routing/decision_builders.h @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_DECISION_BUILDERS_H_ -#define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_DECISION_BUILDERS_H_ +#ifndef OR_TOOLS_ROUTING_DECISION_BUILDERS_H_ +#define OR_TOOLS_ROUTING_DECISION_BUILDERS_H_ #include #include @@ -21,8 +21,8 @@ #include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.h" #include "ortools/constraint_solver/constraint_solver.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_lp_scheduling.h" +#include "ortools/routing/lp_scheduling.h" +#include "ortools/routing/routing.h" namespace operations_research { @@ -109,4 +109,4 @@ class FinalizerVariables { }; } // namespace operations_research -#endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_DECISION_BUILDERS_H_ +#endif // OR_TOOLS_ROUTING_DECISION_BUILDERS_H_ diff --git a/ortools/constraint_solver/docs/PDP.md b/ortools/routing/docs/PDP.md similarity index 100% rename from ortools/constraint_solver/docs/PDP.md rename to ortools/routing/docs/PDP.md diff --git a/ortools/routing/docs/README.md b/ortools/routing/docs/README.md new file mode 100644 index 0000000000..7a870fc940 --- /dev/null +++ b/ortools/routing/docs/README.md @@ -0,0 +1,10 @@ +# Overview + +You can find here the documentation for the following OR-Tools component. + +* [Routing Solver](ROUTING.md) + + A specialized library for identifying best vehicle routes given constraints. + + This library extension is implemented on top of the + [CP Solver library](../../constraint_solver/docs/README.md). diff --git a/ortools/constraint_solver/docs/ROUTING.md b/ortools/routing/docs/ROUTING.md similarity index 96% rename from ortools/constraint_solver/docs/ROUTING.md rename to ortools/routing/docs/ROUTING.md index 3a75637fd9..7657c34839 100644 --- a/ortools/constraint_solver/docs/ROUTING.md +++ b/ortools/routing/docs/ROUTING.md @@ -24,10 +24,10 @@ and .Net. Each language have different requirements for the code samples. #include #include -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" namespace operations_research { @@ -93,8 +93,8 @@ int main(int /*argc*/, char* /*argv*/[]) { #!/usr/bin/env python3 """Vehicle Routing example.""" -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting def main(): @@ -105,10 +105,10 @@ def main(): depot = 0 # Create the routing index manager. - manager = pywrapcp.RoutingIndexManager(num_locations, num_vehicles, depot) + manager = pywraprouting.RoutingIndexManager(num_locations, num_vehicles, depot) # Create Routing Model. - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # Create and register a transit callback. def distance_callback(from_index, to_index): @@ -124,7 +124,7 @@ def main(): routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) # Setting first solution heuristic. - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) # pylint: disable=no-member diff --git a/ortools/constraint_solver/docs/TSP.md b/ortools/routing/docs/TSP.md similarity index 100% rename from ortools/constraint_solver/docs/TSP.md rename to ortools/routing/docs/TSP.md diff --git a/ortools/constraint_solver/docs/VRP.md b/ortools/routing/docs/VRP.md similarity index 100% rename from ortools/constraint_solver/docs/VRP.md rename to ortools/routing/docs/VRP.md diff --git a/ortools/constraint_solver/docs/generate_svg.sh b/ortools/routing/docs/generate_svg.sh similarity index 100% rename from ortools/constraint_solver/docs/generate_svg.sh rename to ortools/routing/docs/generate_svg.sh diff --git a/ortools/constraint_solver/docs/routing_svg.py b/ortools/routing/docs/routing_svg.py similarity index 100% rename from ortools/constraint_solver/docs/routing_svg.py rename to ortools/routing/docs/routing_svg.py diff --git a/ortools/constraint_solver/docs/tsp.svg b/ortools/routing/docs/tsp.svg similarity index 100% rename from ortools/constraint_solver/docs/tsp.svg rename to ortools/routing/docs/tsp.svg diff --git a/ortools/constraint_solver/docs/tsp_distance_matrix.svg b/ortools/routing/docs/tsp_distance_matrix.svg similarity index 100% rename from ortools/constraint_solver/docs/tsp_distance_matrix.svg rename to ortools/routing/docs/tsp_distance_matrix.svg diff --git a/ortools/constraint_solver/docs/tsp_distance_matrix_solution.svg b/ortools/routing/docs/tsp_distance_matrix_solution.svg similarity index 100% rename from ortools/constraint_solver/docs/tsp_distance_matrix_solution.svg rename to ortools/routing/docs/tsp_distance_matrix_solution.svg diff --git a/ortools/constraint_solver/docs/tsp_solution.svg b/ortools/routing/docs/tsp_solution.svg similarity index 100% rename from ortools/constraint_solver/docs/tsp_solution.svg rename to ortools/routing/docs/tsp_solution.svg diff --git a/ortools/constraint_solver/docs/vrp.svg b/ortools/routing/docs/vrp.svg similarity index 100% rename from ortools/constraint_solver/docs/vrp.svg rename to ortools/routing/docs/vrp.svg diff --git a/ortools/constraint_solver/docs/vrp_capacity.svg b/ortools/routing/docs/vrp_capacity.svg similarity index 100% rename from ortools/constraint_solver/docs/vrp_capacity.svg rename to ortools/routing/docs/vrp_capacity.svg diff --git a/ortools/constraint_solver/docs/vrp_capacity_solution.svg b/ortools/routing/docs/vrp_capacity_solution.svg similarity index 100% rename from ortools/constraint_solver/docs/vrp_capacity_solution.svg rename to ortools/routing/docs/vrp_capacity_solution.svg diff --git a/ortools/constraint_solver/docs/vrp_drop_nodes.svg b/ortools/routing/docs/vrp_drop_nodes.svg similarity index 100% rename from ortools/constraint_solver/docs/vrp_drop_nodes.svg rename to ortools/routing/docs/vrp_drop_nodes.svg diff --git a/ortools/constraint_solver/docs/vrp_drop_nodes_solution.svg b/ortools/routing/docs/vrp_drop_nodes_solution.svg similarity index 100% rename from ortools/constraint_solver/docs/vrp_drop_nodes_solution.svg rename to ortools/routing/docs/vrp_drop_nodes_solution.svg diff --git a/ortools/constraint_solver/docs/vrp_global_span.svg b/ortools/routing/docs/vrp_global_span.svg similarity index 100% rename from ortools/constraint_solver/docs/vrp_global_span.svg rename to ortools/routing/docs/vrp_global_span.svg diff --git a/ortools/constraint_solver/docs/vrp_global_span_solution.svg b/ortools/routing/docs/vrp_global_span_solution.svg similarity index 100% rename from ortools/constraint_solver/docs/vrp_global_span_solution.svg rename to ortools/routing/docs/vrp_global_span_solution.svg diff --git a/ortools/constraint_solver/docs/vrp_pickup_delivery.svg b/ortools/routing/docs/vrp_pickup_delivery.svg similarity index 100% rename from ortools/constraint_solver/docs/vrp_pickup_delivery.svg rename to ortools/routing/docs/vrp_pickup_delivery.svg diff --git a/ortools/constraint_solver/docs/vrp_pickup_delivery_fifo_solution.svg b/ortools/routing/docs/vrp_pickup_delivery_fifo_solution.svg similarity index 100% rename from ortools/constraint_solver/docs/vrp_pickup_delivery_fifo_solution.svg rename to ortools/routing/docs/vrp_pickup_delivery_fifo_solution.svg diff --git a/ortools/constraint_solver/docs/vrp_pickup_delivery_lifo_solution.svg b/ortools/routing/docs/vrp_pickup_delivery_lifo_solution.svg similarity index 100% rename from ortools/constraint_solver/docs/vrp_pickup_delivery_lifo_solution.svg rename to ortools/routing/docs/vrp_pickup_delivery_lifo_solution.svg diff --git a/ortools/constraint_solver/docs/vrp_pickup_delivery_solution.svg b/ortools/routing/docs/vrp_pickup_delivery_solution.svg similarity index 100% rename from ortools/constraint_solver/docs/vrp_pickup_delivery_solution.svg rename to ortools/routing/docs/vrp_pickup_delivery_solution.svg diff --git a/ortools/constraint_solver/docs/vrp_resources.svg b/ortools/routing/docs/vrp_resources.svg similarity index 100% rename from ortools/constraint_solver/docs/vrp_resources.svg rename to ortools/routing/docs/vrp_resources.svg diff --git a/ortools/constraint_solver/docs/vrp_resources_solution.svg b/ortools/routing/docs/vrp_resources_solution.svg similarity index 100% rename from ortools/constraint_solver/docs/vrp_resources_solution.svg rename to ortools/routing/docs/vrp_resources_solution.svg diff --git a/ortools/constraint_solver/docs/vrp_solution.svg b/ortools/routing/docs/vrp_solution.svg similarity index 100% rename from ortools/constraint_solver/docs/vrp_solution.svg rename to ortools/routing/docs/vrp_solution.svg diff --git a/ortools/constraint_solver/docs/vrp_starts_ends.svg b/ortools/routing/docs/vrp_starts_ends.svg similarity index 100% rename from ortools/constraint_solver/docs/vrp_starts_ends.svg rename to ortools/routing/docs/vrp_starts_ends.svg diff --git a/ortools/constraint_solver/docs/vrp_starts_ends_solution.svg b/ortools/routing/docs/vrp_starts_ends_solution.svg similarity index 100% rename from ortools/constraint_solver/docs/vrp_starts_ends_solution.svg rename to ortools/routing/docs/vrp_starts_ends_solution.svg diff --git a/ortools/constraint_solver/docs/vrp_time_windows.svg b/ortools/routing/docs/vrp_time_windows.svg similarity index 100% rename from ortools/constraint_solver/docs/vrp_time_windows.svg rename to ortools/routing/docs/vrp_time_windows.svg diff --git a/ortools/constraint_solver/docs/vrp_time_windows_solution.svg b/ortools/routing/docs/vrp_time_windows_solution.svg similarity index 100% rename from ortools/constraint_solver/docs/vrp_time_windows_solution.svg rename to ortools/routing/docs/vrp_time_windows_solution.svg diff --git a/ortools/constraint_solver/routing_filters.cc b/ortools/routing/filters.cc similarity index 98% rename from ortools/constraint_solver/routing_filters.cc rename to ortools/routing/filters.cc index b9f08039c1..dc54fbc016 100644 --- a/ortools/constraint_solver/routing_filters.cc +++ b/ortools/routing/filters.cc @@ -13,7 +13,7 @@ // Implementation of local search filters for routing models. -#include "ortools/constraint_solver/routing_filters.h" +#include "ortools/routing/filters.h" #include @@ -46,10 +46,10 @@ #include "ortools/base/types.h" #include "ortools/constraint_solver/constraint_solver.h" #include "ortools/constraint_solver/constraint_solveri.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_lp_scheduling.h" -#include "ortools/constraint_solver/routing_types.h" +#include "ortools/routing/lp_scheduling.h" #include "ortools/routing/parameters.pb.h" +#include "ortools/routing/routing.h" +#include "ortools/routing/types.h" #include "ortools/util/bitset.h" #include "ortools/util/piecewise_linear_function.h" #include "ortools/util/saturated_arithmetic.h" @@ -60,6 +60,105 @@ ABSL_FLAG(bool, routing_strong_debug_checks, false, namespace operations_research { +namespace { +// Route constraint filter + +class RouteConstraintFilter : public BasePathFilter { + public: + explicit RouteConstraintFilter(const RoutingModel& routing_model) + : BasePathFilter(routing_model.Nexts(), + routing_model.Size() + routing_model.vehicles(), + routing_model.GetPathsMetadata()), + routing_model_(routing_model), + current_vehicle_cost_(0), + delta_vehicle_cost_(0), + current_vehicle_costs_(routing_model.vehicles(), 0) { + start_to_vehicle_.resize(Size(), -1); + vehicle_to_start_.resize(routing_model.vehicles()); + for (int v = 0; v < routing_model.vehicles(); v++) { + const int64_t start = routing_model.Start(v); + start_to_vehicle_[start] = v; + vehicle_to_start_[v] = start; + } + } + ~RouteConstraintFilter() override {} + std::string DebugString() const override { return "RouteConstraintFilter"; } + int64_t GetSynchronizedObjectiveValue() const override { + return current_vehicle_cost_; + } + int64_t GetAcceptedObjectiveValue() const override { + return lns_detected() ? 0 : delta_vehicle_cost_; + } + + private: + void OnSynchronizePathFromStart(int64_t start) override { + route_.clear(); + int64_t node = start; + while (node < Size()) { + route_.push_back(node); + node = Value(node); + } + route_.push_back(node); + std::optional route_cost = routing_model_.GetRouteCost(route_); + DCHECK(route_cost.has_value()); + current_vehicle_costs_[start_to_vehicle_[start]] = route_cost.value(); + } + void OnAfterSynchronizePaths() override { + current_vehicle_cost_ = 0; + for (int vehicle = 0; vehicle < vehicle_to_start_.size(); vehicle++) { + const int64_t start = vehicle_to_start_[vehicle]; + DCHECK_EQ(vehicle, start_to_vehicle_[start]); + if (!IsVarSynced(start)) { + return; + } + CapAddTo(current_vehicle_costs_[vehicle], ¤t_vehicle_cost_); + } + } + bool InitializeAcceptPath() override { + delta_vehicle_cost_ = current_vehicle_cost_; + return true; + } + bool AcceptPath(int64_t path_start, int64_t /*chain_start*/, + int64_t /*chain_end*/) override { + delta_vehicle_cost_ = + CapSub(delta_vehicle_cost_, + current_vehicle_costs_[start_to_vehicle_[path_start]]); + route_.clear(); + int64_t node = path_start; + while (node < Size()) { + route_.push_back(node); + node = GetNext(node); + } + route_.push_back(node); + std::optional route_cost = routing_model_.GetRouteCost(route_); + if (!route_cost.has_value()) { + return false; + } + CapAddTo(route_cost.value(), &delta_vehicle_cost_); + return true; + } + bool FinalizeAcceptPath(int64_t /*objective_min*/, + int64_t objective_max) override { + return delta_vehicle_cost_ <= objective_max; + } + + const RoutingModel& routing_model_; + int64_t current_vehicle_cost_; + int64_t delta_vehicle_cost_; + std::vector current_vehicle_costs_; + std::vector vehicle_to_start_; + std::vector start_to_vehicle_; + std::vector route_; +}; + +} // namespace + +IntVarLocalSearchFilter* MakeRouteConstraintFilter( + const RoutingModel& routing_model) { + return routing_model.solver()->RevAlloc( + new RouteConstraintFilter(routing_model)); +} + namespace { // Max active vehicles filter. diff --git a/ortools/constraint_solver/routing_filters.h b/ortools/routing/filters.h similarity index 99% rename from ortools/constraint_solver/routing_filters.h rename to ortools/routing/filters.h index 314e800e01..b7cfd50e7b 100644 --- a/ortools/constraint_solver/routing_filters.h +++ b/ortools/routing/filters.h @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_FILTERS_H_ -#define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_FILTERS_H_ +#ifndef OR_TOOLS_ROUTING_FILTERS_H_ +#define OR_TOOLS_ROUTING_FILTERS_H_ #include #include @@ -27,15 +27,18 @@ #include "ortools/base/types.h" #include "ortools/constraint_solver/constraint_solver.h" #include "ortools/constraint_solver/constraint_solveri.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_lp_scheduling.h" -#include "ortools/constraint_solver/routing_types.h" +#include "ortools/routing/lp_scheduling.h" #include "ortools/routing/parameters.pb.h" +#include "ortools/routing/routing.h" +#include "ortools/routing/types.h" #include "ortools/util/bitset.h" #include "ortools/util/range_minimum_query.h" namespace operations_research { +/// Returns a filter tracking route constraints. +IntVarLocalSearchFilter* MakeRouteConstraintFilter( + const RoutingModel& routing_model); /// Returns a filter ensuring that max active vehicles constraints are enforced. IntVarLocalSearchFilter* MakeMaxActiveVehiclesFilter( const RoutingModel& routing_model); @@ -976,4 +979,4 @@ class BasePathFilter : public IntVarLocalSearchFilter { } // namespace operations_research -#endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_FILTERS_H_ +#endif // OR_TOOLS_ROUTING_FILTERS_H_ diff --git a/ortools/constraint_solver/routing_flow.cc b/ortools/routing/flow.cc similarity index 99% rename from ortools/constraint_solver/routing_flow.cc rename to ortools/routing/flow.cc index f97d23f033..453da68b63 100644 --- a/ortools/constraint_solver/routing_flow.cc +++ b/ortools/routing/flow.cc @@ -28,10 +28,10 @@ #include "ortools/base/logging.h" #include "ortools/base/map_util.h" #include "ortools/constraint_solver/constraint_solver.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_lp_scheduling.h" #include "ortools/graph/min_cost_flow.h" +#include "ortools/routing/lp_scheduling.h" #include "ortools/routing/parameters.pb.h" +#include "ortools/routing/routing.h" #include "ortools/util/saturated_arithmetic.h" namespace operations_research { diff --git a/ortools/constraint_solver/routing_ils.cc b/ortools/routing/ils.cc similarity index 97% rename from ortools/constraint_solver/routing_ils.cc rename to ortools/routing/ils.cc index 79c5a08092..db3bd787eb 100644 --- a/ortools/constraint_solver/routing_ils.cc +++ b/ortools/routing/ils.cc @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "ortools/constraint_solver/routing_ils.h" +#include "ortools/routing/ils.h" #include #include @@ -30,11 +30,11 @@ #include "ortools/base/logging.h" #include "ortools/base/protoutil.h" #include "ortools/constraint_solver/constraint_solver.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_search.h" -#include "ortools/constraint_solver/routing_types.h" #include "ortools/routing/ils.pb.h" #include "ortools/routing/parameters.pb.h" +#include "ortools/routing/routing.h" +#include "ortools/routing/search.h" +#include "ortools/routing/types.h" namespace operations_research { namespace { @@ -86,14 +86,22 @@ std::unique_ptr MakeRuinProcedure( const uint32_t preferred_num_neighbors = parameters.route_selection_neighbors_ratio() * num_non_start_end_nodes; + // TODO(user): rename parameters.route_selection_max_neighbors to something + // more general that can be used by multiple ruin procedures. + const uint32_t num_neighbors_for_route_selection = + std::min(parameters.route_selection_max_neighbors(), + std::max(parameters.route_selection_min_neighbors(), + preferred_num_neighbors)); switch (parameters.ruin_strategy()) { case RuinStrategy::SPATIALLY_CLOSE_ROUTES_REMOVAL: return std::make_unique( model, rnd, parameters.num_ruined_routes(), - std::min(parameters.route_selection_max_neighbors(), - std::max(parameters.route_selection_min_neighbors(), - preferred_num_neighbors))); + num_neighbors_for_route_selection); break; + case RuinStrategy::RANDOM_WALK_REMOVAL: + return std::make_unique( + model, rnd, parameters.num_removed_visits(), + num_neighbors_for_route_selection); default: LOG(ERROR) << "Unsupported ruin procedure."; return nullptr; @@ -395,7 +403,7 @@ RandomWalkRemovalRuinProcedure::RandomWalkRemovalRuinProcedure( std::function RandomWalkRemovalRuinProcedure::Ruin( const Assignment* assignment) { - if (!HasPerformedNodes(model_, *assignment)) { + if (!HasPerformedNodes(model_, *assignment) || walk_length_ == 0) { return [&model = model_, assignment](int64_t node) { return assignment->Value(model.NextVar(node)); }; diff --git a/ortools/constraint_solver/routing_ils.h b/ortools/routing/ils.h similarity index 97% rename from ortools/constraint_solver/routing_ils.h rename to ortools/routing/ils.h index e3bc2229fc..2713281b2f 100644 --- a/ortools/constraint_solver/routing_ils.h +++ b/ortools/routing/ils.h @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_ILS_H_ -#define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_ILS_H_ +#ifndef OR_TOOLS_ROUTING_ILS_H_ +#define OR_TOOLS_ROUTING_ILS_H_ #include #include @@ -24,9 +24,9 @@ #include "absl/time/time.h" #include "ortools/constraint_solver/constraint_solver.h" -#include "ortools/constraint_solver/routing.h" #include "ortools/routing/ils.pb.h" #include "ortools/routing/parameters.pb.h" +#include "ortools/routing/routing.h" #include "ortools/util/bitset.h" namespace operations_research { @@ -176,4 +176,4 @@ std::pair GetSimulatedAnnealingTemperatures( } // namespace operations_research -#endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_ILS_H_ +#endif // OR_TOOLS_ROUTING_ILS_H_ diff --git a/ortools/routing/ils.proto b/ortools/routing/ils.proto index e197e5842e..adcf4fa6d8 100644 --- a/ortools/routing/ils.proto +++ b/ortools/routing/ils.proto @@ -37,6 +37,13 @@ message RuinStrategy { // Removes a number of spatially close routes. SPATIALLY_CLOSE_ROUTES_REMOVAL = 1; + // Removes a number of customers by performing a random walk on the + // underlying routing solution. More precisely, starting from a randomly + // selected seed visit, the walk is extended by either moving within the + // same route or by jumping to a visit served by a different neighboring + // route. Every active visit encountered along this random walk is made + // unperformed. + RANDOM_WALK_REMOVAL = 2; } } @@ -50,6 +57,12 @@ message RuinRecreateParameters { // Number of routes removed during a ruin application defined on routes. optional uint32 num_ruined_routes = 3; + // Number of visits removed during a ruin application defined on visits. + // Note that pickup and delivery pairs are considered as a single entity, + // i.e., the removal of a pickup (respectively delivery) causes the removal of + // the associated delivery (respectively pickup) and it counts as a single + // removal. + optional uint32 num_removed_visits = 7; // Ratio in [0, 1] of non start/end nodes to consider as neighbors for the // identification of routes spatially close to a non start/end seed node. diff --git a/ortools/constraint_solver/routing_index_manager.cc b/ortools/routing/index_manager.cc similarity index 98% rename from ortools/constraint_solver/routing_index_manager.cc rename to ortools/routing/index_manager.cc index 2efe210994..b7519a3fae 100644 --- a/ortools/constraint_solver/routing_index_manager.cc +++ b/ortools/routing/index_manager.cc @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "ortools/constraint_solver/routing_index_manager.h" +#include "ortools/routing/index_manager.h" #include #include diff --git a/ortools/constraint_solver/routing_index_manager.h b/ortools/routing/index_manager.h similarity index 95% rename from ortools/constraint_solver/routing_index_manager.h rename to ortools/routing/index_manager.h index fe8046b8d1..69efb7d2d4 100644 --- a/ortools/constraint_solver/routing_index_manager.h +++ b/ortools/routing/index_manager.h @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_INDEX_MANAGER_H_ -#define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_INDEX_MANAGER_H_ +#ifndef OR_TOOLS_ROUTING_INDEX_MANAGER_H_ +#define OR_TOOLS_ROUTING_INDEX_MANAGER_H_ #include #include @@ -20,7 +20,7 @@ #include "absl/log/check.h" #include "ortools/base/strong_vector.h" -#include "ortools/constraint_solver/routing_types.h" +#include "ortools/routing/types.h" namespace operations_research { @@ -118,4 +118,4 @@ class RoutingIndexManager { } // namespace operations_research -#endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_INDEX_MANAGER_H_ +#endif // OR_TOOLS_ROUTING_INDEX_MANAGER_H_ diff --git a/ortools/constraint_solver/routing_insertion_lns.cc b/ortools/routing/insertion_lns.cc similarity index 98% rename from ortools/constraint_solver/routing_insertion_lns.cc rename to ortools/routing/insertion_lns.cc index e910bece7e..f05c9ca252 100644 --- a/ortools/constraint_solver/routing_insertion_lns.cc +++ b/ortools/routing/insertion_lns.cc @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "ortools/constraint_solver/routing_insertion_lns.h" +#include "ortools/routing/insertion_lns.h" #include #include @@ -25,9 +25,9 @@ #include "ortools/base/int_type.h" #include "ortools/constraint_solver/constraint_solver.h" #include "ortools/constraint_solver/constraint_solveri.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_search.h" -#include "ortools/constraint_solver/routing_utils.h" +#include "ortools/routing/routing.h" +#include "ortools/routing/search.h" +#include "ortools/routing/utils.h" #include "ortools/util/bitset.h" namespace operations_research { diff --git a/ortools/constraint_solver/routing_insertion_lns.h b/ortools/routing/insertion_lns.h similarity index 96% rename from ortools/constraint_solver/routing_insertion_lns.h rename to ortools/routing/insertion_lns.h index 42bac34881..c2e6e9215c 100644 --- a/ortools/constraint_solver/routing_insertion_lns.h +++ b/ortools/routing/insertion_lns.h @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_INSERTION_LNS_H_ -#define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_INSERTION_LNS_H_ +#ifndef OR_TOOLS_ROUTING_INSERTION_LNS_H_ +#define OR_TOOLS_ROUTING_INSERTION_LNS_H_ #include #include @@ -25,9 +25,9 @@ #include "absl/strings/str_cat.h" #include "ortools/constraint_solver/constraint_solver.h" #include "ortools/constraint_solver/constraint_solveri.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_search.h" -#include "ortools/constraint_solver/routing_types.h" +#include "ortools/routing/routing.h" +#include "ortools/routing/search.h" +#include "ortools/routing/types.h" #include "ortools/util/bitset.h" namespace operations_research { @@ -245,4 +245,4 @@ class FilteredHeuristicCloseNodesLNSOperator } // namespace operations_research -#endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_INSERTION_LNS_H_ +#endif // OR_TOOLS_ROUTING_INSERTION_LNS_H_ diff --git a/ortools/routing/java/routing_index_manager.i b/ortools/routing/java/index_manager.i similarity index 91% rename from ortools/routing/java/routing_index_manager.i rename to ortools/routing/java/index_manager.i index c6b061004a..11192062c8 100644 --- a/ortools/routing/java/routing_index_manager.i +++ b/ortools/routing/java/index_manager.i @@ -14,10 +14,10 @@ // Wrapper for RoutingIndexManager. %include "ortools/base/base.i" -%include "ortools/routing/java/routing_types.i" +%include "ortools/routing/java/types.i" %{ -#include "ortools/constraint_solver/routing_index_manager.h" +#include "ortools/routing/index_manager.h" %} DEFINE_INDEX_TYPE_TYPEDEF(operations_research::RoutingNodeIndex, @@ -48,6 +48,6 @@ namespace operations_research { } // namespace operations_research -%include "ortools/constraint_solver/routing_index_manager.h" +%include "ortools/routing/index_manager.h" %unignoreall diff --git a/ortools/routing/java/routing.i b/ortools/routing/java/routing.i index f5ac090214..39546214f0 100644 --- a/ortools/routing/java/routing.i +++ b/ortools/routing/java/routing.i @@ -24,7 +24,7 @@ %import "ortools/constraint_solver/java/constraint_solver.i" %import "ortools/util/java/sorted_interval_list.i" // Domain -%include "ortools/routing/java/routing_index_manager.i" +%include "ortools/routing/java/index_manager.i" // We need to forward-declare the proto here, so that PROTO_INPUT involving it // works correctly. The order matters very much: this declaration needs to be @@ -39,9 +39,9 @@ class RoutingSearchStatus; // Include the files we want to wrap a first time. %{ -#include "ortools/constraint_solver/routing_types.h" -#include "ortools/constraint_solver/routing_parameters.h" -#include "ortools/constraint_solver/routing.h" +#include "ortools/routing/types.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" #include "ortools/routing/enums.pb.h" #include "ortools/routing/parameters.pb.h" #include @@ -423,7 +423,7 @@ PROTO2_RETURN(operations_research::RoutingModelParameters, PROTO_ENUM_RETURN(operations_research::RoutingSearchStatus::Value, com.google.ortools.routing.RoutingSearchStatus.Value) -// Wrap routing_types.h, routing_parameters.h according to the SWIG styleguide. +// Wrap types.h, parameters.h according to the SWIG style guide. %ignoreall %unignore RoutingTransitCallback1; %unignore RoutingTransitCallback2; @@ -439,18 +439,18 @@ import com.google.ortools.constraintsolver.IntVar; namespace operations_research { // Globals -// IMPORTANT(user): These functions from routing_parameters.h are global, so in -// java they are in the Globals.java (import com.[...].routing.Globals). +// IMPORTANT(user): These functions from parameters.h are global, so in Java +// they are in the Globals.java (import com.[...].routing.Globals). %rename (defaultRoutingSearchParameters) DefaultRoutingSearchParameters; %rename (defaultRoutingModelParameters) DefaultRoutingModelParameters; %rename (findErrorInRoutingSearchParameters) FindErrorInRoutingSearchParameters; %rename (makeSetValuesFromTargets) MakeSetValuesFromTargets; } // namespace operations_research -%include "ortools/constraint_solver/routing_types.h" -%include "ortools/constraint_solver/routing_parameters.h" +%include "ortools/routing/types.h" +%include "ortools/routing/parameters.h" %unignoreall // TODO(user): Use ignoreall/unignoreall for this one. A lot of work. //swiglint: disable include-h-allglobals -%include "ortools/constraint_solver/routing.h" +%include "ortools/routing/routing.h" diff --git a/ortools/routing/java/routing_types.i b/ortools/routing/java/types.i similarity index 98% rename from ortools/routing/java/routing_types.i rename to ortools/routing/java/types.i index 6f6c95d5ee..b70becbffe 100644 --- a/ortools/routing/java/routing_types.i +++ b/ortools/routing/java/types.i @@ -21,7 +21,7 @@ %import "ortools/util/java/vector.i" %{ -#include "ortools/constraint_solver/routing_types.h" +#include "ortools/routing/types.h" /* Global JNI reference deleter */ class GlobalRefGuard { diff --git a/ortools/constraint_solver/routing_lp_scheduling.cc b/ortools/routing/lp_scheduling.cc similarity index 99% rename from ortools/constraint_solver/routing_lp_scheduling.cc rename to ortools/routing/lp_scheduling.cc index 6f0f220928..39e3b180ee 100644 --- a/ortools/constraint_solver/routing_lp_scheduling.cc +++ b/ortools/routing/lp_scheduling.cc @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "ortools/constraint_solver/routing_lp_scheduling.h" +#include "ortools/routing/lp_scheduling.h" #include #include @@ -43,12 +43,12 @@ #include "ortools/base/strong_vector.h" #include "ortools/base/types.h" #include "ortools/constraint_solver/constraint_solver.h" -#include "ortools/constraint_solver/routing.h" #include "ortools/glop/parameters.pb.h" #include "ortools/graph/ebert_graph.h" #include "ortools/graph/min_cost_flow.h" #include "ortools/port/proto_utils.h" #include "ortools/routing/parameters.pb.h" +#include "ortools/routing/routing.h" #include "ortools/sat/cp_model.pb.h" #include "ortools/sat/lp_utils.h" #include "ortools/util/flat_matrix.h" diff --git a/ortools/constraint_solver/routing_lp_scheduling.h b/ortools/routing/lp_scheduling.h similarity index 99% rename from ortools/constraint_solver/routing_lp_scheduling.h rename to ortools/routing/lp_scheduling.h index eb7eeddc10..b4bb7a7414 100644 --- a/ortools/constraint_solver/routing_lp_scheduling.h +++ b/ortools/routing/lp_scheduling.h @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_LP_SCHEDULING_H_ -#define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_LP_SCHEDULING_H_ +#ifndef OR_TOOLS_ROUTING_LP_SCHEDULING_H_ +#define OR_TOOLS_ROUTING_LP_SCHEDULING_H_ #include #include @@ -34,13 +34,13 @@ #include "absl/types/span.h" #include "ortools/base/logging.h" #include "ortools/base/mathutil.h" -#include "ortools/constraint_solver/routing.h" #include "ortools/glop/lp_solver.h" #include "ortools/glop/parameters.pb.h" #include "ortools/lp_data/lp_data.h" #include "ortools/lp_data/lp_types.h" #include "ortools/port/proto_utils.h" #include "ortools/routing/parameters.pb.h" +#include "ortools/routing/routing.h" #include "ortools/sat/cp_model.pb.h" #include "ortools/sat/cp_model_solver.h" #include "ortools/sat/model.h" @@ -1067,4 +1067,4 @@ std::vector PiecewiseLinearFormulationToSlopeAndYIntercept( } // namespace operations_research -#endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_LP_SCHEDULING_H_ +#endif // OR_TOOLS_ROUTING_LP_SCHEDULING_H_ diff --git a/ortools/constraint_solver/routing_neighborhoods.cc b/ortools/routing/neighborhoods.cc similarity index 99% rename from ortools/constraint_solver/routing_neighborhoods.cc rename to ortools/routing/neighborhoods.cc index c9c1cb1e47..5612f36df9 100644 --- a/ortools/constraint_solver/routing_neighborhoods.cc +++ b/ortools/routing/neighborhoods.cc @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "ortools/constraint_solver/routing_neighborhoods.h" +#include "ortools/routing/neighborhoods.h" #include #include @@ -24,8 +24,8 @@ #include "ortools/base/types.h" #include "ortools/constraint_solver/constraint_solver.h" #include "ortools/constraint_solver/constraint_solveri.h" -#include "ortools/constraint_solver/routing_types.h" -#include "ortools/constraint_solver/routing_utils.h" +#include "ortools/routing/types.h" +#include "ortools/routing/utils.h" #include "ortools/util/saturated_arithmetic.h" namespace operations_research { diff --git a/ortools/constraint_solver/routing_neighborhoods.h b/ortools/routing/neighborhoods.h similarity index 99% rename from ortools/constraint_solver/routing_neighborhoods.h rename to ortools/routing/neighborhoods.h index cd3ca2582f..d62427a35d 100644 --- a/ortools/constraint_solver/routing_neighborhoods.h +++ b/ortools/routing/neighborhoods.h @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_NEIGHBORHOODS_H_ -#define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_NEIGHBORHOODS_H_ +#ifndef OR_TOOLS_ROUTING_NEIGHBORHOODS_H_ +#define OR_TOOLS_ROUTING_NEIGHBORHOODS_H_ #include #include @@ -24,7 +24,7 @@ #include "absl/types/span.h" #include "ortools/constraint_solver/constraint_solver.h" #include "ortools/constraint_solver/constraint_solveri.h" -#include "ortools/constraint_solver/routing_types.h" +#include "ortools/routing/types.h" #include "ortools/util/bitset.h" namespace operations_research { @@ -750,4 +750,4 @@ class ExchangeSubtrip : public PathOperator { } // namespace operations_research -#endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_NEIGHBORHOODS_H_ +#endif // OR_TOOLS_ROUTING_NEIGHBORHOODS_H_ diff --git a/ortools/constraint_solver/routing_parameters.cc b/ortools/routing/parameters.cc similarity index 99% rename from ortools/constraint_solver/routing_parameters.cc rename to ortools/routing/parameters.cc index c3b96037fc..39692d1d4c 100644 --- a/ortools/constraint_solver/routing_parameters.cc +++ b/ortools/routing/parameters.cc @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "ortools/constraint_solver/routing_parameters.h" +#include "ortools/routing/parameters.h" #include #include @@ -59,6 +59,7 @@ IteratedLocalSearchParameters CreateDefaultIteratedLocalSearchParameters() { rr->set_ruin_strategy(RuinStrategy::SPATIALLY_CLOSE_ROUTES_REMOVAL); rr->set_recreate_strategy(FirstSolutionStrategy::LOCAL_CHEAPEST_INSERTION); rr->set_num_ruined_routes(2); + rr->set_num_removed_visits(10); rr->set_route_selection_neighbors_ratio(1.0); rr->set_route_selection_min_neighbors(10); rr->set_route_selection_max_neighbors(100); diff --git a/ortools/constraint_solver/routing_parameters.h b/ortools/routing/parameters.h similarity index 89% rename from ortools/constraint_solver/routing_parameters.h rename to ortools/routing/parameters.h index 6b2204ba79..a678d0fcb5 100644 --- a/ortools/constraint_solver/routing_parameters.h +++ b/ortools/routing/parameters.h @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_PARAMETERS_H_ -#define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_PARAMETERS_H_ +#ifndef OR_TOOLS_ROUTING_PARAMETERS_H_ +#define OR_TOOLS_ROUTING_PARAMETERS_H_ #include #include @@ -37,4 +37,4 @@ std::vector FindErrorsInRoutingSearchParameters( } // namespace operations_research -#endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_PARAMETERS_H_ +#endif // OR_TOOLS_ROUTING_PARAMETERS_H_ diff --git a/ortools/routing/parameters.proto b/ortools/routing/parameters.proto index ac5f8faa36..0e1066c317 100644 --- a/ortools/routing/parameters.proto +++ b/ortools/routing/parameters.proto @@ -36,7 +36,7 @@ package operations_research; // then the routing library will pick its preferred value for that parameter // automatically: this should be the case for most parameters. // To see those "default" parameters, call GetDefaultRoutingSearchParameters(). -// Next ID: 61 +// Next ID: 63 message RoutingSearchParameters { reserved 19; @@ -460,6 +460,13 @@ message RoutingSearchParameters { // Whether to reset penalties when a new best solution is found. The effect is // that a greedy descent is started before the next penalization phase. bool guided_local_search_reset_penalties_on_new_best_solution = 51; + // When an arc leaving a vehicle start or arriving at a vehicle end is + // penalized, this field controls whether to penalize all other equivalent + // arcs with starts or ends in the same vehicle class. + bool guided_local_search_penalize_with_vehicle_classes = 61; + // Whether to consider arc penalties in cost functions used in local search + // operators using arc costs. + bool use_guided_local_search_penalties_in_local_search_operators = 62; // --- Search control --- // diff --git a/ortools/routing/parsers/BUILD.bazel b/ortools/routing/parsers/BUILD.bazel index 1182fa5b0a..763a6b89af 100644 --- a/ortools/routing/parsers/BUILD.bazel +++ b/ortools/routing/parsers/BUILD.bazel @@ -339,7 +339,7 @@ cc_library( hdrs = ["cvrptw_lib.h"], deps = [ "//ortools/base", - "//ortools/constraint_solver:routing", + "//ortools/routing", "//ortools/util:random_engine", ], ) @@ -351,7 +351,7 @@ cc_library( deps = [ ":capacity_planning_cc_proto", "//ortools/base", - "//ortools/constraint_solver:routing", + "//ortools/routing", "//ortools/util:random_engine", ], ) diff --git a/ortools/routing/parsers/cvrptw_lib.cc b/ortools/routing/parsers/cvrptw_lib.cc index 5645ae0684..d547db3765 100644 --- a/ortools/routing/parsers/cvrptw_lib.cc +++ b/ortools/routing/parsers/cvrptw_lib.cc @@ -18,15 +18,16 @@ #include #include #include -#include #include #include #include "absl/container/btree_set.h" +#include "absl/random/distributions.h" #include "absl/strings/str_format.h" #include "ortools/base/logging.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" +#include "ortools/constraint_solver/constraint_solver.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/routing.h" namespace operations_research { diff --git a/ortools/routing/parsers/cvrptw_lib.h b/ortools/routing/parsers/cvrptw_lib.h index f2840ed6c1..5f2148c757 100644 --- a/ortools/routing/parsers/cvrptw_lib.h +++ b/ortools/routing/parsers/cvrptw_lib.h @@ -22,7 +22,7 @@ #include #include "ortools/base/strong_vector.h" -#include "ortools/constraint_solver/routing.h" +#include "ortools/routing/routing.h" namespace operations_research { @@ -70,7 +70,8 @@ class LocationContainer { std::mt19937 randomizer_; const int64_t speed_; - util_intops::StrongVector locations_; + util_intops::StrongVector + locations_; }; // Random demand. diff --git a/ortools/routing/parsers/solution_serializer.cc b/ortools/routing/parsers/solution_serializer.cc index 5be2974aca..7ff7894161 100644 --- a/ortools/routing/parsers/solution_serializer.cc +++ b/ortools/routing/parsers/solution_serializer.cc @@ -384,7 +384,7 @@ std::string SerializeRouteToCVRPLIBString(const RoutingSolution::Route& route) { // Before serializing the route, make some tests to check that the hypotheses // are respected (otherwise, the output of the function is highly likely // pure garbage). - RoutingSolution::Event first_event = route[0]; + const RoutingSolution::Event& first_event = route[0]; CHECK(first_event.type == RoutingSolution::Event::Type::kStart) << "The route does not begin with a Start event to indicate " "the depot."; @@ -397,7 +397,7 @@ std::string SerializeRouteToCVRPLIBString(const RoutingSolution::Route& route) { std::string current_route; for (int64_t i = 1; i < route.size() - 1; ++i) { - RoutingSolution::Event event = route[i]; + const RoutingSolution::Event& event = route[i]; // Ignore the depot, as CVRPLIB doesn't output the depot in the routes // (all routes implicitly start and end at the depot). @@ -410,7 +410,7 @@ std::string SerializeRouteToCVRPLIBString(const RoutingSolution::Route& route) { // Last event: end at a depot. Due to the strange way CVRPLIB // outputs nodes, the depot must be the same at the beginning and the // end of the route. - RoutingSolution::Event last_event = route.back(); + const RoutingSolution::Event& last_event = route.back(); if (last_event.type == RoutingSolution::Event::Type::kEnd) { CHECK_EQ(depot, last_event.arc.tail()); CHECK_EQ(last_event.arc.tail(), last_event.arc.head()); diff --git a/ortools/routing/python/CMakeLists.txt b/ortools/routing/python/CMakeLists.txt index c3b4235ce4..264e228817 100644 --- a/ortools/routing/python/CMakeLists.txt +++ b/ortools/routing/python/CMakeLists.txt @@ -11,9 +11,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -pybind11_add_module(routing_pybind11 MODULE routing_model.cc) +# routing +pybind11_add_module(routing_pybind11 MODULE model.cc) set_target_properties(routing_pybind11 PROPERTIES - LIBRARY_OUTPUT_NAME "routing_model") + LIBRARY_OUTPUT_NAME "model") # note: macOS is APPLE and also UNIX ! if(APPLE) @@ -36,6 +37,44 @@ target_link_libraries(routing_pybind11 PRIVATE ) add_library(${PROJECT_NAMESPACE}::routing_pybind11 ALIAS routing_pybind11) +# legacy pywraprouting +set_property(SOURCE routing.i PROPERTY CPLUSPLUS ON) +set_property(SOURCE routing.i PROPERTY SWIG_MODULE_NAME pywraprouting) +set_property(SOURCE routing.i PROPERTY COMPILE_DEFINITIONS + ${OR_TOOLS_COMPILE_DEFINITIONS} ABSL_MUST_USE_RESULT=) +set_property(SOURCE routing.i PROPERTY COMPILE_OPTIONS -nofastunpack) +swig_add_library(pywraprouting + TYPE MODULE + LANGUAGE python + OUTPUT_DIR ${PYTHON_PROJECT_DIR}/routing + SOURCES routing.i) + +target_include_directories(pywraprouting PRIVATE ${Python3_INCLUDE_DIRS}) +set_property(TARGET pywraprouting PROPERTY SWIG_USE_TARGET_INCLUDE_DIRECTORIES ON) +target_compile_definitions(pywraprouting PUBLIC "PY3") + +# note: macOS is APPLE and also UNIX ! +if(APPLE) + set_target_properties(pywraprouting PROPERTIES + SUFFIX ".so" + INSTALL_RPATH "@loader_path;@loader_path/../../${PROJECT_NAME}/.libs") + set_property(TARGET pywraprouting APPEND PROPERTY + LINK_FLAGS "-flat_namespace -undefined suppress") +elseif(UNIX) + set_target_properties(pywraprouting PROPERTIES + INSTALL_RPATH "$ORIGIN:$ORIGIN/../../${PROJECT_NAME}/.libs") +endif() +target_link_libraries(pywraprouting PRIVATE ortools::ortools) + +# Variable PYTHON_LIBRARIES can contains keyword `optimized` +# which won't be interpreted inside a generator expression. +# i.e. we can't use: $<$:${PYTHON_LIBRARIES}> +# see: https://cmake.org/cmake/help/git-stage/command/target_link_libraries.html#command:target_link_libraries +if(MSVC) + target_link_libraries(pywraprouting PRIVATE ${Python3_LIBRARIES}) +endif() + +# Test if(BUILD_TESTING) file(GLOB PYTHON_SRCS "*_test.py") foreach(FILE_NAME IN LISTS PYTHON_SRCS) diff --git a/ortools/routing/python/routing_doc.h b/ortools/routing/python/doc.h similarity index 100% rename from ortools/routing/python/routing_doc.h rename to ortools/routing/python/doc.h diff --git a/ortools/constraint_solver/python/routing_index_manager.i b/ortools/routing/python/index_manager.i similarity index 90% rename from ortools/constraint_solver/python/routing_index_manager.i rename to ortools/routing/python/index_manager.i index 4a9d2b7d58..d4eafe51c8 100644 --- a/ortools/constraint_solver/python/routing_index_manager.i +++ b/ortools/routing/python/index_manager.i @@ -14,11 +14,11 @@ // Wrapper for RoutingIndexManager. %include "ortools/base/base.i" -%include "ortools/constraint_solver/python/routing_types.i" +%include "ortools/routing/python/types.i" %import "ortools/util/python/vector.i" %{ -#include "ortools/constraint_solver/routing_index_manager.h" +#include "ortools/routing/index_manager.h" %} DEFINE_INDEX_TYPE_TYPEDEF(operations_research::RoutingNodeIndex, @@ -49,6 +49,6 @@ namespace operations_research { } // namespace operations_research -%include "ortools/constraint_solver/routing_index_manager.h" +%include "ortools/routing/index_manager.h" %unignoreall diff --git a/ortools/routing/python/routing_index_manager_doc.h b/ortools/routing/python/index_manager_doc.h similarity index 100% rename from ortools/routing/python/routing_index_manager_doc.h rename to ortools/routing/python/index_manager_doc.h diff --git a/ortools/routing/python/routing_model.cc b/ortools/routing/python/model.cc similarity index 93% rename from ortools/routing/python/routing_model.cc rename to ortools/routing/python/model.cc index 35d5b4e4b2..b63e1560e7 100644 --- a/ortools/routing/python/routing_model.cc +++ b/ortools/routing/python/model.cc @@ -16,13 +16,13 @@ #include #include "ortools/constraint_solver/constraint_solver.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/constraint_solver/solver_parameters.pb.h" -#include "ortools/routing/python/routing_doc.h" -#include "ortools/routing/python/routing_index_manager_doc.h" -#include "ortools/routing/python/routing_parameters_doc.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/python/doc.h" +#include "ortools/routing/python/index_manager_doc.h" +#include "ortools/routing/python/parameters_doc.h" +#include "ortools/routing/routing.h" #include "pybind11/cast.h" #include "pybind11/functional.h" #include "pybind11/gil.h" diff --git a/ortools/routing/python/routing_parameters_doc.h b/ortools/routing/python/parameters_doc.h similarity index 100% rename from ortools/routing/python/routing_parameters_doc.h rename to ortools/routing/python/parameters_doc.h diff --git a/ortools/constraint_solver/python/pywraprouting_test.py b/ortools/routing/python/pywraprouting_test.py similarity index 85% rename from ortools/constraint_solver/python/pywraprouting_test.py rename to ortools/routing/python/pywraprouting_test.py index 130f6b2f8c..b0fa3b217f 100755 --- a/ortools/constraint_solver/python/pywraprouting_test.py +++ b/ortools/routing/python/pywraprouting_test.py @@ -19,6 +19,7 @@ import functools from absl.testing import absltest from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting def Distance(node_i, node_j): @@ -58,7 +59,7 @@ class Callback: class TestPyWrapRoutingIndexManager(absltest.TestCase): def testCtor(self): - manager = pywrapcp.RoutingIndexManager(42, 3, 7) + manager = pywraprouting.RoutingIndexManager(42, 3, 7) self.assertIsNotNone(manager) self.assertEqual(42, manager.GetNumberOfNodes()) self.assertEqual(3, manager.GetNumberOfVehicles()) @@ -68,7 +69,7 @@ class TestPyWrapRoutingIndexManager(absltest.TestCase): self.assertEqual(7, manager.IndexToNode(manager.GetEndIndex(i))) def testCtorMultiDepotSame(self): - manager = pywrapcp.RoutingIndexManager(42, 3, [0, 0, 0], [0, 0, 0]) + manager = pywraprouting.RoutingIndexManager(42, 3, [0, 0, 0], [0, 0, 0]) self.assertIsNotNone(manager) self.assertEqual(42, manager.GetNumberOfNodes()) self.assertEqual(3, manager.GetNumberOfVehicles()) @@ -78,7 +79,7 @@ class TestPyWrapRoutingIndexManager(absltest.TestCase): self.assertEqual(0, manager.IndexToNode(manager.GetEndIndex(i))) def testCtorMultiDepotAllDiff(self): - manager = pywrapcp.RoutingIndexManager(42, 3, [1, 2, 3], [4, 5, 6]) + manager = pywraprouting.RoutingIndexManager(42, 3, [1, 2, 3], [4, 5, 6]) self.assertIsNotNone(manager) self.assertEqual(42, manager.GetNumberOfNodes()) self.assertEqual(3, manager.GetNumberOfVehicles()) @@ -91,18 +92,18 @@ class TestPyWrapRoutingIndexManager(absltest.TestCase): class TestPyWrapRoutingModel(absltest.TestCase): def testCtor(self): - manager = pywrapcp.RoutingIndexManager(42, 3, 7) + manager = pywraprouting.RoutingIndexManager(42, 3, 7) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) for i in range(manager.GetNumberOfVehicles()): self.assertEqual(7, manager.IndexToNode(model.Start(i))) self.assertEqual(7, manager.IndexToNode(model.End(i))) def testSolve(self): - manager = pywrapcp.RoutingIndexManager(42, 3, 7) + manager = pywraprouting.RoutingIndexManager(42, 3, 7) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) self.assertEqual( enums_pb2.RoutingSearchStatus.ROUTING_NOT_SOLVED, model.status() @@ -113,9 +114,9 @@ class TestPyWrapRoutingModel(absltest.TestCase): self.assertEqual(0, assignment.ObjectiveValue()) def testSolveMultiDepot(self): - manager = pywrapcp.RoutingIndexManager(42, 3, [1, 2, 3], [4, 5, 6]) + manager = pywraprouting.RoutingIndexManager(42, 3, [1, 2, 3], [4, 5, 6]) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) self.assertEqual( enums_pb2.RoutingSearchStatus.ROUTING_NOT_SOLVED, model.status() @@ -126,9 +127,9 @@ class TestPyWrapRoutingModel(absltest.TestCase): self.assertEqual(0, assignment.ObjectiveValue()) def testTransitCallback(self): - manager = pywrapcp.RoutingIndexManager(5, 1, 0) + manager = pywraprouting.RoutingIndexManager(5, 1, 0) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) transit_idx = model.RegisterTransitCallback( functools.partial(TransitDistance, manager) @@ -144,9 +145,9 @@ class TestPyWrapRoutingModel(absltest.TestCase): self.assertEqual(20, assignment.ObjectiveValue()) def testTransitLambda(self): - manager = pywrapcp.RoutingIndexManager(5, 1, 0) + manager = pywraprouting.RoutingIndexManager(5, 1, 0) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) transit_id = model.RegisterTransitCallback(lambda from_index, to_index: 1) self.assertEqual(1, transit_id) @@ -160,9 +161,9 @@ class TestPyWrapRoutingModel(absltest.TestCase): self.assertEqual(5, assignment.ObjectiveValue()) def testTransitMatrix(self): - manager = pywrapcp.RoutingIndexManager(5, 1, 0) + manager = pywraprouting.RoutingIndexManager(5, 1, 0) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) matrix = [[i + 1 for i in range(5)] for _ in range(5)] transit_idx = model.RegisterTransitMatrix(matrix) @@ -177,9 +178,9 @@ class TestPyWrapRoutingModel(absltest.TestCase): self.assertEqual(15, assignment.ObjectiveValue()) def testUnaryTransitCallback(self): - manager = pywrapcp.RoutingIndexManager(5, 1, 0) + manager = pywraprouting.RoutingIndexManager(5, 1, 0) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) transit_idx = model.RegisterUnaryTransitCallback( functools.partial(UnaryTransitDistance, manager) @@ -195,9 +196,9 @@ class TestPyWrapRoutingModel(absltest.TestCase): self.assertEqual(10, assignment.ObjectiveValue()) def testUnaryTransitLambda(self): - manager = pywrapcp.RoutingIndexManager(5, 1, 0) + manager = pywraprouting.RoutingIndexManager(5, 1, 0) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) transit_id = model.RegisterUnaryTransitCallback(lambda from_index: 1) self.assertEqual(1, transit_id) @@ -211,9 +212,9 @@ class TestPyWrapRoutingModel(absltest.TestCase): self.assertEqual(5, assignment.ObjectiveValue()) def testUnaryTransitVector(self): - manager = pywrapcp.RoutingIndexManager(10, 1, 0) + manager = pywraprouting.RoutingIndexManager(10, 1, 0) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) vector = list(range(10)) transit_idx = model.RegisterUnaryTransitVector(vector) @@ -229,9 +230,9 @@ class TestPyWrapRoutingModel(absltest.TestCase): def testTSP(self): # Create routing model - manager = pywrapcp.RoutingIndexManager(10, 1, 0) + manager = pywraprouting.RoutingIndexManager(10, 1, 0) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) # Add cost function transit_idx = model.RegisterTransitCallback( @@ -242,7 +243,7 @@ class TestPyWrapRoutingModel(absltest.TestCase): enums_pb2.RoutingSearchStatus.ROUTING_NOT_SOLVED, model.status() ) # Solve - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.FIRST_UNBOUND_MIN_VALUE ) @@ -260,9 +261,9 @@ class TestPyWrapRoutingModel(absltest.TestCase): def testVRP(self): # Create routing model - manager = pywrapcp.RoutingIndexManager(10, 2, [0, 1], [1, 0]) + manager = pywraprouting.RoutingIndexManager(10, 2, [0, 1], [1, 0]) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) # Add cost function transit_idx = model.RegisterTransitCallback( @@ -270,7 +271,7 @@ class TestPyWrapRoutingModel(absltest.TestCase): ) model.SetArcCostEvaluatorOfAllVehicles(transit_idx) # Solve - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.FIRST_UNBOUND_MIN_VALUE ) @@ -288,9 +289,9 @@ class TestPyWrapRoutingModel(absltest.TestCase): def testDimensionTSP(self): # Create routing model - manager = pywrapcp.RoutingIndexManager(10, 1, 0) + manager = pywraprouting.RoutingIndexManager(10, 1, 0) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) # Add cost function transit_idx = model.RegisterTransitCallback( @@ -301,7 +302,7 @@ class TestPyWrapRoutingModel(absltest.TestCase): model.AddDimension(transit_idx, 90, 90, True, "distance") distance_dimension = model.GetDimensionOrDie("distance") # Solve - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.FIRST_UNBOUND_MIN_VALUE ) @@ -318,9 +319,9 @@ class TestPyWrapRoutingModel(absltest.TestCase): def testDimensionWithVehicleCapacitiesTSP(self): # Create routing model - manager = pywrapcp.RoutingIndexManager(10, 1, 0) + manager = pywraprouting.RoutingIndexManager(10, 1, 0) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) # Add cost function transit_idx = model.RegisterTransitCallback( @@ -331,7 +332,7 @@ class TestPyWrapRoutingModel(absltest.TestCase): model.AddDimensionWithVehicleCapacity(transit_idx, 90, [90], True, "distance") distance_dimension = model.GetDimensionOrDie("distance") # Solve - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.FIRST_UNBOUND_MIN_VALUE ) @@ -348,9 +349,9 @@ class TestPyWrapRoutingModel(absltest.TestCase): def testDimensionWithVehicleTransitsTSP(self): # Create routing model - manager = pywrapcp.RoutingIndexManager(10, 1, 0) + manager = pywraprouting.RoutingIndexManager(10, 1, 0) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) # Add cost function transit_idx = model.RegisterTransitCallback( @@ -361,7 +362,7 @@ class TestPyWrapRoutingModel(absltest.TestCase): model.AddDimensionWithVehicleTransits([transit_idx], 90, 90, True, "distance") distance_dimension = model.GetDimensionOrDie("distance") # Solve - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.FIRST_UNBOUND_MIN_VALUE ) @@ -378,9 +379,9 @@ class TestPyWrapRoutingModel(absltest.TestCase): def testDimensionWithVehicleTransitsVRP(self): # Create routing model - manager = pywrapcp.RoutingIndexManager(10, 3, 0) + manager = pywraprouting.RoutingIndexManager(10, 3, 0) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) # Add cost function transit_idx = model.RegisterTransitCallback( @@ -396,7 +397,7 @@ class TestPyWrapRoutingModel(absltest.TestCase): model.AddDimensionWithVehicleTransits(distances, 90, 90, True, "distance") distance_dimension = model.GetDimensionOrDie("distance") # Solve - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.FIRST_UNBOUND_MIN_VALUE ) @@ -418,9 +419,9 @@ class TestPyWrapRoutingModel(absltest.TestCase): def testConstantDimensionTSP(self): # Create routing model - manager = pywrapcp.RoutingIndexManager(10, 3, 0) + manager = pywraprouting.RoutingIndexManager(10, 3, 0) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) # Add cost function transit_idx = model.RegisterTransitCallback( @@ -433,7 +434,7 @@ class TestPyWrapRoutingModel(absltest.TestCase): self.assertEqual(transit_idx + 1, constant_id) count_dimension = model.GetDimensionOrDie("count") # Solve - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.FIRST_UNBOUND_MIN_VALUE ) @@ -450,9 +451,9 @@ class TestPyWrapRoutingModel(absltest.TestCase): def testVectorDimensionTSP(self): # Create routing model - manager = pywrapcp.RoutingIndexManager(10, 1, 0) + manager = pywraprouting.RoutingIndexManager(10, 1, 0) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) # Add cost function transit_idx = model.RegisterTransitCallback( @@ -468,7 +469,7 @@ class TestPyWrapRoutingModel(absltest.TestCase): self.assertEqual(transit_idx + 1, unary_transit_id) vector_dimension = model.GetDimensionOrDie("vector") # Solve - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.FIRST_UNBOUND_MIN_VALUE ) @@ -489,9 +490,9 @@ class TestPyWrapRoutingModel(absltest.TestCase): def testMatrixDimensionTSP(self): # Create routing model - manager = pywrapcp.RoutingIndexManager(5, 1, 0) + manager = pywraprouting.RoutingIndexManager(5, 1, 0) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) # Add cost function cost = model.RegisterTransitCallback( @@ -505,7 +506,7 @@ class TestPyWrapRoutingModel(absltest.TestCase): self.assertEqual(cost + 1, transit_id) dimension = model.GetDimensionOrDie("matrix") # Solve - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.FIRST_UNBOUND_MIN_VALUE ) @@ -525,9 +526,9 @@ class TestPyWrapRoutingModel(absltest.TestCase): index = assignment.Value(model.NextVar(index)) def testMatrixDimensionVRP(self): - manager = pywrapcp.RoutingIndexManager(5, 2, 0) + manager = pywraprouting.RoutingIndexManager(5, 2, 0) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) # Add cost function matrix = [[i + j for i in range(5)] for j in range(5)] @@ -541,7 +542,7 @@ class TestPyWrapRoutingModel(absltest.TestCase): self.assertEqual(transit_idx + 1, matrix_transit_idx) dimension = model.GetDimensionOrDie("matrix") # Solve - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.FIRST_UNBOUND_MIN_VALUE ) @@ -566,9 +567,9 @@ class TestPyWrapRoutingModel(absltest.TestCase): def testDisjunctionTSP(self): # Create routing model - manager = pywrapcp.RoutingIndexManager(10, 1, 0) + manager = pywraprouting.RoutingIndexManager(10, 1, 0) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) # Add cost function transit_idx = model.RegisterTransitCallback( @@ -589,7 +590,7 @@ class TestPyWrapRoutingModel(absltest.TestCase): for disjunction in disjunctions: model.AddDisjunction(disjunction) # Solve - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.FIRST_UNBOUND_MIN_VALUE ) @@ -605,9 +606,9 @@ class TestPyWrapRoutingModel(absltest.TestCase): def testDisjunctionPenaltyTSP(self): # Create routing model - manager = pywrapcp.RoutingIndexManager(10, 1, 0) + manager = pywraprouting.RoutingIndexManager(10, 1, 0) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) # Add cost function transit_idx = model.RegisterTransitCallback( @@ -628,7 +629,7 @@ class TestPyWrapRoutingModel(absltest.TestCase): for disjunction, penalty in disjunctions: model.AddDisjunction(disjunction, penalty) # Solve - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.FIRST_UNBOUND_MIN_VALUE ) @@ -644,22 +645,22 @@ class TestPyWrapRoutingModel(absltest.TestCase): def testRoutingModelParameters(self): # Create routing model with parameters - parameters = pywrapcp.DefaultRoutingModelParameters() + parameters = pywraprouting.DefaultRoutingModelParameters() parameters.solver_parameters.CopyFrom(pywrapcp.Solver.DefaultSolverParameters()) parameters.solver_parameters.trace_propagation = True - manager = pywrapcp.RoutingIndexManager(10, 1, 0) + manager = pywraprouting.RoutingIndexManager(10, 1, 0) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager, parameters) + model = pywraprouting.RoutingModel(manager, parameters) self.assertIsNotNone(model) self.assertEqual(1, model.vehicles()) self.assertTrue(model.solver().Parameters().trace_propagation) def testRoutingLocalSearchFiltering(self): - parameters = pywrapcp.DefaultRoutingModelParameters() + parameters = pywraprouting.DefaultRoutingModelParameters() parameters.solver_parameters.profile_local_search = True - manager = pywrapcp.RoutingIndexManager(10, 1, 0) + manager = pywraprouting.RoutingIndexManager(10, 1, 0) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager, parameters) + model = pywraprouting.RoutingModel(manager, parameters) self.assertIsNotNone(model) model.Solve() profile = model.solver().LocalSearchProfile() @@ -669,9 +670,9 @@ class TestPyWrapRoutingModel(absltest.TestCase): def testRoutingSearchParameters(self): # Create routing model - manager = pywrapcp.RoutingIndexManager(10, 1, 0) + manager = pywraprouting.RoutingIndexManager(10, 1, 0) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) # Add cost function transit_idx = model.RegisterTransitCallback( @@ -679,14 +680,14 @@ class TestPyWrapRoutingModel(absltest.TestCase): ) model.SetArcCostEvaluatorOfAllVehicles(transit_idx) # Close with parameters - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.SAVINGS ) search_parameters.local_search_metaheuristic = ( enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH ) - search_parameters.local_search_operators.use_two_opt = pywrapcp.BOOL_FALSE + search_parameters.local_search_operators.use_two_opt = pywraprouting.BOOL_FALSE search_parameters.solution_limit = 20 model.CloseModelWithParameters(search_parameters) # Solve with parameters @@ -702,14 +703,14 @@ class TestPyWrapRoutingModel(absltest.TestCase): self.assertEqual(90, assignment.ObjectiveValue()) def testFindErrorInRoutingSearchParameters(self): - params = pywrapcp.DefaultRoutingSearchParameters() - params.local_search_operators.use_cross = pywrapcp.BOOL_UNSPECIFIED - self.assertIn("cross", pywrapcp.FindErrorInRoutingSearchParameters(params)) + params = pywraprouting.DefaultRoutingSearchParameters() + params.local_search_operators.use_cross = pywraprouting.BOOL_UNSPECIFIED + self.assertIn("cross", pywraprouting.FindErrorInRoutingSearchParameters(params)) def testCallback(self): - manager = pywrapcp.RoutingIndexManager(10, 1, 0) + manager = pywraprouting.RoutingIndexManager(10, 1, 0) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) transit_idx = model.RegisterTransitCallback( functools.partial(TransitDistance, manager) @@ -717,7 +718,7 @@ class TestPyWrapRoutingModel(absltest.TestCase): model.SetArcCostEvaluatorOfAllVehicles(transit_idx) callback = Callback(model) model.AddAtSolutionCallback(callback) - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) @@ -727,9 +728,9 @@ class TestPyWrapRoutingModel(absltest.TestCase): self.assertEqual(90, callback.costs[0]) def testReadAssignment(self): - manager = pywrapcp.RoutingIndexManager(10, 2, 0) + manager = pywraprouting.RoutingIndexManager(10, 2, 0) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) # TODO(user): porting this segfaults the tests. transit_idx = model.RegisterTransitCallback( @@ -752,7 +753,7 @@ class TestPyWrapRoutingModel(absltest.TestCase): ], ] assignment = model.ReadAssignmentFromRoutes(routes, False) - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.solution_limit = 1 solution = model.SolveFromAssignmentWithParameters( assignment, search_parameters @@ -768,9 +769,9 @@ class TestPyWrapRoutingModel(absltest.TestCase): count += 1 def testAutomaticFirstSolutionStrategy_simple(self): - manager = pywrapcp.RoutingIndexManager(31, 7, 3) + manager = pywraprouting.RoutingIndexManager(31, 7, 3) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) # Add cost function transit_idx = model.RegisterTransitCallback( @@ -778,7 +779,7 @@ class TestPyWrapRoutingModel(absltest.TestCase): ) model.SetArcCostEvaluatorOfAllVehicles(transit_idx) # Solve - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() self.assertIsNotNone(model.SolveWithParameters(search_parameters)) self.assertEqual( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC, @@ -786,9 +787,9 @@ class TestPyWrapRoutingModel(absltest.TestCase): ) def testAutomaticFirstSolutionStrategy_pd(self): - manager = pywrapcp.RoutingIndexManager(31, 7, 0) + manager = pywraprouting.RoutingIndexManager(31, 7, 0) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) # Add cost function transit_idx = model.RegisterTransitCallback( @@ -810,7 +811,7 @@ class TestPyWrapRoutingModel(absltest.TestCase): <= dst_dimension.CumulVar(delivery_index) ) # Solve - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() self.assertIsNotNone(model.SolveWithParameters(search_parameters)) self.assertEqual( enums_pb2.FirstSolutionStrategy.PARALLEL_CHEAPEST_INSERTION, @@ -821,12 +822,12 @@ class TestPyWrapRoutingModel(absltest.TestCase): class TestBoundCost(absltest.TestCase): def testCtor(self): - bound_cost = pywrapcp.BoundCost() + bound_cost = pywraprouting.BoundCost() self.assertIsNotNone(bound_cost) self.assertEqual(0, bound_cost.bound) self.assertEqual(0, bound_cost.cost) - bound_cost = pywrapcp.BoundCost(97, 43) + bound_cost = pywraprouting.BoundCost(97, 43) self.assertIsNotNone(bound_cost) self.assertEqual(97, bound_cost.bound) self.assertEqual(43, bound_cost.cost) @@ -835,9 +836,9 @@ class TestBoundCost(absltest.TestCase): class TestRoutingDimension(absltest.TestCase): def testCtor(self): - manager = pywrapcp.RoutingIndexManager(31, 7, 3) + manager = pywraprouting.RoutingIndexManager(31, 7, 3) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) transit_idx = model.RegisterTransitCallback( functools.partial(TransitDistance, manager) @@ -846,9 +847,9 @@ class TestRoutingDimension(absltest.TestCase): model.GetDimensionOrDie("distance") def testSoftSpanUpperBound(self): - manager = pywrapcp.RoutingIndexManager(31, 7, 3) + manager = pywraprouting.RoutingIndexManager(31, 7, 3) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) transit_idx = model.RegisterTransitCallback( functools.partial(TransitDistance, manager) @@ -856,7 +857,7 @@ class TestRoutingDimension(absltest.TestCase): self.assertTrue(model.AddDimension(transit_idx, 100, 100, True, "distance")) dimension = model.GetDimensionOrDie("distance") - bound_cost = pywrapcp.BoundCost(97, 43) + bound_cost = pywraprouting.BoundCost(97, 43) self.assertIsNotNone(bound_cost) self.assertFalse(dimension.HasSoftSpanUpperBounds()) for v in range(manager.GetNumberOfVehicles()): @@ -868,9 +869,9 @@ class TestRoutingDimension(absltest.TestCase): self.assertTrue(dimension.HasSoftSpanUpperBounds()) def testQuadraticCostSoftSpanUpperBound(self): - manager = pywrapcp.RoutingIndexManager(31, 7, 3) + manager = pywraprouting.RoutingIndexManager(31, 7, 3) self.assertIsNotNone(manager) - model = pywrapcp.RoutingModel(manager) + model = pywraprouting.RoutingModel(manager) self.assertIsNotNone(model) transit_idx = model.RegisterTransitCallback( functools.partial(TransitDistance, manager) @@ -878,7 +879,7 @@ class TestRoutingDimension(absltest.TestCase): self.assertTrue(model.AddDimension(transit_idx, 100, 100, True, "distance")) dimension = model.GetDimensionOrDie("distance") - bound_cost = pywrapcp.BoundCost(97, 43) + bound_cost = pywraprouting.BoundCost(97, 43) self.assertIsNotNone(bound_cost) self.assertFalse(dimension.HasQuadraticCostSoftSpanUpperBounds()) for v in range(manager.GetNumberOfVehicles()): diff --git a/ortools/constraint_solver/python/routing.i b/ortools/routing/python/routing.i similarity index 80% rename from ortools/constraint_solver/python/routing.i rename to ortools/routing/python/routing.i index f65485326f..d103231829 100644 --- a/ortools/constraint_solver/python/routing.i +++ b/ortools/routing/python/routing.i @@ -15,12 +15,18 @@ //swiglint: disable full-signature %include "ortools/base/base.i" +%include "ortools/util/python/proto.i" +// PY_CONVERT_HELPER_* macros. +%include "ortools/constraint_solver/python/constraint_solver_helpers.i" + +%include "ortools/util/python/functions.i" %include "ortools/util/python/pair.i" +%include "ortools/util/python/vector.i" -%include "ortools/constraint_solver/python/constraint_solver.i" -%include "ortools/constraint_solver/python/routing_types.i" -%include "ortools/constraint_solver/python/routing_index_manager.i" +%import "ortools/constraint_solver/python/constraint_solver.i" +%include "ortools/routing/python/types.i" +%include "ortools/routing/python/index_manager.i" // We need to forward-declare the proto here, so that PROTO_INPUT involving it // works correctly. The order matters very much: this declaration needs to be @@ -34,10 +40,10 @@ class RoutingSearchStatus; // Include the files we want to wrap a first time. %{ #include "ortools/routing/enums.pb.h" -#include "ortools/constraint_solver/routing_types.h" +#include "ortools/routing/types.h" #include "ortools/routing/parameters.pb.h" -#include "ortools/constraint_solver/routing_parameters.h" -#include "ortools/constraint_solver/routing.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" #include "ortools/util/optional_boolean.pb.h" %} @@ -57,6 +63,13 @@ DEFINE_INDEX_TYPE_TYPEDEF( operations_research::RoutingResourceClassIndex, operations_research::RoutingModel::ResourceClassIndex); +// See ./constraint_solver_helpers.i. +PY_CONVERT_HELPER_INTEXPR_AND_INTVAR(); +PY_CONVERT_HELPER_PTR(IntervalVar); +PY_CONVERT_HELPER_PTR(LocalSearchFilter); +PY_CONVERT_HELPER_PTR(LocalSearchOperator); +PY_CONVERT_HELPER_PTR(SearchMonitor); + %ignore operations_research::RoutingModel::RegisterStateDependentTransitCallback; %ignore operations_research::RoutingModel::StateDependentTransitCallback; %ignore operations_research::RoutingModel::MakeStateDependentTransit; @@ -71,7 +84,7 @@ PY_PROTO_TYPEMAP(ortools.routing.parameters_pb2, RoutingSearchParameters, operations_research::RoutingSearchParameters) -// Wrap routing_types.h, routing_parameters.h according to the SWIG styleguide. +// Wrap types.h, parameters.h according to the SWIG style guide. %ignoreall %unignore RoutingTransitCallback1; %unignore RoutingTransitCallback2; @@ -82,8 +95,8 @@ PY_PROTO_TYPEMAP(ortools.routing.parameters_pb2, %unignore DefaultRoutingModelParameters; %unignore FindErrorInRoutingSearchParameters; -%include "ortools/constraint_solver/routing_types.h" -%include "ortools/constraint_solver/routing_parameters.h" +%include "ortools/routing/types.h" +%include "ortools/routing/parameters.h" %unignoreall // %including a .pb.h is frowned upon (for good general reasons), so we @@ -118,4 +131,4 @@ struct RoutingSearchStatus { // TODO(user): Use ignoreall/unignoreall for this one. A lot of work. //swiglint: disable include-h-allglobals -%include "ortools/constraint_solver/routing.h" +%include "ortools/routing/routing.h" diff --git a/ortools/constraint_solver/python/routing_types.i b/ortools/routing/python/types.i similarity index 98% rename from ortools/constraint_solver/python/routing_types.i rename to ortools/routing/python/types.i index 4e1737b99c..782a6b7750 100644 --- a/ortools/constraint_solver/python/routing_types.i +++ b/ortools/routing/python/types.i @@ -21,7 +21,7 @@ %import "ortools/util/python/vector.i" %{ -#include "ortools/constraint_solver/routing_types.h" +#include "ortools/routing/types.h" template inline PyObject* PyInt_FromIndexT(const IndexT i) { diff --git a/ortools/constraint_solver/routing.cc b/ortools/routing/routing.cc similarity index 98% rename from ortools/constraint_solver/routing.cc rename to ortools/routing/routing.cc index e4f6b6cc9e..de38847c4c 100644 --- a/ortools/constraint_solver/routing.cc +++ b/ortools/routing/routing.cc @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "ortools/constraint_solver/routing.h" +#include "ortools/routing/routing.h" #include @@ -61,25 +61,25 @@ #include "ortools/base/types.h" #include "ortools/constraint_solver/constraint_solver.h" #include "ortools/constraint_solver/constraint_solveri.h" -#include "ortools/constraint_solver/routing_constraints.h" -#include "ortools/constraint_solver/routing_decision_builders.h" -#include "ortools/constraint_solver/routing_filters.h" -#include "ortools/constraint_solver/routing_ils.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_insertion_lns.h" -#include "ortools/constraint_solver/routing_lp_scheduling.h" -#include "ortools/constraint_solver/routing_neighborhoods.h" -#include "ortools/constraint_solver/routing_parameters.h" -#include "ortools/constraint_solver/routing_search.h" -#include "ortools/constraint_solver/routing_types.h" -#include "ortools/constraint_solver/routing_utils.h" #include "ortools/constraint_solver/solver_parameters.pb.h" #include "ortools/graph/connected_components.h" #include "ortools/graph/ebert_graph.h" #include "ortools/graph/linear_assignment.h" +#include "ortools/routing/constraints.h" +#include "ortools/routing/decision_builders.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/filters.h" +#include "ortools/routing/ils.h" #include "ortools/routing/ils.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/insertion_lns.h" +#include "ortools/routing/lp_scheduling.h" +#include "ortools/routing/neighborhoods.h" +#include "ortools/routing/parameters.h" #include "ortools/routing/parameters.pb.h" +#include "ortools/routing/search.h" +#include "ortools/routing/types.h" +#include "ortools/routing/utils.h" #include "ortools/util/bitset.h" #include "ortools/util/optional_boolean.pb.h" #include "ortools/util/piecewise_linear_function.h" @@ -249,6 +249,7 @@ void RoutingModel::NodeNeighborsByCostClass::ComputeNeighbors( const int max_num_neighbors = std::max(num_non_start_end_nodes - 1, 0); num_neighbors = std::min(max_num_neighbors, num_neighbors); node_index_to_neighbors_by_cost_class_.clear(); + node_index_to_neighbor_indicator_by_cost_class_.clear(); if (num_neighbors == max_num_neighbors && only_sort_neighbors_for_partial_neighborhoods) { all_nodes_.reserve(size); @@ -262,8 +263,7 @@ void RoutingModel::NodeNeighborsByCostClass::ComputeNeighbors( const int num_cost_classes = routing_model.GetCostClassesCount(); node_index_to_neighbors_by_cost_class_.resize(num_cost_classes); - std::vector>> - node_index_to_neighbor_indicator_by_cost_class(num_cost_classes); + node_index_to_neighbor_indicator_by_cost_class_.resize(num_cost_classes); std::vector>> node_index_to_costs_by_cost_class(num_cost_classes); for (int cc = 0; cc < num_cost_classes; cc++) { @@ -272,14 +272,14 @@ void RoutingModel::NodeNeighborsByCostClass::ComputeNeighbors( RoutingCostClassIndex(cc))) { continue; } - node_index_to_neighbor_indicator_by_cost_class[cc].resize( + node_index_to_neighbor_indicator_by_cost_class_[cc].resize( size_with_vehicle_nodes); node_index_to_costs_by_cost_class[cc].resize(size_with_vehicle_nodes); for (int node = 0; node < size_with_vehicle_nodes; node++) { node_index_to_neighbors_by_cost_class_[cc][node].reserve( num_neighbors + routing_model.vehicles()); - node_index_to_neighbor_indicator_by_cost_class[cc][node].resize(size, - false); + node_index_to_neighbor_indicator_by_cost_class_[cc][node].resize(size, + false); node_index_to_costs_by_cost_class[cc][node].resize(size, -1); } } @@ -294,7 +294,7 @@ void RoutingModel::NodeNeighborsByCostClass::ComputeNeighbors( std::vector>& node_index_to_neighbors = node_index_to_neighbors_by_cost_class_[cost_class]; std::vector>& node_index_to_neighbor_indicator = - node_index_to_neighbor_indicator_by_cost_class[cost_class]; + node_index_to_neighbor_indicator_by_cost_class_[cost_class]; std::vector>& node_index_to_costs = node_index_to_costs_by_cost_class[cost_class]; for (int node_index = 0; node_index < size; ++node_index) { @@ -1306,6 +1306,15 @@ void RoutingModel::SetAmortizedCostFactorsOfVehicle( quadratic_cost_factor_of_vehicle_[vehicle] = quadratic_cost_factor; } +void RoutingModel::AddRouteConstraint( + std::function(const std::vector&)> + route_evaluator, + bool costs_are_homogeneous_across_vehicles) { + costs_are_homogeneous_across_vehicles_ &= + costs_are_homogeneous_across_vehicles; + route_evaluators_.push_back(std::move(route_evaluator)); +} + void RoutingModel::FinalizeAllowedVehicles() { const std::vector unary_dimensions = GetUnaryDimensions(); @@ -1831,9 +1840,11 @@ IntVar* RoutingModel::CreateDisjunction(DisjunctionIndex disjunction) { } const int64_t max_cardinality = disjunctions_[disjunction].value.max_cardinality; + IntVar* number_active_vars = solver_->MakeIntVar(0, max_cardinality); solver_->AddConstraint( solver_->MakeSumEquality(disjunction_vars, number_active_vars)); + const int64_t penalty = disjunctions_[disjunction].value.penalty; // If penalty is negative, then disjunction is mandatory // i.e. number of active vars must be equal to max cardinality. @@ -2116,6 +2127,36 @@ int RoutingModel::GetVehicleStartClass(int64_t start_index) const { return kUnassigned; } +const std::deque& RoutingModel::GetVehiclesOfSameClass( + int64_t start_end_index) const { + const int vehicle = VehicleIndex(start_end_index); + DCHECK_NE(vehicle, kUnassigned); + return GetVehicleTypeContainer().vehicles_per_vehicle_class + [GetVehicleClassIndexOfVehicle(vehicle).value()]; +} + +std::vector> RoutingModel::GetSameVehicleClassArcs( + int64_t from_index, int64_t to_index) const { + std::vector> arcs; + if (IsStart(from_index)) { + for (int vehicle : GetVehiclesOfSameClass(from_index)) { + const int64_t start = Start(vehicle); + if (!IsEnd(to_index)) { + arcs.push_back({start, to_index}); + } else { + arcs.push_back({start, End(vehicle)}); + } + } + } else if (IsEnd(to_index)) { + for (int vehicle : GetVehiclesOfSameClass(to_index)) { + arcs.push_back({from_index, End(vehicle)}); + } + } else { + arcs.push_back({from_index, to_index}); + } + return arcs; +} + std::string RoutingModel::FindErrorInSearchParametersForModel( const RoutingSearchParameters& search_parameters) const { const FirstSolutionStrategy::Value first_solution_strategy = @@ -2163,7 +2204,7 @@ class RoutingModelInspector : public ModelVisitor { } RegisterInspectors(); } - ~RoutingModelInspector() override {} + ~RoutingModelInspector() override = default; void EndVisitModel(const std::string& /*solver_name*/) override { const std::vector node_to_same_vehicle_component_id = same_vehicle_components_.GetComponentIds(); @@ -2499,6 +2540,15 @@ void RoutingModel::CloseModelWithParameters( is_bound_to_end_[end]->SetValue(1); } + // Adding route constraint. + std::vector route_cost_vars; + if (!route_evaluators_.empty()) { + solver()->MakeIntVarArray(vehicles(), 0, kint64max, &route_cost_vars); + solver()->AddConstraint(MakeRouteConstraint( + this, route_cost_vars, + absl::bind_front(&RoutingModel::GetRouteCost, this))); + } + std::vector cost_elements; // Arc and dimension costs. if (vehicles_ > 0) { @@ -2721,6 +2771,9 @@ void RoutingModel::CloseModelWithParameters( solver_->AddConstraint( solver_->MakePathEnergyCostConstraint(std::move(specification))); } + for (IntVar* route_cost_var : route_cost_vars) { + cost_elements.push_back(route_cost_var); + } // cost_ is the sum of cost_elements. cost_ = solver_->MakeSum(cost_elements)->Var(); cost_->set_name("Cost"); @@ -3917,6 +3970,29 @@ int64_t RoutingModel::GetArcCostForClassInternal( return cost; } +std::function +RoutingModel::GetLocalSearchArcCostCallback( + const RoutingSearchParameters& parameters) const { + return parameters + .use_guided_local_search_penalties_in_local_search_operators() + ? absl::bind_front( + &RoutingModel::GetArcCostWithGuidedLocalSearchPenalties, + this) + : absl::bind_front(&RoutingModel::GetArcCostForVehicle, this); +} + +std::function +RoutingModel::GetLocalSearchHomogeneousArcCostCallback( + const RoutingSearchParameters& parameters) const { + return parameters + .use_guided_local_search_penalties_in_local_search_operators() + ? absl::bind_front( + &RoutingModel:: + GetHomogeneousArcCostWithGuidedLocalSearchPenalties, + this) + : absl::bind_front(&RoutingModel::GetHomogeneousCost, this); +} + bool RoutingModel::IsVehicleUsed(const Assignment& assignment, int vehicle) const { CHECK_GE(vehicle, 0); @@ -4504,8 +4580,7 @@ void RoutingModel::CreateNeighborhoodOperators( {TSP_OPT, Solver::TSPOPT}, {TSP_LNS, Solver::TSPLNS}}; for (const auto [type, op] : operator_by_type) { - auto arc_cost = - absl::bind_front(&RoutingModel::GetArcCostForVehicle, this); + auto arc_cost = GetLocalSearchArcCostCallback(parameters); local_search_operators_[type] = CostsAreHomogeneousAcrossVehicles() ? solver_->MakeOperator(nexts_, std::move(arc_cost), op) @@ -4545,7 +4620,7 @@ void RoutingModel::CreateNeighborhoodOperators( local_search_operators_[SHORTEST_PATH_SWAP_ACTIVE] = CreateOperator( std::move(alternative_sets), - absl::bind_front(&RoutingModel::GetHomogeneousCost, this)); + GetLocalSearchHomogeneousArcCostCallback(parameters)); // Routing-specific operators. local_search_operators_[MAKE_ACTIVE] = CreateInsertionOperator(); @@ -4578,7 +4653,7 @@ void RoutingModel::CreateNeighborhoodOperators( local_search_operators_[RELOCATE_NEIGHBORS] = CreateOperatorWithNeighborsRatio( neighbors_ratio_used, get_neighbors, - absl::bind_front(&RoutingModel::GetHomogeneousCost, this)); + GetLocalSearchHomogeneousArcCostCallback(parameters)); local_search_operators_[NODE_PAIR_SWAP] = solver_->ConcatenateOperators( {CreatePairOperator(), CreatePairOperator>(), @@ -4589,10 +4664,11 @@ void RoutingModel::CreateNeighborhoodOperators( CreatePairOperator(neighbors_ratio_used, get_neighbors); const auto arc_cost_for_path_start = - [this](int64_t before_node, int64_t after_node, int64_t start_index) { + [this, arc_cost_getter = GetLocalSearchArcCostCallback(parameters)]( + int64_t before_node, int64_t after_node, int64_t start_index) { const int vehicle = VehicleIndex(start_index); const int64_t arc_cost = - GetArcCostForVehicle(before_node, after_node, vehicle); + arc_cost_getter(before_node, after_node, vehicle); return (before_node != start_index || IsEnd(after_node)) ? arc_cost : CapSub(arc_cost, GetFixedCostOfVehicle(vehicle)); @@ -4622,7 +4698,7 @@ void RoutingModel::CreateNeighborhoodOperators( parameters.cheapest_insertion_add_unperformed_entries(); return std::make_unique( this, [this]() { return CheckLimit(time_buffer_); }, - absl::bind_front(&RoutingModel::GetArcCostForVehicle, this), + GetLocalSearchArcCostCallback(parameters), absl::bind_front(&RoutingModel::UnperformedPenaltyOrValue, this, 0), GetOrCreateLocalSearchFilterManager( parameters, @@ -4633,7 +4709,7 @@ void RoutingModel::CreateNeighborhoodOperators( [this, ¶meters]() { return std::make_unique( this, [this]() { return CheckLimit(time_buffer_); }, - absl::bind_front(&RoutingModel::GetArcCostForVehicle, this), + GetLocalSearchArcCostCallback(parameters), parameters.local_cheapest_insertion_pickup_delivery_strategy(), GetOrCreateLocalSearchFilterManager( parameters, @@ -5036,6 +5112,12 @@ RoutingModel::CreateLocalSearchFilters( priority = max_priority; } + if (!route_evaluators_.empty()) { + ++priority; + filter_events.push_back( + {MakeRouteConstraintFilter(*this), kAccept, priority}); + } + { ++priority; for (const RoutingDimension* dimension : dimensions_) { @@ -5875,13 +5957,21 @@ void RoutingModel::SetupMetaheuristics( MathUtil::SafeRound(search_parameters.optimization_step()), One()); switch (metaheuristic) { - case LocalSearchMetaheuristic::GUIDED_LOCAL_SEARCH: + case LocalSearchMetaheuristic::GUIDED_LOCAL_SEARCH: { + std::function>(int64_t, int64_t)> + same_class_arc_getter; + if (search_parameters + .guided_local_search_penalize_with_vehicle_classes()) { + same_class_arc_getter = + absl::bind_front(&RoutingModel::GetSameVehicleClassArcs, this); + } if (CostsAreHomogeneousAcrossVehicles()) { optimize = solver_->MakeGuidedLocalSearch( false, cost_, [this](int64_t i, int64_t j) { return GetHomogeneousCost(i, j); }, optimization_step, nexts_, search_parameters.guided_local_search_lambda_coefficient(), + std::move(same_class_arc_getter), search_parameters .guided_local_search_reset_penalties_on_new_best_solution()); } else { @@ -5892,10 +5982,12 @@ void RoutingModel::SetupMetaheuristics( }, optimization_step, nexts_, vehicle_vars_, search_parameters.guided_local_search_lambda_coefficient(), + std::move(same_class_arc_getter), search_parameters .guided_local_search_reset_penalties_on_new_best_solution()); } break; + } case LocalSearchMetaheuristic::SIMULATED_ANNEALING: optimize = solver_->MakeSimulatedAnnealing(false, cost_, optimization_step, 100); diff --git a/ortools/constraint_solver/routing.h b/ortools/routing/routing.h similarity index 98% rename from ortools/constraint_solver/routing.h rename to ortools/routing/routing.h index 597b0a219d..9789f6a2ae 100644 --- a/ortools/constraint_solver/routing.h +++ b/ortools/routing/routing.h @@ -153,8 +153,8 @@ /// Keywords: Vehicle Routing, Traveling Salesman Problem, TSP, VRP, CVRPTW, /// PDP. -#ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_ -#define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_ +#ifndef OR_TOOLS_ROUTING_ROUTING_H_ +#define OR_TOOLS_ROUTING_ROUTING_H_ #include #include @@ -184,12 +184,12 @@ #include "ortools/base/types.h" #include "ortools/constraint_solver/constraint_solver.h" #include "ortools/constraint_solver/constraint_solveri.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_types.h" -#include "ortools/constraint_solver/routing_utils.h" #include "ortools/graph/graph.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" #include "ortools/routing/parameters.pb.h" +#include "ortools/routing/types.h" +#include "ortools/routing/utils.h" #include "ortools/sat/theta_tree.h" #include "ortools/util/piecewise_linear_function.h" #include "ortools/util/range_query_function.h" @@ -860,6 +860,7 @@ class RoutingModel { /// The following enum is used to describe how the penalty cost is computed /// when using @ref AddDisjunction. enum PenaltyCostBehavior { PENALIZE_ONCE, PENALIZE_PER_INACTIVE }; + /// Adds a disjunction constraint on the indices: exactly 'max_cardinality' of /// the indices are active. Start and end indices of any vehicle cannot be /// part of a disjunction. @@ -1260,6 +1261,24 @@ class RoutingModel { return quadratic_cost_factor_of_vehicle_; } + // Adds a custom route constraint based on a route evaluation callback. The + // callback must not return a value if the route vector is invalid, and + // returns the value of the route otherwise. + // The callback must always return the same value for a given route. + void AddRouteConstraint( + std::function(const std::vector&)> + route_evaluator, + bool costs_are_homogeneous_across_vehicles = false); + std::optional GetRouteCost(const std::vector& route) const { + int64_t route_cost = 0; + for (const auto& evaluator : route_evaluators_) { + std::optional cost = evaluator(route); + if (!cost.has_value()) return std::nullopt; + CapAddTo(cost.value(), &route_cost); + } + return route_cost; + } + void SetVehicleUsedWhenEmpty(bool is_used, int vehicle) { DCHECK_LT(vehicle, vehicles_); vehicle_used_when_empty_[vehicle] = is_used; @@ -1609,10 +1628,21 @@ class RoutingModel { : node_index_to_neighbors_by_cost_class_[cost_class] [node_index]; } + /// Returns whether or not node 'neighbor_index' is actually a neighbor of + /// node 'node_index' for the given cost_class. + bool IsNeighborOfNodeForCostClass(int cost_class, int node_index, + int neighbor_index) const { + return node_index_to_neighbor_indicator_by_cost_class_.empty() + ? true + : node_index_to_neighbor_indicator_by_cost_class_ + [cost_class][node_index][neighbor_index]; + } private: std::vector>> node_index_to_neighbors_by_cost_class_; + std::vector>> + node_index_to_neighbor_indicator_by_cost_class_; std::vector all_nodes_; }; @@ -1978,6 +2008,18 @@ class RoutingModel { } #endif // SWIG + /// Returns indices of the vehicles which are in the same vehicle class as the + /// vehicle starting or ending at start_end_index. + const std::deque& GetVehiclesOfSameClass(int64_t start_end_index) const; + + /// Returns all arcs which are equivalent to the {from_index, to_index} arc + /// wrt vehicle classes. Arcs will be returned only if from_index is the + /// start of a vehicle or if to_index is the end of a vehicle. The returned + /// arcs will then be starting or ending at start or end nodes of vehicles in + /// the same vehicle class. The input arc is included in the returned vector. + std::vector> GetSameVehicleClassArcs( + int64_t from_index, int64_t to_index) const; + private: /// Local search move operator usable in routing. enum RoutingLocalSearchOperator { @@ -2138,6 +2180,24 @@ class RoutingModel { void TopologicallySortVisitTypes(); int64_t GetArcCostForClassInternal(int64_t from_index, int64_t to_index, CostClassIndex cost_class_index) const; + int64_t GetArcCostWithGuidedLocalSearchPenalties(int64_t from_index, + int64_t to_index, + int64_t vehicle) const { + return CapAdd( + GetArcCostForVehicle(from_index, to_index, vehicle), + solver()->GetGuidedLocalSearchPenalty(from_index, to_index, vehicle)); + } + std::function + GetLocalSearchArcCostCallback( + const RoutingSearchParameters& parameters) const; + int64_t GetHomogeneousArcCostWithGuidedLocalSearchPenalties( + int64_t from_index, int64_t to_index) const { + return GetArcCostWithGuidedLocalSearchPenalties(from_index, to_index, + /*vehicle=*/0); + } + std::function + GetLocalSearchHomogeneousArcCostCallback( + const RoutingSearchParameters& parameters) const; void AppendHomogeneousArcCosts(const RoutingSearchParameters& parameters, int node_index, std::vector* cost_elements); @@ -2467,6 +2527,9 @@ class RoutingModel { std::vector linear_cost_factor_of_vehicle_; std::vector quadratic_cost_factor_of_vehicle_; bool vehicle_amortized_cost_factors_set_; + std::vector< + std::function(const std::vector&)>> + route_evaluators_; /// vehicle_used_when_empty_[vehicle] determines if "vehicle" should be /// taken into account for costs (arc costs, span costs, etc.) and constraints /// (eg. resources) even when the route of the vehicle is empty (i.e. goes @@ -3697,4 +3760,4 @@ IntVarLocalSearchFilter* MakeVehicleBreaksFilter( #endif } // namespace operations_research -#endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_ +#endif // OR_TOOLS_ROUTING_ROUTING_H_ diff --git a/ortools/routing/samples/BUILD.bazel b/ortools/routing/samples/BUILD.bazel index 83e648522b..eb7742d101 100644 --- a/ortools/routing/samples/BUILD.bazel +++ b/ortools/routing/samples/BUILD.bazel @@ -11,12 +11,51 @@ # See the License for the specific language governing permissions and # limitations under the License. +load(":code_samples.bzl", "code_sample_cc") + +code_sample_cc(name="simple_routing_program") + +code_sample_cc(name="tsp") + +code_sample_cc(name="tsp_circuit_board") + +code_sample_cc(name="tsp_cities") + +code_sample_cc(name="tsp_distance_matrix") + +code_sample_cc(name="vrp") + +code_sample_cc(name="vrp_breaks") + +code_sample_cc(name="vrp_capacity") + +code_sample_cc(name="vrp_drop_nodes") + +code_sample_cc(name="vrp_global_span") + +code_sample_cc(name="vrp_initial_routes") + +code_sample_cc(name="vrp_pickup_delivery") + +code_sample_cc(name="vrp_pickup_delivery_fifo") + +code_sample_cc(name="vrp_pickup_delivery_lifo") + +code_sample_cc(name="vrp_resources") + +code_sample_cc(name="vrp_starts_ends") + +code_sample_cc(name="vrp_time_windows") + +code_sample_cc(name="vrp_with_time_limit") + +# cvrptw samples cc_binary( name = "cvrptw", srcs = ["cvrptw.cc"], deps = [ "//ortools/base", - "//ortools/constraint_solver:routing", + "//ortools/routing", "//ortools/routing/parsers:cvrptw_lib", ], ) @@ -26,7 +65,7 @@ cc_binary( srcs = ["cvrp_disjoint_tw.cc"], deps = [ "//ortools/base", - "//ortools/constraint_solver:routing", + "//ortools/routing", "//ortools/routing/parsers:cvrptw_lib", ], ) @@ -36,7 +75,7 @@ cc_binary( srcs = ["cvrptw_with_breaks.cc"], deps = [ "//ortools/base", - "//ortools/constraint_solver:routing", + "//ortools/routing", "//ortools/routing:enums_cc_proto", "//ortools/routing/parsers:cvrptw_lib", "@com_google_absl//absl/strings", @@ -48,7 +87,7 @@ cc_binary( srcs = ["cvrptw_with_resources.cc"], deps = [ "//ortools/base", - "//ortools/constraint_solver:routing", + "//ortools/routing", "//ortools/routing/parsers:cvrptw_lib", ], ) @@ -58,7 +97,7 @@ cc_binary( srcs = ["cvrptw_with_stop_times_and_resources.cc"], deps = [ "//ortools/base", - "//ortools/constraint_solver:routing", + "//ortools/routing", "//ortools/routing/parsers:cvrptw_lib", "@com_google_absl//absl/strings", ], @@ -69,7 +108,7 @@ cc_binary( srcs = ["cvrptw_with_refueling.cc"], deps = [ "//ortools/base", - "//ortools/constraint_solver:routing", + "//ortools/routing", "//ortools/routing/parsers:cvrptw_lib", ], ) diff --git a/ortools/routing/samples/code_samples.bzl b/ortools/routing/samples/code_samples.bzl new file mode 100644 index 0000000000..563a791c54 --- /dev/null +++ b/ortools/routing/samples/code_samples.bzl @@ -0,0 +1,37 @@ +# Copyright 2010-2024 Google LLC +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Helper macro to compile and test code samples.""" + +def code_sample_cc(name): + native.cc_binary( + name=name + "_cc", + srcs=[name + ".cc"], + deps=[ + "//ortools/base", + "//ortools/routing:routing", + "//ortools/routing:enums_cc_proto", + ], + ) + + native.cc_test( + name=name + "_cc_test", + size="small", + srcs=[name + ".cc"], + deps=[ + ":" + name + "_cc", + "//ortools/base", + "//ortools/routing:routing", + "//ortools/routing:enums_cc_proto", + ], + ) diff --git a/ortools/routing/samples/cvrp_disjoint_tw.cc b/ortools/routing/samples/cvrp_disjoint_tw.cc index 02bfcc802c..5e66df3c8d 100644 --- a/ortools/routing/samples/cvrp_disjoint_tw.cc +++ b/ortools/routing/samples/cvrp_disjoint_tw.cc @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "absl/random/random.h" @@ -33,11 +34,11 @@ #include "ortools/base/init_google.h" #include "ortools/base/logging.h" #include "ortools/base/types.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" #include "ortools/routing/parameters.pb.h" #include "ortools/routing/parsers/cvrptw_lib.h" +#include "ortools/routing/routing.h" using operations_research::Assignment; using operations_research::DefaultRoutingSearchParameters; @@ -170,12 +171,13 @@ int main(int argc, char** argv) { order < manager.num_nodes(); ++order) { group.push_back(manager.NodeToIndex(order)); if (group.size() == kMaxNodesPerGroup) { - routing.AddSoftSameVehicleConstraint(group, kSameVehicleCost); + routing.AddSoftSameVehicleConstraint(std::move(group), + kSameVehicleCost); group.clear(); } } if (!group.empty()) { - routing.AddSoftSameVehicleConstraint(group, kSameVehicleCost); + routing.AddSoftSameVehicleConstraint(std::move(group), kSameVehicleCost); } } diff --git a/ortools/constraint_solver/samples/cvrp_reload.py b/ortools/routing/samples/cvrp_reload.py similarity index 98% rename from ortools/constraint_solver/samples/cvrp_reload.py rename to ortools/routing/samples/cvrp_reload.py index 5521a999e7..cc7ae75459 100755 --- a/ortools/constraint_solver/samples/cvrp_reload.py +++ b/ortools/routing/samples/cvrp_reload.py @@ -44,8 +44,8 @@ into account in `create_distance_evaluator()`. from functools import partial -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting ########################### @@ -372,12 +372,12 @@ def main(): data = create_data_model() # Create the routing index manager - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( data["num_locations"], data["num_vehicles"], data["depot"] ) # Create Routing Model - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # Define weight of each edge distance_evaluator_index = routing.RegisterTransitCallback( @@ -401,7 +401,7 @@ def main(): add_time_window_constraints(routing, manager, data, time_evaluator_index) # Setting first solution heuristic (cheapest addition). - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) # pylint: disable=no-member diff --git a/ortools/routing/samples/cvrptw.cc b/ortools/routing/samples/cvrptw.cc index d07534fabe..f30796a4a6 100644 --- a/ortools/routing/samples/cvrptw.cc +++ b/ortools/routing/samples/cvrptw.cc @@ -23,6 +23,7 @@ #include #include +#include #include #include "absl/random/random.h" @@ -31,11 +32,11 @@ #include "ortools/base/init_google.h" #include "ortools/base/logging.h" #include "ortools/base/types.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" #include "ortools/routing/parameters.pb.h" #include "ortools/routing/parsers/cvrptw_lib.h" +#include "ortools/routing/routing.h" using operations_research::Assignment; using operations_research::DefaultRoutingSearchParameters; @@ -155,12 +156,13 @@ int main(int argc, char** argv) { order < manager.num_nodes(); ++order) { group.push_back(manager.NodeToIndex(order)); if (group.size() == kMaxNodesPerGroup) { - routing.AddSoftSameVehicleConstraint(group, kSameVehicleCost); + routing.AddSoftSameVehicleConstraint(std::move(group), + kSameVehicleCost); group.clear(); } } if (!group.empty()) { - routing.AddSoftSameVehicleConstraint(group, kSameVehicleCost); + routing.AddSoftSameVehicleConstraint(std::move(group), kSameVehicleCost); } } diff --git a/ortools/constraint_solver/samples/cvrptw_break.py b/ortools/routing/samples/cvrptw_break.py similarity index 98% rename from ortools/constraint_solver/samples/cvrptw_break.py rename to ortools/routing/samples/cvrptw_break.py index b6b58c8027..b9dd910f51 100755 --- a/ortools/constraint_solver/samples/cvrptw_break.py +++ b/ortools/routing/samples/cvrptw_break.py @@ -25,8 +25,8 @@ Distances are in meters and time in minutes. # [START import] import functools -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting # [END import] @@ -287,12 +287,12 @@ def main(): # [END data] # Create the routing index manager - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( data["numlocations_"], data["num_vehicles"], data["depot"] ) # Create Routing Model - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # Define weight of each edge distance_evaluator_index = routing.RegisterTransitCallback( @@ -339,7 +339,7 @@ def main(): # Setting first solution heuristic (cheapest addition). # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) # pylint: disable=no-member diff --git a/ortools/routing/samples/cvrptw_soft_capacity.cc b/ortools/routing/samples/cvrptw_soft_capacity.cc index defd4c6302..cc9e0234ce 100644 --- a/ortools/routing/samples/cvrptw_soft_capacity.cc +++ b/ortools/routing/samples/cvrptw_soft_capacity.cc @@ -22,6 +22,7 @@ #include #include +#include #include #include "absl/random/random.h" @@ -30,11 +31,11 @@ #include "ortools/base/init_google.h" #include "ortools/base/logging.h" #include "ortools/base/types.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" #include "ortools/routing/parameters.pb.h" #include "ortools/routing/parsers/cvrptw_lib.h" +#include "ortools/routing/routing.h" using operations_research::Assignment; using operations_research::DefaultRoutingSearchParameters; @@ -179,12 +180,13 @@ int main(int argc, char** argv) { order < manager.num_nodes(); ++order) { group.push_back(manager.NodeToIndex(order)); if (group.size() == kMaxNodesPerGroup) { - routing.AddSoftSameVehicleConstraint(group, kSameVehicleCost); + routing.AddSoftSameVehicleConstraint(std::move(group), + kSameVehicleCost); group.clear(); } } if (!group.empty()) { - routing.AddSoftSameVehicleConstraint(group, kSameVehicleCost); + routing.AddSoftSameVehicleConstraint(std::move(group), kSameVehicleCost); } } diff --git a/ortools/routing/samples/cvrptw_with_breaks.cc b/ortools/routing/samples/cvrptw_with_breaks.cc index 2f57cf4f90..2b2b0cf4c4 100644 --- a/ortools/routing/samples/cvrptw_with_breaks.cc +++ b/ortools/routing/samples/cvrptw_with_breaks.cc @@ -37,12 +37,12 @@ #include "ortools/base/init_google.h" #include "ortools/base/logging.h" #include "ortools/base/types.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" #include "ortools/routing/parameters.pb.h" #include "ortools/routing/parsers/cvrptw_lib.h" +#include "ortools/routing/routing.h" using operations_research::Assignment; using operations_research::DefaultRoutingSearchParameters; diff --git a/ortools/routing/samples/cvrptw_with_precedences.cc b/ortools/routing/samples/cvrptw_with_precedences.cc index fdfd73b487..12ad737f16 100644 --- a/ortools/routing/samples/cvrptw_with_precedences.cc +++ b/ortools/routing/samples/cvrptw_with_precedences.cc @@ -32,12 +32,12 @@ #include "ortools/base/init_google.h" #include "ortools/base/logging.h" #include "ortools/base/types.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/graph/graph_builder.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" #include "ortools/routing/parameters.pb.h" #include "ortools/routing/parsers/cvrptw_lib.h" +#include "ortools/routing/routing.h" using operations_research::Assignment; using operations_research::DefaultRoutingSearchParameters; @@ -165,12 +165,13 @@ int main(int argc, char** argv) { order < manager.num_nodes(); ++order) { group.push_back(manager.NodeToIndex(order)); if (group.size() == kMaxNodesPerGroup) { - routing.AddSoftSameVehicleConstraint(group, kSameVehicleCost); + routing.AddSoftSameVehicleConstraint(std::move(group), + kSameVehicleCost); group.clear(); } } if (!group.empty()) { - routing.AddSoftSameVehicleConstraint(group, kSameVehicleCost); + routing.AddSoftSameVehicleConstraint(std::move(group), kSameVehicleCost); } } diff --git a/ortools/routing/samples/cvrptw_with_refueling.cc b/ortools/routing/samples/cvrptw_with_refueling.cc index 4c47cae256..609fcfbbf9 100644 --- a/ortools/routing/samples/cvrptw_with_refueling.cc +++ b/ortools/routing/samples/cvrptw_with_refueling.cc @@ -29,11 +29,11 @@ #include "ortools/base/init_google.h" #include "ortools/base/logging.h" #include "ortools/base/types.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" #include "ortools/routing/parameters.pb.h" #include "ortools/routing/parsers/cvrptw_lib.h" +#include "ortools/routing/routing.h" using operations_research::Assignment; using operations_research::DefaultRoutingSearchParameters; diff --git a/ortools/routing/samples/cvrptw_with_resources.cc b/ortools/routing/samples/cvrptw_with_resources.cc index e9e0692807..6c4876975a 100644 --- a/ortools/routing/samples/cvrptw_with_resources.cc +++ b/ortools/routing/samples/cvrptw_with_resources.cc @@ -31,11 +31,11 @@ #include "ortools/base/init_google.h" #include "ortools/base/logging.h" #include "ortools/base/types.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" #include "ortools/routing/parameters.pb.h" #include "ortools/routing/parsers/cvrptw_lib.h" +#include "ortools/routing/routing.h" using operations_research::Assignment; using operations_research::DefaultRoutingSearchParameters; diff --git a/ortools/routing/samples/cvrptw_with_stop_times_and_resources.cc b/ortools/routing/samples/cvrptw_with_stop_times_and_resources.cc index fb1b607005..cd046c6801 100644 --- a/ortools/routing/samples/cvrptw_with_stop_times_and_resources.cc +++ b/ortools/routing/samples/cvrptw_with_stop_times_and_resources.cc @@ -30,11 +30,11 @@ #include "ortools/base/init_google.h" #include "ortools/base/logging.h" #include "ortools/base/types.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" #include "ortools/routing/parameters.pb.h" #include "ortools/routing/parsers/cvrptw_lib.h" +#include "ortools/routing/routing.h" using operations_research::Assignment; using operations_research::DefaultRoutingSearchParameters; diff --git a/ortools/routing/samples/cvrptw_with_time_dependent_costs.cc b/ortools/routing/samples/cvrptw_with_time_dependent_costs.cc index 4017cdc7e6..7cfd184859 100644 --- a/ortools/routing/samples/cvrptw_with_time_dependent_costs.cc +++ b/ortools/routing/samples/cvrptw_with_time_dependent_costs.cc @@ -29,11 +29,11 @@ #include "ortools/base/init_google.h" #include "ortools/base/logging.h" #include "ortools/base/types.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" #include "ortools/routing/parameters.pb.h" #include "ortools/routing/parsers/cvrptw_lib.h" +#include "ortools/routing/routing.h" #include "ortools/util/range_query_function.h" #include "ortools/util/step_function.h" diff --git a/ortools/constraint_solver/samples/simple_routing_program.cc b/ortools/routing/samples/simple_routing_program.cc similarity index 94% rename from ortools/constraint_solver/samples/simple_routing_program.cc rename to ortools/routing/samples/simple_routing_program.cc index ea09c2e30a..a760ff7791 100644 --- a/ortools/constraint_solver/samples/simple_routing_program.cc +++ b/ortools/routing/samples/simple_routing_program.cc @@ -18,10 +18,10 @@ #include #include -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" // [END import] namespace operations_research { diff --git a/ortools/constraint_solver/samples/simple_routing_program.py b/ortools/routing/samples/simple_routing_program.py similarity index 91% rename from ortools/constraint_solver/samples/simple_routing_program.py rename to ortools/routing/samples/simple_routing_program.py index a7c0d72766..88c8a5847f 100644 --- a/ortools/constraint_solver/samples/simple_routing_program.py +++ b/ortools/routing/samples/simple_routing_program.py @@ -16,8 +16,8 @@ """Vehicle Routing example.""" # [START import] -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting # [END import] @@ -32,12 +32,12 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager(num_locations, num_vehicles, depot) + manager = pywraprouting.RoutingIndexManager(num_locations, num_vehicles, depot) # [END index_manager] # Create Routing Model. # [START routing_model] - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. @@ -59,7 +59,7 @@ def main(): # Setting first solution heuristic. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) # pylint: disable=no-member diff --git a/ortools/constraint_solver/samples/tsp.cc b/ortools/routing/samples/tsp.cc similarity index 97% rename from ortools/constraint_solver/samples/tsp.cc rename to ortools/routing/samples/tsp.cc index 33e5217fe9..d42be1a852 100644 --- a/ortools/constraint_solver/samples/tsp.cc +++ b/ortools/routing/samples/tsp.cc @@ -20,10 +20,10 @@ #include "ortools/base/logging.h" #include "ortools/constraint_solver/constraint_solver.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" // [END import] namespace operations_research { diff --git a/ortools/routing/samples/tsp.py b/ortools/routing/samples/tsp.py index b2ee240be8..c22055ceb8 100644 --- a/ortools/routing/samples/tsp.py +++ b/ortools/routing/samples/tsp.py @@ -22,7 +22,7 @@ http://en.wikipedia.org/wiki/Travelling_salesperson_problem. # [START import] from ortools.routing import enums_pb2 from ortools.routing import parameters_pb2 -from ortools.routing.python import routing_model +from ortools.routing.python import model FirstSolutionStrategy = enums_pb2.FirstSolutionStrategy RoutingSearchStatus = enums_pb2.RoutingSearchStatus @@ -117,15 +117,15 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = routing_model.RoutingIndexManager( + manager = model.RoutingIndexManager( len(data["locations"]), data["num_vehicles"], data["depot"] ) # [END index_manager] # Create Routing Model. - # [START routing_model] - routing = routing_model.RoutingModel(manager) - # [END routing_model] + # [START model] + routing = model.RoutingModel(manager) + # [END model] # Create and register a transit callback. # [START transit_callback] @@ -141,7 +141,7 @@ def main(): # Setting first solution heuristic. # [START parameters] search_parameters: parameters_pb2.RoutingSearchParameters = ( - routing_model.default_routing_search_parameters() + model.default_routing_search_parameters() ) search_parameters.first_solution_strategy = FirstSolutionStrategy.PATH_CHEAPEST_ARC # [END parameters] diff --git a/ortools/constraint_solver/samples/tsp_circuit_board.cc b/ortools/routing/samples/tsp_circuit_board.cc similarity index 98% rename from ortools/constraint_solver/samples/tsp_circuit_board.cc rename to ortools/routing/samples/tsp_circuit_board.cc index 2030427602..f52d86a6c1 100644 --- a/ortools/constraint_solver/samples/tsp_circuit_board.cc +++ b/ortools/routing/samples/tsp_circuit_board.cc @@ -18,10 +18,10 @@ #include #include -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" // [END import] namespace operations_research { diff --git a/ortools/constraint_solver/samples/tsp_circuit_board.py b/ortools/routing/samples/tsp_circuit_board.py similarity index 97% rename from ortools/constraint_solver/samples/tsp_circuit_board.py rename to ortools/routing/samples/tsp_circuit_board.py index 8a17fde545..8189aadc34 100644 --- a/ortools/constraint_solver/samples/tsp_circuit_board.py +++ b/ortools/routing/samples/tsp_circuit_board.py @@ -17,8 +17,8 @@ # [START import] import math -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting # [END import] @@ -129,14 +129,14 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( len(data["locations"]), data["num_vehicles"], data["depot"] ) # [END index_manager] # Create Routing Model. # [START routing_model] - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # [END routing_model] # [START transit_callback] @@ -159,7 +159,7 @@ def main(): # Setting first solution heuristic. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) diff --git a/ortools/constraint_solver/samples/tsp_cities.cc b/ortools/routing/samples/tsp_cities.cc similarity index 96% rename from ortools/constraint_solver/samples/tsp_cities.cc rename to ortools/routing/samples/tsp_cities.cc index 7387c9ebfd..b73251b104 100644 --- a/ortools/constraint_solver/samples/tsp_cities.cc +++ b/ortools/routing/samples/tsp_cities.cc @@ -18,10 +18,10 @@ #include #include -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" // [END import] namespace operations_research { diff --git a/ortools/constraint_solver/samples/tsp_cities.py b/ortools/routing/samples/tsp_cities.py similarity index 95% rename from ortools/constraint_solver/samples/tsp_cities.py rename to ortools/routing/samples/tsp_cities.py index 2d33e9ce06..8acd49ff96 100644 --- a/ortools/constraint_solver/samples/tsp_cities.py +++ b/ortools/routing/samples/tsp_cities.py @@ -16,8 +16,8 @@ """Simple Travelling Salesperson Problem (TSP) between cities.""" # [START import] -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting # [END import] @@ -73,14 +73,14 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( len(data["distance_matrix"]), data["num_vehicles"], data["depot"] ) # [END index_manager] # Create Routing Model. # [START routing_model] - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # [END routing_model] @@ -102,7 +102,7 @@ def main(): # Setting first solution heuristic. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) diff --git a/ortools/constraint_solver/samples/tsp_cities_routes.cc b/ortools/routing/samples/tsp_cities_routes.cc similarity index 96% rename from ortools/constraint_solver/samples/tsp_cities_routes.cc rename to ortools/routing/samples/tsp_cities_routes.cc index 080595a4f5..9af1b9b79e 100644 --- a/ortools/constraint_solver/samples/tsp_cities_routes.cc +++ b/ortools/routing/samples/tsp_cities_routes.cc @@ -18,10 +18,10 @@ #include #include -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" // [END import] namespace operations_research { diff --git a/ortools/constraint_solver/samples/tsp_distance_matrix.cc b/ortools/routing/samples/tsp_distance_matrix.cc similarity index 97% rename from ortools/constraint_solver/samples/tsp_distance_matrix.cc rename to ortools/routing/samples/tsp_distance_matrix.cc index 3eb95c2183..b0b8c0e991 100644 --- a/ortools/constraint_solver/samples/tsp_distance_matrix.cc +++ b/ortools/routing/samples/tsp_distance_matrix.cc @@ -17,10 +17,10 @@ #include #include -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" // [END import] namespace operations_research { diff --git a/ortools/constraint_solver/samples/tsp_distance_matrix.py b/ortools/routing/samples/tsp_distance_matrix.py similarity index 95% rename from ortools/constraint_solver/samples/tsp_distance_matrix.py rename to ortools/routing/samples/tsp_distance_matrix.py index 594e0c2caf..bf5e6d61de 100644 --- a/ortools/constraint_solver/samples/tsp_distance_matrix.py +++ b/ortools/routing/samples/tsp_distance_matrix.py @@ -16,8 +16,8 @@ """Simple Travelling Salesman Problem.""" # [START import] -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting # [END import] @@ -79,14 +79,14 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( len(data["distance_matrix"]), data["num_vehicles"], data["depot"] ) # [END index_manager] # Create Routing Model. # [START routing_model] - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. @@ -108,7 +108,7 @@ def main(): # Setting first solution heuristic. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) diff --git a/ortools/constraint_solver/samples/tsp.py b/ortools/routing/samples/tsp_legacy.py similarity index 95% rename from ortools/constraint_solver/samples/tsp.py rename to ortools/routing/samples/tsp_legacy.py index 92b1c21dab..7f9fc65243 100644 --- a/ortools/constraint_solver/samples/tsp.py +++ b/ortools/routing/samples/tsp_legacy.py @@ -20,8 +20,8 @@ http://en.wikipedia.org/wiki/Travelling_salesperson_problem. """ # [START import] -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting FirstSolutionStrategy = enums_pb2.FirstSolutionStrategy RoutingSearchStatus = enums_pb2.RoutingSearchStatus @@ -116,14 +116,14 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( len(data["locations"]), data["num_vehicles"], data["depot"] ) # [END index_manager] # Create Routing Model. # [START routing_model] - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. @@ -139,7 +139,7 @@ def main(): # Setting first solution heuristic. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = FirstSolutionStrategy.PATH_CHEAPEST_ARC # [END parameters] diff --git a/ortools/constraint_solver/samples/vrp.cc b/ortools/routing/samples/vrp.cc similarity index 97% rename from ortools/constraint_solver/samples/vrp.cc rename to ortools/routing/samples/vrp.cc index b6cfaff554..679d68b9c8 100644 --- a/ortools/constraint_solver/samples/vrp.cc +++ b/ortools/routing/samples/vrp.cc @@ -20,10 +20,10 @@ #include "ortools/base/logging.h" #include "ortools/constraint_solver/constraint_solver.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" // [END import] namespace operations_research { diff --git a/ortools/constraint_solver/samples/vrp.py b/ortools/routing/samples/vrp.py similarity index 96% rename from ortools/constraint_solver/samples/vrp.py rename to ortools/routing/samples/vrp.py index dccfcfdc1a..0085d48224 100644 --- a/ortools/constraint_solver/samples/vrp.py +++ b/ortools/routing/samples/vrp.py @@ -24,8 +24,8 @@ Distances are in meters. """ # [START import] -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting FirstSolutionStrategy = enums_pb2.FirstSolutionStrategy RoutingSearchStatus = enums_pb2.RoutingSearchStatus @@ -104,14 +104,14 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( len(data["distance_matrix"]), data["num_vehicles"], data["depot"] ) # [END index_manager] # Create Routing Model. # [START routing_model] - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. @@ -133,7 +133,7 @@ def main(): # Setting first solution heuristic. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = FirstSolutionStrategy.PATH_CHEAPEST_ARC # [END parameters] diff --git a/ortools/constraint_solver/samples/vrp_breaks.cc b/ortools/routing/samples/vrp_breaks.cc similarity index 97% rename from ortools/constraint_solver/samples/vrp_breaks.cc rename to ortools/routing/samples/vrp_breaks.cc index fcc82f6a6e..debaf81acd 100644 --- a/ortools/constraint_solver/samples/vrp_breaks.cc +++ b/ortools/routing/samples/vrp_breaks.cc @@ -25,10 +25,10 @@ #include #include "ortools/constraint_solver/constraint_solver.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" // [END import] namespace operations_research { diff --git a/ortools/constraint_solver/samples/vrp_breaks.py b/ortools/routing/samples/vrp_breaks.py similarity index 97% rename from ortools/constraint_solver/samples/vrp_breaks.py rename to ortools/routing/samples/vrp_breaks.py index fcad91faf9..c12d8c58a1 100755 --- a/ortools/constraint_solver/samples/vrp_breaks.py +++ b/ortools/routing/samples/vrp_breaks.py @@ -24,8 +24,8 @@ Durations are in minutes. """ # [START import] -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting # [END import] @@ -108,14 +108,14 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( len(data["time_matrix"]), data["num_vehicles"], data["depot"] ) # [END index_manager] # Create Routing Model. # [START routing_model] - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. @@ -173,7 +173,7 @@ def main(): # Setting first solution heuristic. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) diff --git a/ortools/constraint_solver/samples/vrp_breaks_from_start.py b/ortools/routing/samples/vrp_breaks_from_start.py similarity index 97% rename from ortools/constraint_solver/samples/vrp_breaks_from_start.py rename to ortools/routing/samples/vrp_breaks_from_start.py index 7123c24383..eebdbc6b48 100755 --- a/ortools/constraint_solver/samples/vrp_breaks_from_start.py +++ b/ortools/routing/samples/vrp_breaks_from_start.py @@ -25,8 +25,8 @@ Durations are in minutes. """ # [START import] -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting # [END import] @@ -113,14 +113,14 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( len(data["time_matrix"]), data["num_vehicles"], data["depot"] ) # [END index_manager] # Create Routing Model. # [START routing_model] - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. @@ -182,7 +182,7 @@ def main(): # Setting first solution heuristic. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) diff --git a/ortools/constraint_solver/samples/vrp_capacity.cc b/ortools/routing/samples/vrp_capacity.cc similarity index 97% rename from ortools/constraint_solver/samples/vrp_capacity.cc rename to ortools/routing/samples/vrp_capacity.cc index 82206a0c83..65b2499b7d 100644 --- a/ortools/constraint_solver/samples/vrp_capacity.cc +++ b/ortools/routing/samples/vrp_capacity.cc @@ -18,10 +18,10 @@ #include #include "google/protobuf/duration.pb.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" // [END import] namespace operations_research { diff --git a/ortools/constraint_solver/samples/vrp_capacity.py b/ortools/routing/samples/vrp_capacity.py similarity index 96% rename from ortools/constraint_solver/samples/vrp_capacity.py rename to ortools/routing/samples/vrp_capacity.py index a5fba65d92..d58721267e 100644 --- a/ortools/constraint_solver/samples/vrp_capacity.py +++ b/ortools/routing/samples/vrp_capacity.py @@ -16,8 +16,8 @@ """Capacited Vehicles Routing Problem (CVRP).""" # [START import] -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting # [END import] @@ -96,14 +96,14 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( len(data["distance_matrix"]), data["num_vehicles"], data["depot"] ) # [END index_manager] # Create Routing Model. # [START routing_model] - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. @@ -143,7 +143,7 @@ def main(): # Setting first solution heuristic. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) diff --git a/ortools/constraint_solver/samples/vrp_drop_nodes.cc b/ortools/routing/samples/vrp_drop_nodes.cc similarity index 97% rename from ortools/constraint_solver/samples/vrp_drop_nodes.cc rename to ortools/routing/samples/vrp_drop_nodes.cc index 3e0ba0e5bf..31484d7d71 100644 --- a/ortools/constraint_solver/samples/vrp_drop_nodes.cc +++ b/ortools/routing/samples/vrp_drop_nodes.cc @@ -18,10 +18,10 @@ #include #include "google/protobuf/duration.pb.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" // [END import] namespace operations_research { diff --git a/ortools/constraint_solver/samples/vrp_drop_nodes.py b/ortools/routing/samples/vrp_drop_nodes.py similarity index 97% rename from ortools/constraint_solver/samples/vrp_drop_nodes.py rename to ortools/routing/samples/vrp_drop_nodes.py index a19589a5d4..bf20de4239 100644 --- a/ortools/constraint_solver/samples/vrp_drop_nodes.py +++ b/ortools/routing/samples/vrp_drop_nodes.py @@ -16,8 +16,8 @@ """Capacited Vehicles Routing Problem (CVRP).""" # [START import] -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting # [END import] @@ -105,14 +105,14 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( len(data["distance_matrix"]), data["num_vehicles"], data["depot"] ) # [END index_manager] # Create Routing Model. # [START routing_model] - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. @@ -156,7 +156,7 @@ def main(): # Setting first solution heuristic. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) diff --git a/ortools/constraint_solver/samples/vrp_global_span.cc b/ortools/routing/samples/vrp_global_span.cc similarity index 97% rename from ortools/constraint_solver/samples/vrp_global_span.cc rename to ortools/routing/samples/vrp_global_span.cc index e17f77b329..5106fbadf5 100644 --- a/ortools/constraint_solver/samples/vrp_global_span.cc +++ b/ortools/routing/samples/vrp_global_span.cc @@ -18,10 +18,10 @@ #include #include -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" // [END import] namespace operations_research { diff --git a/ortools/constraint_solver/samples/vrp_global_span.py b/ortools/routing/samples/vrp_global_span.py similarity index 96% rename from ortools/constraint_solver/samples/vrp_global_span.py rename to ortools/routing/samples/vrp_global_span.py index 9120582770..5a3055d688 100644 --- a/ortools/constraint_solver/samples/vrp_global_span.py +++ b/ortools/routing/samples/vrp_global_span.py @@ -24,8 +24,8 @@ Distances are in meters. """ # [START import] -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting # [END import] @@ -93,14 +93,14 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( len(data["distance_matrix"]), data["num_vehicles"], data["depot"] ) # [END index_manager] # Create Routing Model. # [START routing_model] - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. @@ -136,7 +136,7 @@ def main(): # Setting first solution heuristic. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) diff --git a/ortools/constraint_solver/samples/vrp_initial_routes.cc b/ortools/routing/samples/vrp_initial_routes.cc similarity index 97% rename from ortools/constraint_solver/samples/vrp_initial_routes.cc rename to ortools/routing/samples/vrp_initial_routes.cc index 611b0bf435..a70e260ed6 100644 --- a/ortools/constraint_solver/samples/vrp_initial_routes.cc +++ b/ortools/routing/samples/vrp_initial_routes.cc @@ -22,10 +22,10 @@ #include "google/protobuf/duration.pb.h" #include "ortools/base/logging.h" #include "ortools/constraint_solver/constraint_solver.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" // [END import] namespace operations_research { diff --git a/ortools/constraint_solver/samples/vrp_initial_routes.py b/ortools/routing/samples/vrp_initial_routes.py similarity index 96% rename from ortools/constraint_solver/samples/vrp_initial_routes.py rename to ortools/routing/samples/vrp_initial_routes.py index 46781b73c4..df5b604c32 100644 --- a/ortools/constraint_solver/samples/vrp_initial_routes.py +++ b/ortools/routing/samples/vrp_initial_routes.py @@ -16,8 +16,8 @@ """Vehicles Routing Problem (VRP).""" # [START import] -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting # [END import] @@ -95,14 +95,14 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( len(data["distance_matrix"]), data["num_vehicles"], data["depot"] ) # [END index_manager] # Create Routing Model. # [START routing_model] - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. @@ -138,7 +138,7 @@ def main(): # Close model with the custom search parameters. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) diff --git a/ortools/constraint_solver/samples/vrp_items_to_deliver.py b/ortools/routing/samples/vrp_items_to_deliver.py similarity index 98% rename from ortools/constraint_solver/samples/vrp_items_to_deliver.py rename to ortools/routing/samples/vrp_items_to_deliver.py index 35e81b94b9..0cf223aca8 100755 --- a/ortools/constraint_solver/samples/vrp_items_to_deliver.py +++ b/ortools/routing/samples/vrp_items_to_deliver.py @@ -14,9 +14,8 @@ fleet: """ # [START import] -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 - +from ortools.routing import pywraprouting # [END import] @@ -463,7 +462,7 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( len(data["distance_matrix"]), data["num_vehicles"], data["starts"], @@ -473,7 +472,7 @@ def main(): # Create Routing Model. # [START routing_model] - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # [END routing_model] @@ -570,7 +569,7 @@ def main(): # Setting first solution heuristic. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) diff --git a/ortools/constraint_solver/samples/vrp_node_max.py b/ortools/routing/samples/vrp_node_max.py similarity index 97% rename from ortools/constraint_solver/samples/vrp_node_max.py rename to ortools/routing/samples/vrp_node_max.py index e7eabaf258..aef1afe931 100755 --- a/ortools/constraint_solver/samples/vrp_node_max.py +++ b/ortools/routing/samples/vrp_node_max.py @@ -20,8 +20,8 @@ road multiply by a constant factor (4200) """ # [START import] -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting # [END import] @@ -127,14 +127,14 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( len(data["distance_matrix"]), data["num_vehicles"], data["depot"] ) # [END index_manager] # Create Routing Model. # [START routing_model] - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. @@ -238,7 +238,7 @@ def main(): # Setting first solution heuristic. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) diff --git a/ortools/constraint_solver/samples/vrp_nodes_indices.py b/ortools/routing/samples/vrp_nodes_indices.py similarity index 95% rename from ortools/constraint_solver/samples/vrp_nodes_indices.py rename to ortools/routing/samples/vrp_nodes_indices.py index 83b5a7574f..8bbcb1a5ec 100755 --- a/ortools/constraint_solver/samples/vrp_nodes_indices.py +++ b/ortools/routing/samples/vrp_nodes_indices.py @@ -42,7 +42,7 @@ manager.NodeToIndex(). manager::num_indices() (C++) """ -from ortools.constraint_solver import pywrapcp +from ortools.routing import pywraprouting def main(): @@ -53,8 +53,8 @@ def main(): vehicles = len(starts) assert len(starts) == len(ends) - manager = pywrapcp.RoutingIndexManager(locations, vehicles, starts, ends) - routing = pywrapcp.RoutingModel(manager) + manager = pywraprouting.RoutingIndexManager(locations, vehicles, starts, ends) + routing = pywraprouting.RoutingModel(manager) print("Starts/Ends:") header = "| |" diff --git a/ortools/constraint_solver/samples/vrp_pickup_delivery.cc b/ortools/routing/samples/vrp_pickup_delivery.cc similarity index 97% rename from ortools/constraint_solver/samples/vrp_pickup_delivery.cc rename to ortools/routing/samples/vrp_pickup_delivery.cc index c5317106a3..b2cd27c0a8 100644 --- a/ortools/constraint_solver/samples/vrp_pickup_delivery.cc +++ b/ortools/routing/samples/vrp_pickup_delivery.cc @@ -17,10 +17,10 @@ #include #include -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" // [END import] namespace operations_research { diff --git a/ortools/constraint_solver/samples/vrp_pickup_delivery.py b/ortools/routing/samples/vrp_pickup_delivery.py similarity index 96% rename from ortools/constraint_solver/samples/vrp_pickup_delivery.py rename to ortools/routing/samples/vrp_pickup_delivery.py index e6479665f1..7b08e0ac75 100755 --- a/ortools/constraint_solver/samples/vrp_pickup_delivery.py +++ b/ortools/routing/samples/vrp_pickup_delivery.py @@ -16,8 +16,8 @@ """Simple Pickup Delivery Problem (PDP).""" # [START import] -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting # [END import] @@ -97,14 +97,14 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( len(data["distance_matrix"]), data["num_vehicles"], data["depot"] ) # [END index_manager] # Create Routing Model. # [START routing_model] - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # [END routing_model] @@ -152,7 +152,7 @@ def main(): # Setting first solution heuristic. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PARALLEL_CHEAPEST_INSERTION ) diff --git a/ortools/constraint_solver/samples/vrp_pickup_delivery_fifo.cc b/ortools/routing/samples/vrp_pickup_delivery_fifo.cc similarity index 97% rename from ortools/constraint_solver/samples/vrp_pickup_delivery_fifo.cc rename to ortools/routing/samples/vrp_pickup_delivery_fifo.cc index 49bf9d348d..5508d3eb23 100644 --- a/ortools/constraint_solver/samples/vrp_pickup_delivery_fifo.cc +++ b/ortools/routing/samples/vrp_pickup_delivery_fifo.cc @@ -17,10 +17,10 @@ #include #include -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" // [END import] namespace operations_research { diff --git a/ortools/constraint_solver/samples/vrp_pickup_delivery_fifo.py b/ortools/routing/samples/vrp_pickup_delivery_fifo.py similarity index 95% rename from ortools/constraint_solver/samples/vrp_pickup_delivery_fifo.py rename to ortools/routing/samples/vrp_pickup_delivery_fifo.py index ed3155c158..f437c9b980 100755 --- a/ortools/constraint_solver/samples/vrp_pickup_delivery_fifo.py +++ b/ortools/routing/samples/vrp_pickup_delivery_fifo.py @@ -16,8 +16,8 @@ """Simple Pickup Delivery Problem (PDP).""" # [START import] -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting # [END import] @@ -97,14 +97,14 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( len(data["distance_matrix"]), data["num_vehicles"], data["depot"] ) # [END index_manager] # Create Routing Model. # [START routing_model] - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # [END routing_model] @@ -149,13 +149,13 @@ def main(): <= distance_dimension.CumulVar(delivery_index) ) routing.SetPickupAndDeliveryPolicyOfAllVehicles( - pywrapcp.RoutingModel.PICKUP_AND_DELIVERY_FIFO + pywraprouting.RoutingModel.PICKUP_AND_DELIVERY_FIFO ) # [END pickup_delivery_constraint] # Setting first solution heuristic. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PARALLEL_CHEAPEST_INSERTION ) diff --git a/ortools/constraint_solver/samples/vrp_pickup_delivery_lifo.cc b/ortools/routing/samples/vrp_pickup_delivery_lifo.cc similarity index 97% rename from ortools/constraint_solver/samples/vrp_pickup_delivery_lifo.cc rename to ortools/routing/samples/vrp_pickup_delivery_lifo.cc index 9264132cab..0c5ed67919 100644 --- a/ortools/constraint_solver/samples/vrp_pickup_delivery_lifo.cc +++ b/ortools/routing/samples/vrp_pickup_delivery_lifo.cc @@ -17,10 +17,10 @@ #include #include -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" // [END import] namespace operations_research { diff --git a/ortools/constraint_solver/samples/vrp_pickup_delivery_lifo.py b/ortools/routing/samples/vrp_pickup_delivery_lifo.py similarity index 95% rename from ortools/constraint_solver/samples/vrp_pickup_delivery_lifo.py rename to ortools/routing/samples/vrp_pickup_delivery_lifo.py index e3ef6e4746..6f32c74953 100755 --- a/ortools/constraint_solver/samples/vrp_pickup_delivery_lifo.py +++ b/ortools/routing/samples/vrp_pickup_delivery_lifo.py @@ -16,8 +16,8 @@ """Simple Pickup Delivery Problem (PDP).""" # [START import] -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting # [END import] @@ -97,14 +97,14 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( len(data["distance_matrix"]), data["num_vehicles"], data["depot"] ) # [END index_manager] # Create Routing Model. # [START routing_model] - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # [END routing_model] @@ -149,13 +149,13 @@ def main(): <= distance_dimension.CumulVar(delivery_index) ) routing.SetPickupAndDeliveryPolicyOfAllVehicles( - pywrapcp.RoutingModel.PICKUP_AND_DELIVERY_LIFO + pywraprouting.RoutingModel.PICKUP_AND_DELIVERY_LIFO ) # [END pickup_delivery_constraint] # Setting first solution heuristic. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PARALLEL_CHEAPEST_INSERTION ) diff --git a/ortools/constraint_solver/samples/vrp_resources.cc b/ortools/routing/samples/vrp_resources.cc similarity index 98% rename from ortools/constraint_solver/samples/vrp_resources.cc rename to ortools/routing/samples/vrp_resources.cc index 2f3151e29b..2cb6fb5c08 100644 --- a/ortools/constraint_solver/samples/vrp_resources.cc +++ b/ortools/routing/samples/vrp_resources.cc @@ -19,10 +19,10 @@ #include #include -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" // [END import] namespace operations_research { diff --git a/ortools/constraint_solver/samples/vrp_resources.py b/ortools/routing/samples/vrp_resources.py similarity index 97% rename from ortools/constraint_solver/samples/vrp_resources.py rename to ortools/routing/samples/vrp_resources.py index 00e55ca24f..da049359ad 100644 --- a/ortools/constraint_solver/samples/vrp_resources.py +++ b/ortools/routing/samples/vrp_resources.py @@ -16,8 +16,8 @@ """Vehicles Routing Problem (VRP) with Resource Constraints.""" # [START import] -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting # [END import] @@ -112,14 +112,14 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( len(data["time_matrix"]), data["num_vehicles"], data["depot"] ) # [END index_manager] # Create Routing Model. # [START routing_model] - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. @@ -205,7 +205,7 @@ def main(): # Setting first solution heuristic. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) diff --git a/ortools/constraint_solver/samples/vrp_routes.cc b/ortools/routing/samples/vrp_routes.cc similarity index 97% rename from ortools/constraint_solver/samples/vrp_routes.cc rename to ortools/routing/samples/vrp_routes.cc index 72d3e2c28a..c5de3197ab 100644 --- a/ortools/constraint_solver/samples/vrp_routes.cc +++ b/ortools/routing/samples/vrp_routes.cc @@ -17,10 +17,10 @@ #include #include -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" // [END import] namespace operations_research { diff --git a/ortools/constraint_solver/samples/vrp_solution_callback.cc b/ortools/routing/samples/vrp_solution_callback.cc similarity index 97% rename from ortools/constraint_solver/samples/vrp_solution_callback.cc rename to ortools/routing/samples/vrp_solution_callback.cc index b6fc7c4947..c53b5d8857 100644 --- a/ortools/constraint_solver/samples/vrp_solution_callback.cc +++ b/ortools/routing/samples/vrp_solution_callback.cc @@ -20,10 +20,10 @@ #include #include "google/protobuf/duration.pb.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" // [END import] namespace operations_research { diff --git a/ortools/constraint_solver/samples/vrp_solution_callback.py b/ortools/routing/samples/vrp_solution_callback.py similarity index 94% rename from ortools/constraint_solver/samples/vrp_solution_callback.py rename to ortools/routing/samples/vrp_solution_callback.py index 59c67b1794..8bdab91529 100755 --- a/ortools/constraint_solver/samples/vrp_solution_callback.py +++ b/ortools/routing/samples/vrp_solution_callback.py @@ -26,8 +26,8 @@ Distances are in meters. # [START import] import weakref -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting # [END import] @@ -64,8 +64,8 @@ def create_data_model(): # [START solution_callback_printer] def print_solution( - routing_manager: pywrapcp.RoutingIndexManager, - routing_model: pywrapcp.RoutingModel, + routing_manager: pywraprouting.RoutingIndexManager, + routing_model: pywraprouting.RoutingModel, ): """Prints solution on console.""" print("################") @@ -87,6 +87,7 @@ def print_solution( print(plan_output) total_distance += route_distance print(f"Total Distance of all routes: {total_distance}m") + # [END solution_callback_printer] @@ -96,8 +97,8 @@ class SolutionCallback: def __init__( self, - manager: pywrapcp.RoutingIndexManager, - model: pywrapcp.RoutingModel, + manager: pywraprouting.RoutingIndexManager, + model: pywraprouting.RoutingModel, limit: int, ): # We need a weak ref on the routing model to avoid a cycle. @@ -119,6 +120,7 @@ class SolutionCallback: self._counter += 1 if self._counter > self._counter_limit: self._routing_model_ref().solver().FinishCurrentSearch() # pytype: disable=attribute-error + # [END solution_callback] @@ -131,14 +133,14 @@ def main(): # Create the routing index manager. # [START index_manager] - routing_manager = pywrapcp.RoutingIndexManager( + routing_manager = pywraprouting.RoutingIndexManager( len(data["distance_matrix"]), data["num_vehicles"], data["depot"] ) # [END index_manager] # Create Routing Model. # [START routing_model] - routing_model = pywrapcp.RoutingModel(routing_manager) + routing_model = pywraprouting.RoutingModel(routing_manager) # [END routing_model] @@ -181,7 +183,7 @@ def main(): # Setting first solution heuristic. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) diff --git a/ortools/constraint_solver/samples/vrp_starts_ends.cc b/ortools/routing/samples/vrp_starts_ends.cc similarity index 97% rename from ortools/constraint_solver/samples/vrp_starts_ends.cc rename to ortools/routing/samples/vrp_starts_ends.cc index 24851d203e..5d6de02071 100644 --- a/ortools/constraint_solver/samples/vrp_starts_ends.cc +++ b/ortools/routing/samples/vrp_starts_ends.cc @@ -18,10 +18,10 @@ #include #include -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" // [END import] namespace operations_research { diff --git a/ortools/constraint_solver/samples/vrp_starts_ends.py b/ortools/routing/samples/vrp_starts_ends.py similarity index 96% rename from ortools/constraint_solver/samples/vrp_starts_ends.py rename to ortools/routing/samples/vrp_starts_ends.py index b78f3380ff..cde2b08d64 100644 --- a/ortools/constraint_solver/samples/vrp_starts_ends.py +++ b/ortools/routing/samples/vrp_starts_ends.py @@ -16,8 +16,8 @@ """Simple Vehicles Routing Problem.""" # [START import] -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting # [END import] @@ -88,7 +88,7 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( len(data["distance_matrix"]), data["num_vehicles"], data["starts"], @@ -98,7 +98,7 @@ def main(): # Create Routing Model. # [START routing_model] - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. @@ -134,7 +134,7 @@ def main(): # Setting first solution heuristic. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) diff --git a/ortools/constraint_solver/samples/vrp_time_windows.cc b/ortools/routing/samples/vrp_time_windows.cc similarity index 97% rename from ortools/constraint_solver/samples/vrp_time_windows.cc rename to ortools/routing/samples/vrp_time_windows.cc index c2587c3912..cef85b80d5 100644 --- a/ortools/constraint_solver/samples/vrp_time_windows.cc +++ b/ortools/routing/samples/vrp_time_windows.cc @@ -19,10 +19,10 @@ #include #include -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" // [END import] // [START program_part1] diff --git a/ortools/constraint_solver/samples/vrp_time_windows.py b/ortools/routing/samples/vrp_time_windows.py similarity index 96% rename from ortools/constraint_solver/samples/vrp_time_windows.py rename to ortools/routing/samples/vrp_time_windows.py index c39c98a79c..6ae68c1ce8 100644 --- a/ortools/constraint_solver/samples/vrp_time_windows.py +++ b/ortools/routing/samples/vrp_time_windows.py @@ -16,8 +16,8 @@ """Vehicles Routing Problem (VRP) with Time Windows.""" # [START import] -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting # [END import] @@ -107,14 +107,14 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( len(data["time_matrix"]), data["num_vehicles"], data["depot"] ) # [END index_manager] # Create Routing Model. # [START routing_model] - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. @@ -171,7 +171,7 @@ def main(): # Setting first solution heuristic. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) diff --git a/ortools/constraint_solver/samples/vrp_time_windows_per_vehicles.py b/ortools/routing/samples/vrp_time_windows_per_vehicles.py similarity index 97% rename from ortools/constraint_solver/samples/vrp_time_windows_per_vehicles.py rename to ortools/routing/samples/vrp_time_windows_per_vehicles.py index e14d482a26..2484d0dd76 100755 --- a/ortools/constraint_solver/samples/vrp_time_windows_per_vehicles.py +++ b/ortools/routing/samples/vrp_time_windows_per_vehicles.py @@ -30,9 +30,8 @@ location: [49-64] vehicle: 3 TW: [900, 1020] (3pm-5pm) """ # [START import] -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 - +from ortools.routing import pywraprouting # [END import] @@ -126,14 +125,14 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( 1 + 16 * 4, data["num_vehicles"], data["depot"] # number of locations ) # [END index_manager] # Create Routing Model. # [START routing_model] - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # [END routing_model] @@ -227,7 +226,7 @@ def main(): # Setting first solution heuristic. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) diff --git a/ortools/constraint_solver/samples/vrp_tokens.py b/ortools/routing/samples/vrp_tokens.py similarity index 96% rename from ortools/constraint_solver/samples/vrp_tokens.py rename to ortools/routing/samples/vrp_tokens.py index 0b72b82c4f..71fd42ed27 100755 --- a/ortools/constraint_solver/samples/vrp_tokens.py +++ b/ortools/routing/samples/vrp_tokens.py @@ -15,8 +15,8 @@ """Simple VRP with special locations which need to be visited at end of the route.""" # [START import] -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting # [END import] @@ -91,12 +91,12 @@ def main(): data = create_data_model() # Create the routing index manager. - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( len(data["tokens"]), data["num_vehicles"], data["depot"] ) # Create Routing Model. - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # Create and register a transit callback. def distance_callback(from_index, to_index): @@ -153,7 +153,7 @@ def main(): # [END depot_start_end_times] # Setting first solution heuristic. - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) diff --git a/ortools/constraint_solver/samples/vrp_with_time_limit.cc b/ortools/routing/samples/vrp_with_time_limit.cc similarity index 96% rename from ortools/constraint_solver/samples/vrp_with_time_limit.cc rename to ortools/routing/samples/vrp_with_time_limit.cc index c04833ab0b..3006c30e9c 100644 --- a/ortools/constraint_solver/samples/vrp_with_time_limit.cc +++ b/ortools/routing/samples/vrp_with_time_limit.cc @@ -19,10 +19,10 @@ #include #include "google/protobuf/duration.pb.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" // [END import] namespace operations_research { diff --git a/ortools/constraint_solver/samples/vrp_with_time_limit.py b/ortools/routing/samples/vrp_with_time_limit.py similarity index 93% rename from ortools/constraint_solver/samples/vrp_with_time_limit.py rename to ortools/routing/samples/vrp_with_time_limit.py index dc0085ea36..60fa4fe616 100644 --- a/ortools/constraint_solver/samples/vrp_with_time_limit.py +++ b/ortools/routing/samples/vrp_with_time_limit.py @@ -16,8 +16,8 @@ """Vehicles Routing Problem (VRP).""" # [START import] -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting # [END import] @@ -56,12 +56,12 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager(num_locations, num_vehicles, depot) + manager = pywraprouting.RoutingIndexManager(num_locations, num_vehicles, depot) # [END index_manager] # Create Routing Model. # [START routing_model] - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # [END routing_model] @@ -96,7 +96,7 @@ def main(): # Setting first solution heuristic. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) diff --git a/ortools/constraint_solver/samples/vrptw_store_solution_data.cc b/ortools/routing/samples/vrptw_store_solution_data.cc similarity index 98% rename from ortools/constraint_solver/samples/vrptw_store_solution_data.cc rename to ortools/routing/samples/vrptw_store_solution_data.cc index 7d5be38ffc..d6e99f3dba 100644 --- a/ortools/constraint_solver/samples/vrptw_store_solution_data.cc +++ b/ortools/routing/samples/vrptw_store_solution_data.cc @@ -19,10 +19,10 @@ #include #include -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_index_manager.h" -#include "ortools/constraint_solver/routing_parameters.h" #include "ortools/routing/enums.pb.h" +#include "ortools/routing/index_manager.h" +#include "ortools/routing/parameters.h" +#include "ortools/routing/routing.h" // [END import] // [START program_part1] diff --git a/ortools/constraint_solver/samples/vrptw_store_solution_data.py b/ortools/routing/samples/vrptw_store_solution_data.py similarity index 97% rename from ortools/constraint_solver/samples/vrptw_store_solution_data.py rename to ortools/routing/samples/vrptw_store_solution_data.py index 9f65f78d8d..ce1f82f262 100644 --- a/ortools/constraint_solver/samples/vrptw_store_solution_data.py +++ b/ortools/routing/samples/vrptw_store_solution_data.py @@ -16,8 +16,8 @@ """VRPTW example that stores routes and cumulative data in an array.""" # [START import] -from ortools.constraint_solver import pywrapcp from ortools.routing import enums_pb2 +from ortools.routing import pywraprouting # [END import] @@ -67,6 +67,7 @@ def create_data_model(): data["num_vehicles"] = 4 data["depot"] = 0 return data + # [END data_model] @@ -104,6 +105,7 @@ def print_solution(routes, cumul_data): total_time += cumul_data[i][len(route) - 1][0] route_str += f"Total time: {total_time}min" print(route_str) + # [END solution_printer] @@ -121,6 +123,7 @@ def get_routes(solution, routing, manager): route.append(manager.IndexToNode(index)) routes.append(route) return routes + # [END get_routes] @@ -144,6 +147,7 @@ def get_cumul_data(solution, routing, dimension): route_data.append([solution.Min(dim_var), solution.Max(dim_var)]) cumul_data.append(route_data) return cumul_data + # [END get_cumulative_data] @@ -156,14 +160,14 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager( + manager = pywraprouting.RoutingIndexManager( len(data["time_matrix"]), data["num_vehicles"], data["depot"] ) # [END index_manager] # Create Routing Model. # [START routing_model] - routing = pywrapcp.RoutingModel(manager) + routing = pywraprouting.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. @@ -220,7 +224,7 @@ def main(): # Setting first solution heuristic. # [START parameters] - search_parameters = pywrapcp.DefaultRoutingSearchParameters() + search_parameters = pywraprouting.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) diff --git a/ortools/constraint_solver/routing_sat.cc b/ortools/routing/sat.cc similarity index 99% rename from ortools/constraint_solver/routing_sat.cc rename to ortools/routing/sat.cc index 00c44c0bea..943f3969b2 100644 --- a/ortools/constraint_solver/routing_sat.cc +++ b/ortools/routing/sat.cc @@ -28,9 +28,9 @@ #include "absl/types/span.h" #include "ortools/base/map_util.h" #include "ortools/constraint_solver/constraint_solver.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_types.h" #include "ortools/routing/parameters.pb.h" +#include "ortools/routing/routing.h" +#include "ortools/routing/types.h" #include "ortools/sat/cp_model.pb.h" #include "ortools/sat/cp_model_solver.h" #include "ortools/sat/integer.h" diff --git a/ortools/constraint_solver/routing_search.cc b/ortools/routing/search.cc similarity index 98% rename from ortools/constraint_solver/routing_search.cc rename to ortools/routing/search.cc index 524fa1436e..ac905d09ed 100644 --- a/ortools/constraint_solver/routing_search.cc +++ b/ortools/routing/search.cc @@ -16,7 +16,7 @@ // and local search filters. // TODO(user): Move all existing routing search code here. -#include "ortools/constraint_solver/routing_search.h" +#include "ortools/routing/search.h" #include #include @@ -50,12 +50,12 @@ #include "ortools/base/types.h" #include "ortools/constraint_solver/constraint_solver.h" #include "ortools/constraint_solver/constraint_solveri.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_types.h" -#include "ortools/constraint_solver/routing_utils.h" #include "ortools/graph/christofides.h" #include "ortools/routing/enums.pb.h" #include "ortools/routing/parameters.pb.h" +#include "ortools/routing/routing.h" +#include "ortools/routing/types.h" +#include "ortools/routing/utils.h" #include "ortools/util/bitset.h" #include "ortools/util/range_query_function.h" #include "ortools/util/saturated_arithmetic.h" @@ -1199,9 +1199,11 @@ bool GlobalCheapestInsertionFilteredHeuristic::InsertNodesOnRoutes( const std::map>& nodes_by_bucket, const absl::flat_hash_set& vehicles) { NodeEntryQueue queue(model()->Nexts().size()); - std::vector nodes_to_insert(model()->Size(), false); + SparseBitset nodes_to_insert(model()->Size()); for (const auto& [bucket, nodes] : nodes_by_bucket) { - for (int node : nodes) nodes_to_insert[node] = true; + for (int node : nodes) { + nodes_to_insert.Set(node); + } if (!InitializePositions(nodes_to_insert, vehicles, &queue)) { return false; } @@ -1258,15 +1260,22 @@ bool GlobalCheapestInsertionFilteredHeuristic::InsertNodesOnRoutes( } // In case all nodes could not be inserted, pushing uninserted ones to the // next bucket. - for (int node = 0; node < nodes_to_insert.size(); ++node) { - if (Contains(node)) nodes_to_insert[node] = false; + std::vector non_inserted_nodes; + non_inserted_nodes.reserve( + nodes_to_insert.NumberOfSetCallsWithDifferentArguments()); + for (int node : nodes_to_insert.PositionsSetAtLeastOnce()) { + if (!Contains(node)) non_inserted_nodes.push_back(node); + } + nodes_to_insert.SparseClearAll(); + for (int node : non_inserted_nodes) { + nodes_to_insert.Set(node); } } return true; } bool GlobalCheapestInsertionFilteredHeuristic:: - InsertNodeEntryUsingEmptyVehicleTypeCurator(const std::vector& nodes, + InsertNodeEntryUsingEmptyVehicleTypeCurator(const SparseBitset& nodes, bool all_vehicles, NodeEntryQueue* queue) { const NodeEntryQueue::Entry* node_entry = queue->Top(); @@ -1976,7 +1985,7 @@ GlobalCheapestInsertionFilteredHeuristic::GetInsertionValueForPairAtPositions( } bool GlobalCheapestInsertionFilteredHeuristic::InitializePositions( - const std::vector& nodes, const absl::flat_hash_set& vehicles, + const SparseBitset& nodes, const absl::flat_hash_set& vehicles, NodeEntryQueue* queue) { queue->Clear(); @@ -1984,10 +1993,9 @@ bool GlobalCheapestInsertionFilteredHeuristic::InitializePositions( vehicles.empty() ? model()->vehicles() : vehicles.size(); const bool all_vehicles = (num_vehicles == model()->vehicles()); - for (int node = 0; node < nodes.size(); node++) { - if (!nodes[node] || Contains(node)) { - continue; - } + for (int node : nodes.PositionsSetAtLeastOnce()) { + if (Contains(node)) continue; + if (StopSearch()) return false; // Add insertion entry making node unperformed. if (gci_params_.add_unperformed_entries && @@ -2060,7 +2068,7 @@ void GlobalCheapestInsertionFilteredHeuristic:: } bool GlobalCheapestInsertionFilteredHeuristic::UpdateAfterNodeInsertion( - const std::vector& nodes, int vehicle, int64_t node, + const SparseBitset& nodes, int vehicle, int64_t node, int64_t insert_after, bool all_vehicles, NodeEntryQueue* queue) { // Update cost of existing entries after "insert_after" which now have new // nexts. @@ -2078,7 +2086,7 @@ bool GlobalCheapestInsertionFilteredHeuristic::UpdateAfterNodeInsertion( } bool GlobalCheapestInsertionFilteredHeuristic::UpdateExistingNodeEntriesOnChain( - const std::vector& nodes, int vehicle, int64_t insert_after_start, + const SparseBitset& nodes, int vehicle, int64_t insert_after_start, int64_t insert_after_end, bool all_vehicles, NodeEntryQueue* queue) { int64_t insert_after = insert_after_start; while (insert_after != insert_after_end) { @@ -2090,18 +2098,32 @@ bool GlobalCheapestInsertionFilteredHeuristic::UpdateExistingNodeEntriesOnChain( } bool GlobalCheapestInsertionFilteredHeuristic::AddNodeEntriesAfter( - const std::vector& nodes, int vehicle, int64_t insert_after, + const SparseBitset& nodes, int vehicle, int64_t insert_after, bool all_vehicles, NodeEntryQueue* queue) { const int cost_class = model()->GetCostClassIndexOfVehicle(vehicle).value(); // Remove existing entries at 'insert_after', needed either when updating // entries or if unperformed node insertions were present. queue->ClearInsertions(insert_after); - for (int node : - node_index_to_neighbors_by_cost_class_->GetNeighborsOfNodeForCostClass( - cost_class, insert_after)) { - if (StopSearch()) return false; - if (!Contains(node) && nodes[node]) { - AddNodeEntry(node, insert_after, vehicle, all_vehicles, queue); + const std::vector& neighbors = + node_index_to_neighbors_by_cost_class_->GetNeighborsOfNodeForCostClass( + cost_class, insert_after); + if (neighbors.size() < nodes.NumberOfSetCallsWithDifferentArguments()) { + // Iterate on the neighbors. + for (int node : neighbors) { + if (StopSearch()) return false; + if (!Contains(node) && nodes[node]) { + AddNodeEntry(node, insert_after, vehicle, all_vehicles, queue); + } + } + } else { + // Iterate on the nodes to insert. + for (int node : nodes.PositionsSetAtLeastOnce()) { + if (StopSearch()) return false; + if (!Contains(node) && + node_index_to_neighbors_by_cost_class_->IsNeighborOfNodeForCostClass( + cost_class, insert_after, node)) { + AddNodeEntry(node, insert_after, vehicle, all_vehicles, queue); + } } } return true; @@ -3525,7 +3547,7 @@ SavingsFilteredHeuristic::SavingsFilteredHeuristic( DCHECK_GT(savings_params_.arc_coefficient, 0); } -SavingsFilteredHeuristic::~SavingsFilteredHeuristic() {} +SavingsFilteredHeuristic::~SavingsFilteredHeuristic() = default; bool SavingsFilteredHeuristic::BuildSolutionInternal() { if (vehicle_type_curator_ == nullptr) { @@ -4166,7 +4188,7 @@ namespace { struct SweepIndex { SweepIndex(const int64_t index, const double angle, const double distance) : index(index), angle(angle), distance(distance) {} - ~SweepIndex() {} + ~SweepIndex() = default; int64_t index; double angle; @@ -4242,7 +4264,7 @@ struct Link { vehicle_class(vehicle_class), start_depot(start_depot), end_depot(end_depot) {} - ~Link() {} + ~Link() = default; std::pair link; int64_t value; @@ -4287,7 +4309,7 @@ class RouteConstructor { new_possible_cumuls_.resize(dimensions_.size()); } - ~RouteConstructor() {} + ~RouteConstructor() = default; void Construct() { model_->solver()->TopPeriodicCheck(); @@ -4722,7 +4744,7 @@ class SweepBuilder : public DecisionBuilder { public: SweepBuilder(RoutingModel* const model, bool check_assignment) : model_(model), check_assignment_(check_assignment) {} - ~SweepBuilder() override {} + ~SweepBuilder() override = default; Decision* Next(Solver* const solver) override { // Setup the model of the instance for the Sweep Algorithm @@ -4787,7 +4809,7 @@ class AllUnperformed : public DecisionBuilder { public: // Does not take ownership of model. explicit AllUnperformed(RoutingModel* const model) : model_(model) {} - ~AllUnperformed() override {} + ~AllUnperformed() override = default; Decision* Next(Solver* const /*solver*/) override { // Solver::(Un)FreezeQueue is private, passing through the public API // on PropagationBaseObject. diff --git a/ortools/constraint_solver/routing_search.h b/ortools/routing/search.h similarity index 97% rename from ortools/constraint_solver/routing_search.h rename to ortools/routing/search.h index 3b9cc40ff9..7c74c684be 100644 --- a/ortools/constraint_solver/routing_search.h +++ b/ortools/routing/search.h @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_SEARCH_H_ -#define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_SEARCH_H_ +#ifndef OR_TOOLS_ROUTING_SEARCH_H_ +#define OR_TOOLS_ROUTING_SEARCH_H_ #include #include @@ -38,11 +38,12 @@ #include "ortools/base/adjustable_priority_queue.h" #include "ortools/constraint_solver/constraint_solver.h" #include "ortools/constraint_solver/constraint_solveri.h" -#include "ortools/constraint_solver/routing.h" -#include "ortools/constraint_solver/routing_types.h" -#include "ortools/constraint_solver/routing_utils.h" #include "ortools/routing/enums.pb.h" #include "ortools/routing/parameters.pb.h" +#include "ortools/routing/routing.h" +#include "ortools/routing/types.h" +#include "ortools/routing/utils.h" +#include "ortools/util/bitset.h" namespace operations_research { @@ -154,7 +155,7 @@ class IntVarFilteredDecisionBuilder : public DecisionBuilder { explicit IntVarFilteredDecisionBuilder( std::unique_ptr heuristic); - ~IntVarFilteredDecisionBuilder() override {} + ~IntVarFilteredDecisionBuilder() override = default; Decision* Next(Solver* solver) override; @@ -175,7 +176,7 @@ class IntVarFilteredHeuristic { const std::vector& secondary_vars, LocalSearchFilterManager* filter_manager); - virtual ~IntVarFilteredHeuristic() {} + virtual ~IntVarFilteredHeuristic() = default; /// Builds a solution. Returns the resulting assignment if a solution was /// found, and nullptr otherwise. @@ -271,7 +272,7 @@ class RoutingFilteredHeuristic : public IntVarFilteredHeuristic { RoutingFilteredHeuristic(RoutingModel* model, std::function stop_search, LocalSearchFilterManager* filter_manager); - ~RoutingFilteredHeuristic() override {} + ~RoutingFilteredHeuristic() override = default; /// Builds a solution starting from the routes formed by the next accessor. Assignment* BuildSolutionFromRoutes( const std::function& next_accessor); @@ -321,7 +322,7 @@ class CheapestInsertionFilteredHeuristic : public RoutingFilteredHeuristic { std::function evaluator, std::function penalty_evaluator, LocalSearchFilterManager* filter_manager); - ~CheapestInsertionFilteredHeuristic() override {} + ~CheapestInsertionFilteredHeuristic() override = default; protected: struct NodeInsertion { @@ -469,7 +470,7 @@ class GlobalCheapestInsertionFilteredHeuristic std::function penalty_evaluator, LocalSearchFilterManager* filter_manager, GlobalCheapestInsertionParameters parameters); - ~GlobalCheapestInsertionFilteredHeuristic() override {} + ~GlobalCheapestInsertionFilteredHeuristic() override = default; bool BuildSolutionInternal() override; std::string DebugString() const override { return "GlobalCheapestInsertionFilteredHeuristic"; @@ -544,7 +545,7 @@ class GlobalCheapestInsertionFilteredHeuristic template class EntryAllocator { public: - EntryAllocator() {} + EntryAllocator() = default; void Clear() { entries_.clear(); free_entries_.clear(); @@ -625,7 +626,7 @@ class GlobalCheapestInsertionFilteredHeuristic /// UseEmptyVehicleTypeCuratorForVehicle(node_entry.vehicle(), all_vehicles) /// is true. bool InsertNodeEntryUsingEmptyVehicleTypeCurator( - const std::vector& nodes, bool all_vehicles, NodeEntryQueue* queue); + const SparseBitset& nodes, bool all_vehicles, NodeEntryQueue* queue); /// Inserts non-inserted individual nodes on routes by constructing routes /// sequentially. @@ -769,7 +770,7 @@ class GlobalCheapestInsertionFilteredHeuristic /// Initializes the priority queue and the node entries with the current state /// of the solution on the given vehicle routes. - bool InitializePositions(const std::vector& nodes, + bool InitializePositions(const SparseBitset& nodes, const absl::flat_hash_set& vehicles, NodeEntryQueue* queue); /// Adds insertion entries performing 'node', and updates 'queue' and @@ -782,20 +783,20 @@ class GlobalCheapestInsertionFilteredHeuristic NodeEntryQueue* queue); /// Performs all the necessary updates after 'node' was successfully inserted /// on the 'vehicle' after 'insert_after'. - bool UpdateAfterNodeInsertion(const std::vector& nodes, int vehicle, + bool UpdateAfterNodeInsertion(const SparseBitset& nodes, int vehicle, int64_t node, int64_t insert_after, bool all_vehicles, NodeEntryQueue* queue); /// Updates all existing node entries inserting a node after nodes of the /// chain starting at 'insert_after_start' and ending before /// 'insert_after_end', and updates the priority queue accordingly. - bool UpdateExistingNodeEntriesOnChain(const std::vector& nodes, + bool UpdateExistingNodeEntriesOnChain(const SparseBitset& nodes, int vehicle, int64_t insert_after_start, int64_t insert_after_end, bool all_vehicles, NodeEntryQueue* queue); /// Adds node entries inserting a node after "insert_after" and updates the /// priority queue accordingly. - bool AddNodeEntriesAfter(const std::vector& nodes, int vehicle, + bool AddNodeEntriesAfter(const SparseBitset& nodes, int vehicle, int64_t insert_after, bool all_vehicles, NodeEntryQueue* queue); @@ -1008,7 +1009,7 @@ class InsertionSequenceContainer { // Generates insertion positions respecting structural constraints. class InsertionSequenceGenerator { public: - InsertionSequenceGenerator() {} + InsertionSequenceGenerator() = default; /// Generates insertions for a pickup and delivery pair in a multitour path: /// - a series of pickups may only start if all the deliveries of previous @@ -1073,7 +1074,7 @@ class LocalCheapestInsertionFilteredHeuristic std::function&, std::vector*)> optimize_on_insertion = nullptr); - ~LocalCheapestInsertionFilteredHeuristic() override {} + ~LocalCheapestInsertionFilteredHeuristic() override = default; bool BuildSolutionInternal() override; std::string DebugString() const override { return "LocalCheapestInsertionFilteredHeuristic"; @@ -1148,7 +1149,7 @@ class CheapestAdditionFilteredHeuristic : public RoutingFilteredHeuristic { CheapestAdditionFilteredHeuristic(RoutingModel* model, std::function stop_search, LocalSearchFilterManager* filter_manager); - ~CheapestAdditionFilteredHeuristic() override {} + ~CheapestAdditionFilteredHeuristic() override = default; bool BuildSolutionInternal() override; private: @@ -1194,7 +1195,7 @@ class EvaluatorCheapestAdditionFilteredHeuristic RoutingModel* model, std::function stop_search, std::function evaluator, LocalSearchFilterManager* filter_manager); - ~EvaluatorCheapestAdditionFilteredHeuristic() override {} + ~EvaluatorCheapestAdditionFilteredHeuristic() override = default; std::string DebugString() const override { return "EvaluatorCheapestAdditionFilteredHeuristic"; } @@ -1218,7 +1219,7 @@ class ComparatorCheapestAdditionFilteredHeuristic RoutingModel* model, std::function stop_search, Solver::VariableValueComparator comparator, LocalSearchFilterManager* filter_manager); - ~ComparatorCheapestAdditionFilteredHeuristic() override {} + ~ComparatorCheapestAdditionFilteredHeuristic() override = default; std::string DebugString() const override { return "ComparatorCheapestAdditionFilteredHeuristic"; } @@ -1346,7 +1347,7 @@ class SequentialSavingsFilteredHeuristic : public SavingsFilteredHeuristic { LocalSearchFilterManager* filter_manager) : SavingsFilteredHeuristic(model, std::move(stop_search), parameters, filter_manager) {} - ~SequentialSavingsFilteredHeuristic() override {} + ~SequentialSavingsFilteredHeuristic() override = default; std::string DebugString() const override { return "SequentialSavingsFilteredHeuristic"; } @@ -1368,7 +1369,7 @@ class ParallelSavingsFilteredHeuristic : public SavingsFilteredHeuristic { LocalSearchFilterManager* filter_manager) : SavingsFilteredHeuristic(model, std::move(stop_search), parameters, filter_manager) {} - ~ParallelSavingsFilteredHeuristic() override {} + ~ParallelSavingsFilteredHeuristic() override = default; std::string DebugString() const override { return "ParallelSavingsFilteredHeuristic"; } @@ -1414,7 +1415,7 @@ class ChristofidesFilteredHeuristic : public RoutingFilteredHeuristic { std::function stop_search, LocalSearchFilterManager* filter_manager, bool use_minimum_matching); - ~ChristofidesFilteredHeuristic() override {} + ~ChristofidesFilteredHeuristic() override = default; bool BuildSolutionInternal() override; std::string DebugString() const override { return "ChristofidesFilteredHeuristic"; @@ -1435,7 +1436,7 @@ class SweepArranger { SweepArranger(const SweepArranger&) = delete; SweepArranger& operator=(const SweepArranger&) = delete; - virtual ~SweepArranger() {} + virtual ~SweepArranger() = default; void ArrangeIndices(std::vector* indices); void SetSectors(int sectors) { sectors_ = sectors; } @@ -1455,4 +1456,4 @@ DecisionBuilder* MakeAllUnperformed(RoutingModel* model); } // namespace operations_research -#endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_SEARCH_H_ +#endif // OR_TOOLS_ROUTING_SEARCH_H_ diff --git a/ortools/constraint_solver/routing_types.h b/ortools/routing/types.h similarity index 92% rename from ortools/constraint_solver/routing_types.h rename to ortools/routing/types.h index 6b6a69d1e5..c95063bec1 100644 --- a/ortools/constraint_solver/routing_types.h +++ b/ortools/routing/types.h @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_TYPES_H_ -#define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_TYPES_H_ +#ifndef OR_TOOLS_ROUTING_TYPES_H_ +#define OR_TOOLS_ROUTING_TYPES_H_ #include #include @@ -50,4 +50,4 @@ typedef std::function RoutingTransitCallback2; } // namespace operations_research -#endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_TYPES_H_ +#endif // OR_TOOLS_ROUTING_TYPES_H_ diff --git a/ortools/constraint_solver/routing_utils.cc b/ortools/routing/utils.cc similarity index 99% rename from ortools/constraint_solver/routing_utils.cc rename to ortools/routing/utils.cc index 192602f10e..c2d6540cf0 100644 --- a/ortools/constraint_solver/routing_utils.cc +++ b/ortools/routing/utils.cc @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "ortools/constraint_solver/routing_utils.h" +#include "ortools/routing/utils.h" #include #include diff --git a/ortools/constraint_solver/routing_utils.h b/ortools/routing/utils.h similarity index 95% rename from ortools/constraint_solver/routing_utils.h rename to ortools/routing/utils.h index 2a82d3b221..a81918f3bb 100644 --- a/ortools/constraint_solver/routing_utils.h +++ b/ortools/routing/utils.h @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_UTILS_H_ -#define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_UTILS_H_ +#ifndef OR_TOOLS_ROUTING_UTILS_H_ +#define OR_TOOLS_ROUTING_UTILS_H_ #include #include @@ -91,4 +91,4 @@ bool FindMostExpensiveArcsOnRoute( } // namespace operations_research -#endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_UTILS_H_ +#endif // OR_TOOLS_ROUTING_UTILS_H_