diff --git a/cpp/include/cuopt/mathematical_optimization/constants.h b/cpp/include/cuopt/mathematical_optimization/constants.h index 0ac8c01875..6e2a139d23 100644 --- a/cpp/include/cuopt/mathematical_optimization/constants.h +++ b/cpp/include/cuopt/mathematical_optimization/constants.h @@ -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" diff --git a/cpp/include/cuopt/mathematical_optimization/pdlp/solver_settings.hpp b/cpp/include/cuopt/mathematical_optimization/pdlp/solver_settings.hpp index 0882f75e0f..66b6eef4f6 100644 --- a/cpp/include/cuopt/mathematical_optimization/pdlp/solver_settings.hpp +++ b/cpp/include/cuopt/mathematical_optimization/pdlp/solver_settings.hpp @@ -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}; diff --git a/cpp/src/barrier/barrier.cu b/cpp/src/barrier/barrier.cu index c164296a25..8c6988649c 100644 --- a/cpp/src/barrier/barrier.cu +++ b/cpp/src/barrier/barrier.cu @@ -97,6 +97,15 @@ bool validate_barrier_cone_layout(const lp_problem_t& problem, return true; } +// -1 automatic: enable for cones, disable otherwise; 0 off; 1 on +template +bool should_use_adaptive_regularization(const simplex_solver_settings_t& settings, + bool has_cones) +{ + return settings.barrier_adaptive_regularization > 0 || + (settings.barrier_adaptive_regularization < 0 && has_cones); +} + template [[maybe_unused]] static void pairwise_multiply( f_t* a, f_t* b, f_t* out, int size, rmm::cuda_stream_view stream) @@ -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. @@ -2914,7 +2920,7 @@ i_t barrier_solver_t::gpu_compute_search_direction(iteration_data_t 1e-2) { @@ -4163,6 +4169,15 @@ lp_status_t barrier_solver_t::solve(f_t start_time, lp_solution_t settings.time_limit) { settings.log.printf("Barrier time limit exceeded\n"); @@ -4176,6 +4191,7 @@ lp_status_t barrier_solver_t::solve(f_t start_time, lp_solution_t::solve(f_t start_time, lp_solution_tset_barrier_dual_initial_point(settings.barrier_dual_initial_point); pb_settings->set_eliminate_dense_columns(settings.eliminate_dense_columns); pb_settings->set_barrier_iterative_refinement(settings.barrier_iterative_refinement); + pb_settings->set_barrier_adaptive_regularization(settings.barrier_adaptive_regularization); pb_settings->set_barrier_step_scale(settings.barrier_step_scale); pb_settings->set_postsolve_info(settings.postsolve_info); pb_settings->set_save_best_primal_so_far(settings.save_best_primal_so_far); diff --git a/cpp/src/grpc/codegen/generated/generated_proto_to_pdlp_settings.inc b/cpp/src/grpc/codegen/generated/generated_proto_to_pdlp_settings.inc index 29e6c4cca2..5e910b3c2b 100644 --- a/cpp/src/grpc/codegen/generated/generated_proto_to_pdlp_settings.inc +++ b/cpp/src/grpc/codegen/generated/generated_proto_to_pdlp_settings.inc @@ -76,6 +76,9 @@ if (pb_settings.has_barrier_iterative_refinement()) { settings.barrier_iterative_refinement = pb_settings.barrier_iterative_refinement(); } + if (pb_settings.has_barrier_adaptive_regularization()) { + settings.barrier_adaptive_regularization = pb_settings.barrier_adaptive_regularization(); + } if (pb_settings.has_barrier_step_scale()) { settings.barrier_step_scale = pb_settings.barrier_step_scale(); } diff --git a/cpp/src/math_optimization/solver_settings.cu b/cpp/src/math_optimization/solver_settings.cu index 44f8ac8246..db1e0019d6 100644 --- a/cpp/src/math_optimization/solver_settings.cu +++ b/cpp/src/math_optimization/solver_settings.cu @@ -187,7 +187,8 @@ solver_settings_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::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::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"}, }; diff --git a/cpp/src/pdlp/solve.cu b/cpp/src/pdlp/solve.cu index b8cb4aead8..5f49efdf0e 100644 --- a/cpp/src/pdlp/solve.cu +++ b/cpp/src/pdlp/solve.cu @@ -515,6 +515,7 @@ std::tuple, 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; @@ -690,27 +691,28 @@ static optimization_problem_solution_t run_pdlp_solver_in_fp32( static_cast(settings.tolerances.primal_infeasible_tolerance); fs.tolerances.dual_infeasible_tolerance = static_cast(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(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(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 solver(float_problem, fs, is_batch_mode); if (settings.inside_mip) { solver.set_inside_mip(true); } diff --git a/docs/cuopt/source/convex-settings.rst b/docs/cuopt/source/convex-settings.rst index 7bff025e5d..ee2253d669 100644 --- a/docs/cuopt/source/convex-settings.rst +++ b/docs/cuopt/source/convex-settings.rst @@ -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 + +.. note:: The default value is ``-1`` (automatic).