Skip to content

Commit 971ddf5

Browse files
committed
HiPDLP now solves avgas
1 parent 9831690 commit 971ddf5

File tree

4 files changed

+122
-51
lines changed

4 files changed

+122
-51
lines changed

highs/pdlp/HiPdlpWrapper.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@
1010
* @author Julian Hall
1111
*/
1212
#include "pdlp/HiPdlpWrapper.h"
13+
#include "pdlp/hipdlp/logger.hpp"
14+
#include "pdlp/hipdlp/pdhg.hpp"
1315
#include "pdlp/hipdlp/restart.hpp"
1416

15-
void getHiPpdlpParamsFromOptions(const HighsOptions& options);
17+
void getHiPpdlpParamsFromOptions(const HighsOptions& options, PrimalDualParams& params);
1618

1719
HighsStatus solveLpHiPdlp(HighsLpSolverObject& solver_object) {
1820
return solveLpHiPdlp(solver_object.options_, solver_object.timer_,
@@ -29,8 +31,26 @@ HighsStatus solveLpHiPdlp(const HighsOptions& options, HighsTimer& timer,
2931
// Indicate that no imprecise solution has (yet) been found
3032
resetModelStatusAndHighsInfo(model_status, highs_info);
3133

32-
34+
std::string log_filename = "";
35+
LogLevel log_level = LogLevel::kInfo;
36+
37+
// --- Initialize Logger ---
38+
Logger logger(log_level);
39+
if (!log_filename.empty()) logger.set_log_file(log_filename);
40+
logger.print_header();
41+
42+
// --- Initialize Parameters with Defaults ---
43+
PrimalDualParams params{};
3344

45+
getHiPpdlpParamsFromOptions(options, params);
46+
std::vector<double> x, y;
47+
PDLPSolver pdlp(logger);
48+
49+
Timer total_timer;
50+
pdlp.Solve((HighsLp&)lp, params, x, y);
51+
52+
// --- Print Summary ---
53+
logger.print_summary(pdlp.GetResults(), pdlp.GetIterationCount(), total_timer.read());
3454
return HighsStatus::kError;
3555
}
3656

highs/pdlp/hipdlp/pdhg.cc

Lines changed: 40 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -82,29 +82,50 @@ void PDLPSolver::PreprocessLp(const HighsLp& original_lp, HighsLp& processed_lp)
8282
}
8383

8484
// 5. Formulate the new constraints matrix (A') and RHS (b')
85-
// We build it in COO format first for easier construction, then convert to CSC.
86-
std::vector<std::tuple<int, int, double>> coo_entries;
87-
88-
// Copy original matrix entries, transforming rows as needed
89-
for (int iCol = 0; iCol < nCols_orig; ++iCol) {
90-
for (int iEl = original_lp.a_matrix_.start_[iCol]; iEl < original_lp.a_matrix_.start_[iCol + 1]; ++iEl) {
91-
int iRow = original_lp.a_matrix_.index_[iEl];
92-
double value = original_lp.a_matrix_.value_[iEl];
93-
94-
if (constraint_types_[iRow] == LEQ) {
95-
coo_entries.emplace_back(iRow, iCol, -value);
96-
} else {
97-
coo_entries.emplace_back(iRow, iCol, value);
98-
}
99-
}
85+
//
86+
// Take a copy of the original LP's constraint matrix since we
87+
// need it rowwise and it's const
88+
HighsSparseMatrix original_matrix = original_lp.a_matrix_;
89+
original_matrix.ensureRowwise();
90+
// Set up the processed constraint matrix as an empty row-wise
91+
// matrix that can have nCols_orig columns
92+
HighsSparseMatrix& processed_matrix = processed_lp.a_matrix_;
93+
processed_matrix.clear();
94+
processed_matrix.num_col_ = nCols_orig;
95+
processed_matrix.format_ = MatrixFormat::kRowwise;
96+
HighsSparseMatrix row;
97+
const double negative_one = -1.0;
98+
const double* negative_one_p = &negative_one;
99+
for (int i = 0; i < nRows_orig; ++i) {
100+
// Get the row from the original constraint matrix
101+
original_matrix.getRow(i, row);
102+
// Scale the row by -1 if it's a LEQ
103+
if (constraint_types_[i] == LEQ)
104+
row.scaleRows(negative_one_p);
105+
// Add the row to the processed constraint matrix
106+
processed_matrix.addRows(row);
100107
}
108+
// Convert the processed constraint matrix to column-wise orientation
109+
processed_matrix.ensureColwise();
101110

102111
// Add slack variable entries (-1) for BOUND and FREE constraints
103112
current_slack_col = nCols_orig;
113+
// Set up a negated identity column as a column-wise matrix with
114+
// nRows_orig rows and a single column containing -1 in row 0 (for
115+
// now)
116+
HighsSparseMatrix col;
117+
assert(col.isColwise());
118+
col.num_col_ = 1;
119+
col.num_row_ = nRows_orig;
120+
col.start_.push_back(1);
121+
col.index_.push_back(0);
122+
col.value_.push_back(-1);
104123
for (int iRow = 0; iRow < nRows_orig; ++iRow) {
105124
if (constraint_types_[iRow] == BOUND || constraint_types_[iRow] == FREE) {
106-
coo_entries.emplace_back(iRow, current_slack_col, -1.0);
107-
current_slack_col++;
125+
// Put the -1 in row iRow, and add the column to the matrix
126+
col.index_[0] = iRow;
127+
processed_matrix.addCols(col);
128+
current_slack_col++;
108129
}
109130
}
110131

@@ -133,37 +154,9 @@ void PDLPSolver::PreprocessLp(const HighsLp& original_lp, HighsLp& processed_lp)
133154
}
134155
}
135156

136-
/*
137157
// 7. Convert COO matrix to CSC for the processed_lp
138-
std::sort(coo_entries.begin(), coo_entries.end(),
139-
[](const auto& a, const auto& b) {
140-
if (std::get<1>(a) != std::get<1>(b)) return std::get<1>(a) < std::get<1>(b);
141-
return std::get<0>(a) < std::get<0>(b);
142-
});
143-
144-
processed_lp.a_matrix_.start_.assign(processed_lp.num_col_ + 1, 0);
145-
processed_lp.a_matrix_.index_.resize(coo_entries.size());
146-
processed_lp.a_matrix_.value_.resize(coo_entries.size());
147-
148-
int current_col_idx = 0;
149-
processed_lp.a_matrix_.start_[0] = 0;
150-
for (size_t i = 0; i < coo_entries.size(); ++i) {
151-
int row = std::get<0>(coo_entries[i]);
152-
int col = std::get<1>(coo_entries[i]);
153-
double val = std::get<2>(coo_entries[i]);
154-
155-
processed_lp.a_matrix_.index_[i] = row;
156-
processed_lp.a_matrix_.value_[i] = val;
157-
158-
while (current_col_idx < col) {
159-
current_col_idx++;
160-
processed_lp.a_matrix_.start_[current_col_idx] = i;
161-
}
162-
}
163-
for (int col = current_col_idx; col < processed_lp.num_col_; ++col) {
164-
processed_lp.a_matrix_.start_[col + 1] = coo_entries.size();
165-
}
166-
*/
158+
//
159+
// Already achieved by construction
167160
logger_.info("Preprocessing complete. New dimensions: " + std::to_string(processed_lp.num_row_) + " rows, " + std::to_string(processed_lp.num_col_) + " cols.");
168161
}
169162

highs/util/HighsSparseMatrix.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,38 @@ void HighsSparseMatrix::addVec(const HighsInt num_nz, const HighsInt* index,
250250
}
251251
}
252252

253+
void HighsSparseMatrix::scaleCols(const double* scale) {
254+
if (this->isColwise()) {
255+
for (HighsInt iCol = 0; iCol < this->num_col_; iCol++) {
256+
for (HighsInt iEl = this->start_[iCol]; iCol < this->start_[iCol + 1];
257+
iEl++)
258+
this->value_[iEl] *= scale[iCol];
259+
}
260+
} else {
261+
for (HighsInt iRow = 0; iRow < this->num_row_; iRow++) {
262+
for (HighsInt iEl = this->start_[iRow]; iRow < this->start_[iRow + 1];
263+
iEl++)
264+
this->value_[iEl] *= scale[this->index_[iEl]];
265+
}
266+
}
267+
}
268+
269+
void HighsSparseMatrix::scaleRows(const double* scale) {
270+
if (this->isColwise()) {
271+
for (HighsInt iCol = 0; iCol < this->num_col_; iCol++) {
272+
for (HighsInt iEl = this->start_[iCol]; iCol < this->start_[iCol + 1];
273+
iEl++)
274+
this->value_[iEl] *= scale[this->index_[iEl]];
275+
}
276+
} else {
277+
for (HighsInt iRow = 0; iRow < this->num_row_; iRow++) {
278+
for (HighsInt iEl = this->start_[iRow]; iRow < this->start_[iRow + 1];
279+
iEl++)
280+
this->value_[iEl] *= scale[iRow];
281+
}
282+
}
283+
}
284+
253285
void HighsSparseMatrix::addCols(const HighsSparseMatrix new_cols,
254286
const int8_t* in_partition) {
255287
assert(new_cols.isColwise());
@@ -539,6 +571,28 @@ void HighsSparseMatrix::addRows(const HighsSparseMatrix new_rows,
539571
this->num_row_ += num_new_row;
540572
}
541573

574+
void HighsSparseMatrix::getCol(const HighsInt iCol,
575+
HighsSparseMatrix& col) const {
576+
col.format_ = MatrixFormat::kColwise;
577+
col.num_row_ = this->num_row_;
578+
col.num_col_ = 1;
579+
col.start_.resize(2);
580+
col.index_.resize(this->num_row_);
581+
col.value_.resize(this->num_row_);
582+
this->getCol(iCol, col.start_[1], col.index_.data(), col.value_.data());
583+
}
584+
585+
void HighsSparseMatrix::getRow(const HighsInt iRow,
586+
HighsSparseMatrix& row) const {
587+
row.format_ = MatrixFormat::kRowwise;
588+
row.num_row_ = 1;
589+
row.num_col_ = this->num_col_;
590+
row.start_.resize(2);
591+
row.index_.resize(this->num_col_);
592+
row.value_.resize(this->num_col_);
593+
this->getRow(iRow, row.start_[1], row.index_.data(), row.value_.data());
594+
}
595+
542596
void HighsSparseMatrix::getCol(const HighsInt iCol, HighsInt& num_nz,
543597
HighsInt* index, double* value) const {
544598
assert(iCol >= 0 && iCol < this->num_col_);

highs/util/HighsSparseMatrix.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,18 @@ class HighsSparseMatrix {
5252

5353
void addVec(const HighsInt num_nz, const HighsInt* index, const double* value,
5454
const double multiple = 1);
55+
void scaleCols(const double* scale);
56+
void scaleRows(const double* scale);
5557
void addCols(const HighsSparseMatrix new_cols,
5658
const int8_t* in_partition = NULL);
5759
void addRows(const HighsSparseMatrix new_rows,
5860
const int8_t* in_partition = NULL);
59-
void getRow(const HighsInt iRow, HighsInt& num_nz, HighsInt* index,
60-
double* value) const;
61+
void getCol(const HighsInt iCol, HighsSparseMatrix& col) const;
62+
void getRow(const HighsInt iRow, HighsSparseMatrix& row) const;
6163
void getCol(const HighsInt iCol, HighsInt& num_nz, HighsInt* index,
6264
double* value) const;
65+
void getRow(const HighsInt iRow, HighsInt& num_nz, HighsInt* index,
66+
double* value) const;
6367
void deleteCols(const HighsIndexCollection& index_collection);
6468
void deleteRows(const HighsIndexCollection& index_collection);
6569
HighsStatus assessDimensions(const HighsLogOptions& log_options,

0 commit comments

Comments
 (0)