Skip to content

Commit f65c78a

Browse files
committed
Build linked lists to access A by rows
1 parent ba1f9b9 commit f65c78a

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

highs/ipm/hipo/ipm/FactorHiGHSSolver.cpp

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ Int FactorHiGHSSolver::buildNEstructureDense(const HighsSparseMatrix& A,
7777
// Build lower triangular structure of AAt.
7878
// This approach should be advantageous if AAt is expected to be relatively
7979
// dense.
80-
// It actually seems to work well in general, so I use this for now.
8180

8281
// create row-wise copy of the matrix
8382
AT_ = A;
@@ -182,7 +181,7 @@ Int FactorHiGHSSolver::buildNEstructureSparse(const HighsSparseMatrix& A,
182181
++nz_in_col;
183182
}
184183

185-
// the same if loop could be executed without branching:
184+
// the same if statement could be executed without branching:
186185
// (there does not seem to be a performance advantage)
187186
/*
188187
Int old_v = is_nz[row2];
@@ -260,6 +259,43 @@ Int FactorHiGHSSolver::buildNEvalues(const HighsSparseMatrix& A,
260259
return kStatusOk;
261260
}
262261

262+
Int FactorHiGHSSolver::buildNEstructureJacek(const HighsSparseMatrix& A,
263+
int64_t nz_limit) {
264+
// Build lower triangular structure of AAt.
265+
// This approach uses a column-wise copy of A and a collection of linked lists
266+
// to access the rows
267+
268+
// NB: A must have sorted columns for this to work
269+
270+
// colNE stores the index of the column of each entry.
271+
// It's useless when accessing the matrix by columns, but useful when doing it
272+
// by rows.
273+
colNE_.resize(A.numNz());
274+
275+
// head and next are a collection of linked lists to access the matrix by
276+
// rows.
277+
nextNE_.resize(A.numNz(), -1);
278+
headNE_.resize(A.num_row_, -1);
279+
280+
// temp stores the address of the latest entry in each row
281+
std::vector<Int> temp(A.num_row_, -1);
282+
283+
// build linked lists for row access
284+
for (Int col = 0; col < A.num_col_; ++col) {
285+
for (Int el = A.start_[col]; el < A.start_[col + 1]; ++el) {
286+
Int row = A.index_[el];
287+
colNE_[el] = col;
288+
289+
if (temp[row] == -1)
290+
headNE_[row] = el;
291+
else
292+
nextNE_[temp[row]] = el;
293+
294+
temp[row] = el;
295+
}
296+
}
297+
}
298+
263299
Int FactorHiGHSSolver::factorAS(const HighsSparseMatrix& A,
264300
const std::vector<double>& scaling) {
265301
// only execute factorisation if it has not been done yet
@@ -455,6 +491,8 @@ Int FactorHiGHSSolver::analyseNE(Symbolic& S, int64_t nz_limit) {
455491

456492
log_.printDevInfo("Building NE structure\n");
457493

494+
buildNEstructureJacek(model_.A(), nz_limit);
495+
458496
Clock clock;
459497
if (Int status = buildNEstructureSparse(model_.A(), nz_limit)) return status;
460498
if (info_) info_->matrix_structure_time = clock.stop();

highs/ipm/hipo/ipm/FactorHiGHSSolver.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class FactorHiGHSSolver : public LinearSolver {
2323
std::vector<Int> ptrNE_, rowsNE_;
2424
std::vector<double> valNE_;
2525
HighsSparseMatrix AT_;
26+
std::vector<Int> colNE_, nextNE_, headNE_;
2627

2728
const Regularisation& regul_;
2829

@@ -43,6 +44,9 @@ class FactorHiGHSSolver : public LinearSolver {
4344
Int buildNEvalues(const HighsSparseMatrix& A,
4445
const std::vector<double>& scaling);
4546

47+
Int buildNEstructureJacek(const HighsSparseMatrix& A,
48+
int64_t nz_limit = kHighsIInf);
49+
4650
Int analyseAS(Symbolic& S);
4751
Int analyseNE(Symbolic& S, int64_t nz_limit = kHighsIInf);
4852

0 commit comments

Comments
 (0)