@@ -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
@@ -635,8 +643,12 @@ void PDLPSolver::solve(std::vector<double>& x, std::vector<double>& y) {
635643
636644 restart_scheme_.last_restart_iter_ = iter;
637645 // Recompute Ax and ATy for the restarted iterates
646+ hipdlpTimerStart (kHipdlpClockMatrixMultiply );
638647 linalg::Ax (lp, x_current_, Ax_cache_);
648+ hipdlpTimerStop (kHipdlpClockMatrixMultiply );
649+ hipdlpTimerStart (kHipdlpClockMatrixTransposeMultiply );
639650 linalg::ATy (lp, y_current_, ATy_cache_);
651+ hipdlpTimerStop (kHipdlpClockMatrixTransposeMultiply );
640652
641653 restart_scheme_.SetLastRestartIter (iter);
642654 }
@@ -679,9 +691,12 @@ void PDLPSolver::solve(std::vector<double>& x, std::vector<double>& y) {
679691
680692 // Compute ATy for the new iterate
681693 Ax_cache_ = Ax_next_;
694+ /*
682695 hipdlpTimerStart(kHipdlpClockMatrixTransposeMultiply);
683696 linalg::ATy(lp, y_next_, ATy_cache_);
684697 hipdlpTimerStop(kHipdlpClockMatrixTransposeMultiply);
698+ */
699+ ATy_cache_ = ATy_next_;
685700
686701 hipdlpTimerStop (kHipdlpClockIterateUpdate );
687702
@@ -866,16 +881,23 @@ void PDLPSolver::computeDualSlacks(const std::vector<double>& ATy_vector) {
866881 if (dSlackNeg_.size () != lp_.num_col_ ) dSlackNeg_.resize (lp_.num_col_ );
867882
868883 for (HighsInt i = 0 ; i < lp_.num_col_ ; ++i) {
869- double reduced_cost = lp_.col_cost_ [i] - ATy_vector[i];
870-
871- // Slack for lower bound l_i <= x_i (dual variable is non-negative)
872- dSlackPos_[i] =
873- (lp_.col_lower_ [i] > -kHighsInf ) ? std::max (0.0 , reduced_cost) : 0.0 ;
884+ double dual_residual = lp_.col_cost_ [i] - ATy_vector[i];
874885
875- // Slack for upper bound x_i <= u_i (dual variable is non-positive, so slack
876- // is non-negative)
877- dSlackNeg_[i] =
878- (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+ }
879901 }
880902}
881903
@@ -1239,7 +1261,6 @@ void PDLPSolver::setup(const HighsOptions& options, HighsTimer& timer) {
12391261 restart_scheme_.passParams (¶ms_);
12401262 // Copy what's needed to use HiGHS logging
12411263 params_.log_options_ = options.log_options ;
1242-
12431264 // log the options
12441265 logger_.print_params (params_);
12451266}
@@ -1249,9 +1270,6 @@ void PDLPSolver::scaleProblem() {
12491270 scaling_.passParams (¶ms_);
12501271 scaling_.Initialize (lp_);
12511272 scaling_.scaleProblem ();
1252- // print the norm of lp_.col_cost_
1253- unscaled_c_norm_ = linalg::vector_norm (lp_.col_cost_ );
1254- std::cout << " Unscaled cost norm = " << unscaled_c_norm_ << std::endl;
12551273}
12561274
12571275void PDLPSolver::unscaleSolution (std::vector<double >& x,
@@ -1264,8 +1282,10 @@ void PDLPSolver::unscaleSolution(std::vector<double>& x,
12641282 const std::vector<double >& col_scale = scaling_.GetColScaling ();
12651283 if (!dSlackPos_.empty () && col_scale.size () == dSlackPos_.size ()) {
12661284 for (size_t i = 0 ; i < dSlackPos_.size (); ++i) {
1267- dSlackPos_[i] /= col_scale[i];
1268- dSlackNeg_[i] /= col_scale[i];
1285+ std::cout << " dSlackPos_ before unscale[" << i << " ] = " << dSlackPos_[i]
1286+ << std::endl;
1287+ dSlackPos_[i] *= col_scale[i];
1288+ dSlackNeg_[i] *= col_scale[i];
12691289 }
12701290 }
12711291}
@@ -1403,6 +1423,10 @@ void PDLPSolver::updateIteratesFixed() {
14031423 hipdlpTimerStart (kHipdlpClockProjectY );
14041424 y_next_ = updateY (y_current_, Ax_cache_, Ax_next_, stepsize_.dual_step );
14051425 hipdlpTimerStop (kHipdlpClockProjectY );
1426+
1427+ hipdlpTimerStart (kHipdlpClockMatrixTransposeMultiply );
1428+ linalg::ATy (lp_, y_next_, ATy_next_);
1429+ hipdlpTimerStop (kHipdlpClockMatrixTransposeMultiply );
14061430}
14071431
14081432void PDLPSolver::updateIteratesAdaptive () {
0 commit comments