From 8d2b601fe41a2971a8ef8bf8d23488951d90dc55 Mon Sep 17 00:00:00 2001 From: Rajesh Gandham Date: Fri, 14 Aug 2026 12:20:09 -0700 Subject: [PATCH 1/6] Add a setting for controlling adaptive regularization --- .../mathematical_optimization/constants.h | 1 + .../pdlp/solver_settings.hpp | 1 + cpp/src/barrier/barrier.cu | 20 ++++++++- .../dual_simplex/simplex_solver_settings.hpp | 9 ++-- cpp/src/math_optimization/solver_settings.cu | 1 + cpp/src/pdlp/solve.cu | 44 ++++++++++--------- 6 files changed, 49 insertions(+), 27 deletions(-) diff --git a/cpp/include/cuopt/mathematical_optimization/constants.h b/cpp/include/cuopt/mathematical_optimization/constants.h index 467aa7fce3..03093b5861 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..cae0bfe520 100644 --- a/cpp/src/barrier/barrier.cu +++ b/cpp/src/barrier/barrier.cu @@ -2081,6 +2081,15 @@ class iteration_data_t { const simplex_solver_settings_t& settings_; }; +// -1 automatic: enable for cones, disable otherwise; 0 off; 1 on +template +bool should_use_adaptive_regularization(const simplex_solver_settings_t& settings, + const iteration_data_t& data) +{ + return settings.barrier_adaptive_regularization > 0 || + (settings.barrier_adaptive_regularization < 0 && data.has_cones()); +} + // Move the Cholesky debug logic to a reusable function. template @@ -2914,7 +2923,7 @@ i_t barrier_solver_t::gpu_compute_search_direction(iteration_data_t 1e-2) { @@ -4176,6 +4185,13 @@ lp_status_t barrier_solver_t::solve(f_t start_time, lp_solution_t::solve(f_t start_time, lp_solution_t::solver_settings_t() : pdlp_settings(), mip_settings {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_ADAPTIVE_REGULARIZATION, &pdlp_settings.barrier_adaptive_regularization, -1, 1, -1, "Adaptive regularization for barrier method: false disabled, true 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 80b3da2c18..ec9aa0d0a0 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); } From 63954b2ac0ba5762fb5cc0103e1897705103400e Mon Sep 17 00:00:00 2001 From: Rajesh Gandham Date: Tue, 18 Aug 2026 11:34:17 -0700 Subject: [PATCH 2/6] Add docs --- docs/cuopt/source/convex-settings.rst | 12 ++++++++++++ 1 file changed, 12 insertions(+) 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). From 06c8bb55c82786bcb3e91cb3aaec4f8e00ee934b Mon Sep 17 00:00:00 2001 From: Rajesh Gandham Date: Tue, 18 Aug 2026 11:38:16 -0700 Subject: [PATCH 3/6] Add an initializer --- cpp/src/dual_simplex/simplex_solver_settings.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/src/dual_simplex/simplex_solver_settings.hpp b/cpp/src/dual_simplex/simplex_solver_settings.hpp index 1b497d0b38..1247bcb460 100644 --- a/cpp/src/dual_simplex/simplex_solver_settings.hpp +++ b/cpp/src/dual_simplex/simplex_solver_settings.hpp @@ -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), From 90b1c7c2322381c94ad81e22483a330a81b1e517 Mon Sep 17 00:00:00 2001 From: Rajesh Gandham Date: Tue, 18 Aug 2026 13:48:04 -0700 Subject: [PATCH 4/6] Move the adaptive refinement logic to initial point computation --- cpp/src/barrier/barrier.cu | 48 +++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/cpp/src/barrier/barrier.cu b/cpp/src/barrier/barrier.cu index cae0bfe520..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. @@ -2081,15 +2087,6 @@ class iteration_data_t { const simplex_solver_settings_t& settings_; }; -// -1 automatic: enable for cones, disable otherwise; 0 off; 1 on -template -bool should_use_adaptive_regularization(const simplex_solver_settings_t& settings, - const iteration_data_t& data) -{ - return settings.barrier_adaptive_regularization > 0 || - (settings.barrier_adaptive_regularization < 0 && data.has_cones()); -} - // Move the Cholesky debug logic to a reusable function. template @@ -2923,7 +2920,7 @@ i_t barrier_solver_t::gpu_compute_search_direction(iteration_data_t 1e-2) { @@ -4172,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"); @@ -4186,12 +4192,6 @@ lp_status_t barrier_solver_t::solve(f_t start_time, lp_solution_t Date: Tue, 18 Aug 2026 13:50:35 -0700 Subject: [PATCH 5/6] Correct variable description --- cpp/src/math_optimization/solver_settings.cu | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/src/math_optimization/solver_settings.cu b/cpp/src/math_optimization/solver_settings.cu index baa0804842..03b8b9f1f1 100644 --- a/cpp/src/math_optimization/solver_settings.cu +++ b/cpp/src/math_optimization/solver_settings.cu @@ -187,8 +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_ADAPTIVE_REGULARIZATION, &pdlp_settings.barrier_adaptive_regularization, -1, 1, -1, "Adaptive regularization for barrier method: false disabled, true 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"}, }; From 203f4f041773b3f117012e82bde5992b0252a74b Mon Sep 17 00:00:00 2001 From: Rajesh Gandham Date: Wed, 19 Aug 2026 11:54:32 -0700 Subject: [PATCH 6/6] Add the new parameter to registry --- cpp/src/grpc/codegen/field_registry.yaml | 4 ++++ cpp/src/grpc/codegen/generated/cuopt_remote_data.proto | 1 + .../codegen/generated/generated_pdlp_settings_to_proto.inc | 1 + .../codegen/generated/generated_proto_to_pdlp_settings.inc | 3 +++ 4 files changed, 9 insertions(+) diff --git a/cpp/src/grpc/codegen/field_registry.yaml b/cpp/src/grpc/codegen/field_registry.yaml index 2fb7896027..43b33b895a 100644 --- a/cpp/src/grpc/codegen/field_registry.yaml +++ b/cpp/src/grpc/codegen/field_registry.yaml @@ -548,6 +548,10 @@ pdlp_settings: field_num: 31 type: bool optional: true + - barrier_adaptive_regularization: + field_num: 34 + type: int32 + optional: true - barrier_step_scale: # Step scale used by the barrier method primal/dual updates. Local-solve # binding restricts the range to [0.5, 0.9999] with default 0.9; see diff --git a/cpp/src/grpc/codegen/generated/cuopt_remote_data.proto b/cpp/src/grpc/codegen/generated/cuopt_remote_data.proto index 4b1e36d134..28bfb9b558 100644 --- a/cpp/src/grpc/codegen/generated/cuopt_remote_data.proto +++ b/cpp/src/grpc/codegen/generated/cuopt_remote_data.proto @@ -194,6 +194,7 @@ message PDLPSolverSettings { optional bool barrier_iterative_refinement = 31; optional double barrier_step_scale = 32; optional int32 postsolve_info = 33; + optional int32 barrier_adaptive_regularization = 34; PDLPWarmStartData warm_start_data = 50; } diff --git a/cpp/src/grpc/codegen/generated/generated_pdlp_settings_to_proto.inc b/cpp/src/grpc/codegen/generated/generated_pdlp_settings_to_proto.inc index eb88b192d9..1043d63fc7 100644 --- a/cpp/src/grpc/codegen/generated/generated_pdlp_settings_to_proto.inc +++ b/cpp/src/grpc/codegen/generated/generated_pdlp_settings_to_proto.inc @@ -34,6 +34,7 @@ pb_settings->set_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(); }