Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
d1ab4eb
test fp only
akifcorduk Jul 31, 2025
47708f4
generate and then run FP
akifcorduk Aug 1, 2025
17561a2
with fj
akifcorduk Aug 1, 2025
6276efa
with obj cut
akifcorduk Aug 1, 2025
b2ed360
test FP ls
akifcorduk Aug 4, 2025
ebbb5e4
20s fp run
akifcorduk Aug 4, 2025
90c1696
fix feasibility run. 20s LS
akifcorduk Aug 4, 2025
7e859fb
fix feasibility run. 20s LS
akifcorduk Aug 4, 2025
5363e79
add as part of the local search
akifcorduk Aug 5, 2025
474d170
fp ls with mab
akifcorduk Aug 5, 2025
0690083
try with shorter run time
akifcorduk Aug 5, 2025
6c02547
tidy up functions and reduce local min to 500
akifcorduk Aug 6, 2025
0a176f1
revert cmake comments
akifcorduk Aug 6, 2025
e2d0d8b
fix typo
akifcorduk Aug 6, 2025
a4c37d6
fix typo
akifcorduk Aug 6, 2025
49584ed
remove the warning in pdlp solve
akifcorduk Aug 6, 2025
5ea08e8
handle review comments
akifcorduk Aug 7, 2025
85820e0
handle review comments
akifcorduk Aug 7, 2025
4437481
try without fp
akifcorduk Aug 8, 2025
c0b0a21
fix warning
akifcorduk Aug 8, 2025
ebb4958
enable lp and probing cache
akifcorduk Aug 11, 2025
54afd53
fix issues including the objective cut not being on copy constructor
akifcorduk Aug 14, 2025
df34a01
without probing cache
akifcorduk Aug 15, 2025
5ebb86c
nearest rounding
akifcorduk Aug 15, 2025
57b1b9d
FJ alone run
akifcorduk Aug 15, 2025
ee861a2
remove unnecessary function
akifcorduk Aug 18, 2025
f960946
Merge branch 'branch-25.10' of github.com:NVIDIA/cuopt into fp_ls
akifcorduk Aug 18, 2025
cc21c3d
add assert
akifcorduk Aug 19, 2025
9821f03
handle weight issue on fj with changed size
akifcorduk Aug 19, 2025
9cd097a
Merge branch 'branch-25.10' of github.com:NVIDIA/cuopt into fp_ls
akifcorduk Aug 19, 2025
f337b16
fix to_repair queue
akifcorduk Aug 20, 2025
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
12 changes: 6 additions & 6 deletions benchmarks/linear_programming/cuopt/run_mip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,12 +201,12 @@ int run_single_file(std::string file_path,
}
}

settings.time_limit = time_limit;
settings.heuristics_only = heuristics_only;
settings.num_cpu_threads = num_cpu_threads;
settings.log_to_console = log_to_console;
// settings.tolerances.relative_tolerance = 1e-10;
// settings.tolerances.absolute_tolerance = 1e-6;
settings.time_limit = time_limit;
settings.heuristics_only = heuristics_only;
settings.num_cpu_threads = num_cpu_threads;
settings.log_to_console = log_to_console;
settings.tolerances.relative_tolerance = 1e-12;
settings.tolerances.absolute_tolerance = 1e-6;
cuopt::linear_programming::benchmark_info_t benchmark_info;
settings.benchmark_info_ptr = &benchmark_info;
auto start_run_solver = std::chrono::high_resolution_clock::now();
Expand Down
4 changes: 4 additions & 0 deletions cpp/src/dual_simplex/branch_and_bound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,10 @@ branch_and_bound_t<i_t, f_t>::branch_and_bound_t(
template <typename i_t, typename f_t>
mip_status_t branch_and_bound_t<i_t, f_t>::solve(mip_solution_t<i_t, f_t>& solution)
{
// TODO remove this after submip PR merge
global_variables::mutex_upper.lock();
global_variables::repair_queue.clear();
global_variables::mutex_upper.unlock();
mip_status_t status = mip_status_t::UNSET;
mip_solution_t<i_t, f_t> incumbent(original_lp.num_cols);
if (guess.size() != 0) {
Expand Down
31 changes: 24 additions & 7 deletions cpp/src/mip/diversity/diversity_manager.cu
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

constexpr bool from_dir = false;
constexpr bool fj_only_run = false;
constexpr bool fp_only_run = false;

namespace cuopt::linear_programming::detail {

Expand Down Expand Up @@ -112,8 +113,8 @@ bool diversity_manager_t<i_t, f_t>::run_local_search(solution_t<i_t, f_t>& solut
timer_t& timer,
ls_config_t<i_t, f_t>& ls_config)
{
// i_t ls_mab_option = mab_ls.select_mab_option();
// mab_ls_config_t<i_t, f_t>::get_local_search_and_lm_from_config(ls_mab_option, ls_config);
i_t ls_mab_option = mab_ls.select_mab_option();
mab_ls_config_t<i_t, f_t>::get_local_search_and_lm_from_config(ls_mab_option, ls_config);
assignment_hash_map.insert(solution);
constexpr i_t skip_solutions_threshold = 3;
if (assignment_hash_map.check_skip_solution(solution, skip_solutions_threshold)) { return false; }
Expand Down Expand Up @@ -293,7 +294,7 @@ void diversity_manager_t<i_t, f_t>::generate_initial_solutions()
population.var_threshold);
population.print();
auto new_sol_vector = population.get_external_solutions();
if (!fj_only_run) { recombine_and_ls_with_all(new_sol_vector); }
if (!fj_only_run && !fp_only_run) { recombine_and_ls_with_all(new_sol_vector); }
}

template <typename i_t, typename f_t>
Expand Down Expand Up @@ -322,7 +323,6 @@ bool diversity_manager_t<i_t, f_t>::run_presolve(f_t time_limit)
stats.presolve_time = presolve_timer.elapsed_time();
lp_optimal_solution.resize(problem_ptr->n_variables, problem_ptr->handle_ptr->get_stream());
problem_ptr->handle_ptr->sync_stream();
cudaDeviceSynchronize();
return true;
}

Expand Down Expand Up @@ -382,6 +382,15 @@ void diversity_manager_t<i_t, f_t>::run_fj_alone(solution_t<i_t, f_t>& solution)
CUOPT_LOG_INFO("FJ alone finished!");
}

// returns the best feasible solution
template <typename i_t, typename f_t>
void diversity_manager_t<i_t, f_t>::run_fp_alone(solution_t<i_t, f_t>& solution)
{
CUOPT_LOG_INFO("Running FP alone!");
ls.run_fp(solution, timer, &population.weights, false);
CUOPT_LOG_INFO("FP alone finished!");
}

// returns the best feasible solution
template <typename i_t, typename f_t>
solution_t<i_t, f_t> diversity_manager_t<i_t, f_t>::run_solver()
Expand Down Expand Up @@ -411,7 +420,7 @@ solution_t<i_t, f_t> diversity_manager_t<i_t, f_t>::run_solver()
population.initialize_population();
if (check_b_b_preemption()) { return population.best_feasible(); }
// before probing cache or LP, run FJ to generate initial primal feasible solution
if (!from_dir) { generate_quick_feasible_solution(); }
if (!from_dir && !fp_only_run && !fj_only_run) { generate_quick_feasible_solution(); }
constexpr f_t time_ratio_of_probing_cache = diversity_config_t::time_ratio_of_probing_cache;
constexpr f_t max_time_on_probing = diversity_config_t::max_time_on_probing;
f_t time_for_probing_cache =
Expand Down Expand Up @@ -477,8 +486,10 @@ solution_t<i_t, f_t> diversity_manager_t<i_t, f_t>::run_solver()
}
population.allocate_solutions();
if (check_b_b_preemption()) { return population.best_feasible(); }
// generate a population with 5 solutions(FP+FJ)
generate_initial_solutions();
if (!fp_only_run) {
// generate a population with 5 solutions(FP+FJ)
generate_initial_solutions();
}
if (context.settings.benchmark_info_ptr != nullptr) {
context.settings.benchmark_info_ptr->objective_of_initial_population =
population.best_feasible().get_user_objective();
Expand All @@ -489,6 +500,12 @@ solution_t<i_t, f_t> diversity_manager_t<i_t, f_t>::run_solver()
return population.best_feasible();
}

if (fp_only_run) {
auto sol = generate_solution(timer.remaining_time(), false);
run_fp_alone(sol);
return sol;
}

if (timer.check_time_limit()) { return population.best_feasible(); }
main_loop();
return population.best_feasible();
Expand Down
1 change: 1 addition & 0 deletions cpp/src/mip/diversity/diversity_manager.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class diversity_manager_t {
// generates initial solutions
void generate_initial_solutions();
void run_fj_alone(solution_t<i_t, f_t>& solution);
void run_fp_alone(solution_t<i_t, f_t>& solution);
// main loop of diversity improvements
void main_loop();
// randomly chooses a recombiner and returns the offspring
Expand Down
23 changes: 5 additions & 18 deletions cpp/src/mip/diversity/multi_armed_bandit.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,13 @@ constexpr double ls_alpha = 0.03;

template <typename i_t, typename f_t>
struct mab_ls_config_t {
static constexpr i_t n_of_ls = 2;
static constexpr i_t n_of_configs = 4;
static constexpr i_t n_of_arms = n_of_ls * n_of_configs;
static constexpr i_t ls_local_mins[n_of_configs] = {50, 100, 200, 500};
static constexpr i_t ls_line_segment_local_mins[n_of_configs] = {10, 20, 40, 100};
// RANDOM is the last ls method
static constexpr i_t n_of_arms = static_cast<i_t>(ls_method_t::LS_METHODS_SIZE);

static void get_local_search_and_lm_from_config(i_t config_id, ls_config_t<i_t, f_t>& ls_config)
{
ls_method_t local_search = ls_method_t(config_id % n_of_ls);
i_t lm_id = config_id / n_of_ls;
if (local_search == ls_method_t::FJ_LINE_SEGMENT) {
ls_config.ls_method = ls_method_t::FJ_LINE_SEGMENT;
ls_config.n_local_mins_for_line_segment = ls_line_segment_local_mins[lm_id];
} else {
ls_config.ls_method = ls_method_t::FJ_ANNEALING;
ls_config.n_local_mins = ls_local_mins[lm_id];
}
mab_ls_config_t<i_t, f_t>::last_lm_config = lm_id;
ls_method_t local_search = ls_method_t(config_id % n_of_arms);
ls_config.ls_method = local_search;
mab_ls_config_t<i_t, f_t>::last_ls_mab_option = config_id;
}
static i_t last_lm_config;
Expand All @@ -61,11 +50,9 @@ i_t mab_ls_config_t<i_t, f_t>::last_ls_mab_option = 0;

struct ls_work_normalized_reward_t {
int option_id;
static constexpr double reward_per_option[mab_ls_config_t<int, double>::n_of_configs] = {
2, 1, 0.5, 0.25};
ls_work_normalized_reward_t(int option_id) : option_id(option_id) {}

double operator()(double factor) const { return factor * reward_per_option[option_id]; }
double operator()(double factor) const { return factor; }
};

struct recombiner_work_normalized_reward_t {
Expand Down
30 changes: 24 additions & 6 deletions cpp/src/mip/feasibility_jump/feasibility_jump.cu
Original file line number Diff line number Diff line change
Expand Up @@ -239,13 +239,31 @@ void fj_t<i_t, f_t>::populate_climber_views()

template <typename i_t, typename f_t>
void fj_t<i_t, f_t>::copy_weights(const weight_t<i_t, f_t>& weights,
const raft::handle_t* handle_ptr)
const raft::handle_t* handle_ptr,
std::optional<i_t> new_size)
{
cuopt_assert(cstr_weights.size() == weights.cstr_weights.size(), "Size mismatch");
raft::copy(cstr_weights.data(),
weights.cstr_weights.data(),
weights.cstr_weights.size(),
handle_ptr->get_stream());
i_t old_size = weights.cstr_weights.size();
cstr_weights.resize(new_size.value_or(weights.cstr_weights.size()), handle_ptr->get_stream());
cstr_left_weights.resize(new_size.value_or(weights.cstr_weights.size()),
handle_ptr->get_stream());
cstr_right_weights.resize(new_size.value_or(weights.cstr_weights.size()),
handle_ptr->get_stream());
thrust::for_each(handle_ptr->get_thrust_policy(),
thrust::counting_iterator<i_t>(0),
thrust::counting_iterator<i_t>(new_size.value_or(weights.cstr_weights.size())),
[old_size,
fj_weights = make_span(cstr_weights),
fj_left_weights = make_span(cstr_left_weights),
fj_right_weights = make_span(cstr_right_weights),
new_weights = make_span(weights.cstr_weights)] __device__(i_t idx) {
fj_weights[idx] = idx >= old_size ? 1. : new_weights[idx];
// TODO: ask Alice how we can manage the previous left,right weights
fj_left_weights[idx] = idx >= old_size ? 1. : new_weights[idx];
fj_right_weights[idx] = idx >= old_size ? 1. : new_weights[idx];
cuopt_assert(isfinite(fj_weights[idx]), "invalid weight");
cuopt_assert(isfinite(fj_left_weights[idx]), "invalid left weight");
cuopt_assert(isfinite(fj_right_weights[idx]), "invalid right weight");
});
thrust::transform(handle_ptr->get_thrust_policy(),
weights.objective_weight.data(),
weights.objective_weight.data() + 1,
Expand Down
4 changes: 3 additions & 1 deletion cpp/src/mip/feasibility_jump/feasibility_jump.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,9 @@ class fj_t {
void set_fj_settings(fj_settings_t settings_);
void reset_weights(const rmm::cuda_stream_view& stream, f_t weight = 10.);
void randomize_weights(const raft::handle_t* handle_ptr);
void copy_weights(const weight_t<i_t, f_t>& weights, const raft::handle_t* handle_ptr);
void copy_weights(const weight_t<i_t, f_t>& weights,
const raft::handle_t* handle_ptr,
std::optional<i_t> new_size = std::nullopt);
i_t host_loop(solution_t<i_t, f_t>& solution, i_t climber_idx = 0);
void run_step_device(i_t climber_idx = 0, bool use_graph = true);
void run_step_device(const rmm::cuda_stream_view& stream,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ bool feasibility_pump_t<i_t, f_t>::run_fj_cycle_escape(solution_t<i_t, f_t>& sol
bool is_feasible;
fj.settings.mode = fj_mode_t::EXIT_NON_IMPROVING;
fj.settings.update_weights = true;
fj.settings.feasibility_run = true;
fj.settings.feasibility_run = false;
fj.settings.n_of_minimums_for_exit = 5000;
fj.settings.time_limit = std::min(3., timer.remaining_time());
is_feasible = fj.solve(solution);
Expand Down Expand Up @@ -344,9 +344,10 @@ bool feasibility_pump_t<i_t, f_t>::handle_cycle(solution_t<i_t, f_t>& solution)
cuopt_assert(solution.test_number_all_integer(), "All must be integers before fj");
is_feasible = run_fj_cycle_escape(solution);
cuopt_assert(solution.test_number_all_integer(), "All must be integers after fj");
if (!is_feasible && cycle_queue.check_cycle(solution)) {
if (cycle_queue.check_cycle(solution)) {
CUOPT_LOG_DEBUG("Cycle couldn't be broken. Perturbating FP");
perturbate(solution);
is_feasible = solution.get_feasible();
}
cycle_queue.n_iterations_without_cycle = 0;
cycle_queue.update_recent_solutions(solution);
Expand Down Expand Up @@ -381,7 +382,6 @@ void feasibility_pump_t<i_t, f_t>::reset()
total_fp_time_until_cycle = 0;
fp_fj_cycle_time_begin = timer.remaining_time();
max_n_of_integers = 0;
run_intensive_restart = false;
config.alpha = default_alpha;
last_distances.resize(0);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,7 @@ class feasibility_pump_t {
f_t proj_and_round_time;
f_t proj_begin;
i_t n_fj_single_descents;
i_t max_n_of_integers = 0;
bool run_intensive_restart = false;
i_t max_n_of_integers = 0;
cuopt::timer_t timer;
};

Expand Down
Loading