Skip to content

Commit 02102aa

Browse files
committed
Updated kYanyuPowerMethodDev to back-calculate RQ
1 parent 9e341c1 commit 02102aa

File tree

3 files changed

+36
-30
lines changed

3 files changed

+36
-30
lines changed

check/TestPdlp.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ TEST_CASE("hi-pdlp", "[pdlp]") {
344344
h.setOptionValue("pdlp_restart_strategy", 0);
345345
h.setOptionValue("pdlp_step_size_strategy", 0);
346346

347-
h.setOptionValue("pdlp_iteration_limit", 100000);
347+
h.setOptionValue("pdlp_iteration_limit", 1000000);
348348
// h.setOptionValue("log_dev_level", kHighsLogDevLevelVerbose);
349349
HighsStatus run_status = h.run();
350350
// REQUIRE(run_status == HighsStatus::kOk);

highs/pdlp/cupdlp/cupdlp_step.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ cupdlp_retcode PDHG_Power_Method(CUPDLPwork *work, cupdlp_float *lambda) {
9696
// y is stored in aty->data
9797
//
9898
int log_iters = work->settings->nLogLevel > 1;
99-
// log_iters = 1;
99+
log_iters = 1;
100100

101101
if (log_iters)
102102
cupdlp_printf("It lambda dl_lambda residual\n");

highs/pdlp/hipdlp/pdhg.cc

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -803,10 +803,22 @@ HighsStatus PDLPSolver::PowerMethod(HighsLp &lp, double& op_norm_sq) {
803803
linalg::normalize(x_vec); // Assumes a normalize function in linalg
804804

805805
const HighsInt kYanyuPowerMethod = 0;
806-
const HighsInt kATAPowerMethod = 1;
806+
const HighsInt kYanyuPowerMethodDev = 1;
807807
const HighsInt kCuPdlpAATPowerMethod = 2;
808808

809-
const HighsInt power_method = kYanyuPowerMethod;//kCuPdlpAATPowerMethod;//
809+
const HighsInt power_method =
810+
kYanyuPowerMethod;
811+
// kYanyuPowerMethodDev;
812+
// kCuPdlpAATPowerMethod;
813+
printf("Power method: %s\n", power_method == kYanyuPowerMethod ? "Yanyu" : power_method == kYanyuPowerMethodDev ? "Yanyu dev" : "CuPdlp-C");
814+
// Dev version of Yanyu power method (based on A'A) has
815+
//
816+
// * First iterate as vector of ones
817+
//
818+
// * No "convergence" check
819+
820+
// cuPDLP-C version of power method is based on AA'
821+
//
810822
// Allocate memory for matrix-vector products
811823
std::vector<double> y_vec;
812824
std::vector<double> z_vec;
@@ -821,11 +833,12 @@ HighsStatus PDLPSolver::PowerMethod(HighsLp &lp, double& op_norm_sq) {
821833
double op_norm_sq_old = 0.0;
822834
LogLevel log_level = logger_.getLogLevel();
823835
int log_iters = log_level == LogLevel::kVerbose || log_level == LogLevel::kDebug;
824-
// log_iters = 1;
836+
log_iters = 1;
825837

826838
if (log_iters) printf("It lambda dl_lambda\n");
827839

828-
if (power_method == kATAPowerMethod) {
840+
if (power_method == kYanyuPowerMethodDev) {
841+
// Start from a vector
829842
x_vec.assign(lp.num_col_, 1);
830843
} else if (power_method == kCuPdlpAATPowerMethod) {
831844
x_vec.assign(lp.num_row_, 1);
@@ -837,11 +850,11 @@ HighsStatus PDLPSolver::PowerMethod(HighsLp &lp, double& op_norm_sq) {
837850
if (power_method == kYanyuPowerMethod) {
838851
// Original Yanyu power method
839852
//
840-
// Compute ATAx = A^T * (A * x)
853+
// Compute A'Ax = A'(Ax)
841854
linalg::Ax(lp, x_vec, y_vec);
842-
linalg::ATy(lp, y_vec, z_vec); // Note: ATy computes A^T * vector
855+
linalg::ATy(lp, y_vec, z_vec); // Note: ATy computes A' * vector
843856

844-
// Estimate the squared operator norm (largest eigenvalue of A^T*A)
857+
// Estimate the squared operator norm (largest eigenvalue of A'A)
845858
op_norm_sq = linalg::dot(x_vec, z_vec); // Assumes a dot product function in linalg
846859

847860
// Check for convergence
@@ -856,38 +869,32 @@ HighsStatus PDLPSolver::PowerMethod(HighsLp &lp, double& op_norm_sq) {
856869
x_vec = z_vec;
857870
if (log_iters) printf("%2d %12.6g %11.4g\n", iter, op_norm_sq, dl_op_norm_sq);
858871
} else {
859-
if (power_method == kATAPowerMethod) {
860-
// Yanyu power method corrected - with Rayleigh quotient
872+
if (power_method == kYanyuPowerMethodDev) {
873+
// Yanyu power method without "convergence" check
861874
//
862-
// Compute z = ATAx = A^T * (A * x)
875+
// Compute z = A'Ax = A'(Ax)
863876
matrix.product(y_vec, x_vec);
864877
matrix.productTranspose(z_vec, y_vec);
865-
// q = z / norm(z)
878+
// Compute the Rayleigh quotient of x which, since x'x=1, is
879+
//
880+
// lambda = x'A'Ax = x'(A'Ax) = x'z
881+
lambda = linalg::dot(x_vec, z_vec);
882+
// x = z / norm(z)
866883
double z_norm = std::sqrt(linalg::dot(z_vec, z_vec));
867-
double denom = 1.0 / z_norm;
868884
for (HighsInt iCol = 0; iCol < lp.num_col_; iCol++)
869-
z_vec[iCol] *= denom;
870-
// Now compute the Rayleigh quotient of q which, since q'q=1 is
871-
//
872-
// lambda = q'A'Aq = w^Tw = ||w||_2
873-
//
874-
// where w = Aq
875-
//
876-
// y_vec is no longer needed, so w is stored in it
877-
matrix.product(y_vec, z_vec);
878-
lambda = linalg::dot(y_vec, y_vec);
885+
x_vec[iCol] = z_vec[iCol] / z_norm;
886+
879887
} else {
880888
// cuPDLP-C power method
881889
//
882-
// Compute z = AA^Tx = A * (A^T * x)
890+
// Compute z = AA'x = A(A'x)
883891
matrix.productTranspose(y_vec, x_vec);
884892
matrix.product(z_vec, y_vec);
885893
// q = z / norm(z)
886894
double z_norm = std::sqrt(linalg::dot(z_vec, z_vec));
887-
double denom = 1.0 / z_norm;
888895
for (HighsInt iRow = 0; iRow < lp.num_row_; iRow++)
889-
z_vec[iRow] *= denom;
890-
// Now compute the Rayleigh quotient of q which, since q'q=1 is
896+
z_vec[iRow] /= z_norm;
897+
// Compute the Rayleigh quotient of q which, since q'q=1, is
891898
//
892899
// lambda = q'AA'q = w^Tw = ||w||_2
893900
//
@@ -896,11 +903,10 @@ HighsStatus PDLPSolver::PowerMethod(HighsLp &lp, double& op_norm_sq) {
896903
// y_vec is no longer needed, so w is stored in it
897904
matrix.productTranspose(y_vec, z_vec);
898905
lambda = linalg::dot(y_vec, y_vec);
906+
x_vec = z_vec;
899907
}
900908
double dl_lambda = std::fabs(lambda - previous_lambda);
901909
previous_lambda = lambda;
902-
903-
x_vec = z_vec;
904910
if (log_iters) printf("%2d %12.6g %11.4g\n", iter, lambda, dl_lambda);
905911
}
906912
}

0 commit comments

Comments
 (0)