Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
3 changes: 1 addition & 2 deletions cpp/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
# SPDX-License-Identifier: Apache-2.0
# cmake-format: on

set(UTIL_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/utilities/seed_generator.cu
${CMAKE_CURRENT_SOURCE_DIR}/utilities/logger.cpp
set(UTIL_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/utilities/logger.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utilities/version_info.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utilities/timestamp_utils.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utilities/work_unit_scheduler.cpp)
Expand Down
9 changes: 6 additions & 3 deletions cpp/src/mip_heuristics/diversity/diversity_manager.cu
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,13 @@ diversity_manager_t<i_t, f_t>::diversity_manager_t(mip_solver_context_t<i_t, f_t
context.problem_ptr->handle_ptr),
sub_mip_recombiner(
context, population, context.problem_ptr->n_variables, context.problem_ptr->handle_ptr),
rng(cuopt::seed_generator::get_seed()),
rng(context.problem_ptr->seed_gen.get_seed()),
stats(context.stats),
mab_recombiner(0, cuopt::seed_generator::get_seed(), recombiner_alpha, "recombiner"),
mab_ls(mab_ls_config_t<i_t, f_t>::n_of_arms, cuopt::seed_generator::get_seed(), ls_alpha, "ls"),
mab_recombiner(0, context.problem_ptr->seed_gen.get_seed(), recombiner_alpha, "recombiner"),
mab_ls(mab_ls_config_t<i_t, f_t>::n_of_arms,
context.problem_ptr->seed_gen.get_seed(),
ls_alpha,
"ls"),
ls_hash_map(*context.problem_ptr)
{
int max_config = -1;
Expand Down
2 changes: 1 addition & 1 deletion cpp/src/mip_heuristics/diversity/population.cu
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ population_t<i_t, f_t>::population_t(std::string const& name_,
max_solutions(max_solutions_),
infeasibility_importance(infeasibility_weight_),
weights(0, context.problem_ptr->handle_ptr),
rng(cuopt::seed_generator::get_seed()),
rng(context.problem_ptr->seed_gen.get_seed()),
early_exit_primal_generation(false),
population_hash_map(*problem_ptr),
timer(0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class bound_prop_recombiner_t : public recombiner_t<i_t, f_t> {
const raft::handle_t* handle_ptr)
: recombiner_t<i_t, f_t>(context, n_vars, handle_ptr),
constraint_prop(constraint_prop_),
rng(cuopt::seed_generator::get_seed()),
rng(context.problem_ptr->seed_gen.get_seed()),
vars_to_fix(n_vars, handle_ptr->get_stream())
{
}
Expand Down Expand Up @@ -65,7 +65,7 @@ class bound_prop_recombiner_t : public recombiner_t<i_t, f_t> {
offspring_view,
int_tol,
probing_values = probing_values.data(),
seed = cuopt::seed_generator::get_seed()] __device__(i_t idx) {
seed = this->context.problem_ptr->seed_gen.get_seed()] __device__(i_t idx) {
f_t guiding_val = guiding_view.assignment[idx];
f_t other_val = other_view.assignment[idx];
cuopt_assert(guiding_view.problem.check_variable_within_bounds(idx, guiding_val), "");
Expand Down Expand Up @@ -151,7 +151,7 @@ class bound_prop_recombiner_t : public recombiner_t<i_t, f_t> {
if (n_different_vars > (i_t)bp_recombiner_config_t::max_n_of_vars_from_other) {
fixed_from_guiding = n_vars_from_other - bp_recombiner_config_t::max_n_of_vars_from_other;
n_vars_from_other = bp_recombiner_config_t::max_n_of_vars_from_other;
thrust::default_random_engine g{(unsigned int)cuopt::seed_generator::get_seed()};
thrust::default_random_engine g{(unsigned int)this->context.problem_ptr->seed_gen.get_seed()};
thrust::shuffle(a.handle_ptr->get_thrust_policy(),
this->remaining_indices.data(),
this->remaining_indices.data() + n_different_vars,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class fp_recombiner_t : public recombiner_t<i_t, f_t> {
i_t n_vars_from_other = n_different_vars;
if (n_vars_from_other > (i_t)fp_recombiner_config_t::max_n_of_vars_from_other) {
n_vars_from_other = fp_recombiner_config_t::max_n_of_vars_from_other;
thrust::default_random_engine g{(unsigned int)cuopt::seed_generator::get_seed()};
thrust::default_random_engine g{(unsigned int)this->context.problem_ptr->seed_gen.get_seed()};
thrust::shuffle(a.handle_ptr->get_thrust_policy(),
this->remaining_indices.data(),
this->remaining_indices.data() + n_different_vars,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class line_segment_recombiner_t : public recombiner_t<i_t, f_t> {
i_t n_vars_from_other = remaining_variables;
if (n_vars_from_other > (i_t)ls_recombiner_config_t::max_n_of_vars_from_other) {
n_vars_from_other = ls_recombiner_config_t::max_n_of_vars_from_other;
thrust::default_random_engine g{(unsigned int)cuopt::seed_generator::get_seed()};
thrust::default_random_engine g{(unsigned int)this->context.problem_ptr->seed_gen.get_seed()};
thrust::shuffle(guiding_solution.handle_ptr->get_thrust_policy(),
this->remaining_indices.data(),
this->remaining_indices.data() + remaining_variables,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ class recombiner_t {
objective_indices.size());
if (objective_indices.size() > 0 &&
objective_indices_in_subproblem.size() < 0.4 * remaining_variables) {
std::default_random_engine rng_host(cuopt::seed_generator::get_seed());
std::default_random_engine rng_host(context.problem_ptr->seed_gen.get_seed());
std::vector<i_t> objective_indices_not_in_subproblem;
std::set_difference(objective_indices.begin(),
objective_indices.end(),
Expand Down
2 changes: 1 addition & 1 deletion cpp/src/mip_heuristics/diversity/recombiners/sub_mip.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class sub_mip_recombiner_t : public recombiner_t<i_t, f_t> {
i_t n_vars_from_other = n_different_vars;
if (n_vars_from_other > (i_t)sub_mip_recombiner_config_t::max_n_of_vars_from_other) {
n_vars_from_other = sub_mip_recombiner_config_t::max_n_of_vars_from_other;
thrust::default_random_engine g{(unsigned int)cuopt::seed_generator::get_seed()};
thrust::default_random_engine g{(unsigned int)this->context.problem_ptr->seed_gen.get_seed()};
thrust::shuffle(a.handle_ptr->get_thrust_policy(),
this->remaining_indices.data(),
this->remaining_indices.data() + n_different_vars,
Expand Down
4 changes: 2 additions & 2 deletions cpp/src/mip_heuristics/feasibility_jump/feasibility_jump.cu
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ void fj_t<i_t, f_t>::reset_weights(const rmm::cuda_stream_view& climber_stream,
template <typename i_t, typename f_t>
void fj_t<i_t, f_t>::randomize_weights(const raft::handle_t* handle_ptr)
{
std::mt19937 rng(cuopt::seed_generator::get_seed());
std::mt19937 rng(context.problem_ptr->seed_gen.get_seed());
constexpr f_t min_weight = 10.;
constexpr f_t max_weight = 30.;
// generate a range of weights between 10. and 30.
Expand Down Expand Up @@ -671,7 +671,7 @@ void fj_t<i_t, f_t>::run_step_device(const rmm::cuda_stream_view& climber_stream

auto& data = *climbers[climber_idx];
auto v = data.view();
settings.seed = cuopt::seed_generator::get_seed();
settings.seed = context.problem_ptr->seed_gen.get_seed();
// ensure an updated copy of the settings is used device-side
raft::copy(v.settings, &settings, 1, climber_stream);

Expand Down
8 changes: 4 additions & 4 deletions cpp/src/mip_heuristics/feasibility_jump/fj_cpu.cu
Original file line number Diff line number Diff line change
Expand Up @@ -1492,7 +1492,7 @@ static std::unique_ptr<fj_cpu_climber_t<i_t, f_t>> init_fj_cpu_from_host_lp(
fj_settings.iteration_limit = std::numeric_limits<int>::max();
fj_settings.update_weights = true;
fj_settings.feasibility_run = false;
fj_settings.seed = seed >= 0 ? seed : cuopt::seed_generator::get_seed();
fj_settings.seed = seed >= 0 ? seed : settings.random_seed;

auto fj_cpu = std::make_unique<fj_cpu_climber_t<i_t, f_t>>(preemption_flag);
fj_cpu->view = typename fj_t<i_t, f_t>::climber_data_t::view_t{};
Expand Down Expand Up @@ -1595,13 +1595,13 @@ std::unique_ptr<fj_cpu_climber_t<i_t, f_t>> fj_t<i_t, f_t>::create_cpu_climber(
init_fj_cpu(*fj_cpu, solution, left_weights, right_weights, objective_weight);
fj_cpu->settings = settings;
if (randomize_params) {
auto rng = std::mt19937(cuopt::seed_generator::get_seed());
auto rng = std::mt19937(solution.problem_ptr->seed_gen.get_seed());
fj_cpu->mtm_viol_samples = std::uniform_int_distribution<i_t>(15, 50)(rng);
fj_cpu->mtm_sat_samples = std::uniform_int_distribution<i_t>(10, 30)(rng);
fj_cpu->nnz_samples = std::uniform_int_distribution<i_t>(2000, 15000)(rng);
fj_cpu->perturb_interval = std::uniform_int_distribution<i_t>(50, 500)(rng);
}
fj_cpu->settings.seed = cuopt::seed_generator::get_seed();
fj_cpu->settings.seed = solution.problem_ptr->seed_gen.get_seed();
return fj_cpu; // move
}

Expand Down Expand Up @@ -1786,7 +1786,7 @@ std::unique_ptr<fj_cpu_climber_t<i_t, f_t>> init_fj_cpu_standalone(
std::vector<f_t> default_weights(problem.n_constraints, 1.0);
init_fj_cpu(*fj_cpu, solution, default_weights, default_weights, 0.0);
fj_cpu->settings = settings;
fj_cpu->settings.seed = cuopt::seed_generator::get_seed();
fj_cpu->settings.seed = solution.problem_ptr->seed_gen.get_seed();

return fj_cpu;
}
Expand Down
4 changes: 2 additions & 2 deletions cpp/src/mip_heuristics/feasibility_jump/fj_cpu_worker.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ struct fj_cpu_worker_t {
~fj_cpu_worker_t() { stop(); }

// `seed` selects the FJ RNG seed: pass a non-negative value for a deterministic seed,
// or -1 to draw from the global cuopt::seed_generator (the historical behavior).
// or -1 to fall back to the simplex settings' random_seed.
// In deterministic mode the caller MUST pass an explicit seed, otherwise the underlying
// seed_generator::get_seed() racing with concurrent callers breaks reproducibility.
// shared seed source racing with concurrent callers breaks reproducibility.
void create_worker(const simplex::lp_problem_t<i_t, f_t>& problem,
const std::vector<simplex::variable_type_t>& variable_types,
const std::vector<f_t>& seed_assignment,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ feasibility_pump_t<i_t, f_t>::feasibility_pump_t(
orig_variable_types(context.problem_ptr->n_variables,
context.problem_ptr->handle_ptr->get_stream()),
lp_optimal_solution(lp_optimal_solution_),
rng(cuopt::seed_generator::get_seed()),
rng(context.problem_ptr->seed_gen.get_seed()),
timer(20.)
{
}
Expand Down
2 changes: 1 addition & 1 deletion cpp/src/mip_heuristics/local_search/local_search.cu
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ local_search_t<i_t, f_t>::local_search_t(mip_solver_context_t<i_t, f_t>& context
constraint_prop,
line_segment_search,
lp_optimal_solution_),
rng(cuopt::seed_generator::get_seed()),
rng(context.problem_ptr->seed_gen.get_seed()),
problem_with_objective_cut(*context.problem_ptr, context.problem_ptr->handle_ptr)
{
const int n_cpufj = context.settings.heuristic_params.num_cpufj_threads;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ bounds_repair_t<i_t, f_t>::bounds_repair_t(const problem_t<i_t, f_t>& pb,
violated_constraints(0, pb.handle_ptr->get_stream()),
violated_cstr_map(0, pb.handle_ptr->get_stream()),
total_vio(pb.handle_ptr->get_stream()),
gen(cuopt::seed_generator::get_seed()),
gen(pb.seed_gen.get_seed()),
cycle_vector(MAX_CYCLE_SEQUENCE, -1)
{
}
Expand Down
33 changes: 17 additions & 16 deletions cpp/src/mip_heuristics/local_search/rounding/constraint_prop.cu
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ constraint_prop_t<i_t, f_t>::constraint_prop_t(mip_solver_context_t<i_t, f_t>& c
ub_restore(context.problem_ptr->n_variables, context.problem_ptr->handle_ptr->get_stream()),
assignment_restore(context.problem_ptr->n_variables,
context.problem_ptr->handle_ptr->get_stream()),
rng(cuopt::seed_generator::get_seed(), 0, 0)
rng(context.problem_ptr->seed_gen.get_seed(), 0, 0)
{
}

Expand Down Expand Up @@ -604,7 +604,7 @@ thrust::pair<f_t, f_t> constraint_prop_t<i_t, f_t>::generate_double_probing_pair
if (probing_config.has_value()) {
// for now get the first one
auto [from_first, from_second] = probing_config.value().get().probing_values[unset_var_idx];
std::mt19937 rng(cuopt::seed_generator::get_seed());
std::mt19937 rng(context.problem_ptr->seed_gen.get_seed());
std::uniform_real_distribution<float> dist(0.0f, 1.0f);
f_t random_value = dist(rng);
f_t average_value = (from_first + from_second) / 2;
Expand Down Expand Up @@ -848,7 +848,7 @@ bool constraint_prop_t<i_t, f_t>::find_integer(
{
using crit_t = termination_criterion_t;
auto& unset_integer_vars = unset_vars;
std::mt19937 rng(cuopt::seed_generator::get_seed());
std::mt19937 rng(context.problem_ptr->seed_gen.get_seed());
lb_restore.resize(sol.problem_ptr->n_variables, sol.handle_ptr->get_stream());
ub_restore.resize(sol.problem_ptr->n_variables, sol.handle_ptr->get_stream());
assignment_restore.resize(sol.problem_ptr->n_variables, sol.handle_ptr->get_stream());
Expand Down Expand Up @@ -879,19 +879,20 @@ bool constraint_prop_t<i_t, f_t>::find_integer(
// round first unset_integer_vars.size() - 50, leave last 50 to be rounded by the algo
i_t n_to_round = std::max(unset_integer_vars.size() - 50, 0lu);
if (n_to_round > 0) {
thrust::for_each(
sol.handle_ptr->get_thrust_policy(),
unset_integer_vars.begin(),
unset_integer_vars.begin() + n_to_round,
[sol = sol.view(), seed = cuopt::seed_generator::get_seed()] __device__(i_t var_idx) {
raft::random::PCGenerator rng(seed, var_idx, 0);
auto var_bnd = sol.problem.variable_bounds[var_idx];
sol.assignment[var_idx] = round_nearest(sol.assignment[var_idx],
get_lower(var_bnd),
get_upper(var_bnd),
sol.problem.tolerances.integrality_tolerance,
rng);
});
thrust::for_each(sol.handle_ptr->get_thrust_policy(),
unset_integer_vars.begin(),
unset_integer_vars.begin() + n_to_round,
[sol = sol.view(),
seed = context.problem_ptr->seed_gen.get_seed()] __device__(i_t var_idx) {
raft::random::PCGenerator rng(seed, var_idx, 0);
auto var_bnd = sol.problem.variable_bounds[var_idx];
sol.assignment[var_idx] =
round_nearest(sol.assignment[var_idx],
get_lower(var_bnd),
get_upper(var_bnd),
sol.problem.tolerances.integrality_tolerance,
rng);
});
find_unset_integer_vars(sol, unset_integer_vars);
}
set_bounds_on_fixed_vars(sol);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@
namespace cuopt::mathematical_optimization::mip {

template <typename i_t, typename f_t>
lb_bounds_repair_t<i_t, f_t>::lb_bounds_repair_t(const raft::handle_t* handle_ptr)
lb_bounds_repair_t<i_t, f_t>::lb_bounds_repair_t(const raft::handle_t* handle_ptr, int64_t seed)
: candidates(handle_ptr),
best_bounds(handle_ptr),
cstr_violations_up(0, handle_ptr->get_stream()),
cstr_violations_down(0, handle_ptr->get_stream()),
violated_constraints(0, handle_ptr->get_stream()),
violated_cstr_map(0, handle_ptr->get_stream()),
total_vio(handle_ptr->get_stream()),
gen(cuopt::seed_generator::get_seed()),
gen(seed),
cycle_vector(MAX_CYCLE_SEQUENCE, -1)
{
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ struct lb_bounds_t {
template <typename i_t, typename f_t>
class lb_bounds_repair_t {
public:
lb_bounds_repair_t(const raft::handle_t* handle_ptr);
// The seed is supplied by the caller: this class has no route back to the problem
// that owns the seed source.
lb_bounds_repair_t(const raft::handle_t* handle_ptr, int64_t seed);
void resize(const load_balanced_problem_t<i_t, f_t>& problem);
void reset();
std::tuple<f_t, i_t> get_ii_violation(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ lb_constraint_prop_t<i_t, f_t>::lb_constraint_prop_t(mip_solver_context_t<i_t, f
: context(context_),
temp_problem(*context.problem_ptr),
bounds_update(temp_problem, context),
bounds_repair(context.problem_ptr->handle_ptr),
bounds_repair(context.problem_ptr->handle_ptr, context.problem_ptr->seed_gen.get_seed()),
unset_vars(context.problem_ptr->n_variables, context.problem_ptr->handle_ptr->get_stream()),
temp_assignment(context.problem_ptr->n_variables,
context.problem_ptr->handle_ptr->get_stream()),
bounds_restore(2 * context.problem_ptr->n_variables,
context.problem_ptr->handle_ptr->get_stream()),
assignment_restore(context.problem_ptr->n_variables,
context.problem_ptr->handle_ptr->get_stream()),
rng(cuopt::seed_generator::get_seed(), 0, 0)
rng(context.problem_ptr->seed_gen.get_seed(), 0, 0)
{
}

Expand Down Expand Up @@ -765,7 +765,7 @@ bool lb_constraint_prop_t<i_t, f_t>::find_integer(

using crit_t = termination_criterion_t;
auto& unset_integer_vars = unset_vars;
std::mt19937 rng(cuopt::seed_generator::get_seed());
std::mt19937 rng(context.problem_ptr->seed_gen.get_seed());

bounds_restore.resize(2 * orig_sol.problem_ptr->n_variables, orig_sol.handle_ptr->get_stream());
assignment_restore.resize(orig_sol.problem_ptr->n_variables, orig_sol.handle_ptr->get_stream());
Expand Down
Loading
Loading