From ff667239e78982acda2093942fbf206543cd7736 Mon Sep 17 00:00:00 2001 From: Juan Francisco Robles Date: Fri, 22 May 2026 08:41:43 +0200 Subject: [PATCH 1/3] refactor(routing): standardize cost terminology All files referenced in this commit are part of the routing package of the cuOpt library. Replace distance naming with cost naming where the value represents the cuOpt cost matrix rather than physical distance. Rename distance route/node helpers to cost counterparts and update routing internals that consume those types. Affected routing files: - cpp/include/cuopt/routing/data_model_view.hpp - cpp/src/routing/arc_value.hpp - cpp/src/routing/dimensions.cuh - cpp/src/routing/diversity/helpers.hpp - cpp/src/routing/diversity/macros.hpp - cpp/src/routing/ges/lexicographic_search/lexicographic_search.cu - cpp/src/routing/ges/lexicographic_search/node_stack.cuh - cpp/src/routing/local_search/compute_compatible.cu - cpp/src/routing/local_search/permutation_helper.cuh - cpp/src/routing/local_search/sliding_tsp.cu - cpp/src/routing/local_search/sliding_window.cu - cpp/src/routing/local_search/two_opt.cu - cpp/src/routing/local_search/vrp/fragment_kernels.cuh - cpp/src/routing/local_search/vrp/vrp_search.cu - cpp/src/routing/node/cost_node.cuh - cpp/src/routing/node/node.cuh - cpp/src/routing/problem/problem.cu - cpp/src/routing/route/cost_route.cuh - cpp/src/routing/route/dimensions_route.cuh - cpp/src/routing/route/mismatch_route.cuh - cpp/src/routing/route/prize_route.cuh - cpp/src/routing/route/service_time_route.cuh - cpp/src/routing/route/tasks_route.cuh - cpp/src/routing/route/vehicle_fixed_cost_route.cuh - cpp/src/routing/util_kernels/set_nodes_data.cuh This improves clarity without changing route optimization behavior. Signed-off-by: Juan Francisco Robles --- cpp/include/cuopt/routing/data_model_view.hpp | 2 +- cpp/src/routing/arc_value.hpp | 8 +- cpp/src/routing/dimensions.cuh | 12 +- cpp/src/routing/diversity/helpers.hpp | 2 +- cpp/src/routing/diversity/macros.hpp | 4 +- .../lexicographic_search.cu | 6 +- .../ges/lexicographic_search/node_stack.cuh | 42 ++-- .../local_search/compute_compatible.cu | 18 +- .../local_search/permutation_helper.cuh | 11 +- cpp/src/routing/local_search/sliding_tsp.cu | 100 +++++----- .../routing/local_search/sliding_window.cu | 2 +- cpp/src/routing/local_search/two_opt.cu | 12 +- .../local_search/vrp/fragment_kernels.cuh | 26 ++- .../routing/local_search/vrp/vrp_search.cu | 8 +- .../node/{distance_node.cuh => cost_node.cuh} | 46 ++--- cpp/src/routing/node/node.cuh | 4 +- cpp/src/routing/problem/problem.cu | 8 +- cpp/src/routing/route/cost_route.cuh | 179 +++++++++++++++++ cpp/src/routing/route/dimensions_route.cuh | 14 +- cpp/src/routing/route/distance_route.cuh | 185 ------------------ cpp/src/routing/route/mismatch_route.cuh | 2 +- cpp/src/routing/route/prize_route.cuh | 2 +- cpp/src/routing/route/service_time_route.cuh | 2 +- cpp/src/routing/route/tasks_route.cuh | 2 +- .../route/vehicle_fixed_cost_route.cuh | 2 +- .../routing/util_kernels/set_nodes_data.cuh | 4 +- 26 files changed, 346 insertions(+), 357 deletions(-) rename cpp/src/routing/node/{distance_node.cuh => cost_node.cuh} (52%) create mode 100644 cpp/src/routing/route/cost_route.cuh delete mode 100644 cpp/src/routing/route/distance_route.cuh diff --git a/cpp/include/cuopt/routing/data_model_view.hpp b/cpp/include/cuopt/routing/data_model_view.hpp index fa7aec73ec..6977130109 100644 --- a/cpp/include/cuopt/routing/data_model_view.hpp +++ b/cpp/include/cuopt/routing/data_model_view.hpp @@ -55,7 +55,7 @@ class data_model_view_t { i_t num_orders = -1); /** - * @brief Set a cost (distance) matrix for all locations (depot included) at + * @brief Set a cost matrix for all locations (depot included) at * once. A cost matrix is defined a square matrix containing the * costs, taken pairwise, between all locations. Entries are non-negative * real numbers. Diagonal elements diff --git a/cpp/src/routing/arc_value.hpp b/cpp/src/routing/arc_value.hpp index 77f41805b9..d29db0b503 100644 --- a/cpp/src/routing/arc_value.hpp +++ b/cpp/src/routing/arc_value.hpp @@ -48,7 +48,7 @@ static constexpr NodeInfo load(i_t pos, NodeInfo const* path_node) // All values pre-loaded overload template -static constexpr double get_distance(const NodeInfo& l1, +static constexpr double get_arc_cost(const NodeInfo& l1, const NodeInfo& l2, const VehicleInfo& vehicle_info) { @@ -96,7 +96,7 @@ static constexpr double get_arc_dimension(dim_t dim, const NodeInfo& l2, const VehicleInfo& vehicle_info) { - if (dim == dim_t::DIST) { return get_distance(l1, l2, vehicle_info); } + if (dim == dim_t::COST) { return get_arc_cost(l1, l2, vehicle_info); } return get_transit_time(l1, l2, vehicle_info); } @@ -105,8 +105,8 @@ static constexpr double get_arc_of_dimension(const NodeInfo& l1, const NodeInfo& l2, const VehicleInfo& vehicle_info) { - if constexpr (dim == dim_t::DIST) { - return get_distance(l1, l2, vehicle_info); + if constexpr (dim == dim_t::COST) { + return get_arc_cost(l1, l2, vehicle_info); } else if constexpr (dim == dim_t::TIME) { return get_transit_time(l1, l2, vehicle_info, true); } else if constexpr (dim == dim_t::SERVICE_TIME) { diff --git a/cpp/src/routing/dimensions.cuh b/cpp/src/routing/dimensions.cuh index af50b2c56d..3bdfb7f183 100644 --- a/cpp/src/routing/dimensions.cuh +++ b/cpp/src/routing/dimensions.cuh @@ -17,7 +17,7 @@ namespace detail { constexpr double EPSILON = 0.0001; enum class dim_t { - DIST = 0, + COST = 0, // time TIME, // pdp capacity ( positive/negative supply ) @@ -241,8 +241,8 @@ static HDI const auto& get_dimension_of(const T& obj) noexcept { if constexpr (I == dim_t::TIME) { return obj.time_dim; - } else if constexpr (I == dim_t::DIST) { - return obj.distance_dim; + } else if constexpr (I == dim_t::COST) { + return obj.cost_dim; } else if constexpr (I == dim_t::CAP) { return obj.capacity_dim; } else if constexpr (I == dim_t::PRIZE) { @@ -278,8 +278,8 @@ constexpr auto dim_to_string() noexcept { if constexpr (I == (int)dim_t::TIME) { return "Time dimension"; - } else if constexpr (I == (int)dim_t::DIST) { - return "Distance dimension"; + } else if constexpr (I == (int)dim_t::COST) { + return "Cost dimension"; } else if constexpr (I == (int)dim_t::CAP) { return "Capacity dimension"; } else if constexpr (I == (int)dim_t::PRIZE) { @@ -395,7 +395,7 @@ class enabled_dimensions_t { return get_dimension<(size_t)dim>(); } - cost_dimension_info_t distance_dim; + cost_dimension_info_t cost_dim; time_dimension_info_t time_dim; capacity_dimension_info_t capacity_dim; prize_dimension_info_t prize_dim; diff --git a/cpp/src/routing/diversity/helpers.hpp b/cpp/src/routing/diversity/helpers.hpp index 7c1e73fe1b..ccc355888a 100644 --- a/cpp/src/routing/diversity/helpers.hpp +++ b/cpp/src/routing/diversity/helpers.hpp @@ -27,7 +27,7 @@ constexpr bool is_constraint(size_t index) { - if (index == DIST) return false; + if (index == COST) return false; return true; } diff --git a/cpp/src/routing/diversity/macros.hpp b/cpp/src/routing/diversity/macros.hpp index 95d7d6ef02..44ef8d1ccf 100644 --- a/cpp/src/routing/diversity/macros.hpp +++ b/cpp/src/routing/diversity/macros.hpp @@ -15,8 +15,8 @@ #define DEPO 0 // Array indexes for evaluation of distinct features -// distance -constexpr int DIST = 0; +// cost +constexpr int COST = 0; // time constexpr int TIME = 1; // pdp capacity ( positive/negative supply ) diff --git a/cpp/src/routing/ges/lexicographic_search/lexicographic_search.cu b/cpp/src/routing/ges/lexicographic_search/lexicographic_search.cu index 2dd48ea3af..10368c9670 100644 --- a/cpp/src/routing/ges/lexicographic_search/lexicographic_search.cu +++ b/cpp/src/routing/ges/lexicographic_search/lexicographic_search.cu @@ -312,8 +312,7 @@ __global__ void lexicographic_search(typename solution_t::vie bool is_delivery_time_dist_feasible = node_stack.delivery_node.time_dim.forward_feasible( node_stack.s_route.vehicle_info()) && - node_stack.delivery_node.distance_dim.forward_feasible( - node_stack.s_route.vehicle_info()); + node_stack.delivery_node.cost_dim.forward_feasible(node_stack.s_route.vehicle_info()); if (!is_delivery_time_dist_feasible) { if (--node_stack.stack_top <= 1) { break; } cuopt_assert(node_stack.template k_max_ejection_check(), ""); @@ -393,8 +392,7 @@ __global__ void lexicographic_search(typename solution_t::vie bool is_delivery_time_dist_feasible = node_stack.delivery_node.time_dim.forward_feasible( node_stack.s_route.vehicle_info()) && - node_stack.delivery_node.distance_dim.forward_feasible( - node_stack.s_route.vehicle_info()); + node_stack.delivery_node.cost_dim.forward_feasible(node_stack.s_route.vehicle_info()); if (!is_delivery_time_dist_feasible) { if (--node_stack.stack_top <= 1) { break; } advance = true; diff --git a/cpp/src/routing/ges/lexicographic_search/node_stack.cuh b/cpp/src/routing/ges/lexicographic_search/node_stack.cuh index 0f0263261e..2618712d9f 100644 --- a/cpp/src/routing/ges/lexicographic_search/node_stack.cuh +++ b/cpp/src/routing/ges/lexicographic_search/node_stack.cuh @@ -29,7 +29,7 @@ DI static void copy_forward_data(dst_t& dst, const src_t& src) std::is_same>::value; if constexpr (is_src_a_node && !is_dst_a_node) { - dst.distance_forward = src.distance_dim.distance_forward; + dst.cost_forward = src.cost_dim.cost_forward; dst.transit_time_forward = src.time_dim.transit_time_forward; dst.latest_arrival_forward = src.time_dim.latest_arrival_forward; dst.unavoidable_wait_forward = src.time_dim.unavoidable_wait_forward; @@ -42,7 +42,7 @@ DI static void copy_forward_data(dst_t& dst, const src_t& src) } }); } else if constexpr (is_dst_a_node && !is_src_a_node) { - dst.distance_dim.distance_forward = src.distance_forward; + dst.cost_dim.cost_forward = src.cost_forward; dst.time_dim.transit_time_forward = src.transit_time_forward; dst.time_dim.latest_arrival_forward = src.latest_arrival_forward; dst.time_dim.unavoidable_wait_forward = src.unavoidable_wait_forward; @@ -55,7 +55,7 @@ DI static void copy_forward_data(dst_t& dst, const src_t& src) } }); } else if constexpr (!is_src_a_node && !is_dst_a_node) { - dst.distance_forward = src.distance_forward; + dst.cost_forward = src.cost_forward; dst.transit_time_forward = src.transit_time_forward; dst.latest_arrival_forward = src.latest_arrival_forward; dst.unavoidable_wait_forward = src.unavoidable_wait_forward; @@ -66,7 +66,7 @@ DI static void copy_forward_data(dst_t& dst, const src_t& src) dst.max_to_node[i] = src.max_to_node[i]; } } else { - dst.distance_dim.distance_forward = src.distance_dim.distance_forward; + dst.cost_dim.cost_forward = src.cost_dim.cost_forward; dst.time_dim.transit_time_forward = src.time_dim.transit_time_forward; dst.time_dim.latest_arrival_forward = src.time_dim.latest_arrival_forward; dst.time_dim.unavoidable_wait_forward = src.time_dim.unavoidable_wait_forward; @@ -119,7 +119,7 @@ struct node_stack_t { // this will be in shared memory for each thread struct __align__(32ul) item_t { - double distance_forward; + double cost_forward; double transit_time_forward; double latest_arrival_forward; double unavoidable_wait_forward; @@ -210,7 +210,7 @@ struct node_stack_t { (solution_ptr->get_max_active_nodes_for_all_routes() + 1) * sizeof(f_t); sh_size += shared_for_time_buffers; } - if (solution_ptr->problem_ptr->dimensions_info.distance_dim.has_constraints()) { + if (solution_ptr->problem_ptr->dimensions_info.cost_dim.has_constraints()) { const size_t shared_for_dist_buffers = (2 + (max_neighbors(k_max) + 1)) * (solution_ptr->get_max_active_nodes_for_all_routes() + 1) * sizeof(f_t); @@ -233,7 +233,7 @@ struct node_stack_t { wrap_ptr_as_span(sh_ptr, max_neighbors(k_max) * blockDim.x); loop_over_constrained_dimensions(dim_info(), [&](auto I) { - if constexpr ((I == size_t(dim_t::DIST)) || (I == size_t(dim_t::TIME))) { + if constexpr ((I == size_t(dim_t::COST)) || (I == size_t(dim_t::TIME))) { thrust::tie(dim_delivery_to_all[I], sh_ptr) = wrap_ptr_as_span(sh_ptr, 2 * (route_length + 1)); thrust::tie(dim_buffer_route[I], sh_ptr) = @@ -254,7 +254,7 @@ struct node_stack_t { (best_sequence.size() + p_scores.size() + gathered.size() + max_to_node.size()) * sizeof(i_t); loop_over_constrained_dimensions(dim_info(), [&](auto I) { - if constexpr ((I == size_t(dim_t::DIST)) || (I == size_t(dim_t::TIME))) { + if constexpr ((I == size_t(dim_t::COST)) || (I == size_t(dim_t::TIME))) { total_bytes += (dim_delivery_to_all[I].size() + dim_buffer_route[I].size()) * sizeof(f_t); } }); @@ -292,7 +292,7 @@ struct node_stack_t { template DI void compute_dim_buffers() { - if constexpr ((d == size_t(dim_t::DIST)) || (d == size_t(dim_t::TIME))) { + if constexpr ((d == size_t(dim_t::COST)) || (d == size_t(dim_t::TIME))) { constexpr dim_t dim = dim_t(d); i_t n_nodes_route = s_route.get_num_nodes(); auto& node_infos = s_route.requests().node_info; @@ -357,7 +357,7 @@ struct node_stack_t { * upfront in the lexicographic search kernel so we can safely skip here. Ideal way to handle * this smoothly is to pass vehicle_info to calculate_forward and calculate_backward methods */ - if constexpr ((dim == dim_t::DIST) || (dim == dim_t::TIME)) { + if constexpr ((dim == dim_t::COST) || (dim == dim_t::TIME)) { return dim_delivery_to_all[size_t(dim)][intra_idx]; } else { return f_t{}; @@ -374,7 +374,7 @@ struct node_stack_t { DI f_t get_dim_to_delivery(i_t intra_idx) const { if (!dim_info().has_dimension(dim)) { return f_t{}; } - if constexpr ((dim == dim_t::DIST) || (dim == dim_t::TIME)) { + if constexpr ((dim == dim_t::COST) || (dim == dim_t::TIME)) { return dim_delivery_to_all[size_t(dim)][intra_idx + route_length + 1]; } else { return f_t{}; @@ -391,7 +391,7 @@ struct node_stack_t { DI f_t get_dim_between(i_t intra_idx_1, i_t intra_idx_2) const { if (!dim_info().has_dimension(dim)) { return f_t{}; } - if constexpr ((dim == dim_t::DIST) || (dim == dim_t::TIME)) { + if constexpr ((dim == dim_t::COST) || (dim == dim_t::TIME)) { i_t gap_between = intra_idx_2 - intra_idx_1 - 1; return dim_buffer_route[size_t(dim)][intra_idx_1 + gap_between * route_length]; } else { @@ -864,10 +864,10 @@ struct node_stack_t { f_t orig_time = get_arc_of_dimension( delivery_node.node_info(), node_info, s_route.vehicle_info()); return orig_time == dim_from_buffer; - } else if constexpr (I == (size_t)dim_t::DIST) { - f_t orig_dist = get_arc_of_dimension( + } else if constexpr (I == (size_t)dim_t::COST) { + f_t orig_cost = get_arc_of_dimension( delivery_node.node_info(), node_info, s_route.vehicle_info()); - return orig_dist == dim_from_buffer; + return orig_cost == dim_from_buffer; } else { return true; } @@ -881,10 +881,10 @@ struct node_stack_t { f_t orig_time = get_arc_of_dimension( node_info, delivery_node.node_info(), s_route.vehicle_info()); return orig_time == dim_from_buffer; - } else if constexpr (I == (size_t)dim_t::DIST) { - f_t orig_dist = get_arc_of_dimension( + } else if constexpr (I == (size_t)dim_t::COST) { + f_t orig_cost = get_arc_of_dimension( node_info, delivery_node.node_info(), s_route.vehicle_info()); - return orig_dist == dim_from_buffer; + return orig_cost == dim_from_buffer; } else { return true; } @@ -900,10 +900,10 @@ struct node_stack_t { f_t orig_time = get_arc_of_dimension(node_info_1, node_info_2, s_route.vehicle_info()); return orig_time == dim_from_buffer; - } else if constexpr (I == (size_t)dim_t::DIST) { - f_t orig_dist = + } else if constexpr (I == (size_t)dim_t::COST) { + f_t orig_cost = get_arc_of_dimension(node_info_1, node_info_2, s_route.vehicle_info()); - return orig_dist == dim_from_buffer; + return orig_cost == dim_from_buffer; } else { return true; } diff --git a/cpp/src/routing/local_search/compute_compatible.cu b/cpp/src/routing/local_search/compute_compatible.cu index 457e970632..13a4eace57 100644 --- a/cpp/src/routing/local_search/compute_compatible.cu +++ b/cpp/src/routing/local_search/compute_compatible.cu @@ -455,7 +455,7 @@ void local_search_t::calculate_route_compatibility( RAFT_CHECK_CUDA(sol.sol_handle->get_stream()); } -// sort the viable matrix according to the distance after the insertion +// sort the viable matrix according to the cost after the insertion template void problem_t::sort_viable_matrix(rmm::device_uvector& viable_from_matrix, rmm::device_uvector& viable_to_matrix) @@ -477,7 +477,7 @@ void problem_t::sort_viable_matrix(rmm::device_uvector& viable_fr i_t segment = idx / l_n_requests; return segment; }); - // sort according to distance + // sort according to cost thrust::stable_sort( handle_ptr->get_thrust_policy(), thrust::make_zip_iterator(viable_from_matrix.begin(), segments.begin()), @@ -489,19 +489,19 @@ void problem_t::sort_viable_matrix(rmm::device_uvector& viable_fr i_t from_node_2 = thrust::get<1>(second); if (to_node_1 == -1) return false; if (to_node_2 == -1) return true; - auto dist_between_1 = get_distance( + auto cost_between_1 = get_arc_cost( NodeInfo( from_node_1, order_info_view.get_order_location(from_node_1), node_type_t::PICKUP), NodeInfo( to_node_1, order_info_view.get_order_location(to_node_1), node_type_t::PICKUP), l_vehicle_info); - auto dist_between_2 = get_distance( + auto cost_between_2 = get_arc_cost( NodeInfo( from_node_2, order_info_view.get_order_location(from_node_2), node_type_t::PICKUP), NodeInfo( to_node_2, order_info_view.get_order_location(to_node_2), node_type_t::PICKUP), l_vehicle_info); - return dist_between_1 < dist_between_2; + return cost_between_1 < cost_between_2; }); // sort the segments thrust::stable_sort(handle_ptr->get_thrust_policy(), @@ -521,7 +521,7 @@ void problem_t::sort_viable_matrix(rmm::device_uvector& viable_fr i_t segment = idx / l_n_requests; return segment; }); - // sort according to distance + // sort according to cost thrust::stable_sort( handle_ptr->get_thrust_policy(), thrust::make_zip_iterator(viable_to_matrix.begin(), segments.begin()), @@ -533,19 +533,19 @@ void problem_t::sort_viable_matrix(rmm::device_uvector& viable_fr i_t to_node_2 = thrust::get<1>(second); if (from_node_1 == -1) return false; if (from_node_2 == -1) return true; - auto dist_between_1 = get_distance( + auto cost_between_1 = get_arc_cost( NodeInfo( from_node_1, order_info_view.get_order_location(from_node_1), node_type_t::PICKUP), NodeInfo( to_node_1, order_info_view.get_order_location(to_node_1), node_type_t::PICKUP), l_vehicle_info); - auto dist_between_2 = get_distance( + auto cost_between_2 = get_arc_cost( NodeInfo( from_node_2, order_info_view.get_order_location(from_node_2), node_type_t::PICKUP), NodeInfo( to_node_2, order_info_view.get_order_location(to_node_2), node_type_t::PICKUP), l_vehicle_info); - return dist_between_1 < dist_between_2; + return cost_between_1 < cost_between_2; }); // sort the segments again to get back the segmented sorted thrust::stable_sort(handle_ptr->get_thrust_policy(), diff --git a/cpp/src/routing/local_search/permutation_helper.cuh b/cpp/src/routing/local_search/permutation_helper.cuh index cc1bc37cb1..5647517e0a 100644 --- a/cpp/src/routing/local_search/permutation_helper.cuh +++ b/cpp/src/routing/local_search/permutation_helper.cuh @@ -242,10 +242,10 @@ DI bool forward_fragment_update_cvrp(const node_t& curr_node, { cuopt_assert(fragment_size != 0, "Fragment size cannot be zero!"); - f_t arc_value = get_arc_of_dimension( + f_t arc_value = get_arc_of_dimension( curr_node.request.info, fragment[0].request.info, s_route.vehicle_info()); - fragment[fragment_size - 1].distance_dim.distance_forward = - curr_node.distance_dim.distance_forward + arc_value + fragment_dist; + fragment[fragment_size - 1].cost_dim.cost_forward = + curr_node.cost_dim.cost_forward + arc_value + fragment_dist; fragment[fragment_size - 1].capacity_dim.gathered[0] = curr_node.capacity_dim.gathered[0] + fragment_demand; fragment[fragment_size - 1].capacity_dim.max_to_node[0] = @@ -295,10 +295,9 @@ DI bool backward_fragment_update_cvrp(const node_t& curr_node const infeasible_cost_t& weights, double excess_limit) { - f_t arc_value = get_arc_of_dimension( + f_t arc_value = get_arc_of_dimension( fragment[fragment_size - 1].request.info, curr_node.request.info, s_route.vehicle_info()); - fragment[0].distance_dim.distance_backward = - curr_node.distance_dim.distance_backward + arc_value + fragment_dist; + fragment[0].cost_dim.cost_backward = curr_node.cost_dim.cost_backward + arc_value + fragment_dist; fragment[0].capacity_dim.max_after[0] = curr_node.capacity_dim.max_after[0] + fragment_demand; diff --git a/cpp/src/routing/local_search/sliding_tsp.cu b/cpp/src/routing/local_search/sliding_tsp.cu index c7923c361a..cf02c1b508 100644 --- a/cpp/src/routing/local_search/sliding_tsp.cu +++ b/cpp/src/routing/local_search/sliding_tsp.cu @@ -25,56 +25,56 @@ DI thrust::pair eval_move( typename solution_t::view_t& sol, typename move_candidates_t::view_t& move_candidates, const typename route_t::view_t& s_route, - raft::device_span sh_reverse_dist, + raft::device_span sh_reverse_cost, i_t intra_idx, i_t insertion_pos, i_t window_size, i_t route_max_window_size, bool reverse) { - auto original_window_dist = - s_route.dimensions.distance_dim.distance_forward[intra_idx + window_size - 1] - - s_route.dimensions.distance_dim.distance_forward[intra_idx]; - auto new_window_dist = reverse ? sh_reverse_dist[route_max_window_size - 1] - - sh_reverse_dist[route_max_window_size - window_size] - : original_window_dist; + auto original_window_cost = + s_route.dimensions.cost_dim.cost_forward[intra_idx + window_size - 1] - + s_route.dimensions.cost_dim.cost_forward[intra_idx]; + auto new_window_cost = reverse ? sh_reverse_cost[route_max_window_size - 1] - + sh_reverse_cost[route_max_window_size - window_size] + : original_window_cost; auto original_previous_intra_frag_next = - s_route.dimensions.distance_dim.distance_forward[intra_idx + window_size] - - s_route.dimensions.distance_dim.distance_forward[intra_idx - 1]; + s_route.dimensions.cost_dim.cost_forward[intra_idx + window_size] - + s_route.dimensions.cost_dim.cost_forward[intra_idx - 1]; auto frag_begin = reverse ? intra_idx + window_size - 1 : intra_idx; auto frag_end = reverse ? intra_idx : intra_idx + window_size - 1; auto insertion_pos_frag_begin = - get_arc_of_dimension(s_route.get_node(insertion_pos).node_info(), + get_arc_of_dimension(s_route.get_node(insertion_pos).node_info(), s_route.get_node(frag_begin).node_info(), s_route.vehicle_info()); // in-place if (insertion_pos == intra_idx - 1) { - auto frag_end_frag_next = get_arc_of_dimension( + auto frag_end_frag_next = get_arc_of_dimension( s_route.get_node(frag_end).node_info(), s_route.get_node(intra_idx + window_size).node_info(), s_route.vehicle_info()); - auto delta = insertion_pos_frag_begin + new_window_dist + frag_end_frag_next - + auto delta = insertion_pos_frag_begin + new_window_cost + frag_end_frag_next - original_previous_intra_frag_next; return {delta, delta}; } auto frag_end_insertion_pos_next = - get_arc_of_dimension(s_route.get_node(frag_end).node_info(), + get_arc_of_dimension(s_route.get_node(frag_end).node_info(), s_route.get_node(insertion_pos + 1).node_info(), s_route.vehicle_info()); - auto previous_intra_frag_next = get_arc_of_dimension( + auto previous_intra_frag_next = get_arc_of_dimension( s_route.get_node(intra_idx - 1).node_info(), s_route.get_node(intra_idx + window_size).node_info(), s_route.vehicle_info()); auto insertion_pos_insertion_pos_next = - get_arc_of_dimension(s_route.get_node(insertion_pos).node_info(), + get_arc_of_dimension(s_route.get_node(insertion_pos).node_info(), s_route.get_node(insertion_pos + 1).node_info(), s_route.vehicle_info()); - auto delta = previous_intra_frag_next + insertion_pos_frag_begin + new_window_dist + + auto delta = previous_intra_frag_next + insertion_pos_frag_begin + new_window_cost + frag_end_insertion_pos_next - insertion_pos_insertion_pos_next - original_previous_intra_frag_next; return {delta, delta}; @@ -126,7 +126,7 @@ __global__ void find_sliding_moves_tsp( auto s_route = route_t::view_t::create_shared_route( (i_t*)shmem, route, route.get_num_nodes(), true); - auto sh_reverse_dist = raft::device_span( + auto sh_reverse_cost = raft::device_span( reinterpret_cast(raft::alignTo(s_route.shared_end_address(), sizeof(double))), route_max_window_size); s_route.copy_from(route); @@ -134,9 +134,9 @@ __global__ void find_sliding_moves_tsp( // reverse and non reverse fragment for (i_t tid = threadIdx.x; tid < route_max_window_size; tid += blockDim.x) { - sh_reverse_dist[tid] = - route.dimensions.distance_dim - .reverse_distance[route.get_num_nodes() - intra_idx - (route_max_window_size - 1) + tid]; + sh_reverse_cost[tid] = + route.dimensions.cost_dim + .reverse_cost[route.get_num_nodes() - intra_idx - (route_max_window_size - 1) + tid]; } __syncthreads(); @@ -182,7 +182,7 @@ __global__ void find_sliding_moves_tsp( thrust::tie(cost_delta, selection_delta) = eval_move(sol, move_candidates, s_route, - sh_reverse_dist, + sh_reverse_cost, intra_idx, insertion_pos, window_size, @@ -391,29 +391,29 @@ __global__ void execute_sliding_moves_tsp( } template -__global__ void fill_reverse_distances_kernel(typename solution_t::view_t sol) +__global__ void fill_reverse_costs_kernel(typename solution_t::view_t sol) { - auto route = sol.routes[0]; - auto n_nodes = route.get_num_nodes(); - auto reverse_distances = route.dimensions.distance_dim.reverse_distance; + auto route = sol.routes[0]; + auto n_nodes = route.get_num_nodes(); + auto reverse_costs = route.dimensions.cost_dim.reverse_cost; for (i_t tid = blockIdx.x * blockDim.x + threadIdx.x; tid < n_nodes; tid += blockDim.x * gridDim.x) { - reverse_distances[tid] = - get_arc_of_dimension(route.get_node(n_nodes - tid).node_info(), + reverse_costs[tid] = + get_arc_of_dimension(route.get_node(n_nodes - tid).node_info(), route.get_node(n_nodes - 1 - tid).node_info(), route.vehicle_info()); } } template -__global__ void fill_forward_distances_kernel(typename solution_t::view_t sol) +__global__ void fill_forward_costs_kernel(typename solution_t::view_t sol) { - auto route = sol.routes[0]; - auto n_nodes = route.get_num_nodes(); - auto forward_distances = route.dimensions.distance_dim.distance_forward; + auto route = sol.routes[0]; + auto n_nodes = route.get_num_nodes(); + auto forward_costs = route.dimensions.cost_dim.cost_forward; for (i_t tid = blockIdx.x * blockDim.x + threadIdx.x; tid < n_nodes; tid += blockDim.x * gridDim.x) { - forward_distances[tid] = get_arc_of_dimension( + forward_costs[tid] = get_arc_of_dimension( route.get_node(tid).node_info(), route.get_node(tid + 1).node_info(), route.vehicle_info()); } } @@ -424,11 +424,11 @@ void resize_temp_storage(solution_t& sol, i_t n_nodes, size_t& temp_storage_bytes) { - auto distances_ptr = sol.get_route(0).dimensions.distance_dim.distance_forward.data(); + auto costs_ptr = sol.get_route(0).dimensions.cost_dim.cost_forward.data(); cub::DeviceScan::ExclusiveSum(static_cast(nullptr), temp_storage_bytes, - distances_ptr, - distances_ptr, + costs_ptr, + costs_ptr, n_nodes + 1, sol.sol_handle->get_stream()); @@ -438,21 +438,21 @@ void resize_temp_storage(solution_t& sol, } template -void compute_cumulative_distances(solution_t& sol, - move_candidates_t& move_candidates, - i_t n_nodes, - i_t n_threads, - size_t temp_storage_bytes) +void compute_cumulative_costs(solution_t& sol, + move_candidates_t& move_candidates, + i_t n_nodes, + i_t n_threads, + size_t temp_storage_bytes) { - auto distances_ptr = reverse ? sol.get_route(0).dimensions.distance_dim.reverse_distance.data() - : sol.get_route(0).dimensions.distance_dim.distance_forward.data(); + auto costs_ptr = reverse ? sol.get_route(0).dimensions.cost_dim.reverse_cost.data() + : sol.get_route(0).dimensions.cost_dim.cost_forward.data(); auto n_fill_blocks = (sol.get_num_orders() + n_threads - 1) / n_threads; if (reverse) { - fill_reverse_distances_kernel + fill_reverse_costs_kernel <<get_stream()>>>(sol.view()); RAFT_CHECK_CUDA(sol.sol_handle->get_stream()); } else { - fill_forward_distances_kernel + fill_forward_costs_kernel <<get_stream()>>>(sol.view()); RAFT_CHECK_CUDA(sol.sol_handle->get_stream()); } @@ -460,8 +460,8 @@ void compute_cumulative_distances(solution_t& sol, size_t n_temp_storage_bytes = 0; cub::DeviceScan::ExclusiveSum(static_cast(nullptr), n_temp_storage_bytes, - distances_ptr, - distances_ptr, + costs_ptr, + costs_ptr, n_nodes + 2, sol.sol_handle->get_stream()); @@ -473,8 +473,8 @@ void compute_cumulative_distances(solution_t& sol, cub::DeviceScan::ExclusiveSum(move_candidates.temp_storage.data(), temp_storage_bytes, - distances_ptr, - distances_ptr, + costs_ptr, + costs_ptr, n_nodes + 2, sol.sol_handle->get_stream()); } @@ -499,7 +499,7 @@ bool local_search_t::perform_sliding_tsp( size_t temp_storage_bytes = 0; resize_temp_storage(sol, move_candidates, n_nodes, temp_storage_bytes); - compute_cumulative_distances( + compute_cumulative_costs( sol, move_candidates, n_nodes, n_threads, temp_storage_bytes); auto n_blocks = move_candidates.nodes_to_search.n_sampled_nodes; @@ -558,7 +558,7 @@ bool local_search_t::perform_sliding_tsp( cuopt::make_span(moved_regions_)); RAFT_CHECK_CUDA(sol.sol_handle->get_stream()); - compute_cumulative_distances( + compute_cumulative_costs( sol, move_candidates, n_nodes, n_threads, temp_storage_bytes); cuopt_func_call(sol.compute_cost()); diff --git a/cpp/src/routing/local_search/sliding_window.cu b/cpp/src/routing/local_search/sliding_window.cu index 2d676d9b38..8f00356360 100644 --- a/cpp/src/routing/local_search/sliding_window.cu +++ b/cpp/src/routing/local_search/sliding_window.cu @@ -428,7 +428,7 @@ __device__ void try_permutations_cvrp( f_t fragment_dist = 0.; f_t fragment_demand = nodes[0].capacity_dim.demand[0]; for (int i = 1; i < window_size; ++i) { - fragment_dist += get_arc_of_dimension( + fragment_dist += get_arc_of_dimension( nodes[i - 1].request.info, nodes[i].request.info, s_route.vehicle_info()); fragment_demand += nodes[i].capacity_dim.demand[0]; } diff --git a/cpp/src/routing/local_search/two_opt.cu b/cpp/src/routing/local_search/two_opt.cu index abe6e8a928..05f31991f3 100644 --- a/cpp/src/routing/local_search/two_opt.cu +++ b/cpp/src/routing/local_search/two_opt.cu @@ -51,16 +51,16 @@ DI thrust::pair evaluate_two_opt_cvrp_move( i_t second) { auto n_nodes = route.get_num_nodes(); - double frag_backward = reverse_route.distance_dim.distance_forward[n_nodes - (first + 1)] - - reverse_route.distance_dim.distance_forward[n_nodes - second]; - double forward_sum = route.get_node(second + 1).distance_dim.distance_forward - - route.get_node(first).distance_dim.distance_forward; + double frag_backward = reverse_route.cost_dim.cost_forward[n_nodes - (first + 1)] - + reverse_route.cost_dim.cost_forward[n_nodes - second]; + double forward_sum = + route.get_node(second + 1).cost_dim.cost_forward - route.get_node(first).cost_dim.cost_forward; - double first_second = get_arc_of_dimension( + double first_second = get_arc_of_dimension( route.get_node(first).node_info(), route.get_node(second).node_info(), route.vehicle_info()); double first_next_second_next = - get_arc_of_dimension(route.get_node(first + 1).node_info(), + get_arc_of_dimension(route.get_node(first + 1).node_info(), route.get_node(second + 1).node_info(), route.vehicle_info()); diff --git a/cpp/src/routing/local_search/vrp/fragment_kernels.cuh b/cpp/src/routing/local_search/vrp/fragment_kernels.cuh index cdbfe06ae2..6194e27c34 100644 --- a/cpp/src/routing/local_search/vrp/fragment_kernels.cuh +++ b/cpp/src/routing/local_search/vrp/fragment_kernels.cuh @@ -75,12 +75,11 @@ DI thrust::pair evaluate_fragment( if (!move_candidates.include_objective) { return {0, 0}; } // cost check - double obj_delta = 0.; - double all_forward_1 = - route_1.get_node(start_idx_1 + 1 + frag_size_1).distance_dim.distance_forward - - route_1.get_node(start_idx_1).distance_dim.distance_forward; + double obj_delta = 0.; + double all_forward_1 = route_1.get_node(start_idx_1 + 1 + frag_size_1).cost_dim.cost_forward - + route_1.get_node(start_idx_1).cost_dim.cost_forward; if (frag_size_2 == 0) { - auto direct = get_arc_of_dimension( + auto direct = get_arc_of_dimension( route_1.get_node(start_idx_1).node_info(), route_1.get_node(start_idx_1 + 1 + frag_size_1).node_info(), route_1.vehicle_info()); @@ -89,30 +88,29 @@ DI thrust::pair evaluate_fragment( if (!reverse) { double sd1_sd2_1 = - get_arc_of_dimension(route_1.get_node(start_idx_1).node_info(), + get_arc_of_dimension(route_1.get_node(start_idx_1).node_info(), route_2.get_node(start_idx_2 + 1).node_info(), route_1.vehicle_info()); - double end_node_2_end_node_1 = get_arc_of_dimension( + double end_node_2_end_node_1 = get_arc_of_dimension( route_2.get_node(start_idx_2 + frag_size_2).node_info(), route_1.get_node(start_idx_1 + frag_size_1 + 1).node_info(), route_1.vehicle_info()); - double frag_dist = route_2.get_node(start_idx_2 + frag_size_2).distance_dim.distance_forward - - route_2.get_node(start_idx_2 + 1).distance_dim.distance_forward; + double frag_dist = route_2.get_node(start_idx_2 + frag_size_2).cost_dim.cost_forward - + route_2.get_node(start_idx_2 + 1).cost_dim.cost_forward; obj_delta = sd1_sd2_1 + frag_dist + end_node_2_end_node_1 - all_forward_1; } else { - double sd1_end_frag_2 = get_arc_of_dimension( + double sd1_end_frag_2 = get_arc_of_dimension( route_1.get_node(start_idx_1).node_info(), route_2.get_node(start_idx_2 + frag_size_2).node_info(), route_1.vehicle_info()); - double sd2_1_end_node_1 = get_arc_of_dimension( + double sd2_1_end_node_1 = get_arc_of_dimension( route_2.get_node(start_idx_2 + 1).node_info(), route_1.get_node(start_idx_1 + frag_size_1 + 1).node_info(), route_1.vehicle_info()); - double frag_dist = - route_2.dimensions.distance_dim.reverse_distance[(start_idx_2 + 1)] - - route_2.dimensions.distance_dim.reverse_distance[(start_idx_2 + frag_size_2)]; + double frag_dist = route_2.dimensions.cost_dim.reverse_cost[(start_idx_2 + 1)] - + route_2.dimensions.cost_dim.reverse_cost[(start_idx_2 + frag_size_2)]; obj_delta = sd1_end_frag_2 + frag_dist + sd2_1_end_node_1 - all_forward_1; } diff --git a/cpp/src/routing/local_search/vrp/vrp_search.cu b/cpp/src/routing/local_search/vrp/vrp_search.cu index 1f71458856..18d32ef1ea 100644 --- a/cpp/src/routing/local_search/vrp/vrp_search.cu +++ b/cpp/src/routing/local_search/vrp/vrp_search.cu @@ -29,12 +29,12 @@ __global__ void compute_reverse_distances(typename solution_t auto route_id = route.get_id(); auto n_nodes = route.get_num_nodes(); - route.dimensions.distance_dim.reverse_distance[n_nodes] = 0.; + route.dimensions.cost_dim.reverse_cost[n_nodes] = 0.; for (int i = n_nodes - 1; i >= 0; i--) { - double dist = get_arc_of_dimension( + double cost = get_arc_of_dimension( route.get_node(i + 1).node_info(), route.get_node(i).node_info(), route.vehicle_info()); - route.dimensions.distance_dim.reverse_distance[i] = - dist + route.dimensions.distance_dim.reverse_distance[i + 1]; + route.dimensions.cost_dim.reverse_cost[i] = + cost + route.dimensions.cost_dim.reverse_cost[i + 1]; } } } diff --git a/cpp/src/routing/node/distance_node.cuh b/cpp/src/routing/node/cost_node.cuh similarity index 52% rename from cpp/src/routing/node/distance_node.cuh rename to cpp/src/routing/node/cost_node.cuh index eabf962d8b..99deca6814 100644 --- a/cpp/src/routing/node/distance_node.cuh +++ b/cpp/src/routing/node/cost_node.cuh @@ -13,33 +13,33 @@ namespace routing { namespace detail { template -class distance_node_t { +class cost_node_t { public: - //! Distance gathered to node - double distance_forward = 0.0; - //! Distance gathered after node - double distance_backward = 0.0; + //! Cost gathered to node + double cost_forward = 0.0; + //! Cost gathered after node + double cost_backward = 0.0; - /*! \brief { Calculate next node forward gathered distance data based on actual node} */ - void HDI calculate_forward(distance_node_t& next, double distance_between) const noexcept + /*! \brief { Calculate next node forward gathered cost data based on actual node} */ + void HDI calculate_forward(cost_node_t& next, double cost_between) const noexcept { - next.distance_forward = distance_forward + distance_between; + next.cost_forward = cost_forward + cost_between; } - /*! \brief { Calculate prev node gathered distance backward data based on actual node} */ - void HDI calculate_backward(distance_node_t& prev, double distance_between) const noexcept + /*! \brief { Calculate prev node gathered cost backward data based on actual node} */ + void HDI calculate_backward(cost_node_t& prev, double cost_between) const noexcept { - prev.distance_backward = distance_backward + distance_between; + prev.cost_backward = cost_backward + cost_between; } HDI double forward_excess(const VehicleInfo& vehicle_info) const noexcept { - return max(0.f, distance_forward - vehicle_info.max_cost); + return max(0.f, cost_forward - vehicle_info.max_cost); } HDI double backward_excess(const VehicleInfo& vehicle_info) const noexcept { - return max(0.f, distance_backward - vehicle_info.max_cost); + return max(0.f, cost_backward - vehicle_info.max_cost); } HDI bool forward_feasible(const VehicleInfo& vehicle_info, @@ -50,14 +50,14 @@ class distance_node_t { } /*! \brief { Combine information from begining and ending fragments.} - \return { Distance excess of route represented by nodes prev and next }*/ - static HDI double combine(const distance_node_t& prev, - const distance_node_t& next, + \return { Cost excess of route represented by nodes prev and next }*/ + static HDI double combine(const cost_node_t& prev, + const cost_node_t& next, const VehicleInfo& vehicle_info, - f_t distance_between) noexcept + f_t cost_between) noexcept { - double total_distance = prev.distance_forward + next.distance_backward + distance_between; - return max(0., total_distance - vehicle_info.max_cost); + double total_cost = prev.cost_forward + next.cost_backward + cost_between; + return max(0., total_cost - vehicle_info.max_cost); } HDI bool backward_feasible(const VehicleInfo& vehicle_info, @@ -68,17 +68,17 @@ class distance_node_t { } template - HDI void get_cost([[maybe_unused]] const distance_node_t& prev_node, + HDI void get_cost([[maybe_unused]] const cost_node_t& prev_node, const VehicleInfo& vehicle_info, const cost_dimension_info_t& dim_info, objective_cost_t& obj_cost, infeasible_cost_t& inf_cost) const noexcept { - double total_distance = ((double)distance_forward + (double)distance_backward); + double total_cost = ((double)cost_forward + (double)cost_backward); - obj_cost[objective_t::COST] = total_distance; + obj_cost[objective_t::COST] = total_cost; if (dim_info.has_max_constraint) { - inf_cost[dim_t::DIST] = max(0., total_distance - vehicle_info.max_cost); + inf_cost[dim_t::COST] = max(0., total_cost - vehicle_info.max_cost); } } }; diff --git a/cpp/src/routing/node/node.cuh b/cpp/src/routing/node/node.cuh index 097e3742f8..859f0b1d4e 100644 --- a/cpp/src/routing/node/node.cuh +++ b/cpp/src/routing/node/node.cuh @@ -9,7 +9,7 @@ #include "break_node.cuh" #include "capacity_node.cuh" -#include "distance_node.cuh" +#include "cost_node.cuh" #include "mismatch_node.cuh" #include "pdp_node.cuh" #include "prize_node.cuh" @@ -279,7 +279,7 @@ class node_t { request_info_t request; time_node_t time_dim; capacity_node_t capacity_dim; - distance_node_t distance_dim; + cost_node_t cost_dim; prize_node_t prize_dim; tasks_node_t tasks_dim; service_time_node_t service_time_dim; diff --git a/cpp/src/routing/problem/problem.cu b/cpp/src/routing/problem/problem.cu index 4335b93734..90ad97d25b 100644 --- a/cpp/src/routing/problem/problem.cu +++ b/cpp/src/routing/problem/problem.cu @@ -240,10 +240,10 @@ void problem_t::populate_dimensions_info() // DIST dimension info double cost_obj_weight = specified_weights.count(objective_t::COST) ? specified_weights.at(objective_t::COST) : 1.0; - dimensions_info.enable_dimension(dim_t::DIST); + dimensions_info.enable_dimension(dim_t::COST); dimensions_info.enable_objective(objective_t::COST, cost_obj_weight); - auto& cost_dim_info = dimensions_info.distance_dim; + auto& cost_dim_info = dimensions_info.cost_dim; if (auto vehicle_max_costs = data_view_ptr->get_vehicle_max_costs(); !vehicle_max_costs.empty()) { cost_dim_info.has_max_constraint = true; } @@ -352,7 +352,7 @@ void problem_t::populate_dimensions_info() if (data_view_ptr->get_fleet_size() == 1) { is_tsp = true; loop_over_dimensions(dimensions_info, [&](auto I) { - if constexpr (I != (size_t)dim_t::DIST) { is_tsp = false; } + if constexpr (I != (size_t)dim_t::COST) { is_tsp = false; } }); } dimensions_info.is_tsp = is_tsp; @@ -361,7 +361,7 @@ void problem_t::populate_dimensions_info() is_cvrp_ = !is_pdp() && (data_view_ptr->get_cost_matrices().size() == 1); if (is_cvrp_) { loop_over_dimensions(dimensions_info, [&](auto I) { - if (I != (int)dim_t::DIST && I != (int)dim_t::CAP) { is_cvrp_ = false; } + if (I != (int)dim_t::COST && I != (int)dim_t::CAP) { is_cvrp_ = false; } }); } is_cvrp_ = is_cvrp_ && n_capacity_dims == 1; diff --git a/cpp/src/routing/route/cost_route.cuh b/cpp/src/routing/route/cost_route.cuh new file mode 100644 index 0000000000..bf79e65210 --- /dev/null +++ b/cpp/src/routing/route/cost_route.cuh @@ -0,0 +1,179 @@ +/* clang-format off */ +/* + * SPDX-FileCopyrightText: Copyright (c) 2021-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/* clang-format on */ + +#pragma once + +#include +#include "../node/cost_node.cuh" +#include "../solution/solution_handle.cuh" +#include "routing/routing_helpers.cuh" + +#include +#include + +#include + +#include + +namespace cuopt { +namespace routing { +namespace detail { + +template +class cost_route_t { + public: + cost_route_t(solution_handle_t const* sol_handle_, cost_dimension_info_t& dim_info_) + : dim_info(dim_info_), + cost_forward(0, sol_handle_->get_stream()), + cost_backward(0, sol_handle_->get_stream()), + reverse_cost(0, sol_handle_->get_stream()) + { + raft::common::nvtx::range fun_scope("zero cost_route_t copy_ctr"); + } + + cost_route_t(const cost_route_t& cost_route, solution_handle_t const* sol_handle_) + : dim_info(cost_route.dim_info), + cost_forward(cost_route.cost_forward, sol_handle_->get_stream()), + cost_backward(cost_route.cost_backward, sol_handle_->get_stream()), + reverse_cost(cost_route.reverse_cost, sol_handle_->get_stream()) + { + raft::common::nvtx::range fun_scope("cost route copy_ctr"); + } + + cost_route_t& operator=(cost_route_t&& cost_route) = default; + + void resize(i_t max_nodes_per_route, rmm::cuda_stream_view stream) + { + cost_forward.resize(max_nodes_per_route, stream); + cost_backward.resize(max_nodes_per_route, stream); + reverse_cost.resize(max_nodes_per_route, stream); + } + + struct view_t { + bool is_empty() const { return cost_forward.empty(); } + DI cost_node_t get_node(i_t idx) const + { + cost_node_t cost_node; + cost_node.cost_forward = cost_forward[idx]; + cost_node.cost_backward = cost_backward[idx]; + return cost_node; + } + + DI void set_node(i_t idx, const cost_node_t& node) + { + set_forward_data(idx, node); + set_backward_data(idx, node); + } + + DI void set_forward_data(i_t idx, const cost_node_t& node) + { + cost_forward[idx] = node.cost_forward; + } + + DI void set_backward_data(i_t idx, const cost_node_t& node) + { + cost_backward[idx] = node.cost_backward; + } + + DI void copy_forward_data(const view_t& orig_route, i_t start_idx, i_t end_idx, i_t write_start) + { + i_t size = end_idx - start_idx; + block_copy( + cost_forward.subspan(write_start), orig_route.cost_forward.subspan(start_idx), size); + } + + DI void copy_backward_data(const view_t& orig_route, + i_t start_idx, + i_t end_idx, + i_t write_start) + { + i_t size = end_idx - start_idx; + block_copy( + cost_backward.subspan(write_start), orig_route.cost_backward.subspan(start_idx), size); + } + + DI void copy_fixed_route_data(const view_t& orig_route, + i_t from_idx, + i_t to_idx, + i_t write_start) + { + // there is no fixed route data associated with cost + } + + DI void compute_cost(const VehicleInfo& vehicle_info, + const i_t n_nodes_route, + objective_cost_t& obj_cost, + infeasible_cost_t& inf_cost) const noexcept + { + double objective_cost = cost_forward[n_nodes_route]; + double infeasibility_cost = 0.; + if (dim_info.has_max_constraint) { + infeasibility_cost = max(0., cost_forward[n_nodes_route] - vehicle_info.max_cost); + } + + obj_cost[objective_t::COST] = objective_cost; + inf_cost[dim_t::COST] = infeasibility_cost; + } + + static DI thrust::tuple create_shared_route(i_t* shmem, + const cost_dimension_info_t dim_info, + i_t n_nodes_route) + { + view_t v; + v.dim_info = dim_info; + v.cost_forward = raft::device_span{(double*)shmem, (size_t)n_nodes_route + 1}; + v.cost_backward = raft::device_span{ + (double*)&v.cost_forward.data()[n_nodes_route + 1], (size_t)n_nodes_route + 1}; + + i_t* sh_ptr = (i_t*)&v.cost_backward.data()[n_nodes_route + 1]; + return thrust::make_tuple(v, sh_ptr); + } + + cost_dimension_info_t dim_info; + raft::device_span cost_forward; + raft::device_span cost_backward; + raft::device_span reverse_cost; + }; + + view_t view() + { + view_t v; + v.dim_info = dim_info; + v.cost_forward = raft::device_span{cost_forward.data(), cost_forward.size()}; + v.cost_backward = raft::device_span{cost_backward.data(), cost_backward.size()}; + v.reverse_cost = raft::device_span{reverse_cost.data(), reverse_cost.size()}; + return v; + } + + /** + * @brief Get the shared memory size required to store a cost route of a given size + * + * @param route_size + * @return size_t + */ + HDI static size_t get_shared_size(i_t route_size, + [[maybe_unused]] cost_dimension_info_t dim_info, + [[maybe_unused]] bool is_tsp = false) + { + // forward, backward + return 2 * route_size * sizeof(double); + } + + cost_dimension_info_t dim_info; + + // forward data + rmm::device_uvector cost_forward; + // backward data + rmm::device_uvector cost_backward; + // The info is not updated with the other dimension buffers. + // It is only used for cvrp/tsp and populated in global memory. + rmm::device_uvector reverse_cost; +}; + +} // namespace detail +} // namespace routing +} // namespace cuopt diff --git a/cpp/src/routing/route/dimensions_route.cuh b/cpp/src/routing/route/dimensions_route.cuh index bc08ba9819..48278dad1d 100644 --- a/cpp/src/routing/route/dimensions_route.cuh +++ b/cpp/src/routing/route/dimensions_route.cuh @@ -9,7 +9,7 @@ #include "break_route.cuh" #include "capacity_route.cuh" -#include "distance_route.cuh" +#include "cost_route.cuh" #include "mismatch_route.cuh" #include "pdp_route.cuh" #include "prize_route.cuh" @@ -43,8 +43,8 @@ using route_from_dim = typename std::conditional< ((dim_t)I == dim_t::TIME), time_route_t, typename std::conditional< - ((dim_t)I == dim_t::DIST), - distance_route_t, + ((dim_t)I == dim_t::COST), + cost_route_t, typename std::conditional< ((dim_t)I == dim_t::CAP), capacity_route_t, @@ -73,7 +73,7 @@ class dimensions_route_t { : sol_handle(sol_handle_), time_dim(sol_handle_, dimensions_info_.get_dimension()), capacity_dim(sol_handle_, dimensions_info_.get_dimension()), - distance_dim(sol_handle_, dimensions_info_.get_dimension()), + cost_dim(sol_handle_, dimensions_info_.get_dimension()), prize_dim(sol_handle_, dimensions_info_.get_dimension()), tasks_dim(sol_handle_, dimensions_info_.get_dimension()), service_time_dim(sol_handle_, dimensions_info_.get_dimension()), @@ -91,7 +91,7 @@ class dimensions_route_t { : sol_handle(dim_route.sol_handle), time_dim(dim_route.time_dim, dim_route.sol_handle), capacity_dim(dim_route.capacity_dim, dim_route.sol_handle), - distance_dim(dim_route.distance_dim, dim_route.sol_handle), + cost_dim(dim_route.cost_dim, dim_route.sol_handle), prize_dim(dim_route.prize_dim, dim_route.sol_handle), tasks_dim(dim_route.tasks_dim, dim_route.sol_handle), service_time_dim(dim_route.service_time_dim, dim_route.sol_handle), @@ -209,7 +209,7 @@ class dimensions_route_t { } typename request_route_t::view_t requests; - typename distance_route_t::view_t distance_dim; + typename cost_route_t::view_t cost_dim; typename time_route_t::view_t time_dim; typename capacity_route_t::view_t capacity_dim; typename prize_route_t::view_t prize_dim; @@ -265,7 +265,7 @@ class dimensions_route_t { request_route_t requests; // distance route - distance_route_t distance_dim; + cost_route_t cost_dim; // time route time_route_t time_dim; diff --git a/cpp/src/routing/route/distance_route.cuh b/cpp/src/routing/route/distance_route.cuh deleted file mode 100644 index a5f98c13ce..0000000000 --- a/cpp/src/routing/route/distance_route.cuh +++ /dev/null @@ -1,185 +0,0 @@ -/* clang-format off */ -/* - * SPDX-FileCopyrightText: Copyright (c) 2021-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - */ -/* clang-format on */ - -#pragma once - -#include -#include "../node/distance_node.cuh" -#include "../solution/solution_handle.cuh" -#include "routing/routing_helpers.cuh" - -#include -#include - -#include - -#include - -namespace cuopt { -namespace routing { -namespace detail { - -template -class distance_route_t { - public: - distance_route_t(solution_handle_t const* sol_handle_, cost_dimension_info_t& dim_info_) - : dim_info(dim_info_), - distance_forward(0, sol_handle_->get_stream()), - distance_backward(0, sol_handle_->get_stream()), - reverse_distance(0, sol_handle_->get_stream()) - { - raft::common::nvtx::range fun_scope("zero distance_route_t copy_ctr"); - } - - distance_route_t(const distance_route_t& distance_route, - solution_handle_t const* sol_handle_) - : dim_info(distance_route.dim_info), - distance_forward(distance_route.distance_forward, sol_handle_->get_stream()), - distance_backward(distance_route.distance_backward, sol_handle_->get_stream()), - reverse_distance(distance_route.reverse_distance, sol_handle_->get_stream()) - { - raft::common::nvtx::range fun_scope("distance route copy_ctr"); - } - - distance_route_t& operator=(distance_route_t&& distance_route) = default; - - void resize(i_t max_nodes_per_route, rmm::cuda_stream_view stream) - { - distance_forward.resize(max_nodes_per_route, stream); - distance_backward.resize(max_nodes_per_route, stream); - reverse_distance.resize(max_nodes_per_route, stream); - } - - struct view_t { - bool is_empty() const { return distance_forward.empty(); } - DI distance_node_t get_node(i_t idx) const - { - distance_node_t distance_node; - distance_node.distance_forward = distance_forward[idx]; - distance_node.distance_backward = distance_backward[idx]; - return distance_node; - } - - DI void set_node(i_t idx, const distance_node_t& node) - { - set_forward_data(idx, node); - set_backward_data(idx, node); - } - - DI void set_forward_data(i_t idx, const distance_node_t& node) - { - distance_forward[idx] = node.distance_forward; - } - - DI void set_backward_data(i_t idx, const distance_node_t& node) - { - distance_backward[idx] = node.distance_backward; - } - - DI void copy_forward_data(const view_t& orig_route, i_t start_idx, i_t end_idx, i_t write_start) - { - i_t size = end_idx - start_idx; - block_copy(distance_forward.subspan(write_start), - orig_route.distance_forward.subspan(start_idx), - size); - } - - DI void copy_backward_data(const view_t& orig_route, - i_t start_idx, - i_t end_idx, - i_t write_start) - { - i_t size = end_idx - start_idx; - block_copy(distance_backward.subspan(write_start), - orig_route.distance_backward.subspan(start_idx), - size); - } - - DI void copy_fixed_route_data(const view_t& orig_route, - i_t from_idx, - i_t to_idx, - i_t write_start) - { - // there is no fixed route data associated with distance - } - - DI void compute_cost(const VehicleInfo& vehicle_info, - const i_t n_nodes_route, - objective_cost_t& obj_cost, - infeasible_cost_t& inf_cost) const noexcept - { - double objective_cost = distance_forward[n_nodes_route]; - double infeasibility_cost = 0.; - if (dim_info.has_max_constraint) { - infeasibility_cost = max(0., distance_forward[n_nodes_route] - vehicle_info.max_cost); - } - - obj_cost[objective_t::COST] = objective_cost; - inf_cost[dim_t::DIST] = infeasibility_cost; - } - - static DI thrust::tuple create_shared_route(i_t* shmem, - const cost_dimension_info_t dim_info, - i_t n_nodes_route) - { - view_t v; - v.dim_info = dim_info; - v.distance_forward = raft::device_span{(double*)shmem, (size_t)n_nodes_route + 1}; - v.distance_backward = raft::device_span{ - (double*)&v.distance_forward.data()[n_nodes_route + 1], (size_t)n_nodes_route + 1}; - - i_t* sh_ptr = (i_t*)&v.distance_backward.data()[n_nodes_route + 1]; - return thrust::make_tuple(v, sh_ptr); - } - - cost_dimension_info_t dim_info; - raft::device_span distance_forward; - raft::device_span distance_backward; - raft::device_span reverse_distance; - }; - - view_t view() - { - view_t v; - v.dim_info = dim_info; - v.distance_forward = - raft::device_span{distance_forward.data(), distance_forward.size()}; - v.distance_backward = - raft::device_span{distance_backward.data(), distance_backward.size()}; - v.reverse_distance = - raft::device_span{reverse_distance.data(), reverse_distance.size()}; - return v; - } - - /** - * @brief Get the shared memory size required to store a distance route of a given size - * - * @param route_size - * @return size_t - */ - HDI static size_t get_shared_size(i_t route_size, - [[maybe_unused]] cost_dimension_info_t dim_info, - [[maybe_unused]] bool is_tsp = false) - { - // forward, backward - return 2 * route_size * sizeof(double); - } - - cost_dimension_info_t dim_info; - - // forward data - rmm::device_uvector distance_forward; - // backward data - rmm::device_uvector distance_backward; - // The info is not updated with the other dimension buffers. - // It is only used for cvrp/tsp and populated in global memory. - rmm::device_uvector reverse_distance; -}; - -} // namespace detail -} // namespace routing -} // namespace cuopt diff --git a/cpp/src/routing/route/mismatch_route.cuh b/cpp/src/routing/route/mismatch_route.cuh index 78975750e0..ff09e5ddcb 100644 --- a/cpp/src/routing/route/mismatch_route.cuh +++ b/cpp/src/routing/route/mismatch_route.cuh @@ -138,7 +138,7 @@ class mismatch_route_t { } /** - * @brief Get the shared memory size required to store a distance route of a given size + * @brief Get the shared memory size required to store a cost route of a given size * * @param route_size * @return size_t diff --git a/cpp/src/routing/route/prize_route.cuh b/cpp/src/routing/route/prize_route.cuh index 80b27061b5..8e34ab71b7 100644 --- a/cpp/src/routing/route/prize_route.cuh +++ b/cpp/src/routing/route/prize_route.cuh @@ -148,7 +148,7 @@ class prize_route_t { } /** - * @brief Get the shared memory size required to store a distance route of a given size + * @brief Get the shared memory size required to store a cost route of a given size * * @param route_size * @return size_t diff --git a/cpp/src/routing/route/service_time_route.cuh b/cpp/src/routing/route/service_time_route.cuh index 03c48b2e42..40768e2431 100644 --- a/cpp/src/routing/route/service_time_route.cuh +++ b/cpp/src/routing/route/service_time_route.cuh @@ -140,7 +140,7 @@ class service_time_route_t { } /** - * @brief Get the shared memory size required to store a distance route of a given size + * @brief Get the shared memory size required to store a cost route of a given size * * @param route_size * @return size_t diff --git a/cpp/src/routing/route/tasks_route.cuh b/cpp/src/routing/route/tasks_route.cuh index 3624d647e7..1c03c400e4 100644 --- a/cpp/src/routing/route/tasks_route.cuh +++ b/cpp/src/routing/route/tasks_route.cuh @@ -135,7 +135,7 @@ class tasks_route_t { } /** - * @brief Get the shared memory size required to store a distance route of a given size + * @brief Get the shared memory size required to store a cost route of a given size * * @param route_size * @return size_t diff --git a/cpp/src/routing/route/vehicle_fixed_cost_route.cuh b/cpp/src/routing/route/vehicle_fixed_cost_route.cuh index 1e246fbb6e..0f364a4d7f 100644 --- a/cpp/src/routing/route/vehicle_fixed_cost_route.cuh +++ b/cpp/src/routing/route/vehicle_fixed_cost_route.cuh @@ -104,7 +104,7 @@ class vehicle_fixed_cost_route_t { } /** - * @brief Get the shared memory size required to store a distance route of a given size + * @brief Get the shared memory size required to store a cost route of a given size * * @param route_size * @return size_t diff --git a/cpp/src/routing/util_kernels/set_nodes_data.cuh b/cpp/src/routing/util_kernels/set_nodes_data.cuh index 91458efe1d..5df5455105 100644 --- a/cpp/src/routing/util_kernels/set_nodes_data.cuh +++ b/cpp/src/routing/util_kernels/set_nodes_data.cuh @@ -54,8 +54,8 @@ __device__ void set_route_data(typename problem_t::view_t const& probl route.template get_dim().excess_backward[0]) < 0.0001, "Backward forward mismatch!"); } - route.template get_dim().distance_backward[n_nodes_route] = 0.f; - route.template get_dim().distance_forward[0] = 0.f; + route.template get_dim().cost_backward[n_nodes_route] = 0.f; + route.template get_dim().cost_forward[0] = 0.f; if (problem.dimensions_info.has_dimension(dim_t::CAP)) { route.template get_dim().max_to_node[0] = 0; route.template get_dim().gathered[0] = 0; From a3690bb53e1a707a3e5cf940d027bcf28b7c7305 Mon Sep 17 00:00:00 2001 From: Juanfran-Robles Date: Wed, 27 May 2026 15:09:44 +0200 Subject: [PATCH 2/3] refactor(routing): update distance reference comments in routing files. Modify comments related to distance references in dimensions, route, prize, service, tasks, and vehicle fixed files under /cpp/routing. Signed-off-by: Juanfran-Robles --- cpp/src/routing/route/dimensions_route.cuh | 2 +- cpp/src/routing/route/mismatch_route.cuh | 2 +- cpp/src/routing/route/prize_route.cuh | 2 +- cpp/src/routing/route/service_time_route.cuh | 2 +- cpp/src/routing/route/tasks_route.cuh | 2 +- cpp/src/routing/route/vehicle_fixed_cost_route.cuh | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/src/routing/route/dimensions_route.cuh b/cpp/src/routing/route/dimensions_route.cuh index 48278dad1d..798909306e 100644 --- a/cpp/src/routing/route/dimensions_route.cuh +++ b/cpp/src/routing/route/dimensions_route.cuh @@ -264,7 +264,7 @@ class dimensions_route_t { // pdp route request_route_t requests; - // distance route + // cost route cost_route_t cost_dim; // time route diff --git a/cpp/src/routing/route/mismatch_route.cuh b/cpp/src/routing/route/mismatch_route.cuh index ff09e5ddcb..a186c32120 100644 --- a/cpp/src/routing/route/mismatch_route.cuh +++ b/cpp/src/routing/route/mismatch_route.cuh @@ -138,7 +138,7 @@ class mismatch_route_t { } /** - * @brief Get the shared memory size required to store a cost route of a given size + * @brief Get the shared memory size required to store a mismatch route of a given size * * @param route_size * @return size_t diff --git a/cpp/src/routing/route/prize_route.cuh b/cpp/src/routing/route/prize_route.cuh index 8e34ab71b7..2ab91e1695 100644 --- a/cpp/src/routing/route/prize_route.cuh +++ b/cpp/src/routing/route/prize_route.cuh @@ -148,7 +148,7 @@ class prize_route_t { } /** - * @brief Get the shared memory size required to store a cost route of a given size + * @brief Get the shared memory size required to store a prize route of a given size * * @param route_size * @return size_t diff --git a/cpp/src/routing/route/service_time_route.cuh b/cpp/src/routing/route/service_time_route.cuh index 40768e2431..1555ca3946 100644 --- a/cpp/src/routing/route/service_time_route.cuh +++ b/cpp/src/routing/route/service_time_route.cuh @@ -140,7 +140,7 @@ class service_time_route_t { } /** - * @brief Get the shared memory size required to store a cost route of a given size + * @brief Get the shared memory size required to store a service time route of a given size * * @param route_size * @return size_t diff --git a/cpp/src/routing/route/tasks_route.cuh b/cpp/src/routing/route/tasks_route.cuh index 1c03c400e4..2b6d3ed082 100644 --- a/cpp/src/routing/route/tasks_route.cuh +++ b/cpp/src/routing/route/tasks_route.cuh @@ -135,7 +135,7 @@ class tasks_route_t { } /** - * @brief Get the shared memory size required to store a cost route of a given size + * @brief Get the shared memory size required to store a tasks route of a given size * * @param route_size * @return size_t diff --git a/cpp/src/routing/route/vehicle_fixed_cost_route.cuh b/cpp/src/routing/route/vehicle_fixed_cost_route.cuh index 0f364a4d7f..d0e9a5a5dc 100644 --- a/cpp/src/routing/route/vehicle_fixed_cost_route.cuh +++ b/cpp/src/routing/route/vehicle_fixed_cost_route.cuh @@ -104,7 +104,7 @@ class vehicle_fixed_cost_route_t { } /** - * @brief Get the shared memory size required to store a cost route of a given size + * @brief Get the shared memory size required to store a vehicle fixed route of a given size * * @param route_size * @return size_t From 9e3e2ad4aa075a0f6507eb8dfa1130a9f01fa1e9 Mon Sep 17 00:00:00 2001 From: Juanfran-Robles Date: Wed, 27 May 2026 19:44:24 +0200 Subject: [PATCH 3/3] test(routing): add routing test for COST boundary initialization. Cover VRP and PDP route setup by dirtying COST boundary buffers and verifying set_route_data resets cost_forward[0] and cost_backward[n] Signed-off-by: Juanfran-Robles --- cpp/tests/routing/CMakeLists.txt | 1 + .../cost_boundary_initialization.cu | 118 ++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 cpp/tests/routing/unit_tests/cost_boundary_initialization.cu diff --git a/cpp/tests/routing/CMakeLists.txt b/cpp/tests/routing/CMakeLists.txt index 569f84beb7..d332b16dff 100644 --- a/cpp/tests/routing/CMakeLists.txt +++ b/cpp/tests/routing/CMakeLists.txt @@ -43,5 +43,6 @@ ConfigureTest(ROUTING_UNIT_TEST ${CMAKE_CURRENT_SOURCE_DIR}/unit_tests/objective_function.cu ${CMAKE_CURRENT_SOURCE_DIR}/unit_tests/top_k.cu ${CMAKE_CURRENT_SOURCE_DIR}/unit_tests/batch_tsp.cu + ${CMAKE_CURRENT_SOURCE_DIR}/unit_tests/cost_boundary_initialization.cu ${CMAKE_CURRENT_SOURCE_DIR}/unit_tests/set_shmem_of_kernel.cu LABELS routing) diff --git a/cpp/tests/routing/unit_tests/cost_boundary_initialization.cu b/cpp/tests/routing/unit_tests/cost_boundary_initialization.cu new file mode 100644 index 0000000000..2e4142fd7f --- /dev/null +++ b/cpp/tests/routing/unit_tests/cost_boundary_initialization.cu @@ -0,0 +1,118 @@ +/* clang-format off */ +/* + * SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/* clang-format on */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +namespace cuopt { +namespace routing { +namespace test { + +template +__global__ void set_route_data_kernel(typename detail::solution_t::view_t sol, + const typename detail::problem_t::view_t problem) +{ + detail::set_route_data(problem, sol.routes[0]); +} + +template +void test_cost_boundaries_reset() +{ + constexpr bool is_pdp = REQUEST == request_t::PDP; + const int n_locations = is_pdp ? 3 : 2; + const int n_orders = is_pdp ? 2 : 1; + const int expected_n_nodes = is_pdp ? 3 : 2; + const double forward_dirty = 123.; + const double backward_dirty = 456.; + + std::vector cost_matrix(n_locations * n_locations, 0.f); + for (int from = 0; from < n_locations; ++from) { + for (int to = 0; to < n_locations; ++to) { + if (from != to) { + cost_matrix[from * n_locations + to] = from * n_locations + to + 1.f; + } + } + } + + std::vector order_locations = is_pdp ? std::vector{1, 2} : std::vector{1}; + + raft::handle_t handle; + auto stream = handle.get_stream(); + + auto d_cost_matrix = cuopt::device_copy(cost_matrix, stream); + auto d_order_locations = cuopt::device_copy(order_locations, stream); + + cuopt::routing::data_model_view_t data_model(&handle, n_locations, 1, n_orders); + data_model.add_cost_matrix(d_cost_matrix.data()); + data_model.set_order_locations(d_order_locations.data()); + + rmm::device_uvector d_pickups(is_pdp ? 1 : 0, stream); + rmm::device_uvector d_deliveries(is_pdp ? 1 : 0, stream); + if constexpr (is_pdp) { + const int pickup = 0; + const int delivery = 1; + raft::copy(d_pickups.data(), &pickup, 1, stream); + raft::copy(d_deliveries.data(), &delivery, 1, stream); + data_model.set_pickup_delivery_pairs(d_pickups.data(), d_deliveries.data()); + } + + cuopt::routing::solver_settings_t settings; + detail::problem_t problem(data_model, settings); + detail::solution_handle_t sol_handle(problem.handle_ptr->get_stream()); + detail::solution_t solution( + problem, 0, &sol_handle, std::vector{0}, expected_n_nodes + 1); + + auto& route = solution.get_route(0); + ASSERT_EQ(route.n_nodes.value(stream), expected_n_nodes); + + auto& cost_route = route.template get_dim(); + raft::copy(cost_route.cost_forward.data(), &forward_dirty, 1, stream); + raft::copy(cost_route.cost_backward.data() + expected_n_nodes, &backward_dirty, 1, stream); + handle.sync_stream(); + + { + const auto cost_forward = cuopt::host_copy(cost_route.cost_forward, stream); + const auto cost_backward = cuopt::host_copy(cost_route.cost_backward, stream); + ASSERT_DOUBLE_EQ(cost_forward[0], forward_dirty); + ASSERT_DOUBLE_EQ(cost_backward[expected_n_nodes], backward_dirty); + } + + set_route_data_kernel<<<1, 32, 0, stream>>>(solution.view(), problem.view()); + RAFT_CUDA_TRY(cudaPeekAtLastError()); + handle.sync_stream(); + + const auto cost_forward = cuopt::host_copy(cost_route.cost_forward, stream); + const auto cost_backward = cuopt::host_copy(cost_route.cost_backward, stream); + + EXPECT_DOUBLE_EQ(cost_forward[0], 0.); + EXPECT_DOUBLE_EQ(cost_backward[expected_n_nodes], 0.); +} + +TEST(cost_boundary_initialization, vrp_set_route_data_resets_cost_boundaries) +{ + test_cost_boundaries_reset(); +} + +TEST(cost_boundary_initialization, pdp_set_route_data_resets_cost_boundaries) +{ + test_cost_boundaries_reset(); +} + +} // namespace test +} // namespace routing +} // namespace cuopt