@@ -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+
263299Int 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 ();
0 commit comments