Skip to content

Commit 803d2ea

Browse files
committed
fix highs.solution
1 parent d80bbbe commit 803d2ea

File tree

5 files changed

+43
-29
lines changed

5 files changed

+43
-29
lines changed

check/TestPdlp.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ TEST_CASE("pdlp-restart-add-row", "[pdlp]") {
336336

337337
TEST_CASE("hi-pdlp", "[pdlp]") {
338338
std::string model =
339-
"25fv47"; //"adlittle";//"afiro";// shell// stair //25fv47 //fit2p
339+
"adlittle"; //"adlittle";//"afiro";// shell// stair //25fv47 //fit2p
340340
std::string model_file =
341341
std::string(HIGHS_DIR) + "/check/instances/" + model + ".mps";
342342
Highs h;
@@ -349,7 +349,7 @@ TEST_CASE("hi-pdlp", "[pdlp]") {
349349
HighsInt pdlp_features_off = 0
350350
// kPdlpScalingOff +
351351
// kPdlpRestartOff
352-
//+ kPdlpAdaptiveStepSizeOff
352+
+ kPdlpAdaptiveStepSizeOff
353353
;
354354
h.setOptionValue("pdlp_features_off", pdlp_features_off);
355355

highs/pdlp/cupdlp/cupdlp_defs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ extern "C" {
4141
#define CUPDLP_DUMP_LINESEARCH_STATS (1)
4242
#define CUPDLP_INEXACT_EPS (1e-4)
4343

44-
#define PDLP_DEBUG_LOG (0)
44+
#define PDLP_DEBUG_LOG (1)
4545

4646
typedef struct CUPDLP_CUDA_DENSE_VEC CUPDLPvec;
4747
typedef struct CUPDLP_DENSE_MATRIX CUPDLPdense;

highs/pdlp/cupdlp/cupdlp_solver.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1308,7 +1308,6 @@ cupdlp_retcode PDHG_PostSolve(CUPDLPwork *pdhg, cupdlp_int nCols_origin,
13081308
for (int iRow = 0; iRow < problem->nRows; iRow++)
13091309
printf("PDHG_PostSolve: Row %d dual value = %9.3g\n", iRow, y->data[iRow]);
13101310
*/
1311-
13121311
// unscale
13131312
if (scaling->ifScaled) {
13141313
cupdlp_ediv(x->data, pdhg->colScale, problem->nCols);

highs/pdlp/hipdlp/pdhg.cc

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ void PDLPSolver::preprocessLp() {
164164

165165
int num_new_cols = 0;
166166
int nEqs = 0;
167+
sense_origin_ = (original_lp_->sense_ == ObjSense::kMinimize) ? 1 : -1;
167168
constraint_types_.resize(nRows_orig);
168169

169170
// 1. First pass: Classify constraints and count slack variables needed
@@ -433,21 +434,27 @@ PostSolveRetcode PDLPSolver::postprocess(HighsSolution& solution) {
433434
}
434435
}
435436

436-
std::vector<double> ax_current_(unscaled_processed_lp_.num_row_);
437-
linalg::Ax(unscaled_processed_lp_, x_current_, ax_current_);
437+
std::vector<double> ax_original(original_lp_->num_row_, 0.0);
438+
439+
// Get original matrix in column-wise format
440+
HighsSparseMatrix orig_matrix = original_lp_->a_matrix_;
441+
orig_matrix.ensureColwise();
442+
443+
// Compute Ax using only the original columns (not slack variables)
444+
for (int col = 0; col < original_num_col_; ++col) {
445+
double x_val = x_current_[col]; // Use unscaled x values
446+
447+
for (int el = orig_matrix.start_[col];
448+
el < orig_matrix.start_[col + 1]; ++el) {
449+
int row = orig_matrix.index_[el];
450+
double a_val = orig_matrix.value_[el];
451+
ax_original[row] += a_val * x_val;
452+
}
453+
}
438454

439-
int slack_variable_idx = original_num_col_;
455+
// Now ax_original contains the correct row activity values
440456
for (int orig_row = 0; orig_row < original_lp_->num_row_; ++orig_row) {
441-
int reordered_row = constraint_new_idx_[orig_row];
442-
443-
if (constraint_types_[orig_row] == BOUND ||
444-
constraint_types_[orig_row] == FREE) {
445-
solution.row_value[orig_row] = x_current_[slack_variable_idx++];
446-
} else if (constraint_types_[orig_row] == LEQ) {
447-
solution.row_value[orig_row] = -ax_current_[reordered_row];
448-
} else { // EQ, GEQ
449-
solution.row_value[orig_row] = ax_current_[reordered_row];
450-
}
457+
solution.row_value[orig_row] = ax_original[orig_row];
451458
}
452459

453460
// 6. Recover Dual Column Values (Reduced Costs)
@@ -461,6 +468,7 @@ PostSolveRetcode PDLPSolver::postprocess(HighsSolution& solution) {
461468
return PostSolveRetcode::DIMENSION_MISMATCH;
462469
}
463470
solution.col_dual[i] = dSlackPos_[i] - dSlackNeg_[i];
471+
solution.col_dual[i] *= sense_origin_;
464472
}
465473

466474
solution.value_valid = true; // to do
@@ -873,16 +881,23 @@ void PDLPSolver::computeDualSlacks(const std::vector<double>& ATy_vector) {
873881
if (dSlackNeg_.size() != lp_.num_col_) dSlackNeg_.resize(lp_.num_col_);
874882

875883
for (HighsInt i = 0; i < lp_.num_col_; ++i) {
876-
double reduced_cost = lp_.col_cost_[i] - ATy_vector[i];
877-
878-
// Slack for lower bound l_i <= x_i (dual variable is non-negative)
879-
dSlackPos_[i] =
880-
(lp_.col_lower_[i] > -kHighsInf) ? std::max(0.0, reduced_cost) : 0.0;
884+
double dual_residual = lp_.col_cost_[i] - ATy_vector[i];
881885

882-
// Slack for upper bound x_i <= u_i (dual variable is non-positive, so slack
883-
// is non-negative)
884-
dSlackNeg_[i] =
885-
(lp_.col_upper_[i] < kHighsInf) ? std::max(0.0, -reduced_cost) : 0.0;
886+
// Compute positive slack (for lower bounds)
887+
// CUPDLP: max(dual_residual, 0) * hasLower
888+
if (lp_.col_lower_[i] > -kHighsInf) {
889+
dSlackPos_[i] = std::max(0.0, dual_residual);
890+
} else {
891+
dSlackPos_[i] = 0.0;
892+
}
893+
894+
// Compute negative slack (for upper bounds)
895+
// CUPDLP: -min(dual_residual, 0) * hasUpper
896+
if (lp_.col_upper_[i] < kHighsInf) {
897+
dSlackNeg_[i] = std::max(0.0, -dual_residual);
898+
} else {
899+
dSlackNeg_[i] = 0.0;
900+
}
886901
}
887902
}
888903

@@ -1246,7 +1261,6 @@ void PDLPSolver::setup(const HighsOptions& options, HighsTimer& timer) {
12461261
restart_scheme_.passParams(&params_);
12471262
// Copy what's needed to use HiGHS logging
12481263
params_.log_options_ = options.log_options;
1249-
12501264
// log the options
12511265
logger_.print_params(params_);
12521266
}
@@ -1268,8 +1282,8 @@ void PDLPSolver::unscaleSolution(std::vector<double>& x,
12681282
const std::vector<double>& col_scale = scaling_.GetColScaling();
12691283
if (!dSlackPos_.empty() && col_scale.size() == dSlackPos_.size()) {
12701284
for (size_t i = 0; i < dSlackPos_.size(); ++i) {
1271-
dSlackPos_[i] /= col_scale[i];
1272-
dSlackNeg_[i] /= col_scale[i];
1285+
dSlackPos_[i] *= col_scale[i];
1286+
dSlackNeg_[i] *= col_scale[i];
12731287
}
12741288
}
12751289
}

highs/pdlp/hipdlp/pdhg.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ class PDLPSolver {
121121
std::vector<bool> is_equality_row_;
122122
std::vector<int> constraint_new_idx_;
123123
std::vector<ConstraintType> constraint_types_;
124+
double sense_origin_ = 1; // 1 (min) or -1 (max)
124125

125126
// --- Solver State ---
126127
int final_iter_count_ = 0;

0 commit comments

Comments
 (0)