@@ -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 (¶ms_);
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}
0 commit comments