Skip to content

Commit 8aa3cd9

Browse files
committed
rm step
1 parent 8b7e739 commit 8aa3cd9

File tree

7 files changed

+126
-555
lines changed

7 files changed

+126
-555
lines changed

highs/pdlp/hipdlp/Meld

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,4 @@ meld restart.hpp $CU_PDLP_CPP_ROOT/include/restart.hpp
99
meld restart.cc $CU_PDLP_CPP_ROOT/src/restart.cc
1010
meld scaling.hpp $CU_PDLP_CPP_ROOT/include/scaling.hpp
1111
meld scaling.cc $CU_PDLP_CPP_ROOT/src/scaling.cc
12-
meld solver_results.hpp $CU_PDLP_CPP_ROOT/include/solver_results.hpp
13-
meld step.hpp $CU_PDLP_CPP_ROOT/include/step.hpp
14-
meld step.cc $CU_PDLP_CPP_ROOT/src/step.cc
12+
meld solver_results.hpp $CU_PDLP_CPP_ROOT/include/solver_results.hpp

highs/pdlp/hipdlp/pdhg.cc

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,10 @@ void PDLPSolver::solve(std::vector<double>& x, std::vector<double>& y) {
392392
// --- 2. Main PDHG Loop ---
393393
debugPdlpIterHeaderLog(debug_pdlp_log_file_);
394394
debugPdlpDataInitialise(&debug_pdlp_data_);
395+
debug_pdlp_data_.ax_average_norm = 0.0;
396+
debug_pdlp_data_.aty_average_norm = 0.0;
397+
debug_pdlp_data_.x_average_norm = 0.0;
398+
debug_pdlp_data_.ax_norm = 0.0;
395399

396400
for (int iter = 0; iter < params_.max_iterations; ++iter) {
397401
debugPdlpIterLog(debug_pdlp_log_file_, iter, &debug_pdlp_data_,
@@ -412,7 +416,6 @@ void PDLPSolver::solve(std::vector<double>& x, std::vector<double>& y) {
412416
(iter > 0 && (iter % PDHG_CHECK_INTERVAL == 0));
413417

414418
if (bool_checking) {
415-
std::cout << "sum_weights_ = " << sum_weights_ << "\n";
416419
ComputeAverageIterate(Ax_avg, ATy_avg);
417420
// Compute matrix-vector products for current and average iterates
418421
linalg::Ax(lp, x_current_, Ax_cache_);
@@ -468,8 +471,6 @@ void PDLPSolver::solve(std::vector<double>& x, std::vector<double>& y) {
468471
restart_scheme_.Check(iter, current_results, average_results);
469472

470473
if (restart_info.should_restart) {
471-
logger_.info("Restarting at iteration " + std::to_string(iter));
472-
473474
std::vector<double> restart_x, restart_y;
474475
if (restart_info.restart_to_average) {
475476
// Restart from the average iterate
@@ -501,19 +502,19 @@ void PDLPSolver::solve(std::vector<double>& x, std::vector<double>& y) {
501502

502503
// Recompute Ax and ATy for the restarted iterates
503504
linalg::Ax(lp, x_current_, Ax_cache_);
505+
debug_pdlp_data_.ax_norm = linalg::vector_norm(Ax_cache_);
504506
linalg::ATy(lp, y_current_, ATy_cache_);
505-
507+
debug_pdlp_data_.aty_norm = linalg::vector_norm(ATy_cache_);
506508
restart_scheme_.SetLastRestartIter(iter);
507509
}
508510
} else {
509511
// If not checking, still need Ax and ATy for the update
510512
linalg::Ax(lp, x_current_, Ax_cache_);
513+
debug_pdlp_data_.ax_norm = linalg::vector_norm(Ax_cache_);
511514
linalg::ATy(lp, y_current_, ATy_cache_);
515+
debug_pdlp_data_.aty_norm = linalg::vector_norm(ATy_cache_);
512516
}
513517

514-
// Record Ax norm for debugging
515-
debug_pdlp_data_.ax_norm = linalg::vector_norm(Ax_cache_);
516-
517518
// --- 5. Core PDHG Update Step ---
518519
bool step_success = true;
519520

@@ -654,8 +655,6 @@ void PDLPSolver::UpdateAverageIterates(const std::vector<double>& x,
654655
}
655656

656657
sum_weights_ += dMeanStepSize;
657-
printf("x_sum norm before %g after %g \n", x_norm_before,
658-
linalg::vector_norm(x_sum_));
659658
}
660659

661660
void PDLPSolver::ComputeAverageIterate(std::vector<double>& ax_avg,
@@ -670,10 +669,11 @@ void PDLPSolver::ComputeAverageIterate(std::vector<double>& ax_avg,
670669
y_avg_[i] = y_sum_[i] * dDualScale;
671670
}
672671

673-
debug_pdlp_data_.x_average_norm = linalg::vector_norm(x_avg_);
672+
debug_pdlp_data_.x_average_norm = linalg::vector_norm_squared(x_avg_);
674673
linalg::Ax(lp_, x_avg_, ax_avg);
675674
linalg::ATy(lp_, y_avg_, aty_avg);
676-
debug_pdlp_data_.ax_average_norm = linalg::vector_norm(ax_avg);
675+
debug_pdlp_data_.ax_average_norm = linalg::vector_norm_squared(ax_avg);
676+
debug_pdlp_data_.aty_average_norm = linalg::vector_norm_squared(aty_avg);
677677
}
678678

679679
// lambda = c - proj_{\Lambda}(c - K^T y)

highs/pdlp/hipdlp/restart.cc

Lines changed: 96 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@
1717
#include "io/HighsIO.h" // For pdlpLogging
1818
#include "pdlp/cupdlp/cupdlp.h" // For pdlpLogging
1919

20+
// Helper function to compute the score
21+
static double compute_score(double beta, double primal_feas, double dual_feas, double duality_gap) {
22+
return std::sqrt(beta * primal_feas * primal_feas +
23+
dual_feas * dual_feas / beta +
24+
duality_gap * duality_gap);
25+
}
26+
2027
// Initializes the restart scheme with parameters and initial results
2128
void RestartScheme::Initialize(const SolverResults& results) {
2229
strategy_ = params_->restart_strategy;
@@ -28,34 +35,16 @@ void RestartScheme::Initialize(const SolverResults& results) {
2835
// in the paper, primal weight is the ω:
2936
// ω = √β
3037
beta_ = params_->omega * params_->omega;
31-
32-
last_restart_iter_ = 0;
33-
last_restart_score_ = std::numeric_limits<double>::infinity();
34-
last_candidate_score_ = std::numeric_limits<double>::infinity();
35-
}
36-
37-
// Computes a weighted score to evaluate solution quality
38-
double RestartScheme::ComputeRestartScore(const SolverResults& results) {
39-
double weight_squared = beta_;
40-
double primal_feas_sq =
41-
results.primal_feasibility * results.primal_feasibility;
42-
double dual_feas_sq = results.dual_feasibility * results.dual_feasibility;
43-
double gap_sq = results.duality_gap * results.duality_gap;
44-
45-
// debugPdlpRestarScoretLog(debug_pdlp_log_file_, weight_squared,
46-
// results.primal_feasibility, results.dual_feasibility, results.duality_gap);
47-
48-
return std::sqrt(weight_squared * primal_feas_sq +
49-
dual_feas_sq / weight_squared + gap_sq);
5038
}
5139

40+
/*
5241
// Main logic to check if a restart is needed
5342
RestartInfo RestartScheme::Check(int current_iter,
5443
const SolverResults& current_results,
5544
const SolverResults& average_results) {
5645
RestartInfo info;
5746
58-
if (current_iter == last_restart_iter_) {
47+
if (current_iter <= last_restart_iter_) {
5948
double current_score = ComputeRestartScore(current_results);
6049
last_restart_score_ = current_score;
6150
last_candidate_score_ = current_score;
@@ -77,8 +66,8 @@ RestartInfo RestartScheme::Check(int current_iter,
7766
case RestartStrategy::ADAPTIVE_RESTART: {
7867
double current_score = ComputeRestartScore(current_results);
7968
double average_score = ComputeRestartScore(average_results);
80-
debugPdlpRestartLog(debug_pdlp_log_file_, current_iter, current_score,
81-
average_score);
69+
//debugPdlpRestartLog(debug_pdlp_log_file_, current_iter, current_score,
70+
// average_score);
8271
8372
// Choose the best candidate (current vs. average) based on the score
8473
double candidate_score = std::min(current_score, average_score);
@@ -133,3 +122,88 @@ RestartInfo RestartScheme::Check(int current_iter,
133122
134123
return info;
135124
}
125+
*/
126+
127+
RestartInfo RestartScheme::Check(int current_iter,
128+
const SolverResults& current_results,
129+
const SolverResults& average_results) {
130+
if (strategy_ != RestartStrategy::ADAPTIVE_RESTART) {
131+
if (strategy_ == RestartStrategy::FIXED_RESTART &&
132+
current_iter - last_restart_iter_ >= fixed_restart_interval_) {
133+
return RestartInfo(true, true);
134+
}
135+
return RestartInfo(false, false); // ✨ Corrected return
136+
}
137+
138+
// Base Case: First check after a restart. Initialize state and exit.
139+
if (current_iter == last_restart_iter_) {
140+
primal_feas_last_restart_ = current_results.primal_feasibility;
141+
dual_feas_last_restart_ = current_results.dual_feasibility;
142+
duality_gap_last_restart_ = current_results.duality_gap;
143+
144+
primal_feas_last_candidate_ = current_results.primal_feasibility;
145+
dual_feas_last_candidate_ = current_results.dual_feasibility;
146+
duality_gap_last_candidate_ = current_results.duality_gap;
147+
148+
return {false, false};
149+
}
150+
151+
// 1. Calculate scores and determine the best candidate
152+
double mu_current = compute_score(beta_, current_results.primal_feasibility,
153+
current_results.dual_feasibility, current_results.duality_gap);
154+
double mu_average = compute_score(beta_, average_results.primal_feasibility,
155+
average_results.dual_feasibility, average_results.duality_gap);
156+
debugPdlpRestartLog(debug_pdlp_log_file_, current_iter, mu_current,
157+
mu_average);
158+
double candidate_score;
159+
bool restart_to_average;
160+
if (mu_current < mu_average) {
161+
candidate_score = mu_current;
162+
restart_to_average = false;
163+
} else {
164+
candidate_score = mu_average;
165+
restart_to_average = true;
166+
}
167+
168+
// 2. Check the three restart conditions in order
169+
bool should_restart = false;
170+
PDHG_restart_choice restart_choice_for_logic = PDHG_NO_RESTART;
171+
172+
if ((current_iter - last_restart_iter_) >= 0.36 * current_iter) {
173+
// Condition 1: Artificial Restart
174+
should_restart = true;
175+
} else {
176+
double mu_last_restart = compute_score(beta_, primal_feas_last_restart_,
177+
dual_feas_last_restart_, duality_gap_last_restart_);
178+
179+
if (candidate_score < sufficient_decay_factor_ * mu_last_restart) {
180+
// Condition 2: Sufficient Decay
181+
should_restart = true;
182+
} else {
183+
double mu_last_candidate = compute_score(beta_, primal_feas_last_candidate_,
184+
dual_feas_last_candidate_, duality_gap_last_candidate_);
185+
186+
if (candidate_score < necessary_decay_factor_ * mu_last_restart && candidate_score > mu_last_candidate) {
187+
// Condition 3: Necessary Decay
188+
should_restart = true;
189+
}
190+
}
191+
}
192+
193+
// 3. ALWAYS update the "last candidate" metrics for the next check
194+
if (restart_to_average) {
195+
primal_feas_last_candidate_ = average_results.primal_feasibility;
196+
dual_feas_last_candidate_ = average_results.dual_feasibility;
197+
duality_gap_last_candidate_ = average_results.duality_gap;
198+
} else {
199+
primal_feas_last_candidate_ = current_results.primal_feasibility;
200+
dual_feas_last_candidate_ = current_results.dual_feasibility;
201+
duality_gap_last_candidate_ = current_results.duality_gap;
202+
}
203+
204+
// NOTE: Your main solver loop is responsible for calling `SetLastRestartIter(current_iter)`
205+
// when it receives `should_restart = true`. This function does not modify that state directly,
206+
// it only determines if it *should* happen.
207+
208+
return RestartInfo(should_restart, restart_to_average);
209+
}

highs/pdlp/hipdlp/restart.hpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,16 @@ struct RestartInfo {
2525
bool should_restart = false;
2626
bool restart_to_average =
2727
true; // If true, restart to average; otherwise, to current
28+
29+
RestartInfo(bool should_restart_, bool restart_to_average_)
30+
: should_restart(should_restart_), restart_to_average(restart_to_average_){};
31+
32+
RestartInfo() = default;
2833
};
2934

3035
class RestartScheme {
3136
public:
3237
RestartScheme() = default;
33-
3438
void Initialize(const SolverResults& results);
3539

3640
// Checks if a restart should be performed based on the chosen strategy
@@ -61,17 +65,20 @@ class RestartScheme {
6165
FILE* debug_pdlp_log_file_ = nullptr;
6266
DebugPdlpData* debug_pdlp_data_;
6367

64-
// Computes a merit score for a given set of residuals
65-
double ComputeRestartScore(const SolverResults& results);
66-
6768
RestartStrategy strategy_ = RestartStrategy::NO_RESTART;
6869
int fixed_restart_interval_ = 100;
6970
int last_restart_iter_ = 0;
7071
double beta_;
7172

7273
// State for adaptive restart
73-
double last_restart_score_ = 1;
74-
double last_candidate_score_ = 1;
74+
double primal_feas_last_restart_ = 0.0;
75+
double dual_feas_last_restart_ = 0.0;
76+
double duality_gap_last_restart_ = 0.0;
77+
78+
double primal_feas_last_candidate_ = 0.0;
79+
double dual_feas_last_candidate_ = 0.0;
80+
double duality_gap_last_candidate_ = 0.0;
81+
7582
double sufficient_decay_factor_ = 0.2;
7683
double necessary_decay_factor_ = 0.8;
7784
};

0 commit comments

Comments
 (0)