@@ -16,14 +16,15 @@ using namespace std;
1616
1717int PDLPSolver::GetIterationCount () const { return final_iter_count_; }
1818
19- void PDLPSolver::PreprocessLp (const HighsLp& original_lp,
20- HighsLp& processed_lp) {
19+ void PDLPSolver::PreprocessLp () {
2120 logger_.info (
2221 " Preprocessing LP using cupdlp formulation (slack variables for "
2322 " bounds)..." );
2423
25- int nRows_orig = original_lp.num_row_ ;
26- int nCols_orig = original_lp.num_col_ ;
24+ HighsLp& processed_lp = lp_;
25+
26+ int nRows_orig = original_lp_->num_row_ ;
27+ int nCols_orig = original_lp_->num_col_ ;
2728
2829 int num_new_cols = 0 ;
2930 int nEqs = 0 ;
@@ -32,11 +33,11 @@ void PDLPSolver::PreprocessLp(const HighsLp& original_lp,
3233
3334 // 1. First pass: Classify constraints and count slack variables needed
3435 for (int i = 0 ; i < nRows_orig; ++i) {
35- bool has_lower = original_lp. row_lower_ [i] > -kHighsInf ;
36- bool has_upper = original_lp. row_upper_ [i] < kHighsInf ;
36+ bool has_lower = original_lp_-> row_lower_ [i] > -kHighsInf ;
37+ bool has_upper = original_lp_-> row_upper_ [i] < kHighsInf ;
3738
3839 if (has_lower && has_upper) {
39- if (original_lp. row_lower_ [i] == original_lp. row_upper_ [i]) {
40+ if (original_lp_-> row_lower_ [i] == original_lp_-> row_upper_ [i]) {
4041 constraint_types_[i] = EQ;
4142 } else {
4243 constraint_types_[i] = BOUND;
@@ -67,17 +68,17 @@ void PDLPSolver::PreprocessLp(const HighsLp& original_lp,
6768
6869 // 4. Populate costs and bounds for original and new slack variables
6970 for (int i = 0 ; i < nCols_orig; ++i) {
70- processed_lp.col_cost_ [i] = original_lp. col_cost_ [i];
71- processed_lp.col_lower_ [i] = original_lp. col_lower_ [i];
72- processed_lp.col_upper_ [i] = original_lp. col_upper_ [i];
71+ processed_lp.col_cost_ [i] = original_lp_-> col_cost_ [i];
72+ processed_lp.col_lower_ [i] = original_lp_-> col_lower_ [i];
73+ processed_lp.col_upper_ [i] = original_lp_-> col_upper_ [i];
7374 }
7475
7576 int current_slack_col = nCols_orig;
7677 for (int i = 0 ; i < nRows_orig; ++i) {
7778 if (constraint_types_[i] == BOUND || constraint_types_[i] == FREE) {
7879 processed_lp.col_cost_ [current_slack_col] = 0.0 ;
79- processed_lp.col_lower_ [current_slack_col] = original_lp. row_lower_ [i];
80- processed_lp.col_upper_ [current_slack_col] = original_lp. row_upper_ [i];
80+ processed_lp.col_lower_ [current_slack_col] = original_lp_-> row_lower_ [i];
81+ processed_lp.col_upper_ [current_slack_col] = original_lp_-> row_upper_ [i];
8182 current_slack_col++;
8283 }
8384 }
@@ -86,7 +87,7 @@ void PDLPSolver::PreprocessLp(const HighsLp& original_lp,
8687 //
8788 // Take a copy of the original LP's constraint matrix since we
8889 // need it rowwise and it's const
89- HighsSparseMatrix original_matrix = original_lp. a_matrix_ ;
90+ HighsSparseMatrix original_matrix = original_lp_-> a_matrix_ ;
9091 original_matrix.ensureRowwise ();
9192 // Set up the processed constraint matrix as an empty row-wise
9293 // matrix that can have nCols_orig columns
@@ -133,16 +134,16 @@ void PDLPSolver::PreprocessLp(const HighsLp& original_lp,
133134 for (int i = 0 ; i < nRows_orig; ++i) {
134135 switch (constraint_types_[i]) {
135136 case EQ:
136- processed_lp.row_lower_ [i] = original_lp. row_lower_ [i];
137- processed_lp.row_upper_ [i] = original_lp. row_upper_ [i];
137+ processed_lp.row_lower_ [i] = original_lp_-> row_lower_ [i];
138+ processed_lp.row_upper_ [i] = original_lp_-> row_upper_ [i];
138139 break ;
139140 case GEQ:
140- processed_lp.row_lower_ [i] = original_lp. row_lower_ [i];
141+ processed_lp.row_lower_ [i] = original_lp_-> row_lower_ [i];
141142 processed_lp.row_upper_ [i] = kHighsInf ;
142143 break ;
143144 case LEQ:
144145 // Becomes -Ax >= -b
145- processed_lp.row_lower_ [i] = -original_lp. row_upper_ [i];
146+ processed_lp.row_lower_ [i] = -original_lp_-> row_upper_ [i];
146147 processed_lp.row_upper_ [i] = kHighsInf ;
147148 break ;
148149 case BOUND:
@@ -187,25 +188,25 @@ void PDLPSolver::Postsolve(const HighsLp& original_lp, HighsLp& processed_lp,
187188
188189 // 2. Resize solution object to original dimensions
189190 solution.col_value .resize (original_num_col_);
190- solution.row_value .resize (original_lp. num_row_ );
191+ solution.row_value .resize (original_lp_-> num_row_ );
191192 solution.col_dual .resize (original_num_col_);
192- solution.row_dual .resize (original_lp. num_row_ );
193+ solution.row_dual .resize (original_lp_-> num_row_ );
193194
194195 // 3. Recover Primal Column Values (x)
195196 // This is the easy part: just take the first 'original_num_col_' elements.
196197 for (int i = 0 ; i < original_num_col_; ++i) {
197198 solution.col_value [i] = x_unscaled[i];
198199 }
199200
200- double final_primal_objective = original_lp. offset_ ;
201+ double final_primal_objective = original_lp_-> offset_ ;
201202 for (int i = 0 ; i < original_num_col_; ++i) {
202- final_primal_objective += original_lp. col_cost_ [i] * solution.col_value [i];
203+ final_primal_objective += original_lp_-> col_cost_ [i] * solution.col_value [i];
203204 }
204205 results_.primal_obj = final_primal_objective;
205206
206207 // 4. Recover Dual Row Values (y)
207208 // This requires reversing the sign flip for LEQ constraints.
208- for (int i = 0 ; i < original_lp. num_row_ ; ++i) {
209+ for (int i = 0 ; i < original_lp_-> num_row_ ; ++i) {
209210 if (constraint_types_[i] == LEQ) {
210211 solution.row_dual [i] = -y_unscaled[i];
211212 } else {
@@ -235,7 +236,7 @@ void PDLPSolver::Postsolve(const HighsLp& original_lp, HighsLp& processed_lp,
235236 linalg::Ax (unscaled_processed_lp, x_unscaled, ax_unscaled);
236237
237238 int slack_variable_idx = original_num_col_;
238- for (int i = 0 ; i < original_lp. num_row_ ; ++i) {
239+ for (int i = 0 ; i < original_lp_-> num_row_ ; ++i) {
239240 if (constraint_types_[i] == BOUND || constraint_types_[i] == FREE) {
240241 solution.row_value [i] = x_unscaled[slack_variable_idx++];
241242 } else if (constraint_types_[i] == LEQ) {
@@ -948,3 +949,65 @@ HighsStatus PDLPSolver::PowerMethod(HighsLp& lp, double& op_norm_sq) {
948949 // If the method did not converge within max_iter
949950 return HighsStatus::kWarning ;
950951}
952+
953+ void PDLPSolver::setParams (const HighsOptions& options, HighsTimer& timer) {
954+ params_.initialise ();
955+ // params.eta = 0; Not set in parse_options_file
956+ // params.omega = 0; Not set in parse_options_file
957+ params_.tolerance = options.pdlp_optimality_tolerance ;
958+ if (options.kkt_tolerance != kDefaultKktTolerance ) {
959+ params_.tolerance = options.kkt_tolerance ;
960+ }
961+ params_.max_iterations = options.pdlp_iteration_limit ;
962+ params_.device_type = Device::CPU;
963+ // HiPDLP has its own timer, so set its time limit according to
964+ // the time remaining with respect to the HiGHS time limit (if
965+ // finite)
966+ double time_limit = options.time_limit ;
967+ if (time_limit < kHighsInf ) {
968+ time_limit -= timer.read ();
969+ time_limit = std::max (0.0 , time_limit);
970+ }
971+ params_.time_limit = time_limit;
972+
973+ params_.scaling_method = ScalingMethod::NONE;
974+ params_.use_ruiz_scaling = false ;
975+ params_.use_pc_scaling = false ;
976+ params_.use_l2_scaling = false ;
977+ if ((options.pdlp_features_off & kPdlpScalingOff ) == 0 ) {
978+ // Use scaling: now see which
979+ params_.use_ruiz_scaling = options.pdlp_scaling_mode & kPdlpScalingRuiz ;
980+ params_.use_pc_scaling = options.pdlp_scaling_mode & kPdlpScalingPC ;
981+ params_.use_l2_scaling = options.pdlp_scaling_mode & kPdlpScalingL2 ;
982+ }
983+ params_.ruiz_iterations = options.pdlp_ruiz_iterations ;
984+ // params_.ruiz_norm = INFINITY; Not set in parse_options_file
985+ // params_.pc_alpha = 1.0; Not set in parse_options_file
986+
987+ // Restart strategy maps 0/1/2 to RestartStrategy
988+ params_.restart_strategy = RestartStrategy::NO_RESTART;
989+ if ((options.pdlp_features_off & kPdlpRestartOff ) == 0 ) {
990+ // Use restart: now see which
991+ if (options.pdlp_restart_strategy == kPdlpRestartStrategyFixed ) {
992+ params_.restart_strategy = RestartStrategy::FIXED_RESTART;
993+ } else if (options.pdlp_restart_strategy == kPdlpRestartStrategyAdaptive ) {
994+ params_.restart_strategy = RestartStrategy::ADAPTIVE_RESTART;
995+ }
996+ }
997+ // params_.fixed_restart_interval = 0; Not set in parse_options_file
998+ // params_.use_halpern_restart = false; Not set in parse_options_file
999+
1000+ params_.step_size_strategy = StepSizeStrategy::FIXED;
1001+ if ((options.pdlp_features_off & kPdlpAdaptiveStepSizeOff ) == 0 ) {
1002+ // Use adaptive step size: now see which
1003+ if (options.pdlp_step_size_strategy == kPdlpStepSizeStrategyAdaptive ) {
1004+ params_.step_size_strategy = StepSizeStrategy::ADAPTIVE;
1005+ } else if (options.pdlp_step_size_strategy ==
1006+ kPdlpStepSizeStrategyMalitskyPock ) {
1007+ params_.step_size_strategy = StepSizeStrategy::MALITSKY_POCK;
1008+ }
1009+ }
1010+ // params_.malitsky_pock_params.initialise(); Not set in parse_options_file
1011+ // params_.adaptive_linesearch_params.initialise(); Not set in
1012+ // parse_options_file
1013+ }
0 commit comments