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
1 change: 1 addition & 0 deletions cpp/include/cuopt/mathematical_optimization/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#define CUOPT_POSTSOLVE_INFO "postsolve_info"
#define CUOPT_BARRIER_PRESOLVE_BOUND_FREE_VARIABLES "barrier_presolve_bound_free_variables"
#define CUOPT_BARRIER_ITERATIVE_REFINEMENT "barrier_iterative_refinement"
#define CUOPT_BARRIER_ADAPTIVE_REGULARIZATION "barrier_adaptive_regularization"
#define CUOPT_BARRIER_STEP_SCALE "barrier_step_scale"
#define CUOPT_ELIMINATE_DENSE_COLUMNS "eliminate_dense_columns"
#define CUOPT_CUDSS_DETERMINISTIC "cudss_deterministic"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ class pdlp_solver_settings_t {
bool eliminate_dense_columns{true};
pdlp_precision_t pdlp_precision{pdlp_precision_t::DefaultPrecision};
bool barrier_iterative_refinement{true};
i_t barrier_adaptive_regularization{-1}; // -1 automatic, 0 disabled, 1 enabled
i_t barrier_soc_threshold{100};
f_t barrier_step_scale{0.9};
bool save_best_primal_so_far{false};
Expand Down
36 changes: 26 additions & 10 deletions cpp/src/barrier/barrier.cu
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,15 @@ bool validate_barrier_cone_layout(const lp_problem_t<i_t, f_t>& problem,
return true;
}

// -1 automatic: enable for cones, disable otherwise; 0 off; 1 on
template <typename i_t, typename f_t>
bool should_use_adaptive_regularization(const simplex_solver_settings_t<i_t, f_t>& settings,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: rename should_use_adaptive_regularization to check_adaptive_regularization.

bool has_cones)
{
return settings.barrier_adaptive_regularization > 0 ||
(settings.barrier_adaptive_regularization < 0 && has_cones);
}

template <typename f_t>
[[maybe_unused]] static void pairwise_multiply(
f_t* a, f_t* b, f_t* out, int size, rmm::cuda_stream_view stream)
Expand Down Expand Up @@ -479,14 +488,11 @@ class iteration_data_t {
f_t estimated_nz_AAT = 0.0;

const bool has_soc = has_cones();

if (has_soc) {
primal_perturb = 1e-8;
dual_perturb = 1e-8;
} else {
primal_perturb = 1e-6;
dual_perturb = 0;
}
// Apply the adaptive-regularization policy before form_augmented / initial
// factorization so an explicit enable/disable is honored from the start.
const bool adaptive_reg = should_use_adaptive_regularization(settings, has_soc);
primal_perturb = has_soc ? 1e-8 : 1e-6;
dual_perturb = adaptive_reg ? 1e-8 : 0;

if (has_soc) {
// SOCP always use the augmented KKT; skip dense-column / ADAT heuristics.
Expand Down Expand Up @@ -2914,7 +2920,7 @@ i_t barrier_solver_t<i_t, f_t>::gpu_compute_search_direction(iteration_data_t<i_

// Adaptive regularization: increase/decrease based on IR quality.
// Only adapt on calls where we actually (re)factorized — the affine step.
if (did_factorize && data.has_cones()) {
if (did_factorize && should_use_adaptive_regularization(settings, data.has_cones())) {
constexpr f_t min_perturb = 1e-8;
constexpr f_t max_perturb = 1e-1;
if (solve_err > 1e-2) {
Expand Down Expand Up @@ -4163,6 +4169,15 @@ lp_status_t barrier_solver_t<i_t, f_t>::solve(f_t start_time, lp_solution_t<i_t,
return lp_status_t::TIME_LIMIT;
}

// Handle automatic adaptive regularization (-1: auto, 0: off, 1: on).
// Policy is already applied to data.dual_perturb during construction
// (before form_augmented / initial_point).
const bool adaptive_regularization =
should_use_adaptive_regularization(settings, data.has_cones());
if (settings.barrier_adaptive_regularization == -1 && adaptive_regularization) {
settings.log.printf("Adaptive regularization enabled\n");
}

i_t initial_status = initial_point(data);
if (toc(start_time) > settings.time_limit) {
settings.log.printf("Barrier time limit exceeded\n");
Expand All @@ -4176,6 +4191,7 @@ lp_status_t barrier_solver_t<i_t, f_t>::solve(f_t start_time, lp_solution_t<i_t,
settings.log.printf("Unable to compute initial point\n");
return lp_status_t::NUMERICAL_ISSUES;
}

// Upload initial point to device and compute initial residuals/norms on GPU
data.d_complementarity_wv_residual_.resize(data.n_upper_bounds, stream_view_);
data.d_complementarity_wv_rhs_.resize(data.n_upper_bounds, stream_view_);
Expand Down Expand Up @@ -4271,7 +4287,7 @@ lp_status_t barrier_solver_t<i_t, f_t>::solve(f_t start_time, lp_solution_t<i_t,
const i_t iteration_limit = settings.iteration_limit;

// Adaptive regularization for the augmented system.
f_t dual_perturb = data.has_cones() ? 1e-8 : 0;
f_t dual_perturb = adaptive_regularization ? 1e-8 : 0;
f_t primal_perturb = data.has_cones() ? 1e-8 : 1e-6;

while (iter < iteration_limit) {
Expand Down
10 changes: 6 additions & 4 deletions cpp/src/dual_simplex/simplex_solver_settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ struct simplex_solver_settings_t {
barrier(false),
eliminate_dense_columns(true),
barrier_iterative_refinement(true),
barrier_adaptive_regularization(-1),
barrier_step_scale(0.9),
barrier_soc_threshold(100),
num_gpus(1),
Expand Down Expand Up @@ -163,10 +164,11 @@ struct simplex_solver_settings_t {
bool cudss_deterministic; // true to use cuDSS deterministic mode, false for non-deterministic
bool barrier; // true to use barrier method, false to use dual simplex method
bool deterministic; // true to use B&B deterministic mode, false to use non-deterministic mode
bool eliminate_dense_columns; // true to eliminate dense columns from A*D*A^T
bool barrier_iterative_refinement; // true to use iterative refinement for barrier method
f_t barrier_step_scale; // step scale for barrier method
i_t barrier_soc_threshold; // SOC dimension above which rank-2 sparse scaling is used
bool eliminate_dense_columns; // true to eliminate dense columns from A*D*A^T
bool barrier_iterative_refinement; // true to use iterative refinement for barrier method
int barrier_adaptive_regularization; // -1 automatic, 0 disabled, 1 enabled
Comment thread
coderabbitai[bot] marked this conversation as resolved.
f_t barrier_step_scale; // step scale for barrier method
i_t barrier_soc_threshold; // SOC dimension above which rank-2 sparse scaling is used
int num_gpus; // Number of GPUs to use (maximum of 2 gpus are supported at the moment)
i_t folding; // -1 automatic, 0 don't fold, 1 fold
i_t augmented; // -1 automatic, 0 to solve with ADAT, 1 to solve with augmented system
Expand Down
3 changes: 2 additions & 1 deletion cpp/src/math_optimization/solver_settings.cu
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,8 @@ solver_settings_t<i_t, f_t>::solver_settings_t() : pdlp_settings(), mip_settings
// Recursive sub-MIP (RINS) hyper-parameters (hidden from default --help: name contains "hyper_")
{CUOPT_MIP_HYPER_SUBMIP_NODE_LIMIT_BASE, &mip_settings.submip_params.node_limit_base, 0, std::numeric_limits<i_t>::max(), 200, "base node limit for the sub-MIP"},
{CUOPT_MIP_HYPER_SUBMIP_MAX_LEVEL, &mip_settings.submip_params.max_level, 0, std::numeric_limits<i_t>::max(), 10, "maximum sub-MIP recursion level"},
{CUOPT_BARRIER_PRESOLVE_BOUND_FREE_VARIABLES, &pdlp_settings.barrier_presolve_bound_free_variables, -1, 1, -1, "Bound free variables during barrier presolve: -1 automatic (current default behavior), 0 disabled, 1 enabled"},
{CUOPT_BARRIER_PRESOLVE_BOUND_FREE_VARIABLES, &pdlp_settings.barrier_presolve_bound_free_variables, -1, 1, -1, "Bound free variables during barrier presolve: -1 automatic (default behavior), 0 disabled, 1 enabled"},
{CUOPT_BARRIER_ADAPTIVE_REGULARIZATION, &pdlp_settings.barrier_adaptive_regularization, -1, 1, -1, "Adaptive regularization for barrier method: -1 automatic (default behavior), 0 disabled, 1 enabled"},
// QCQP (barrier) scaling hyper-parameter
{CUOPT_QCQP_HYPER_RUIZ_EQUILIBRATION, &pdlp_settings.qcqp_ruiz_equilibration, -1, 1, -1, "Ruiz equilibration for QCQP barrier scaling: -1 automatic (row/column imbalance heuristic), 0 disabled, 1 enabled"},
};
Expand Down
44 changes: 23 additions & 21 deletions cpp/src/pdlp/solve.cu
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,7 @@ std::tuple<simplex::lp_solution_t<i_t, f_t>, simplex::lp_status_t, f_t, f_t, f_t
barrier_settings.crossover = settings.crossover;
barrier_settings.eliminate_dense_columns = settings.eliminate_dense_columns;
barrier_settings.barrier_iterative_refinement = settings.barrier_iterative_refinement;
barrier_settings.barrier_adaptive_regularization = settings.barrier_adaptive_regularization;
barrier_settings.barrier_soc_threshold = settings.barrier_soc_threshold;
barrier_settings.barrier_step_scale = settings.barrier_step_scale;
barrier_settings.qcqp_ruiz_equilibration = settings.qcqp_ruiz_equilibration;
Expand Down Expand Up @@ -690,27 +691,28 @@ static optimization_problem_solution_t<i_t, double> run_pdlp_solver_in_fp32(
static_cast<float>(settings.tolerances.primal_infeasible_tolerance);
fs.tolerances.dual_infeasible_tolerance =
static_cast<float>(settings.tolerances.dual_infeasible_tolerance);
fs.detect_infeasibility = settings.detect_infeasibility;
fs.strict_infeasibility = settings.strict_infeasibility;
fs.iteration_limit = settings.iteration_limit;
fs.time_limit = static_cast<float>(settings.time_limit);
fs.pdlp_solver_mode = settings.pdlp_solver_mode;
fs.log_to_console = settings.log_to_console;
fs.log_file = settings.log_file;
fs.per_constraint_residual = settings.per_constraint_residual;
fs.save_best_primal_so_far = settings.save_best_primal_so_far;
fs.first_primal_feasible = settings.first_primal_feasible;
fs.all_primal_feasible = settings.all_primal_feasible;
fs.eliminate_dense_columns = settings.eliminate_dense_columns;
fs.barrier_iterative_refinement = settings.barrier_iterative_refinement;
fs.barrier_step_scale = settings.barrier_step_scale;
fs.pdlp_precision = pdlp_precision_t::DefaultPrecision;
fs.method = method_t::PDLP;
fs.inside_mip = settings.inside_mip;
fs.hyper_params = settings.hyper_params;
fs.presolver = settings.presolver;
fs.num_gpus = settings.num_gpus;
fs.concurrent_halt = settings.concurrent_halt;
fs.detect_infeasibility = settings.detect_infeasibility;
fs.strict_infeasibility = settings.strict_infeasibility;
fs.iteration_limit = settings.iteration_limit;
fs.time_limit = static_cast<float>(settings.time_limit);
fs.pdlp_solver_mode = settings.pdlp_solver_mode;
fs.log_to_console = settings.log_to_console;
fs.log_file = settings.log_file;
fs.per_constraint_residual = settings.per_constraint_residual;
fs.save_best_primal_so_far = settings.save_best_primal_so_far;
fs.first_primal_feasible = settings.first_primal_feasible;
fs.all_primal_feasible = settings.all_primal_feasible;
fs.eliminate_dense_columns = settings.eliminate_dense_columns;
fs.barrier_iterative_refinement = settings.barrier_iterative_refinement;
fs.barrier_adaptive_regularization = settings.barrier_adaptive_regularization;
fs.barrier_step_scale = settings.barrier_step_scale;
fs.pdlp_precision = pdlp_precision_t::DefaultPrecision;
fs.method = method_t::PDLP;
fs.inside_mip = settings.inside_mip;
fs.hyper_params = settings.hyper_params;
fs.presolver = settings.presolver;
fs.num_gpus = settings.num_gpus;
fs.concurrent_halt = settings.concurrent_halt;

pdlp::pdlp_solver_t<i_t, float> solver(float_problem, fs, is_batch_mode);
if (settings.inside_mip) { solver.set_inside_mip(true); }
Expand Down
12 changes: 12 additions & 0 deletions docs/cuopt/source/convex-settings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -387,3 +387,15 @@ Barrier Step Scale
The step scale must be strictly less than 1. A value like 0.9 is conservative, while a value like 0.999 is aggressive.

.. note:: By default cuOpt selects the step scale automatically.


Barrier Adaptive Regularization
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

``CUOPT_BARRIER_ADAPTIVE_REGULARIZATION`` controls whether adaptive regularization is enabled in the barrier method.

* ``-1``: Automatic (default) - cuOpt decides whether to enable adaptive regularization based on problem characteristics
* ``0``: Disable adaptive regularization
* ``1``: Enable adaptive regularization
Comment thread
coderabbitai[bot] marked this conversation as resolved.

.. note:: The default value is ``-1`` (automatic).
Loading