Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7f3bd36
Try to find more MIR cuts
chris-maes Feb 24, 2026
95121cd
Merge remote-tracking branch 'cuopt-nvidia/main' into mir_cuts_improve
chris-maes Feb 24, 2026
9f21514
Style fixes
chris-maes Feb 24, 2026
8a1d41a
Fix issues identified by CodeRabbit
chris-maes Feb 25, 2026
7d393b9
Fix bugs found by CodeRabbit
chris-maes Feb 25, 2026
f48f1dc
Remove mir_cut_t. Switch everything to complemented_mir_cut_t. Fix fo…
chris-maes Feb 25, 2026
27c73b0
Merge remote-tracking branch 'cuopt-nvidia/main' into mir_cuts_improve
chris-maes Feb 25, 2026
6320cf2
Fix a bug in MIR aggregation where current row was used. Stop if no c…
chris-maes Feb 26, 2026
6c68ec3
Refactor cuts. Change MIR scoring updates to use priority_queue data …
chris-maes Feb 26, 2026
b78f118
Style fixes
chris-maes Feb 26, 2026
d19b3e8
Merge remote-tracking branch 'cuopt-nvidia/main' into mir_cuts_improve
chris-maes Feb 26, 2026
643004b
Redo cut generation heuristics
chris-maes Feb 27, 2026
e6d9edf
Style fixes
chris-maes Feb 27, 2026
a1620cc
Enable reduced cost strengthening by default
chris-maes Feb 27, 2026
72275b9
Merge remote-tracking branch 'cuopt-nvidia/main' into mir_cuts_improve
chris-maes Feb 27, 2026
e5a4b3c
Multiple bug fixes and numeric improvements in cuts and dual simplex
chris-maes Mar 3, 2026
64fce20
Style fixes
chris-maes Mar 3, 2026
97dca04
Reject small/large multipliers in aggregation
chris-maes Mar 4, 2026
73ed675
Fix bug where we forgot to break out of loop and were generating inva…
chris-maes Mar 4, 2026
dfded88
Style fixes
chris-maes Mar 4, 2026
5be8564
Address issues found by Alice. Thanks Alice
chris-maes Mar 4, 2026
a599d1e
Merge remote-tracking branch 'cuopt-nvidia/main' into mir_cuts_improve
chris-maes Mar 4, 2026
116a846
Remove small coefficients from MIR cuts causing incorrect result on i…
chris-maes Mar 5, 2026
59d4f89
Fix bug where we weren't include the basic leaving index in delta_xB
chris-maes Mar 10, 2026
43a2b79
Merge remote-tracking branch 'cuopt-nvidia/main' into mir_cuts_improve
chris-maes Mar 10, 2026
8655d98
Remove debug printf
chris-maes Mar 10, 2026
4347577
Remove debugging. Fix unit test. Change default for cut_change_threshold
chris-maes Mar 10, 2026
b40b32f
Merge remote-tracking branch 'cuopt-nvidia/main' into mir_cuts_improve
chris-maes Mar 11, 2026
a9c58e8
Style fixes
chris-maes Mar 11, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class mip_solver_settings_t {
i_t clique_cuts = -1;
i_t strong_chvatal_gomory_cuts = -1;
i_t reduced_cost_strengthening = -1;
f_t cut_change_threshold = 1e-3;
f_t cut_change_threshold = -1.0;
f_t cut_min_orthogonality = 0.5;
i_t mip_batch_pdlp_strong_branching = 0;
i_t num_gpus = 1;
Expand Down
23 changes: 20 additions & 3 deletions cpp/src/branch_and_bound/branch_and_bound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1950,6 +1950,12 @@ mip_status_t branch_and_bound_t<i_t, f_t>::solve(mip_solution_t<i_t, f_t>& solut
exploration_stats_.nodes_explored = 0;
original_lp_.A.to_compressed_row(Arow_);

settings_.log.printf("Reduced cost strengthening enabled: %d\n",
settings_.reduced_cost_strengthening);

variable_bounds_t<i_t, f_t> variable_bounds(
original_lp_, settings_, var_types_, Arow_, new_slacks_);

if (guess_.size() != 0) {
raft::common::nvtx::range scope_guess("BB::check_initial_guess");
std::vector<f_t> crushed_guess;
Expand Down Expand Up @@ -2161,9 +2167,11 @@ mip_status_t branch_and_bound_t<i_t, f_t>::solve(mip_solution_t<i_t, f_t>& solut
var_types_,
basis_update,
root_relax_soln_.x,
root_relax_soln_.y,
root_relax_soln_.z,
basic_list,
nonbasic_list,
variable_bounds,
exploration_stats_.start_time);
if (!problem_feasible) {
if (settings_.heuristic_preemption_callback != nullptr) {
Expand Down Expand Up @@ -2232,6 +2240,7 @@ mip_status_t branch_and_bound_t<i_t, f_t>::solve(mip_solution_t<i_t, f_t>& solut
root_vstatus_,
edge_norms_);
var_types_.resize(original_lp_.num_cols, variable_type_t::CONTINUOUS);
variable_bounds.resize(original_lp_.num_cols);
mutex_original_lp_.unlock();
f_t add_cuts_time = toc(add_cuts_start_time);
if (add_cuts_time > 1.0) {
Expand Down Expand Up @@ -2280,6 +2289,9 @@ mip_status_t branch_and_bound_t<i_t, f_t>::solve(mip_solution_t<i_t, f_t>& solut
}
if (!feasible) {
settings_.log.printf("Bound strengthening detected infeasibility\n");
#ifdef WRITE_BOUND_STRENGTHENING_INFEASIBLE_MPS
original_lp_.write_mps("bound_strengthening_infeasible.mps");
#endif
return mip_status_t::INFEASIBLE;
}

Expand All @@ -2301,7 +2313,6 @@ mip_status_t branch_and_bound_t<i_t, f_t>::solve(mip_solution_t<i_t, f_t>& solut
iter,
edge_norms_);
exploration_stats_.total_lp_iters += iter;
root_objective_ = compute_objective(original_lp_, root_relax_soln_.x);
f_t dual_phase2_time = toc(dual_phase2_start_time);
if (dual_phase2_time > 1.0) {
settings_.log.debug("Dual phase2 time %.2f seconds\n", dual_phase2_time);
Expand Down Expand Up @@ -2331,9 +2342,13 @@ mip_status_t branch_and_bound_t<i_t, f_t>::solve(mip_solution_t<i_t, f_t>& solut
root_objective_ = compute_objective(original_lp_, root_relax_soln_.x);
} else {
settings_.log.printf("Cut status %s\n", dual::status_to_string(cut_status).c_str());
#ifdef WRITE_CUT_INFEASIBLE_MPS
original_lp_.write_mps("cut_infeasible.mps");
#endif
return mip_status_t::NUMERICAL;
}
}
root_objective_ = compute_objective(original_lp_, root_relax_soln_.x);

f_t remove_cuts_start_time = tic();
mutex_original_lp_.lock();
Expand All @@ -2352,6 +2367,7 @@ mip_status_t branch_and_bound_t<i_t, f_t>::solve(mip_solution_t<i_t, f_t>& solut
basic_list,
nonbasic_list,
basis_update);
variable_bounds.resize(original_lp_.num_cols);
mutex_original_lp_.unlock();
f_t remove_cuts_time = toc(remove_cuts_start_time);
if (remove_cuts_time > 1.0) {
Expand Down Expand Up @@ -2380,8 +2396,9 @@ mip_status_t branch_and_bound_t<i_t, f_t>::solve(mip_solution_t<i_t, f_t>& solut
f_t change_in_objective = root_objective_ - last_objective;
const f_t factor = settings_.cut_change_threshold;
const f_t min_objective = 1e-3;
if (change_in_objective <= factor * std::max(min_objective, std::abs(root_relax_objective))) {
settings_.log.debug(
if (factor > 0.0 &&
change_in_objective <= factor * std::max(min_objective, std::abs(root_relax_objective))) {
settings_.log.printf(
"Change in objective %.16e is less than 1e-3 of root relax objective %.16e\n",
change_in_objective,
root_relax_objective);
Expand Down
Loading
Loading