Skip to content

Commit 40b3bcb

Browse files
committed
Make iterative refinement options as ENUM & ND level as a hyperparameters
Signed-off-by: yuwenchen95 <yuwchen@nvidia.com>
1 parent 85d25c9 commit 40b3bcb

18 files changed

Lines changed: 126 additions & 163 deletions

File tree

cpp/include/cuopt/mathematical_optimization/constants.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,10 @@
5050
#define CUOPT_POSTSOLVE_INFO "postsolve_info"
5151
#define CUOPT_BARRIER_PRESOLVE_BOUND_FREE_VARIABLES "barrier_presolve_bound_free_variables"
5252
#define CUOPT_BARRIER_ITERATIVE_REFINEMENT "barrier_iterative_refinement"
53-
#define CUOPT_BARRIER_ITERATIVE_REFINEMENT_METHOD "barrier_iterative_refinement_method"
5453
#define CUOPT_BARRIER_STEP_SCALE "barrier_step_scale"
5554
#define CUOPT_ELIMINATE_DENSE_COLUMNS "eliminate_dense_columns"
5655
#define CUOPT_CUDSS_DETERMINISTIC "cudss_deterministic"
57-
#define CUOPT_CUDSS_ND_NLEVELS "cudss_nd_nlevels"
56+
#define CUOPT_CUDSS_HYPER_ND_NLEVELS "cudss_hyper_nd_nlevels"
5857
#define CUOPT_PRESOLVE "presolve"
5958
#define CUOPT_MIP_PROBING "mip_probing"
6059
#define CUOPT_DUAL_POSTSOLVE "dual_postsolve"
@@ -240,8 +239,10 @@
240239
#define CUOPT_MIP_SCALING_ON 1
241240
#define CUOPT_MIP_SCALING_NO_OBJECTIVE 2
242241

243-
#define CUOPT_BARRIER_ITERATIVE_REFINEMENT_OFF 0
244-
#define CUOPT_BARRIER_ITERATIVE_REFINEMENT_ON 1
242+
/* @brief Iterative refinement for barrier method */
243+
#define CUOPT_BARRIER_IR_OFF 0
244+
#define CUOPT_BARRIER_IR_GMRES 1
245+
#define CUOPT_BARRIER_IR_FIXED_POINT 2
245246

246247
/* @brief Scalar problem attribute selectors
247248
* Passed as cuopt_int_t; the valid set depends on the accessor's value type. */

cpp/include/cuopt/mathematical_optimization/pdlp/solver_settings.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,8 @@ class pdlp_solver_settings_t {
304304
i_t qcqp_ruiz_equilibration{-1};
305305
bool eliminate_dense_columns{true};
306306
pdlp_precision_t pdlp_precision{pdlp_precision_t::DefaultPrecision};
307-
bool barrier_iterative_refinement{true};
308-
i_t barrier_iterative_refinement_method{1}; // 0: fixed_point, 1: gmres (default)
307+
// Iterative refinement for barrier method: 0: off, 1: gmres (default), 2: fixed_point
308+
i_t barrier_iterative_refinement{barrier_iterative_refinement_t::GMRES};
309309
i_t barrier_soc_threshold{100};
310310
f_t barrier_step_scale{0.9};
311311
bool save_best_primal_so_far{false};

cpp/include/cuopt/mathematical_optimization/utilities/internals.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,5 +142,19 @@ enum presolver_t : int {
142142
PSLP = CUOPT_PRESOLVE_PSLP
143143
};
144144

145+
/**
146+
* @brief Enum representing the iterative refinement method used by the barrier
147+
* solver after each solve.
148+
*
149+
* Off: Disable iterative refinement.
150+
* GMRES: Use restarted GMRES (default).
151+
* FixedPoint: Use a fixed-point residual-correction loop.
152+
*/
153+
enum barrier_iterative_refinement_t : int {
154+
Off = CUOPT_BARRIER_IR_OFF,
155+
GMRES = CUOPT_BARRIER_IR_GMRES,
156+
FixedPoint = CUOPT_BARRIER_IR_FIXED_POINT
157+
};
158+
145159
} // namespace mathematical_optimization
146160
} // namespace cuopt

cpp/src/barrier/barrier.cu

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2278,10 +2278,13 @@ int barrier_solver_t<i_t, f_t>::initial_point(iteration_data_t<i_t, f_t>& data)
22782278
}
22792279
} op(data);
22802280

2281-
if (settings.barrier_iterative_refinement) {
2281+
if (settings.barrier_iterative_refinement != barrier_iterative_refinement_t::Off) {
22822282
const f_t ir_tol = data.has_sparse_cones() ? f_t(1e-12) : f_t(1e-8);
2283-
iterative_refinement<i_t, f_t, op_t>(
2284-
op, rhs, soln, ir_tol, settings.barrier_iterative_refinement_method);
2283+
2284+
const i_t internal_method =
2285+
(settings.barrier_iterative_refinement == barrier_iterative_refinement_t::FixedPoint) ? 0
2286+
: 1;
2287+
iterative_refinement<i_t, f_t, op_t>(op, rhs, soln, ir_tol, internal_method);
22852288
}
22862289

22872290
for (i_t k = 0; k < lp.num_cols; k++) {
@@ -2904,15 +2907,15 @@ i_t barrier_solver_t<i_t, f_t>::gpu_compute_search_direction(iteration_data_t<i_
29042907
data_.chol->solve(b, x);
29052908
}
29062909
} op(data);
2907-
if (settings.barrier_iterative_refinement) {
2910+
if (settings.barrier_iterative_refinement != barrier_iterative_refinement_t::Off) {
29082911
raft::common::nvtx::range fun_scope("Barrier: iterative_refinement");
29092912
const f_t ir_tol = data.has_sparse_cones() ? f_t(1e-12) : f_t(1e-8);
2910-
const f_t solve_err =
2911-
iterative_refinement<i_t, f_t, op_t>(op,
2912-
data.d_augmented_rhs_,
2913-
data.d_augmented_soln_,
2914-
ir_tol,
2915-
settings.barrier_iterative_refinement_method);
2913+
2914+
const i_t internal_method =
2915+
(settings.barrier_iterative_refinement == barrier_iterative_refinement_t::FixedPoint) ? 0
2916+
: 1;
2917+
const f_t solve_err = iterative_refinement<i_t, f_t, op_t>(
2918+
op, data.d_augmented_rhs_, data.d_augmented_soln_, ir_tol, internal_method);
29162919
if (solve_err > 1e-1) {
29172920
settings.log.printf("|| Aug (dx, dy) - aug_rhs || %e after IR\n", solve_err);
29182921
}
@@ -2982,7 +2985,8 @@ i_t barrier_solver_t<i_t, f_t>::gpu_compute_search_direction(iteration_data_t<i_
29822985
// GMRES can handle large, potentially ill-conditioned systems better than simple Richardson
29832986
// or classical iterative refinement, at the potential cost of higher computational work and
29842987
// memory. This is only used on the pure Schur-complement (n_dense_columns == 0).
2985-
if (settings.barrier_iterative_refinement && data.n_dense_columns == 0) {
2988+
if (settings.barrier_iterative_refinement != barrier_iterative_refinement_t::Off &&
2989+
data.n_dense_columns == 0) {
29862990
struct adat_op_t {
29872991
adat_op_t(iteration_data_t<i_t, f_t>& data) : data_(data) {}
29882992
iteration_data_t<i_t, f_t>& data_;
@@ -2998,8 +3002,12 @@ i_t barrier_solver_t<i_t, f_t>::gpu_compute_search_direction(iteration_data_t<i_
29983002
data_.gpu_solve_adat(b, x);
29993003
}
30003004
} adat_op(data);
3005+
3006+
const i_t internal_method =
3007+
(settings.barrier_iterative_refinement == barrier_iterative_refinement_t::FixedPoint) ? 0
3008+
: 1;
30013009
const f_t adat_solve_err = iterative_refinement<i_t, f_t, adat_op_t>(
3002-
adat_op, data.d_h_, data.d_dy_, f_t(1e-8), settings.barrier_iterative_refinement_method);
3010+
adat_op, data.d_h_, data.d_dy_, f_t(1e-8), internal_method);
30033011
if (adat_solve_err > 1e-1) {
30043012
settings.log.printf("||ADAT*dy - h|| %e after IR\n", adat_solve_err);
30053013
}

cpp/src/barrier/iterative_refinement.hpp

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -362,11 +362,8 @@ f_t iterative_refinement_gmres(T& op,
362362
}
363363

364364
template <typename i_t, typename f_t, typename T>
365-
f_t iterative_refinement(T& op,
366-
const dense_vector_t<i_t, f_t>& b,
367-
dense_vector_t<i_t, f_t>& x,
368-
f_t tol = 1e-8,
369-
i_t method = 1)
365+
f_t iterative_refinement(
366+
T& op, const dense_vector_t<i_t, f_t>& b, dense_vector_t<i_t, f_t>& x, f_t tol, i_t method)
370367
{
371368
rmm::device_uvector<f_t> d_b(b.size(), op.data_.handle_ptr->get_stream());
372369
raft::copy(d_b.data(), b.data(), b.size(), op.data_.handle_ptr->get_stream());
@@ -382,11 +379,8 @@ f_t iterative_refinement(T& op,
382379
}
383380

384381
template <typename i_t, typename f_t, typename T>
385-
f_t iterative_refinement(T& op,
386-
const rmm::device_uvector<f_t>& b,
387-
rmm::device_uvector<f_t>& x,
388-
f_t tol = 1e-8,
389-
i_t method = 1)
382+
f_t iterative_refinement(
383+
T& op, const rmm::device_uvector<f_t>& b, rmm::device_uvector<f_t>& x, f_t tol, i_t method)
390384
{
391385
return (method == 0) ? iterative_refinement_fixed_point<i_t, f_t, T>(op, b, x, tol)
392386
: iterative_refinement_gmres<i_t, f_t, T>(op, b, x, tol);

cpp/src/dual_simplex/simplex_solver_settings.hpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include <cuopt/mathematical_optimization/mip/diving_hyper_params.hpp>
1111
#include <cuopt/mathematical_optimization/mip/submip_hyper_params.hpp>
12+
#include <cuopt/mathematical_optimization/utilities/internals.hpp>
1213

1314
#include <dual_simplex/logger.hpp>
1415
#include <math_optimization/types.hpp>
@@ -70,8 +71,7 @@ struct simplex_solver_settings_t {
7071
deterministic(false),
7172
barrier(false),
7273
eliminate_dense_columns(true),
73-
barrier_iterative_refinement(true),
74-
barrier_iterative_refinement_method(1),
74+
barrier_iterative_refinement(barrier_iterative_refinement_t::GMRES),
7575
barrier_step_scale(0.9),
7676
barrier_soc_threshold(100),
7777
num_gpus(1),
@@ -166,11 +166,10 @@ struct simplex_solver_settings_t {
166166
i_t cudss_nd_nlevels; // -1 automatic/unset, else METIS nested-dissection depth for cuDSS
167167
bool barrier; // true to use barrier method, false to use dual simplex method
168168
bool deterministic; // true to use B&B deterministic mode, false to use non-deterministic mode
169-
bool eliminate_dense_columns; // true to eliminate dense columns from A*D*A^T
170-
bool barrier_iterative_refinement; // true to use iterative refinement for barrier method
171-
i_t barrier_iterative_refinement_method; // 0: fixed_point, 1: gmres
172-
f_t barrier_step_scale; // step scale for barrier method
173-
i_t barrier_soc_threshold; // SOC dimension above which rank-2 sparse scaling is used
169+
bool eliminate_dense_columns; // true to eliminate dense columns from A*D*A^T
170+
i_t barrier_iterative_refinement; // 0: off, 1: gmres (default), 2: fixed_point
171+
f_t barrier_step_scale; // step scale for barrier method
172+
i_t barrier_soc_threshold; // SOC dimension above which rank-2 sparse scaling is used
174173
int num_gpus; // Number of GPUs to use (maximum of 2 gpus are supported at the moment)
175174
i_t folding; // -1 automatic, 0 don't fold, 1 fold
176175
i_t augmented; // -1 automatic, 0 to solve with ADAT, 1 to solve with augmented system

cpp/src/grpc/codegen/field_registry.yaml

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -496,8 +496,7 @@ pdlp_settings:
496496
- dual_postsolve:
497497
# C++ default is `true`; using proto3 `optional` so that a client that
498498
# omits this field gets the solver default rather than the proto3 zero
499-
# (`false`). See also the matching `optional` markers on
500-
# `barrier_iterative_refinement` (pdlp) and `probing` (mip).
499+
# (`false`). See also the matching `optional` marker on `probing` (mip).
501500
field_num: 17
502501
type: bool
503502
optional: true
@@ -539,15 +538,6 @@ pdlp_settings:
539538
field_num: 27
540539
type: bool
541540
optional: true
542-
- barrier_iterative_refinement:
543-
# Whether the barrier method runs iterative refinement after each solve
544-
# (see cpp/src/barrier/barrier.cu). C++ default is `true`. Declared as
545-
# proto3 `optional` so that a client which omits this field preserves
546-
# the solver default; without `optional`, the proto3 wire zero (`false`)
547-
# would silently overwrite the C++ default.
548-
field_num: 31
549-
type: bool
550-
optional: true
551541
- barrier_step_scale:
552542
# Step scale used by the barrier method primal/dual updates. Local-solve
553543
# binding restricts the range to [0.5, 0.9999] with default 0.9; see
@@ -565,7 +555,10 @@ pdlp_settings:
565555
optional: true
566556
# field_num 35-37 previously used by cudss_hybrid_mode/cudss_hybrid_execute_mode/
567557
# cudss_host_nthreads, removed — do not reuse these numbers.
568-
- barrier_iterative_refinement_method:
558+
# field_num 31 previously held `barrier_iterative_refinement` as a bool; that field
559+
# was retired and the name reused below (field_num 38) for the merged int method,
560+
# so the exposed parameter name is unchanged even though the wire field_num moved.
561+
- barrier_iterative_refinement:
569562
field_num: 38
570563
type: int32
571564
optional: true
@@ -736,8 +729,7 @@ mip_settings:
736729
# C++ default is `true`; declared as proto3 `optional` so that a client
737730
# which omits this field preserves the solver default. Without
738731
# `optional`, the proto3 wire zero (`false`) would silently overwrite
739-
# the C++ default. See also `dual_postsolve` and
740-
# `barrier_iterative_refinement` in pdlp_settings.
732+
# the C++ default. See also `dual_postsolve` in pdlp_settings.
741733
field_num: 29
742734
type: bool
743735
optional: true

cpp/src/grpc/codegen/generated/cuopt_remote_data.proto

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,10 @@ message PDLPSolverSettings {
191191
bool save_best_primal_so_far = 28;
192192
bool first_primal_feasible = 29;
193193
optional int32 pdlp_precision = 30;
194-
optional bool barrier_iterative_refinement = 31;
195194
optional double barrier_step_scale = 32;
196195
optional int32 postsolve_info = 33;
197196
optional int32 cudss_nd_nlevels = 34;
198-
optional int32 barrier_iterative_refinement_method = 38;
197+
optional int32 barrier_iterative_refinement = 38;
199198
PDLPWarmStartData warm_start_data = 50;
200199
}
201200

cpp/src/grpc/codegen/generated/generated_pdlp_settings_to_proto.inc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,10 @@
3333
pb_settings->set_ordering(settings.ordering);
3434
pb_settings->set_barrier_dual_initial_point(settings.barrier_dual_initial_point);
3535
pb_settings->set_eliminate_dense_columns(settings.eliminate_dense_columns);
36-
pb_settings->set_barrier_iterative_refinement(settings.barrier_iterative_refinement);
3736
pb_settings->set_barrier_step_scale(settings.barrier_step_scale);
3837
pb_settings->set_postsolve_info(settings.postsolve_info);
3938
pb_settings->set_cudss_nd_nlevels(settings.cudss_nd_nlevels);
40-
pb_settings->set_barrier_iterative_refinement_method(settings.barrier_iterative_refinement_method);
39+
pb_settings->set_barrier_iterative_refinement(settings.barrier_iterative_refinement);
4140
pb_settings->set_save_best_primal_so_far(settings.save_best_primal_so_far);
4241
pb_settings->set_first_primal_feasible(settings.first_primal_feasible);
4342
pb_settings->set_pdlp_precision(static_cast<int32_t>(settings.pdlp_precision));

cpp/src/grpc/codegen/generated/generated_proto_to_pdlp_settings.inc

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,6 @@
7373
if (pb_settings.has_eliminate_dense_columns()) {
7474
settings.eliminate_dense_columns = pb_settings.eliminate_dense_columns();
7575
}
76-
if (pb_settings.has_barrier_iterative_refinement()) {
77-
settings.barrier_iterative_refinement = pb_settings.barrier_iterative_refinement();
78-
}
7976
if (pb_settings.has_barrier_step_scale()) {
8077
settings.barrier_step_scale = pb_settings.barrier_step_scale();
8178
}
@@ -85,8 +82,8 @@
8582
if (pb_settings.has_cudss_nd_nlevels()) {
8683
settings.cudss_nd_nlevels = pb_settings.cudss_nd_nlevels();
8784
}
88-
if (pb_settings.has_barrier_iterative_refinement_method()) {
89-
settings.barrier_iterative_refinement_method = pb_settings.barrier_iterative_refinement_method();
85+
if (pb_settings.has_barrier_iterative_refinement()) {
86+
settings.barrier_iterative_refinement = pb_settings.barrier_iterative_refinement();
9087
}
9188
settings.save_best_primal_so_far = pb_settings.save_best_primal_so_far();
9289
settings.first_primal_feasible = pb_settings.first_primal_feasible();

0 commit comments

Comments
 (0)