Skip to content
16 changes: 16 additions & 0 deletions cpp/include/cuopt/routing/solver_settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,27 @@ class solver_settings_t {
*/
void dump_best_results(const std::string& file_path, i_t interval);

/**
* @brief Set the random seed used by the routing solver.
*
* Controls the initial seed for random number generation. Use -1 to derive the seed
* from the problem, which is the default and reproduces a given problem run to run.
*
* @param[in] seed The seed, or -1 to derive it from the problem
*/
void set_seed(i_t seed);

/**
* @brief Return set solving time
* @return Solving time set in seconds
*/
f_t get_time_limit() const noexcept;

/**
* @brief Return the random seed, or -1 if it is derived from the problem
*/
i_t get_seed() const noexcept;

/**
* @brief Return true if verbose mode is enabled
*/
Expand All @@ -93,6 +108,7 @@ class solver_settings_t {
i_t dump_interval_{std::numeric_limits<i_t>::max()};
bool dump_best_results_{false};
std::string best_result_file_name_;
i_t seed_{-1};
};

} // namespace CUOPT_EXPORT routing
Expand Down
4 changes: 2 additions & 2 deletions cpp/src/routing/adapters/adapted_generator.cu
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* clang-format off */
/*
* SPDX-FileCopyrightText: Copyright (c) 2022-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2022-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
/* clang-format on */
Expand Down Expand Up @@ -72,7 +72,7 @@ void generate_tsp_solution(adapted_sol_t<i_t, f_t, REQUEST>& sol,
for (i_t i = 0; i < (i_t)node_infos.size(); ++i) {
node_infos[i] = sol.problem->get_node_info_of_node(i + sol.problem->order_info.depot_included_);
}
std::mt19937 rng(seed_generator::get_seed());
std::mt19937 rng(sol.problem->seed_gen.get_seed());
std::shuffle(node_infos.begin(), node_infos.end(), rng);
std::vector<std::pair<i_t, std::vector<NodeInfo<>>>> routes_to_add;
routes_to_add.push_back({0, node_infos});
Expand Down
8 changes: 4 additions & 4 deletions cpp/src/routing/adapters/adapted_modifier.cu
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/* clang-format off */
/*
* SPDX-FileCopyrightText: Copyright (c) 2022-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2022-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
/* clang-format on */

#include <utilities/seed_generator.cuh>
#include <routing/utilities/seed_generator.cuh>
#include "../diversity/helpers.hpp"
#include "../ges/guided_ejection_search.cuh"

Expand Down Expand Up @@ -77,7 +77,7 @@ void adapted_modifier_t<i_t, f_t, REQUEST>::add_unserviced_request(
auto gpu_weight = get_cuopt_cost(final_weight);
resource.ls.set_active_weights(gpu_weight, std::numeric_limits<f_t>::max());
adapted_solution.sol.populate_ep_with_unserved(resource.ges.EP);
resource.ges.EP.random_shuffle();
resource.ges.EP.random_shuffle(adapted_solution.sol.problem_ptr->seed_gen.get_seed());
resource.ges.squeeze_all_ep();
adapted_solution.populate_host_data();
adapted_solution.check_device_host_coherence();
Expand All @@ -101,7 +101,7 @@ void adapted_modifier_t<i_t, f_t, REQUEST>::add_selected_unserviced_requests(
auto gpu_weight = get_cuopt_cost(final_weight);
resource.ls.set_active_weights(gpu_weight, std::numeric_limits<f_t>::max());
adapted_solution.sol.populate_ep_with_selected_unserved(resource.ges.EP, unserviced_nodes);
resource.ges.EP.random_shuffle();
resource.ges.EP.random_shuffle(adapted_solution.sol.problem_ptr->seed_gen.get_seed());
resource.ges.squeeze_all_ep();
adapted_solution.populate_host_data();
adapted_solution.check_device_host_coherence();
Expand Down
6 changes: 3 additions & 3 deletions cpp/src/routing/diversity/diverse_solver.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* clang-format off */
/*
* SPDX-FileCopyrightText: Copyright (c) 2022-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2022-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
/* clang-format on */
Expand All @@ -11,7 +11,7 @@
#include "helpers.hpp"
#include "population.hpp"

#include <utilities/seed_generator.cuh>
#include <routing/utilities/seed_generator.cuh>
#include <utilities/timer.hpp>
#include "../crossovers/dispose.hpp"
#include "../crossovers/eax_recombiner.hpp"
Expand Down Expand Up @@ -245,7 +245,7 @@ struct solve {
temp_pair(solution{p_, pool_allocator_.sol_handles[0].get()},
solution{p_, pool_allocator_.sol_handles[0].get()}),
f(file_name),
rng(seed_generator::get_seed()),
rng(p->seed_gen.get_seed()),
timer(timer_),
improvement_timer(timer_),
perturbation_count(0)
Expand Down
4 changes: 2 additions & 2 deletions cpp/src/routing/ges/compute_delivery_insertions.cuh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* clang-format off */
/*
* SPDX-FileCopyrightText: Copyright (c) 2022-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2022-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
/* clang-format on */
Expand All @@ -15,7 +15,7 @@

#include <cub/block/block_merge_sort.cuh>
#include <cub/block/block_scan.cuh>
#include <utilities/seed_generator.cuh>
#include <routing/utilities/seed_generator.cuh>

namespace cuopt {
namespace routing {
Expand Down
10 changes: 5 additions & 5 deletions cpp/src/routing/ges/eject_until_feasible.cu
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* clang-format off */
/*
* SPDX-FileCopyrightText: Copyright (c) 2022-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2022-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
/* clang-format on */
Expand Down Expand Up @@ -365,8 +365,8 @@ void solution_t<i_t, f_t, REQUEST>::eject_until_feasible(bool add_slack_to_sol)
bool is_set = set_shmem_of_kernel(eject_until_feasible_kernel<i_t, f_t, REQUEST>, sh_size);
cuopt_assert(is_set, "Not enough shared memory on device for get_all_feasible_insertion!");
cuopt_expects(is_set, error_type_t::OutOfMemoryError, "Not enough shared memory on device");
eject_until_feasible_kernel<i_t, f_t, REQUEST>
<<<n_routes, TPB, sh_size, stream>>>(view(), add_slack_to_sol, seed_generator::get_seed());
eject_until_feasible_kernel<i_t, f_t, REQUEST><<<n_routes, TPB, sh_size, stream>>>(
view(), add_slack_to_sol, problem_ptr->seed_gen.get_seed());
compute_cost();
global_runtime_checks(false, true, "eject_until_feasible");
}
Expand All @@ -385,7 +385,7 @@ void solution_t<i_t, f_t, REQUEST>::populate_ep_with_unserved(
EP.index_ = ep_index_out.value(stream);
stream.synchronize();
if (EP.size() > 1) {
thrust::default_random_engine g(seed_generator::get_seed());
thrust::default_random_engine g(problem_ptr->seed_gen.get_seed());
thrust::shuffle(
sol_handle->get_thrust_policy(), EP.stack_.begin(), EP.stack_.begin() + EP.size(), g);
}
Expand All @@ -405,7 +405,7 @@ void solution_t<i_t, f_t, REQUEST>::populate_ep_with_selected_unserved(
raft::device_span<i_t const>(unserviced_device.data(), unserviced_device.size());

populate_ep_with_selected_unserved_kernel<i_t, f_t, REQUEST><<<1, TPB, 0, stream>>>(
view(), unserviced_view, EP.view(), ep_index_out.data(), seed_generator::get_seed());
view(), unserviced_view, EP.view(), ep_index_out.data(), problem_ptr->seed_gen.get_seed());
RAFT_CHECK_CUDA(stream);
EP.index_ = ep_index_out.value(stream);
stream.synchronize();
Expand Down
11 changes: 6 additions & 5 deletions cpp/src/routing/ges/ejection_pool.cuh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* clang-format off */
/*
* SPDX-FileCopyrightText: Copyright (c) 2022-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2022-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
/* clang-format on */
Expand All @@ -10,8 +10,8 @@
#include "../node/node.cuh"

#include <cuopt/error.hpp>
#include <routing/utilities/seed_generator.cuh>
#include <utilities/cuda_helpers.cuh>
#include <utilities/seed_generator.cuh>

#include <rmm/cuda_stream_view.hpp>
#include <rmm/device_scalar.hpp>
Expand Down Expand Up @@ -56,13 +56,14 @@ struct ejection_pool_t {

void push_back_last() { ++index_; }

void random_shuffle()
// The seed is supplied by the caller: the pool has no route back to the problem
// that owns the seed source.
void random_shuffle(int64_t seed)
{
// replace with thrust shuffle
// how to get sol_handle::get_thrust_policy?
if (size() > 1)
device_random_shuffle<elemt_t>
<<<1, 1, 0, stream_>>>(stack_.data(), size(), seed_generator::get_seed());
device_random_shuffle<elemt_t><<<1, 1, 0, stream_>>>(stack_.data(), size(), seed);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

bool empty() const
Expand Down
6 changes: 3 additions & 3 deletions cpp/src/routing/ges/execute_insertion.cu
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

#include "../solution/solution.cuh"

#include <routing/utilities/seed_generator.cuh>
#include <utilities/copy_helpers.hpp>
#include <utilities/seed_generator.cuh>
#include "compute_delivery_insertions.cuh"
#include "compute_fragment_ejections.cuh"
#include "ejection_pool.cuh"
Expand Down Expand Up @@ -281,7 +281,7 @@ bool guided_ejection_search_t<i_t, f_t, REQUEST>::execute_best_insertion_ejectio
solution_ptr->get_num_orders(),
solution_ptr->problem_ptr->get_max_break_dimensions(),
solution_ptr->get_n_routes());
int64_t seed = seed_generator::get_seed();
int64_t seed = solution_ptr->problem_ptr->seed_gen.get_seed();
i_t* p_scores = p_scores_.data();
i_t fragment_size_arg = fragment_size;
i_t fragment_step_arg = fragment_step;
Expand Down Expand Up @@ -406,7 +406,7 @@ i_t guided_ejection_search_t<i_t, f_t, REQUEST>::find_single_insertion(
solution_ptr->get_num_orders(),
solution_ptr->problem_ptr->get_max_break_dimensions(),
solution_ptr->get_n_routes()),
seed_generator::get_seed());
solution_ptr->problem_ptr->seed_gen.get_seed());

RAFT_CHECK_CUDA(solution_ptr->sol_handle->get_stream());

Expand Down
8 changes: 4 additions & 4 deletions cpp/src/routing/ges/guided_ejection_search.cu
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* clang-format off */
/*
* SPDX-FileCopyrightText: Copyright (c) 2022-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2022-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
/* clang-format on */
Expand Down Expand Up @@ -62,7 +62,7 @@ guided_ejection_search_t<i_t, f_t, REQUEST>::guided_ejection_search_t(
(solution.get_num_orders() + solution.problem_ptr->get_max_break_dimensions()),
solution.sol_handle->get_stream()),
feasible_candidates_size_(solution.sol_handle->get_stream()),
gen_candidate(seed_generator::get_seed()),
gen_candidate(solution.problem_ptr->seed_gen.get_seed()),
p_scores_(solution.get_num_orders(), solution.sol_handle->get_stream()),
inserted_requests(solution.get_num_orders(), solution.sol_handle->get_stream()),
best_squeeze_per_cand(solution.get_num_requests(), solution.sol_handle->get_stream()),
Expand Down Expand Up @@ -192,7 +192,7 @@ void guided_ejection_search_t<i_t, f_t, REQUEST>::shuffle_pool()
raft::common::nvtx::range fun_scope("shuffle_pool");
// include the ejected request in shuffle
++EP.index_;
EP.random_shuffle();
EP.random_shuffle(solution_ptr->problem_ptr->seed_gen.get_seed());
--EP.index_;
if (dump_intermediate) { dump_to_file("Shuffle"); }
}
Expand Down Expand Up @@ -439,7 +439,7 @@ bool guided_ejection_search_t<i_t, f_t, REQUEST>::construct_feasible_solution()
}
solution_ptr->add_routes(new_routes);
// permutate the EP for randomness
EP.random_shuffle();
EP.random_shuffle(solution_ptr->problem_ptr->seed_gen.get_seed());
bool all_inserted = greedy_insert();
if (!all_inserted) { local_search_ptr_->perturb_solution(*solution_ptr); }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include "lexicographic_search.cuh"

#include <routing/utilities/cuopt_utils.cuh>
#include <utilities/seed_generator.cuh>
#include <routing/utilities/seed_generator.cuh>

#include "raft/core/span.hpp"
#include "raft/random/device/sample.cuh"
Expand Down
2 changes: 1 addition & 1 deletion cpp/src/routing/ges/lexicographic_search/node_stack.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include "../../solution/solution.cuh"

#include <routing/utilities/cuopt_utils.cuh>
#include <utilities/seed_generator.cuh>
#include <routing/utilities/seed_generator.cuh>

#include "raft/core/span.hpp"

Expand Down
12 changes: 6 additions & 6 deletions cpp/src/routing/local_search/compute_insertions.cu
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* clang-format off */
/*
* SPDX-FileCopyrightText: Copyright (c) 2022-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2022-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
/* clang-format on */
Expand All @@ -9,7 +9,7 @@
#include "compute_insertions.cuh"
#include "delivery_insertion.cuh"

#include <utilities/seed_generator.cuh>
#include <routing/utilities/seed_generator.cuh>
#include "routing/utilities/cuopt_utils.cuh"

#include "../routing_helpers.cuh"
Expand Down Expand Up @@ -831,7 +831,7 @@ void find_insertions(solution_t<i_t, f_t, REQUEST>& sol,
cuopt_expects(is_set, error_type_t::OutOfMemoryError, "Not enough shared memory on device");
find_insertions_kernel<i_t, f_t, REQUEST, search_type_t::IMPROVE, insert_unserviced>
<<<n_blocks, TPB, shared_size, sol.sol_handle->get_stream()>>>(
sol.view(), move_candidates.view(), seed_generator::get_seed());
sol.view(), move_candidates.view(), sol.problem_ptr->seed_gen.get_seed());
} else {
// for cross the load-balance factor is always 4
move_candidates.number_of_blocks_per_ls_route =
Expand All @@ -847,7 +847,7 @@ void find_insertions(solution_t<i_t, f_t, REQUEST>& sol,
cuopt_expects(is_set, error_type_t::OutOfMemoryError, "Not enough shared memory on device");
find_insertions_kernel<i_t, f_t, REQUEST, search_type_t::CROSS, insert_unserviced>
<<<n_blocks, TPB, shared_size, sol.sol_handle->get_stream()>>>(
sol.view(), move_candidates.view(), seed_generator::get_seed());
sol.view(), move_candidates.view(), sol.problem_ptr->seed_gen.get_seed());
} else if (search_type == search_type_t::RANDOM) {
// we don't search for relocates in random.
n_blocks = sol.get_num_requests();
Expand All @@ -859,7 +859,7 @@ void find_insertions(solution_t<i_t, f_t, REQUEST>& sol,
cuopt_expects(is_set, error_type_t::OutOfMemoryError, "Not enough shared memory on device");
find_insertions_kernel<i_t, f_t, REQUEST, search_type_t::RANDOM, insert_unserviced>
<<<n_blocks, TPB, shared_size, sol.sol_handle->get_stream()>>>(
sol.view(), move_candidates.view(), seed_generator::get_seed());
sol.view(), move_candidates.view(), sol.problem_ptr->seed_gen.get_seed());
}
}
RAFT_CHECK_CUDA(sol.sol_handle->get_stream());
Expand Down Expand Up @@ -892,7 +892,7 @@ void find_unserviced_insertions(solution_t<i_t, f_t, REQUEST>& sol,
cuopt_expects(is_set, error_type_t::OutOfMemoryError, "Not enough shared memory on device");
find_insertions_kernel<i_t, f_t, REQUEST, search_type_t::IMPROVE, insert_unserviced>
<<<n_blocks, TPB, shared_size, sol.sol_handle->get_stream()>>>(
sol.view(), move_candidates.view(), seed_generator::get_seed());
sol.view(), move_candidates.view(), sol.problem_ptr->seed_gen.get_seed());
RAFT_CHECK_CUDA(sol.sol_handle->get_stream());
sol.sol_handle->sync_stream();
}
Expand Down
6 changes: 3 additions & 3 deletions cpp/src/routing/local_search/fill_gpu_graph.cu
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
/* clang-format off */
/*
* SPDX-FileCopyrightText: Copyright (c) 2022-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2022-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
/* clang-format on */

#include "../solution/solution.cuh"
#include "local_search.cuh"

#include <utilities/seed_generator.cuh>
#include <routing/utilities/seed_generator.cuh>
#include "../util_kernels/top_k.cuh"
#include "cycle_finder/cycle_graph.hpp"
#include "routing/utilities/cuopt_utils.cuh"
Expand Down Expand Up @@ -159,7 +159,7 @@ void local_search_t<i_t, f_t, REQUEST>::fill_gpu_graph(solution_t<i_t, f_t, REQU
const auto stream = solution.sol_handle->get_stream();
move_candidates.graph.special_index = solution.get_num_orders() + solution.n_routes;
fill_intra_candidates<i_t, f_t, REQUEST><<<solution.n_routes, TPB, 0, stream>>>(
solution.view(), move_candidates.view(), seed_generator::get_seed());
solution.view(), move_candidates.view(), solution.problem_ptr->seed_gen.get_seed());
// +1 for special node
i_t n_blocks = solution.get_num_requests() + 1;
fill_graph_kernel<i_t, f_t, REQUEST, TPB>
Expand Down
4 changes: 2 additions & 2 deletions cpp/src/routing/local_search/permutation_helper.cuh
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
/* clang-format off */
/*
* SPDX-FileCopyrightText: Copyright (c) 2023-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
/* clang-format on */

#pragma once

#include <utilities/seed_generator.cuh>
#include <routing/utilities/seed_generator.cuh>
#include "../node/node.cuh"
#include "../route/route.cuh"
#include "../routing_helpers.cuh"
Expand Down
Loading
Loading