Skip to content

Commit d6ed4c1

Browse files
committed
Added (and rationalised) PDLP options, and using them to set up PrimalDualParams
1 parent 971ddf5 commit d6ed4c1

File tree

5 files changed

+174
-22
lines changed

5 files changed

+174
-22
lines changed

highs/highs_bindings.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,9 +1216,8 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) {
12161216
.def_readwrite("timeless_log", &HighsOptions::timeless_log)
12171217
.def_readwrite("ipm_optimality_tolerance", &HighsOptions::ipm_optimality_tolerance)
12181218
.def_readwrite("ipm_iteration_limit", &HighsOptions::ipm_iteration_limit)
1219-
.def_readwrite("pdlp_scaling", &HighsOptions::pdlp_scaling)
12201219
.def_readwrite("pdlp_iteration_limit", &HighsOptions::pdlp_iteration_limit)
1221-
.def_readwrite("pdlp_e_restart_method", &HighsOptions::pdlp_e_restart_method)
1220+
.def_readwrite("pdlp_cupdlpc_restart_method", &HighsOptions::pdlp_cupdlpc_restart_method)
12221221
.def_readwrite("pdlp_optimality_tolerance", &HighsOptions::pdlp_optimality_tolerance)
12231222
.def_readwrite("qp_iteration_limit", &HighsOptions::qp_iteration_limit)
12241223
.def_readwrite("qp_nullspace_limit", &HighsOptions::qp_nullspace_limit)

highs/lp_data/HConst.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,4 +364,39 @@ const int8_t kPivotUnit = 1;
364364
const int8_t kPivotRowSingleton = 2;
365365
const int8_t kPivotColSingleton = 3;
366366
const int8_t kPivotMarkowitz = 4;
367+
368+
// Mask for switching off PDLP features
369+
enum PdlpFeaturesOff {
370+
kPdlpAllFeaturesOn = 0,
371+
kPdlpScalingOff = 1,
372+
kPdlpRestartOff = 2,
373+
kPdlpAdaptiveStepSizeOff = 4,
374+
kPdlpAllFeaturesOff =
375+
kPdlpScalingOff + kPdlpRestartOff + kPdlpAdaptiveStepSizeOff
376+
};
377+
378+
enum PdlpScalingBit {
379+
kPdlpScalingMin = 0,
380+
kPdlpScalingRuiz = 1,
381+
kPdlpScalingL2 = 2,
382+
kPdlpScalingPC = 4,
383+
kPdlpScalingMax = kPdlpScalingRuiz + kPdlpScalingL2 + kPdlpScalingPC
384+
};
385+
386+
enum PdlpStepSizeStrategy {
387+
kPdlpStepSizeStrategyFixed = 0,
388+
kPdlpStepSizeStrategyMin = kPdlpStepSizeStrategyFixed,
389+
kPdlpStepSizeStrategyAdaptive,
390+
kPdlpStepSizeStrategyMalitskyPock,
391+
kPdlpStepSizeStrategyMax = kPdlpStepSizeStrategyMalitskyPock
392+
};
393+
394+
enum PdlpRestartStrategy {
395+
kPdlpRestartStrategyOff = 0,
396+
kPdlpRestartStrategyMin = kPdlpRestartStrategyOff,
397+
kPdlpRestartStrategyFixed,
398+
kPdlpRestartStrategyAdaptive,
399+
kPdlpRestartStrategyMax = kPdlpRestartStrategyAdaptive
400+
};
401+
367402
#endif /* LP_DATA_HCONST_H_ */

highs/lp_data/HighsOptions.h

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -369,9 +369,13 @@ struct HighsOptionsStruct {
369369
std::string hipo_system;
370370

371371
// Options for PDLP solver
372-
bool pdlp_scaling;
372+
HighsInt pdlp_features_off;
373373
HighsInt pdlp_iteration_limit;
374-
HighsInt pdlp_e_restart_method;
374+
HighsInt pdlp_scaling_mode;
375+
HighsInt pdlp_ruiz_iterations;
376+
HighsInt pdlp_restart_strategy;
377+
HighsInt pdlp_cupdlpc_restart_method;
378+
HighsInt pdlp_step_size_strategy;
375379
double pdlp_optimality_tolerance;
376380

377381
// Options for QP solver
@@ -536,9 +540,13 @@ struct HighsOptionsStruct {
536540
ipm_optimality_tolerance(0.0),
537541
ipm_iteration_limit(0),
538542
hipo_system(""),
539-
pdlp_scaling(false),
543+
pdlp_features_off(0),
540544
pdlp_iteration_limit(0),
541-
pdlp_e_restart_method(0),
545+
pdlp_scaling_mode(0),
546+
pdlp_ruiz_iterations(0),
547+
pdlp_restart_strategy(0),
548+
pdlp_cupdlpc_restart_method(0),
549+
pdlp_step_size_strategy(0),
542550
pdlp_optimality_tolerance(0.0),
543551
qp_iteration_limit(0),
544552
qp_nullspace_limit(0),
@@ -1260,20 +1268,48 @@ class HighsOptions : public HighsOptionsStruct {
12601268
advanced, &hipo_system, kHighsChooseString);
12611269
records.push_back(record_string);
12621270

1263-
record_bool = new OptionRecordBool(
1264-
"pdlp_scaling", "Scaling option for PDLP solver: Default = true",
1265-
advanced, &pdlp_scaling, true);
1266-
records.push_back(record_bool);
1271+
record_int = new OptionRecordInt(
1272+
"pdlp_features_off",
1273+
"Mask for switching PDLP features off: 1 => Scaling; 2 => Restart; 4 "
1274+
"=> AdaptiveStepSize",
1275+
advanced, &pdlp_features_off, kPdlpAllFeaturesOn, kPdlpAllFeaturesOn,
1276+
kPdlpAllFeaturesOff);
1277+
records.push_back(record_int);
12671278

12681279
record_int = new OptionRecordInt(
12691280
"pdlp_iteration_limit", "Iteration limit for PDLP solver", advanced,
12701281
&pdlp_iteration_limit, 0, kHighsIInf, kHighsIInf);
12711282
records.push_back(record_int);
12721283

1273-
record_int = new OptionRecordInt("pdlp_e_restart_method",
1274-
"Restart mode for PDLP solver: 0 => none; "
1284+
record_int = new OptionRecordInt("pdlp_scaling_mode",
1285+
"Scaling mode for PDLP solver (default = "
1286+
"5): 1 => Ruiz; 2 => L2; 4 => PC",
1287+
advanced, &pdlp_scaling_mode, kPdlpScalingMin, kPdlpScalingRuiz+kPdlpScalingPC, kPdlpStepSizeStrategyMax);
1288+
records.push_back(record_int);
1289+
1290+
record_int = new OptionRecordInt("pdlp_ruiz_iterations",
1291+
"Number of Ruiz scaling iteraitons for PDLP solver",
1292+
advanced, &pdlp_ruiz_iterations, 0, 10, kHighsIInf);
1293+
records.push_back(record_int);
1294+
1295+
record_int = new OptionRecordInt("pdlp_restart_strategy",
1296+
"Restart strategy for PDLP solver: 0 => off; "
1297+
"1 => fixed; 2 => adaptive",
1298+
advanced, &pdlp_restart_strategy,
1299+
kPdlpRestartStrategyMin, kPdlpRestartStrategyOff, kPdlpRestartStrategyMax);
1300+
records.push_back(record_int);
1301+
1302+
record_int = new OptionRecordInt("pdlp_cupdlpc_restart_method",
1303+
"Restart mode for cuPDLP-C solver: 0 => none; "
12751304
"1 => GPU (default); 2 => CPU ",
1276-
advanced, &pdlp_e_restart_method, 0, 1, 2);
1305+
advanced, &pdlp_cupdlpc_restart_method, 0, 1, 2);
1306+
records.push_back(record_int);
1307+
1308+
record_int = new OptionRecordInt("pdlp_step_size_strategy",
1309+
"Step size strategy for PDLP solver: 0 => fixed; "
1310+
"1 => adaptive; 2 => Malitsky-Pock",
1311+
advanced, &pdlp_step_size_strategy,
1312+
kPdlpStepSizeStrategyMin, kPdlpStepSizeStrategyFixed, kPdlpRestartStrategyMax);
12771313
records.push_back(record_int);
12781314

12791315
record_double = new OptionRecordDouble(

highs/pdlp/CupdlpWrapper.cpp

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ HighsStatus solveLpCupdlp(const HighsOptions& options, HighsTimer& timer,
109109
// H_Init_Scaling(local_log_level, scaling, nCols, nRows, cost, rhs);
110110
Init_Scaling(local_log_level, scaling, nCols, nRows, cost, rhs);
111111

112-
cupdlp_int ifScaling = 1;
112+
cupdlp_int ifScaling = intParam[IF_SCALING];
113113

114114
CUPDLPwork* w = cupdlp_NULL;
115115
cupdlp_init_work(w, 1);
@@ -647,7 +647,25 @@ void getUserParamsFromOptions(const HighsOptions& options, HighsTimer& timer,
647647
intParam[N_LOG_LEVEL] = getCupdlpLogLevel(options);
648648
//
649649
ifChangeIntParam[IF_SCALING] = true;
650-
intParam[IF_SCALING] = options.pdlp_scaling ? 1 : 0;
650+
cupdlp_int scaling_on =
651+
(options.pdlp_features_off & kPdlpScalingOff) == 0 ? 1 : 0;
652+
intParam[IF_SCALING] = scaling_on;
653+
if (scaling_on == 0)
654+
highsLogUser(options.log_options, HighsLogType::kInfo,
655+
"PDLP: Scaling off\n");
656+
//
657+
ifChangeIntParam[E_LINE_SEARCH_METHOD] = true;
658+
cupdlp_int adaptive_lineasearch =
659+
(options.pdlp_features_off & kPdlpAdaptiveStepSizeOff) == 0 ? 1 : 0;
660+
intParam[E_LINE_SEARCH_METHOD] = adaptive_lineasearch;
661+
if (adaptive_lineasearch == 1) {
662+
intParam[E_LINE_SEARCH_METHOD] = PDHG_ADAPTIVE_LINESEARCH;
663+
} else {
664+
intParam[E_LINE_SEARCH_METHOD] = PDHG_FIXED_LINESEARCH;
665+
}
666+
if (adaptive_lineasearch == 0)
667+
highsLogUser(options.log_options, HighsLogType::kInfo,
668+
"PDLP: Adaptive line search off\n");
651669
//
652670
ifChangeFloatParam[D_PRIMAL_TOL] = true;
653671
floatParam[D_PRIMAL_TOL] = options.primal_feasibility_tolerance;
@@ -676,7 +694,13 @@ void getUserParamsFromOptions(const HighsOptions& options, HighsTimer& timer,
676694
floatParam[D_TIME_LIM] = options.time_limit;
677695
//
678696
ifChangeIntParam[E_RESTART_METHOD] = true;
679-
intParam[E_RESTART_METHOD] = int(options.pdlp_e_restart_method);
697+
cupdlp_int restart_on =
698+
(options.pdlp_features_off & kPdlpRestartOff) == 0 ? 1 : 0;
699+
if (options.pdlp_cupdlpc_restart_method == 0) restart_on = 0;
700+
intParam[E_RESTART_METHOD] = restart_on;
701+
if (restart_on == 0)
702+
highsLogUser(options.log_options, HighsLogType::kInfo,
703+
"PDLP: Restart off\n");
680704
}
681705

682706
void analysePdlpSolution(const HighsOptions& options, const HighsLp& lp,

highs/pdlp/HiPdlpWrapper.cpp

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#include "pdlp/hipdlp/pdhg.hpp"
1515
#include "pdlp/hipdlp/restart.hpp"
1616

17-
void getHiPpdlpParamsFromOptions(const HighsOptions& options, PrimalDualParams& params);
17+
void getHiPpdlpParamsFromOptions(const HighsOptions& options, HighsTimer& timer, PrimalDualParams& params);
1818

1919
HighsStatus solveLpHiPdlp(HighsLpSolverObject& solver_object) {
2020
return solveLpHiPdlp(solver_object.options_, solver_object.timer_,
@@ -42,7 +42,7 @@ HighsStatus solveLpHiPdlp(const HighsOptions& options, HighsTimer& timer,
4242
// --- Initialize Parameters with Defaults ---
4343
PrimalDualParams params{};
4444

45-
getHiPpdlpParamsFromOptions(options, params);
45+
getHiPpdlpParamsFromOptions(options, timer, params);
4646
std::vector<double> x, y;
4747
PDLPSolver pdlp(logger);
4848

@@ -54,14 +54,72 @@ HighsStatus solveLpHiPdlp(const HighsOptions& options, HighsTimer& timer,
5454
return HighsStatus::kError;
5555
}
5656

57-
void getHiPpdlpParamsFromOptions(const HighsOptions& options, PrimalDualParams& params) {
57+
void getHiPpdlpParamsFromOptions(const HighsOptions& options, HighsTimer& timer, PrimalDualParams& params) {
5858
params.initialise();
59-
params.tolerance = 1e-4;
60-
params.max_iterations = 40000;
59+
// params.eta = 0; Not set in parse_options_file
60+
// params.omega = 0; Not set in parse_opions_file
61+
//
62+
// Is params.tolerance for primal and dual feasibility, and
63+
// optimality?
64+
params.tolerance = options.pdlp_optimality_tolerance;
65+
if (options.kkt_tolerance != kDefaultKktTolerance) {
66+
params.tolerance = options.kkt_tolerance;
67+
}
68+
params.max_iterations = options.pdlp_iteration_limit;
69+
params.device_type = Device::CPU;
70+
// HiPDLP has its own timer, so set its time limit according to
71+
// the time remaining with respect to the HiGHS time limit (if
72+
// finite)
73+
double time_limit = options.time_limit;
74+
if (time_limit < kHighsInf) {
75+
time_limit -= timer.read();
76+
time_limit = std::max(0.0, time_limit);
77+
}
78+
params.time_limit = time_limit;
79+
80+
params.scaling_method = ScalingMethod::NONE;
81+
params.use_ruiz_scaling = false;
82+
params.use_pc_scaling = false;
83+
params.use_l2_scaling = false;
84+
if ((options.pdlp_features_off & kPdlpScalingOff) == 0) {
85+
// Use scaling: now see which
86+
params.use_ruiz_scaling = options.pdlp_scaling_mode & kPdlpScalingRuiz;
87+
params.use_pc_scaling = options.pdlp_scaling_mode & kPdlpScalingPC;
88+
params.use_l2_scaling = options.pdlp_scaling_mode & kPdlpScalingL2;
89+
}
90+
params.ruiz_iterations = options.pdlp_ruiz_iterations;
91+
// params.ruiz_norm = INFINITY; Not set in parse_opions_file
92+
// params.pc_alpha = 1.0; Not set in parse_opions_file
93+
94+
// Restart strategy maps 0/1/2 to RestartStrategy
95+
params.restart_strategy = RestartStrategy::NO_RESTART;
96+
if ((options.pdlp_features_off & kPdlpRestartOff) == 0) {
97+
// Use restart: now see which
98+
if (options.pdlp_restart_strategy == kPdlpRestartStrategyFixed) {
99+
params.restart_strategy = RestartStrategy::FIXED_RESTART;
100+
} else if (options.pdlp_restart_strategy == kPdlpRestartStrategyAdaptive) {
101+
params.restart_strategy = RestartStrategy::ADAPTIVE_RESTART;
102+
}
103+
}
104+
// params.fixed_restart_interval = 0; Not set in parse_opions_file
105+
// params.use_halpern_restart = false; Not set in parse_opions_file
106+
107+
params.step_size_strategy = StepSizeStrategy::FIXED;
108+
if ((options.pdlp_features_off & kPdlpAdaptiveStepSizeOff) == 0) {
109+
// Use adaptive step size: now see which
110+
if (options.pdlp_step_size_strategy == kPdlpStepSizeStrategyAdaptive) {
111+
params.step_size_strategy = StepSizeStrategy::ADAPTIVE;
112+
} else if (options.pdlp_step_size_strategy == kPdlpStepSizeStrategyMalitskyPock) {
113+
params.step_size_strategy = StepSizeStrategy::MALITSKY_POCK;
114+
}
115+
}
116+
// params.malitsky_pock_params.initialise(); Not set in parse_opions_file
117+
// params.adaptive_linesearch_params.initialise(); Not set in parse_opions_file
118+
61119
}
62120

63121
void PrimalDualParams::initialise() {
64-
this->eta = 0 ;
122+
this->eta = 0;
65123
this->omega = 0;
66124
this->tolerance = 0;
67125
this->max_iterations = 0;

0 commit comments

Comments
 (0)