diff --git a/cpp/src/routing/adapters/adapted_modifier.cu b/cpp/src/routing/adapters/adapted_modifier.cu index 16f28fa48..a99981776 100644 --- a/cpp/src/routing/adapters/adapted_modifier.cu +++ b/cpp/src/routing/adapters/adapted_modifier.cu @@ -127,7 +127,8 @@ template void adapted_modifier_t::equalize_routes_and_nodes( adapted_sol_t& sol_a, adapted_sol_t& sol_b, - costs final_weight) + costs final_weight, + bool skip_adding_nodes_to_a) { raft::common::nvtx::range fun_scope("equalize_routes_and_nodes"); @@ -153,7 +154,7 @@ void adapted_modifier_t::equalize_routes_and_nodes( } } - if (sol_a.sol.get_n_routes() > sol_b.sol.get_n_routes()) { + if (!skip_adding_nodes_to_a && sol_a.sol.get_n_routes() > sol_b.sol.get_n_routes()) { auto removed_nodes = sol_a.priority_remove_diff_routes(sol_b); missing_in_a.insert(missing_in_a.end(), removed_nodes.begin(), removed_nodes.end()); } else if (sol_b.sol.get_n_routes() > sol_a.sol.get_n_routes()) { @@ -164,7 +165,9 @@ void adapted_modifier_t::equalize_routes_and_nodes( // If there are no mutually exclusive requests, take an early exit if (missing_in_a.empty() && missing_in_b.empty()) { return; } - add_selected_unserviced_requests(sol_a, missing_in_a, final_weight); + if (!skip_adding_nodes_to_a) { + add_selected_unserviced_requests(sol_a, missing_in_a, final_weight); + } add_selected_unserviced_requests(sol_b, missing_in_b, final_weight); } diff --git a/cpp/src/routing/adapters/adapted_modifier.cuh b/cpp/src/routing/adapters/adapted_modifier.cuh index 5b39e54b1..545bddb98 100644 --- a/cpp/src/routing/adapters/adapted_modifier.cuh +++ b/cpp/src/routing/adapters/adapted_modifier.cuh @@ -48,7 +48,8 @@ struct adapted_modifier_t { void equalize_routes_and_nodes(adapted_sol_t& sol_a, adapted_sol_t& sol_b, - costs final_weight); + costs final_weight, + bool skip_adding_nodes_to_a = false); void insert_infeasible_nodes(adapted_sol_t& sol, costs& weights); diff --git a/cpp/src/routing/diversity/diverse_solver.hpp b/cpp/src/routing/diversity/diverse_solver.hpp index 2147d23dd..5f4fc1c6b 100644 --- a/cpp/src/routing/diversity/diverse_solver.hpp +++ b/cpp/src/routing/diversity/diverse_solver.hpp @@ -1167,8 +1167,10 @@ struct solve { } case recombiner_t::IX: { + auto skip_adding_nodes_to_a = true; + lm.equalize_routes_and_nodes(a, b, weights, skip_adding_nodes_to_a); success = inversion.recombine(a, b); - if (success) recombine_stats.add_success(); + if (success) { recombine_stats.add_success(); } break; } diff --git a/cpp/src/routing/diversity/injection_info.hpp b/cpp/src/routing/diversity/injection_info.hpp index 76024d8f9..09923fb64 100644 --- a/cpp/src/routing/diversity/injection_info.hpp +++ b/cpp/src/routing/diversity/injection_info.hpp @@ -1,6 +1,6 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 + * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. + * All rights reserved. SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,7 +47,8 @@ struct injection_info_t { auto tmp_routes = cuopt::host_copy(d_routes, stream); auto vehicle_ids = cuopt::host_copy(d_vehicle_ids, stream); auto node_types = cuopt::host_copy(d_types, stream); - n_sol = sol_offsets.size() - 1; + + n_sol = sol_offsets.size() - 1; accepted.resize(n_sol, -1); @@ -87,6 +88,17 @@ struct injection_info_t { added_node_ids.insert(tmp_routes[j]); } + if (p->order_info.is_pdp()) { + for (int node_id : added_node_ids) { + int brother_id = p->get_brother_node_info(p->get_node_info_of_node(node_id)).node(); + auto cond = added_node_ids.count(brother_id) > 0; + if (!cond) { + std::cout << "node_id: " << node_id << " brother_id: " << brother_id << std::endl; + } + cuopt_expects(cond, error_type_t::ValidationError, "Brother node is not served"); + } + } + desired_vehicle_ids.push_back(curr_vehicle_id); sol_routes.push_back({sol_n_routes++, new_route}); cuopt_expects(sol_n_routes <= p->get_fleet_size(), @@ -113,6 +125,7 @@ struct injection_info_t { std::iota(sequence.begin(), sequence.end(), 0); S.remove_routes(sequence); S.add_new_routes(sol_routes); + S.sol.global_runtime_checks(false, false, "Check solution after injection"); solutions.emplace_back(std::move(S)); } return solutions; diff --git a/cpp/src/utilities/copy_helpers.hpp b/cpp/src/utilities/copy_helpers.hpp index 5f39013e3..611e7811a 100644 --- a/cpp/src/utilities/copy_helpers.hpp +++ b/cpp/src/utilities/copy_helpers.hpp @@ -1,6 +1,6 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2022-2025 NVIDIA CORPORATION & AFFILIATES. All rights - * reserved. SPDX-License-Identifier: Apache-2.0 + * SPDX-FileCopyrightText: Copyright (c) 2022-2025 NVIDIA CORPORATION & + * AFFILIATES. All rights reserved. SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -173,6 +173,16 @@ inline auto device_copy(std::vector const& host_vec, rmm::cuda_stream_view return device_vec; } +template +void print(std::string_view const name, std::vector const& container) +{ + std::cout << name << "=["; + for (auto const& item : container) { + std::cout << item << ","; + } + std::cout << "]\n"; +} + template void print(std::string_view const name, rmm::device_uvector const& container) {