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..798909306e 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; @@ -264,8 +264,8 @@ class dimensions_route_t { // pdp route request_route_t requests; - // distance route - distance_route_t distance_dim; + // cost route + 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..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 distance 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 80b27061b5..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 distance 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 03c48b2e42..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 distance 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 3624d647e7..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 distance 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 1e246fbb6e..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 distance 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 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; 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