Skip to content

Commit d1335fb

Browse files
committed
fix reorder final y and print constraint matrix types and var type
1 parent e44adae commit d1335fb

File tree

2 files changed

+129
-12
lines changed

2 files changed

+129
-12
lines changed

highs/pdlp/hipdlp/pdhg.cc

Lines changed: 128 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,113 @@ void vecPrint(const std::vector<double>& vec, const char* name) {
3535
std::cout << "]" << std::endl;
3636
}
3737

38+
void PDLPSolver::printConstraintInfo() {
39+
if (original_lp_ == nullptr) return;
40+
41+
int nRows = original_lp_->num_row_;
42+
int nCols = original_lp_->num_col_;
43+
44+
// Count constraint types BEFORE preprocessing
45+
int eq_count = 0, leq_count = 0, geq_count = 0, bound_count = 0, free_count = 0;
46+
47+
for (int i = 0; i < nRows; ++i) {
48+
bool has_lower = original_lp_->row_lower_[i] > -kHighsInf;
49+
bool has_upper = original_lp_->row_upper_[i] < kHighsInf;
50+
51+
if (has_lower && has_upper) {
52+
if (original_lp_->row_lower_[i] == original_lp_->row_upper_[i]) {
53+
eq_count++;
54+
} else {
55+
bound_count++;
56+
}
57+
} else if (has_lower) {
58+
geq_count++;
59+
} else if (has_upper) {
60+
leq_count++;
61+
} else {
62+
free_count++;
63+
}
64+
}
65+
66+
// Count variable bound types
67+
int var_fixed = 0, var_lower_only = 0, var_upper_only = 0;
68+
int var_boxed = 0, var_free = 0;
69+
70+
for (int i = 0; i < nCols; ++i) {
71+
bool has_lower = original_lp_->col_lower_[i] > -kHighsInf;
72+
bool has_upper = original_lp_->col_upper_[i] < kHighsInf;
73+
74+
if (has_lower && has_upper) {
75+
if (original_lp_->col_lower_[i] == original_lp_->col_upper_[i]) {
76+
var_fixed++;
77+
} else {
78+
var_boxed++;
79+
}
80+
} else if (has_lower) {
81+
var_lower_only++;
82+
} else if (has_upper) {
83+
var_upper_only++;
84+
} else {
85+
var_free++;
86+
}
87+
}
88+
89+
logger_.info("=== BEFORE PREPROCESSING ===");
90+
logger_.info("Rows: " + std::to_string(nRows) + ", Cols: " + std::to_string(nCols));
91+
logger_.info("\nConstraint types:");
92+
logger_.info(" Equality constraints (=): " + std::to_string(eq_count));
93+
logger_.info(" One-sided inequality (>=): " + std::to_string(geq_count));
94+
logger_.info(" One-sided inequality (<=): " + std::to_string(leq_count));
95+
logger_.info(" Two-sided inequality: " + std::to_string(bound_count));
96+
logger_.info(" Free constraints: " + std::to_string(free_count));
97+
98+
logger_.info("\nVariable bound types:");
99+
logger_.info(" Fixed variables (l = u): " + std::to_string(var_fixed));
100+
logger_.info(" Boxed variables (l <= x <= u): " + std::to_string(var_boxed));
101+
logger_.info(" Lower bounded only (l <= x): " + std::to_string(var_lower_only));
102+
logger_.info(" Upper bounded only (x <= u): " + std::to_string(var_upper_only));
103+
logger_.info(" Free variables: " + std::to_string(var_free));
104+
105+
logger_.info("\n=== AFTER PREPROCESSING ===");
106+
logger_.info("Rows: " + std::to_string(lp_.num_row_) +
107+
", Cols: " + std::to_string(lp_.num_col_));
108+
logger_.info("Equality rows (first " + std::to_string(num_eq_rows_) + " rows)");
109+
logger_.info("Inequality rows (remaining " +
110+
std::to_string(lp_.num_row_ - num_eq_rows_) + " rows)");
111+
logger_.info("Slack variables added: " +
112+
std::to_string(lp_.num_col_ - nCols));
113+
114+
// Count variable bounds in processed LP
115+
int proc_var_fixed = 0, proc_var_lower_only = 0, proc_var_upper_only = 0;
116+
int proc_var_boxed = 0, proc_var_free = 0;
117+
118+
for (int i = 0; i < lp_.num_col_; ++i) {
119+
bool has_lower = lp_.col_lower_[i] > -kHighsInf;
120+
bool has_upper = lp_.col_upper_[i] < kHighsInf;
121+
122+
if (has_lower && has_upper) {
123+
if (lp_.col_lower_[i] == lp_.col_upper_[i]) {
124+
proc_var_fixed++;
125+
} else {
126+
proc_var_boxed++;
127+
}
128+
} else if (has_lower) {
129+
proc_var_lower_only++;
130+
} else if (has_upper) {
131+
proc_var_upper_only++;
132+
} else {
133+
proc_var_free++;
134+
}
135+
}
136+
137+
logger_.info("\nProcessed variable bound types:");
138+
logger_.info(" Fixed variables: " + std::to_string(proc_var_fixed));
139+
logger_.info(" Boxed variables: " + std::to_string(proc_var_boxed));
140+
logger_.info(" Lower bounded only: " + std::to_string(proc_var_lower_only));
141+
logger_.info(" Upper bounded only: " + std::to_string(proc_var_upper_only));
142+
logger_.info(" Free variables: " + std::to_string(proc_var_free));
143+
}
144+
38145
void PDLPSolver::preprocessLp() {
39146
logger_.info(
40147
"Preprocessing LP using cupdlp formulation (slack variables for "
@@ -228,6 +335,8 @@ void PDLPSolver::preprocessLp() {
228335
std::to_string(processed_lp.num_col_) + " cols.");
229336
logger_.info("Unscaled norms: ||c|| = " + std::to_string(unscaled_c_norm_) +
230337
", ||b|| = " + std::to_string(unscaled_rhs_norm_));
338+
339+
printConstraintInfo();
231340
}
232341

233342
PostSolveRetcode PDLPSolver::postprocess(HighsSolution& solution) {
@@ -283,11 +392,18 @@ PostSolveRetcode PDLPSolver::postprocess(HighsSolution& solution) {
283392
results_.primal_obj = final_primal_objective;
284393

285394
// 4. Recover Dual Row Values (y)
286-
for (int i = 0; i < original_lp_->num_row_; ++i) {
287-
if (constraint_types_[i] == LEQ) {
288-
solution.row_dual[i] = -y_current_[i];
395+
std::vector<double> y_reordered = y_current_;
396+
for (int orig_row = 0; orig_row < original_lp_->num_row_; ++orig_row) {
397+
int reordered_row = constraint_new_idx_[orig_row];
398+
399+
// Get the dual value from the reordered position
400+
double dual_value = y_reordered[reordered_row];
401+
402+
// Apply sign correction for LEQ constraints
403+
if (constraint_types_[orig_row] == LEQ) {
404+
solution.row_dual[orig_row] = -dual_value;
289405
} else {
290-
solution.row_dual[i] = y_current_[i];
406+
solution.row_dual[orig_row] = dual_value;
291407
}
292408
}
293409

@@ -311,15 +427,15 @@ PostSolveRetcode PDLPSolver::postprocess(HighsSolution& solution) {
311427
linalg::Ax(unscaled_processed_lp_, x_current_, ax_current_);
312428

313429
int slack_variable_idx = original_num_col_;
314-
for (int i = 0; i < original_lp_->num_row_; ++i) {
315-
if (constraint_types_[i] == BOUND || constraint_types_[i] == FREE) {
316-
solution.row_value[i] = x_current_[slack_variable_idx++];
317-
} else if (constraint_types_[i] == LEQ) {
318-
// We transformed Ax <= b to -Ax >= -b. The original row value is Ax.
319-
// The calculated ax_current_ is for -Ax, so we flip the sign back.
320-
solution.row_value[i] = -ax_current_[i];
430+
for (int orig_row = 0; orig_row < original_lp_->num_row_; ++orig_row) {
431+
int reordered_row = constraint_new_idx_[orig_row];
432+
433+
if (constraint_types_[orig_row] == BOUND || constraint_types_[orig_row] == FREE) {
434+
solution.row_value[orig_row] = x_current_[slack_variable_idx++];
435+
} else if (constraint_types_[orig_row] == LEQ) {
436+
solution.row_value[orig_row] = -ax_current_[reordered_row];
321437
} else { // EQ, GEQ
322-
solution.row_value[i] = ax_current_[i];
438+
solution.row_value[orig_row] = ax_current_[reordered_row];
323439
}
324440
}
325441

highs/pdlp/hipdlp/pdhg.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class PDLPSolver {
5555
private:
5656
// --- Core Algorithm Logic ---
5757
void Initialize();
58+
void printConstraintInfo();
5859
bool CheckConvergence(const int iter, const std::vector<double>& x,
5960
const std::vector<double>& y,
6061
const std::vector<double>& ax_vector,

0 commit comments

Comments
 (0)