@@ -343,19 +343,15 @@ PostSolveRetcode PDLPSolver::postprocess(HighsSolution& solution) {
343343
344344void PDLPSolver::solve (std::vector<double >& x, std::vector<double >& y) {
345345 Timer solver_timer;
346-
347346 const HighsLp& lp = lp_;
348347
349348 debug_pdlp_log_file_ = fopen (" HiPDLP.log" , " w" );
350349 assert (debug_pdlp_log_file_);
351350
352351 // --- 0. Using PowerMethod to estimate the largest eigenvalue ---
353- const double op_norm_sq = PowerMethod ();
354- stepsize_ =
355- InitializeStepSizesPowerMethod (op_norm_sq);
356- const double fixed_eta = 0.99 / sqrt (op_norm_sq);
352+ InitializeStepSizes ();
353+
357354 PrimalDualParams working_params = params_;
358-
359355 working_params.omega = std::sqrt (stepsize_.dual_step / stepsize_.primal_step );
360356 working_params.eta = std::sqrt (stepsize_.primal_step * stepsize_.dual_step );
361357 current_eta_ = working_params.eta ;
@@ -386,7 +382,7 @@ void PDLPSolver::solve(std::vector<double>& x, std::vector<double>& y) {
386382 ratio_last_two_step_sizes_ = 1.0 ;
387383 bool using_malitsky_averaging =
388384 (params_.step_size_strategy == StepSizeStrategy::MALITSKY_POCK);
389- bool primal_average_initialized = false ;
385+ bool primal_average_initialized = false ;
390386
391387 // Initialize vectors for matrix-vector products
392388 std::vector<double > Ax_avg (lp.num_row_ , 0.0 );
@@ -534,7 +530,7 @@ void PDLPSolver::solve(std::vector<double>& x, std::vector<double>& y) {
534530 break ;
535531
536532 case StepSizeStrategy::ADAPTIVE:
537- UpdateIteratesAdaptive (iter );
533+ UpdateIteratesAdaptive ();
538534 break ;
539535
540536 case StepSizeStrategy::MALITSKY_POCK:
@@ -1170,62 +1166,101 @@ void AdaptiveLinesearchParams::initialise() {
11701166// SECTION 4: Step Update Methods (from step.cc)
11711167// =============================================================================
11721168
1173- StepSizeConfig PDLPSolver::InitializeStepSizesPowerMethod (double op_norm_sq) {
1174- StepSizeConfig config;
1175- config.power_method_lambda = op_norm_sq;
1176- double cost_norm = linalg::compute_cost_norm (lp_, 2.0 );
1177- double rhs_norm = linalg::compute_rhs_norm (lp_, 2.0 );
1169+ void PDLPSolver::InitializeStepSizes () {
1170+ double cost_norm_sq = linalg::vector_norm_squared (lp_.col_cost_ );
1171+ double rhs_norm_sq = linalg::vector_norm_squared (lp_.row_lower_ );
11781172
1179- highsLogUser (params_.log_options_ , HighsLogType::kInfo ,
1180- " Cost norm: %g, RHS norm: %g\n " , cost_norm, rhs_norm);
1181- config.beta = cost_norm * cost_norm / (rhs_norm * rhs_norm + 1e-10 );
1182-
1183- const double safety_factor = 0.8 ;
1184- double base_step = safety_factor / std::sqrt (op_norm_sq);
1173+ if (std::min (cost_norm_sq, rhs_norm_sq) > 1e-6 ) {
1174+ stepsize_.beta = cost_norm_sq / rhs_norm_sq;
1175+ } else {
1176+ stepsize_.beta = 1.0 ;
1177+ }
11851178
1186- config.primal_step = base_step / std::sqrt (config.beta );
1187- config.dual_step = base_step * std::sqrt (config.beta );
1188- return config;
1179+ // Initialize step sizes based on strategy
1180+ if (params_.step_size_strategy == StepSizeStrategy::FIXED) {
1181+ // Use power method for fixed step size
1182+ const double op_norm_sq = PowerMethod ();
1183+ stepsize_.power_method_lambda = op_norm_sq;
1184+
1185+ const double safety_factor = 0.8 ;
1186+ double base_step = safety_factor / std::sqrt (op_norm_sq);
1187+
1188+ stepsize_.primal_step = base_step / std::sqrt (stepsize_.beta );
1189+ stepsize_.dual_step = base_step * std::sqrt (stepsize_.beta );
1190+
1191+ highsLogUser (params_.log_options_ , HighsLogType::kInfo ,
1192+ " Initial step sizes from power method lambda = %g: primal = %g; dual = %g\n " ,
1193+ op_norm_sq, stepsize_.primal_step , stepsize_.dual_step );
1194+ } else {
1195+ // Use matrix infinity norm for adaptive step size
1196+ // Compute infinity norm of matrix elements
1197+ double mat_elem_norm_inf = 0.0 ;
1198+ const HighsSparseMatrix& matrix = lp_.a_matrix_ ;
1199+ for (int i = 0 ; i < matrix.numNz (); ++i) {
1200+ mat_elem_norm_inf = std::max (mat_elem_norm_inf, std::abs (matrix.value_ [i]));
1201+ }
1202+
1203+ if (mat_elem_norm_inf < 1e-10 ) {
1204+ mat_elem_norm_inf = 1.0 ; // Avoid division by zero
1205+ }
1206+
1207+ // Initialize step sizes using infinity norm
1208+ stepsize_.primal_step = (1.0 / mat_elem_norm_inf) / std::sqrt (stepsize_.beta );
1209+ stepsize_.dual_step = stepsize_.primal_step * stepsize_.beta ;
1210+
1211+ highsLogUser (params_.log_options_ , HighsLogType::kInfo ,
1212+ " Initial step sizes from matrix inf-norm = %g: primal = %g; dual = %g\n " ,
1213+ mat_elem_norm_inf, stepsize_.primal_step , stepsize_.dual_step );
1214+ }
11891215}
11901216
1191- std::vector<double > PDLPSolver::UpdateX () {
1217+ std::vector<double > PDLPSolver::UpdateX (double primal_step ) {
11921218 std::vector<double > x_new (lp_.num_col_ );
11931219 debug_pdlp_data_.aty_norm = linalg::vector_norm (ATy_cache_);
11941220 for (HighsInt i = 0 ; i < lp_.num_col_ ; i++) {
11951221 double gradient = lp_.col_cost_ [i] - ATy_cache_[i];
1196- x_new[i] = linalg::project_box (x_current_[i] - stepsize_. primal_step * gradient,
1222+ x_new[i] = linalg::project_box (x_current_[i] - primal_step * gradient,
11971223 lp_.col_lower_ [i], lp_.col_upper_ [i]);
11981224 }
11991225 return x_new;
12001226}
12011227
1202- std::vector<double > PDLPSolver::UpdateY () {
1228+ std::vector<double > PDLPSolver::UpdateY (double dual_step ) {
12031229 std::vector<double > y_new (lp_.num_row_ );
12041230 for (HighsInt j = 0 ; j < lp_.num_row_ ; j++) {
12051231 double extr_ax = 2 * Ax_next_[j] - Ax_cache_[j];
12061232 bool is_equality = (lp_.row_lower_ [j] == lp_.row_upper_ [j]);
12071233 double q = lp_.row_lower_ [j];
1208- double dual_update = y_current_[j] + stepsize_. dual_step * (q - extr_ax);
1234+ double dual_update = y_current_[j] + dual_step * (q - extr_ax);
12091235 y_new[j] = is_equality ? dual_update : linalg::project_non_negative (dual_update);
12101236 }
12111237 return y_new;
12121238}
12131239
12141240void PDLPSolver::UpdateIteratesFixed () {
1215- x_next_ = UpdateX ();
1241+ x_next_ = UpdateX (stepsize_. primal_step );
12161242 linalg::Ax (lp_, x_next_, Ax_next_);
1217- y_next_ = UpdateY ();
1243+ y_next_ = UpdateY (stepsize_. dual_step );
12181244}
12191245
1220- void PDLPSolver::UpdateIteratesAdaptive (int & step_size_iter_count ) {
1246+ void PDLPSolver::UpdateIteratesAdaptive () {
12211247 const double MIN_ETA = 1e-6 ;
12221248 const double MAX_ETA = 1.0 ;
12231249
12241250 bool accepted_step = false ;
12251251 int inner_iterations = 0 ;
12261252 int num_rejected_steps = 0 ;
12271253
1228- while (!accepted_step) {
1254+ double dStepSizeUpdate = std::sqrt (stepsize_.primal_step *
1255+ stepsize_.dual_step );
1256+
1257+ // Compute candidate solution
1258+ std::vector<double > x_candidate (lp_.num_col_ );
1259+ std::vector<double > y_candidate (lp_.num_row_ );
1260+ std::vector<double > ax_candidate (lp_.num_row_ );
1261+ std::vector<double > aty_candidate (lp_.num_col_ );
1262+ while (!accepted_step) {
1263+ stepsize_.step_size_iter ++; // nStepSizeIter
12291264 inner_iterations++;
12301265
12311266 if (inner_iterations >= 60 ) {
@@ -1235,18 +1270,16 @@ while (!accepted_step) {
12351270 break ;
12361271 }
12371272
1238- // Compute candidate solution
1239- std::vector<double > x_candidate (lp_.num_col_ );
1240- std::vector<double > y_candidate (lp_.num_row_ );
1241- std::vector<double > ax_candidate (lp_.num_row_ );
1242- std::vector<double > aty_candidate (lp_.num_col_ );
1273+ // Calculate step sizes for this iteration
1274+ double primal_step_update = dStepSizeUpdate / std::sqrt (stepsize_.beta );
1275+ double dual_step_update = dStepSizeUpdate * std::sqrt (stepsize_.beta );
12431276
12441277 // Primal update
1245- x_candidate = UpdateX ();
1278+ x_candidate = UpdateX (primal_step_update );
12461279 linalg::Ax (lp_, x_candidate, ax_candidate);
12471280
12481281 // Dual update
1249- y_candidate = UpdateY ();
1282+ y_candidate = UpdateY (dual_step_update );
12501283 linalg::ATy (lp_, y_candidate, aty_candidate);
12511284
12521285 // Compute deltas
@@ -1265,11 +1298,13 @@ while (!accepted_step) {
12651298 }
12661299
12671300 // Check numerical stability
1301+ /*
12681302 if (!CheckNumericalStability(delta_x, delta_y)) {
12691303 std::cerr << "Numerical instability detected" << std::endl;
1270- current_eta_ *= 0.5 ; // Drastically reduce step size
1304+ dStepSizeUpdate *= 0.5; // Drastically reduce step size
12711305 continue;
12721306 }
1307+ */
12731308
12741309 // Compute movement and nonlinearity
12751310 double movement = ComputeMovement (delta_x, delta_y);
@@ -1278,7 +1313,7 @@ while (!accepted_step) {
12781313
12791314 // Compute step size limit
12801315 double step_size_limit = (nonlinearity > 1e-12 )
1281- ? (movement / (2 .0 * nonlinearity))
1316+ ? (movement / (1 .0 * nonlinearity))
12821317 : // in cupdlp-c, the factor is 1
12831318 std::numeric_limits<double >::infinity ();
12841319
@@ -1288,12 +1323,7 @@ while (!accepted_step) {
12881323 = %g\n", int(inner_iterations), current_eta, movement, nonlinearity.
12891324 step_size_limit);
12901325 */
1291- if (current_eta_ <= step_size_limit) {
1292- // Accept the step
1293- x_next_ = x_candidate;
1294- y_next_ = y_candidate;
1295- Ax_next_ = ax_candidate;
1296- ATy_cache_ = aty_candidate;
1326+ if (dStepSizeUpdate <= step_size_limit) {
12971327 accepted_step = true ;
12981328 } else {
12991329 num_rejected_steps++;
@@ -1303,21 +1333,31 @@ while (!accepted_step) {
13031333 double first_term =
13041334 (std::isinf (step_size_limit))
13051335 ? step_size_limit
1306- : (1.0 - std::pow (step_size_iter_count + 1.0 ,
1336+ : (1.0 - std::pow (stepsize_. step_size_iter + 1.0 ,
13071337 -params_.adaptive_linesearch_params
13081338 .step_size_reduction_exponent )) *
13091339 step_size_limit;
13101340
13111341 double second_term =
13121342 (1.0 +
13131343 std::pow (
1314- step_size_iter_count + 1.0 ,
1344+ stepsize_. step_size_iter + 1.0 ,
13151345 -params_.adaptive_linesearch_params .step_size_growth_exponent )) *
1316- current_eta_ ;
1346+ dStepSizeUpdate ;
13171347
1318- current_eta_ = std::min (first_term, second_term);
1319- current_eta_ = std::max (MIN_ETA, std::min (MAX_ETA, current_eta_));
1348+ dStepSizeUpdate = std::min (first_term, second_term);
1349+ // current_eta_ = std::max(MIN_ETA, std::min(MAX_ETA, current_eta_));
13201350 }
1351+
1352+ x_next_ = x_candidate;
1353+ y_next_ = y_candidate;
1354+ Ax_next_ = ax_candidate;
1355+ ATy_next_ = aty_candidate;
1356+
1357+ current_eta_ = dStepSizeUpdate;
1358+ stepsize_.primal_step = dStepSizeUpdate / std::sqrt (stepsize_.beta );
1359+ std::cout << " new primal step: " << stepsize_.primal_step << std::endl;
1360+ stepsize_.dual_step = dStepSizeUpdate * std::sqrt (stepsize_.beta );
13211361}
13221362
13231363bool PDLPSolver::UpdateIteratesMalitskyPock (
0 commit comments